Ignore:
Timestamp:
Aug 4, 2011, 8:42:53 PM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

OS/2: gui: Make blocked widgets follow modal on Z-order change.

This makes sure that whenever the modal widget is brought
to front, all the ones it blocks will be placed right underneath it
keeping their original z-order at the time of blocking.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/kernel/qapplication_pm.cpp

    r936 r938  
    144144    QRect frameStrut() const { return d_func()->frameStrut(); }
    145145    HWND frameWinId() const { return d_func()->frameWinId(); }
     146    QETWidget* modalBlocker() const { return (QETWidget *)d_func()->modalBlocker(); }
    146147    bool        pmEvent(QMSG *m, MRESULT *r) { return QWidget::pmEvent(m, r); }
    147148//  void        markFrameStrutDirty() { data->fstrut_dirty = 1; }
     
    12681269}
    12691270
     1271static void qt_pull_blocked_widgets(QETWidget *widget)
     1272{
     1273    QWidgetList list = QApplication::topLevelWidgets();
     1274    foreach (QWidget *w, list) {
     1275        QETWidget *ew = (QETWidget *)w;
     1276        QETWidget *above = (QETWidget*)ew->modalBlocker();
     1277        if (above == widget) {
     1278            WinSetWindowPos(ew->frameWinId(), widget->frameWinId(),
     1279                            0, 0, 0, 0, SWP_ZORDER);
     1280            qt_pull_blocked_widgets(ew);
     1281        }
     1282    }
     1283}
     1284
    12701285PFNWP QtOldFrameProc = 0;
    12711286
    12721287MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    12731288{
     1289    static bool pullingBlockedWigets = false;
     1290
    12741291    do {
    12751292        if (!qApp) // unstable app state
     
    13151332            // If PM tries to activate a modally blocked window, pass activation
    13161333            // over to the top modal window instead of letting it activate the
    1317             // blocked one. Z-order changes are simply ignored for now.
    1318             // @todo Blocked widgets should keep Z-order WRT their modal
    1319             // blockers whenever they move (e.g. bringing the modal one to top
    1320             // should also put the one it blocks right under it instead of
    1321             // possibly leaving it somewhere behind other windows).
     1334            // blocked one
    13221335            PSWP pswp =(PSWP)qmsg.mp1;
    13231336            if (app_do_modal &&
    13241337                ((pswp->fl & SWP_ACTIVATE) || (pswp->fl & SWP_ZORDER))) {
    1325                 QWidget *top = 0;
    1326                 if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && widget != top) {
     1338                QETWidget *above = (QETWidget *)widget->modalBlocker();
     1339                if (above) {
    13271340                    if (pswp->fl & SWP_ACTIVATE) {
    1328                         if (top->isVisible()) {
    1329                             top->activateWindow();
    1330                         } else {
    1331                             // This is the case when native file dialogs are shown
    1332                             QWidget *p = (top->parentWidget() ? top->parentWidget()->window() : 0);
    1333                             if (p && p->isVisible()) {
    1334                                 p->activateWindow();
    1335                             }
    1336                         }
     1341                        // find the blocker that isn't blocked itself and
     1342                        // delegate activation to it (WM_WINDOWPOSCHANGED will
     1343                        // care about the rest)
     1344                        while (above->modalBlocker())
     1345                            above = above->modalBlocker();
     1346                        WinSetWindowPos(above->frameWinId(), HWND_TOP, 0, 0, 0, 0,
     1347                                        SWP_ACTIVATE | SWP_ZORDER);
    13371348                        pswp->fl &= ~SWP_ACTIVATE;
    13381349                    }
    13391350                    if (pswp->fl & SWP_ZORDER) {
    1340                         pswp->fl &= ~SWP_ZORDER;
     1351                        // forbid changing the Z-order of the blocked widget
     1352                        // (except when it is moved right under its blocker)
     1353                        if (pswp->hwndInsertBehind != above->frameWinId())
     1354                            pswp->fl &= ~SWP_ZORDER;
    13411355                    }
    13421356                }
     1357            }
     1358            break;
     1359        }
     1360
     1361        case WM_WINDOWPOSCHANGED: {
     1362            PSWP pswp =(PSWP)qmsg.mp1;
     1363            // make sure blocked widgets stay behind the blocker on Z-order change
     1364            if (app_do_modal && (pswp->fl & SWP_ZORDER) && !pullingBlockedWigets) {
     1365                // protect against various kinds of recursion (e.g. when the
     1366                // blocked widgets are PM owners of the blocker in which case PM
     1367                // manages pulling on its own and will put us in a loop)
     1368                pullingBlockedWigets = true;
     1369                qt_pull_blocked_widgets(widget);
     1370                pullingBlockedWigets = false;
    13431371            }
    13441372            break;
     
    14781506    // programmatically, e.g. from the Window List)
    14791507    QWidgetList list = QApplication::topLevelWidgets();
    1480     foreach(QWidget *w, list) {
     1508    foreach (QWidget *w, list) {
    14811509        if (w != widget && QApplicationPrivate::isBlockedByModal(w)) {
    1482             WinEnableWindow(w->d_func()->frameWinId(), FALSE);
     1510            if (!w->d_func()->modalBlocker()) {
     1511                WinEnableWindow(w->d_func()->frameWinId(), FALSE);
     1512                // also remember the blocker widget so that the blocked one can
     1513                // pass activation attempts to it (note that the blocker is not
     1514                // necessarily modal itself, it's just the window right above
     1515                // the one being blocked, we will use this to restore z-order of
     1516                // of blocked widgets in qt_pull_blocked_widgets())
     1517                QWidget *widgetAbove = 0;
     1518                HWND above = w->d_func()->frameWinId();
     1519                while (!widgetAbove) {
     1520                    above = WinQueryWindow(above, QW_PREV);
     1521                    if (!above)
     1522                        break;
     1523                    widgetAbove = qt_widget_from_hwnd(above);
     1524                }
     1525                if (!widgetAbove)
     1526                    widgetAbove = widget;
     1527                w->d_func()->setModalBlocker(widgetAbove);
     1528            }
    14831529        }
    14841530    }
     
    15151561        foreach(QWidget *w, list) {
    15161562            if (w != widget && !QApplicationPrivate::isBlockedByModal(w)) {
    1517                 WinEnableWindow(w->d_func()->frameWinId(), TRUE);
     1563                if (w->d_func()->modalBlocker()) {
     1564                    w->d_func()->setModalBlocker(0);
     1565                    WinEnableWindow(w->d_func()->frameWinId(), TRUE);
     1566                }
    15181567            }
    15191568        }
Note: See TracChangeset for help on using the changeset viewer.