Changeset 751


Ignore:
Timestamp:
Jun 15, 2010, 5:00:46 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: OS/2: Exclude children with real HWNDs (a.k.a native widgets) when flushing paint events to make sure they are not painted over by the parent (see #161 for details).

Location:
trunk/src/gui/painting
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/painting/qwindowsurface_pm.cpp

    r746 r751  
    5858#include <qt_os2.h>
    5959#include <qlibrary.h>
     60
     61
    6062
    6163#include "qwindowsurface_pm_p.h"
     
    323325    QPMDiveWindowSurfaceFB(QWidget *widget);
    324326    ~QPMDiveWindowSurfaceFB();
    325     void doFlush(const QRect &from, const QPoint &to);
     327    void doFlush(const QRect &from, const QPoint &to);
    326328};
    327329
    328 struct QPMDiveWindowSurfacePrivate
    329 {
     330struct QPMDiveWindowSurfacePrivate : public QObject, private QWidget::PmEventFilter
     331{
     332    QPMDiveWindowSurface *that;
     333
    330334    QImage *image;
    331335    HDIVE hDive;
     
    333337    ULONG bufNum;
    334338    bool posDirty;
    335     bool vrnDirty;
    336339    bool vrnDisabled;
    337340    bool inDrag;
    338     int windowHeight;
    339341    SETUP_BLITTER setup;
    340     QVector<RECTL> rcls;
    341342
    342343    struct FlushArgs
    343344    {
     345
    344346        QRect from;
    345347        QPoint to;
    346348    };
    347349    QList<FlushArgs> pending;
     350
     351
     352
     353
     354
     355
     356
     357
     358
     359
     360
     361
     362
     363
     364
     365
     366
     367
     368
     369
     370
     371
     372
     373
     374
     375
     376
    348377};
     378
     379
     380
     381
     382
     383
     384
     385
     386
     387
     388
     389
     390
     391
     392
     393
     394
     395
     396
     397
     398
     399
     400
     401
     402
     403
     404
     405
     406
     407
     408
     409
     410
     411
     412
     413
     414
     415
     416
     417
     418
     419
     420
     421
     422
     423
     424
     425
     426
     427
     428
     429
     430
     431
     432
     433
     434
     435
     436
     437
     438
     439
     440
     441
     442
     443
     444
     445
     446
     447
     448
     449
     450
     451
     452
     453
     454
     455
     456
     457
     458
     459
     460
     461
     462
     463
     464
     465
     466
     467
     468
     469
     470
     471
     472
     473
     474
     475
     476
     477
     478
     479
     480
     481
     482
     483
     484
    349485
    350486QPMDiveWindowSurface::QPMDiveWindowSurface(QWidget* widget)
    351487    : QWindowSurface(widget), d(new QPMDiveWindowSurfacePrivate)
    352488{
     489
    353490    d->image = 0;
    354491    d->hDive = NULLHANDLE;
     
    356493    d->bufNum = 0;
    357494    d->posDirty = true;
    358     d->vrnDirty = true;
    359495    d->vrnDisabled = false;
    360496    d->inDrag = false;
    361     d->windowHeight = 0;
     497    d-> = 0;
    362498
    363499    memset(&d->setup, 0, sizeof(SETUP_BLITTER));
     
    369505    d->setup.fccDstColorFormat = FOURCC_SCRN;
    370506
    371     window()->addPmEventFilter(this);
    372     WinSetVisibleRegionNotify(window()->winId(), TRUE);
     507   
     508    );
    373509
    374510    setStaticContentsSupport(true);
     
    377513QPMDiveWindowSurface::~QPMDiveWindowSurface()
    378514{
    379     WinSetVisibleRegionNotify(window()->winId(), FALSE);
    380     window()->removePmEventFilter(this);
     515    if (d->subWidgets) {
     516        foreach(HWND hwnd, d->subWidgets->keys())
     517            d->removeWidget((*d->subWidgets)[hwnd].widget);
     518        Q_ASSERT(d->subWidgets->count() == 0);
     519        delete d->subWidgets;
     520    }
     521
     522    d->removeWidget(window());
    381523
    382524    if (d->bufNum)
     
    400542    if (!d->image || rgn.rectCount() == 0)
    401543        return;
     544
     545
     546
     547
    402548
    403549    QRect br = rgn.boundingRect();
     
    465611    if (d->vrnDisabled) {
    466612        // defer the flush
    467         QPMDiveWindowSurfacePrivate::FlushArgs args = { br, wbr.topLeft() };
     613        QPMDiveWindowSurfacePrivate::FlushArgs args = { widget,
     614                                                        br, wbr.topLeft() };
    468615        d->pending.append(args);
    469616        return;
    470617    }
    471618
    472     doFlush(br, wbr.topLeft());
    473 }
    474 
    475 bool QPMDiveWindowSurface::adjustSetup()
     619    doFlush(br, wbr.topLeft());
     620}
     621
     622bool QPMDiveWindowSurface::adjustSetup()
    476623{
    477624    HWND hwnd = window()->winId();
     
    481628    bool setupDirty = false;
    482629
    483     if (d->posDirty || d->vrnDirty) {
     630    QPMDiveWindowSurfacePrivate::WidgetData *wd = d->widgetData(widget);
     631    Q_ASSERT(wd);
     632
     633    if (d->posDirty || wd->vrnDirty) {
    484634        setupDirty = true;
    485635        d->posDirty = false;
     636
    486637        POINTL ptl = { 0, 0 };
    487638        WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptl, 1);
     
    494645    }
    495646
    496     if (d->vrnDirty) {
     647    bool wasVrnDirty = wd->vrnDirty;
     648
     649    if (wd->vrnDirty) {
    497650        setupDirty = true;
    498         d->vrnDirty = false;
     651        d->vrnDirty = false;
    499652
    500653        HPS hps = window()->getPS();
    501654        HRGN hrgn = GpiCreateRegion(hps, 0L, NULL);
    502655
    503         RGNRECT rgnCtl;
    504         rgnCtl.ircStart = 1;
    505         rgnCtl.crc = rgnCtl.crcReturned = 0;
    506         rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
    507 
    508656        ULONG rc = WinQueryVisibleRegion(hwnd, hrgn);
     657
     658
     659
     660
     661
     662
     663
     664
     665
     666
     667
     668
     669
     670
     671
     672
     673
     674
     675
     676
    509677        if (rc == RGN_RECT || rc == RGN_COMPLEX) {
     678
     679
     680
     681
    510682            if (GpiQueryRegionRects(hps, hrgn, NULL, &rgnCtl, NULL) &&
    511683                rgnCtl.crcReturned) {
     
    513685                rgnCtl.crc = rgnCtl.crcReturned;
    514686                rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
    515                 if (d->rcls.size() < (int)rgnCtl.crc)
    516                     d->rcls.resize((int)rgnCtl.crc);
    517                 GpiQueryRegionRects(hps, hrgn, NULL, &rgnCtl, d->rcls.data());
     687                if (wd->rcls.size() < (int)rgnCtl.crc)
     688                    wd->rcls.resize((int)rgnCtl.crc);
     689                wd->rclCount = rgnCtl.crc;
     690                GpiQueryRegionRects(hps, hrgn, NULL, &rgnCtl, wd->rcls.data());
    518691            }
    519         }
    520 
    521         d->setup.ulNumDstRects = rgnCtl.crcReturned;
    522         d->setup.pVisDstRects = rgnCtl.crcReturned ? d->rcls.data() : NULL;
    523         d->setup.ulStructLen = sizeof(SETUP_BLITTER);
     692        } else if (rc == RGN_NULL) {
     693            wd->rclCount = 0;
     694        }
    524695
    525696        GpiDestroyRegion(hps, hrgn);
     
    528699        // memorize the window height used for the additional visible region
    529700        // validation in doFlush()
    530         d->windowHeight = window()->height();
     701        ->height();
    531702
    532703#if defined(QDIVE_DEBUG)
    533704        DEBUG(() << "QPMDiveWindowSurface::adjustSetup:" << "vrnDirty");
    534         for (size_t i = 0; i < d->setup.ulNumDstRects; ++i)
    535             DEBUG(() << " " << i << ":" << d->setup.pVisDstRects[i]);
     705        for (size_t i = 0; i < ; ++i)
     706            DEBUG(() << " " << i << ":" << s[i]);
    536707#endif
    537708    }
    538709
     710
     711
     712
     713
     714
     715
     716
     717
     718
     719
     720
    539721    return setupDirty;
    540722}
    541723
    542 void QPMDiveWindowSurface::doFlush(const QRect &from, const QPoint &to)
    543 {
    544     DEBUG(() << "QPMDiveWindowSurface::doFlush:" << window()
     724void QPMDiveWindowSurface::doFlush(const QRect &from, const QPoint &to)
     725{
     726    DEBUG(() << "QPMDiveWindowSurface::doFlush:" << window()
    545727             << "from" << from << "to" << to);
    546728
     
    550732    QPoint dst = to + (src.topLeft() - from.topLeft());
    551733
    552     bool setupDirty = adjustSetup();
     734    bool setupDirty = adjustSetup();
    553735
    554736    // note that the source image is expected to be top-left oriented
     
    578760
    579761    DiveBlitImage(d->hDive, d->bufNum, DIVE_BUFFER_SCREEN);
    580 }
    581 
    582 bool QPMDiveWindowSurface::pmEventFilter(QMSG *msg, MRESULT *result)
    583 {
    584     switch (msg->msg) {
    585         case WM_VRNDISABLED: {
    586             if (!d->useFB)
    587                 DiveSetupBlitter(d->hDive, NULL);
    588             d->vrnDisabled = true;
    589             *result = 0;
    590             return true;
    591         }
    592         case DM_DRAGOVER: {
    593             d->inDrag = true;
    594             break;
    595         }
    596         case DM_DRAGLEAVE:
    597         case DM_DROP: {
    598             d->inDrag = false;
    599             break;
    600         }
    601         case WM_VRNENABLED: {
    602             d->vrnDisabled = false;
    603             // Note that when an overlapping window of *other* process is moved
    604             // over this window, PM still sends WM_VRNENABLED to it but with
    605             // ffVisRgnChanged set to FALSE although the visible region *does*
    606             // actually change (it doesn't seem to be the case for windows of
    607             // the same process). The solution is to ignore this flag and always
    608             // assume that the visible region was changed when we get this msg
    609 #if 0
    610             if (LONGFROMMP(msg->mp1)) // window's visible region changed
    611 #endif
    612                 d->vrnDirty = true;
    613             d->posDirty = true;
    614 
    615             // process pending flush events
    616             foreach(const QPMDiveWindowSurfacePrivate::FlushArgs &args, d->pending)
    617                 doFlush(args.from, args.to);
    618             d->pending.clear();
    619 
    620             *result = 0;
    621             return true;
    622         }
    623         default:
    624             break;
    625     }
    626 
    627     return false;
    628762}
    629763
     
    9341068}
    9351069
    936 void QPMDiveWindowSurfaceFB::doFlush(const QRect &from, const QPoint &to)
    937 {
    938     DEBUG(() << "QPMDiveWindowSurfaceFB::doFlush:" << window()
     1070void QPMDiveWindowSurfaceFB::doFlush(const QRect &from, const QPoint &to)
     1071{
     1072    DEBUG(() << "QPMDiveWindowSurfaceFB::doFlush:" << window()
    9391073             << "from" << from << "to" << to);
    9401074
     
    9461080    QPoint dstDelta = from.topLeft() - to;
    9471081
    948     const int windowHeight = window()->height();
     1082    QPMDiveWindowSurfacePrivate::WidgetData *wd = d->widgetData(widget);
     1083    Q_ASSERT(wd);
     1084
     1085    int widgetHeight = widget->height();
    9491086
    9501087    // sometimes PM does not send WM_VRNENABLED although the window size has
     
    9521089    // application) which leads to screen corruption due to outdated visible
    9531090    // regions. A fix is to memorize the window height and check it here
    954     if (windowHeight != d->windowHeight)
    955         d->vrnDirty = true;
     1091    if (wiHeight)
     1092        d->vrnDirty = true;
    9561093
    9571094    bool wasPosDirty = d->posDirty;
    958     bool wasVrnDirty = d->vrnDirty;
    959 
    960     adjustSetup();
     1095    bool wasVrnDirty = wd->vrnDirty;
     1096
     1097    adjustSetup(widget);
     1098
     1099    int windowHeight = window()->height();
    9611100
    9621101    if (wasVrnDirty) {
  • trunk/src/gui/painting/qwindowsurface_pm_p.h

    r713 r751  
    6363struct QPMDiveWindowSurfacePrivate;
    6464
    65 class QPMDiveWindowSurface : public QWindowSurface, private QWidget::PmEventFilter
     65class QPMDiveWindowSurface : public QWindowSurface
    6666{
    6767public:
     
    7777
    7878protected:
    79     bool adjustSetup();
    80     virtual void doFlush(const QRect &from, const QPoint &to);
    81     bool pmEventFilter(QMSG *msg, MRESULT *result);
     79    bool adjustSetup(QWidget *widget);
     80    virtual void doFlush(QWidget *widget, const QRect &from, const QPoint &to);
    8281
    8382    QScopedPointer<QPMDiveWindowSurfacePrivate> d;
     83
    8484};
    8585
Note: See TracChangeset for help on using the changeset viewer.