Changeset 498 for trunk/src


Ignore:
Timestamp:
Feb 1, 2010, 12:24:47 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

gui/kernel: Implemented delivering of QEvent::NonClientAreaMouse* events to top-level widgets (#122).

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

Legend:

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

    r496 r498  
    146146//  void        markFrameStrutDirty() { data->fstrut_dirty = 1; }
    147147    bool        translateMouseEvent(const QMSG &qmsg);
     148    void        translateNonClientMouseEvent(const QMSG &qmsg);
    148149#ifndef QT_NO_WHEELEVENT
    149150    bool        translateWheelEvent(const QMSG &qmsg);
     
    729730}
    730731
     732// QMSG wrapper that translates message coordinates from PM to Qt
     733struct QtQmsg : public QMSG
     734{
     735    QtQmsg(HWND aHwnd, ULONG aMsg, MPARAM aMp1, MPARAM aMp2)
     736    {
     737        hwnd = aHwnd;
     738        msg = aMsg;
     739        mp1 = aMp1;
     740        mp2 = aMp2;
     741        time = WinQueryMsgTime(0);
     742
     743        isTranslatableMouseEvent =
     744            (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) ||
     745            (msg >= WM_EXTMOUSEFIRST && msg <= WM_EXTMOUSELAST);
     746
     747        if (isTranslatableMouseEvent || msg == WM_CONTEXTMENU) {
     748            ptl.x = (short)SHORT1FROMMP(mp1);
     749            ptl.y = (short)SHORT2FROMMP(mp1);
     750            WinMapWindowPoints(hwnd, HWND_DESKTOP, &ptl, 1);
     751        } else {
     752            WinQueryMsgPos(0, &ptl);
     753        }
     754        // flip y coordinate
     755        ptl.y = QApplication::desktop()->height() - (ptl.y + 1);
     756    }
     757
     758    bool isTranslatableMouseEvent;
     759};
     760
    731761// QtWndProc() receives all messages from the main event loop
    732762
     
    745775        QETWidget *widget = 0;
    746776
    747         bool isTranslatableMouseEvent =
    748             (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) ||
    749             (msg >= WM_EXTMOUSEFIRST && msg <= WM_EXTMOUSELAST);
    750 
    751         QMSG qmsg; // create QMSG structure
    752         qmsg.hwnd = hwnd;
    753         qmsg.msg = msg;
    754         qmsg.mp1 = mp1;
    755         qmsg.mp2 = mp2;
    756         qmsg.time = WinQueryMsgTime(0);
    757 
    758         if (isTranslatableMouseEvent || msg == WM_CONTEXTMENU) {
    759             qmsg.ptl.x = (short)SHORT1FROMMP(mp1);
    760             qmsg.ptl.y = (short)SHORT2FROMMP(mp1);
    761             WinMapWindowPoints(qmsg.hwnd, HWND_DESKTOP, &qmsg.ptl, 1);
    762         } else {
    763             WinQueryMsgPos(0, &qmsg.ptl);
    764         }
    765         // flip y coordinate
    766         qmsg.ptl.y = QApplication::desktop()->height() - (qmsg.ptl.y + 1);
     777        QtQmsg qmsg(hwnd, msg, mp1, mp2);
    767778
    768779#if defined(QT_DEBUGMSGFLOW)
     
    904915            return rc;
    905916
    906         if (isTranslatableMouseEvent) {
     917        if (qmsg.isTranslatableMouseEvent) {
    907918            if (qApp->activePopupWidget() != 0) { // in popup mode
    908919                QWidget *w = QApplication::widgetAt(qmsg.ptl.x, qmsg.ptl.y);
     
    12371248        Q_ASSERT(widget->isWindow());
    12381249
    1239         QMSG qmsg; // create QMSG structure
    1240         qmsg.hwnd = hwnd;
    1241         qmsg.msg = msg;
    1242         qmsg.mp1 = mp1;
    1243         qmsg.mp2 = mp2;
     1250        QtQmsg qmsg(hwnd, msg, mp1, mp2);
    12441251
    12451252#if defined(QT_DEBUGMSGFLOW)
     
    12501257        }
    12511258#endif
     1259
     1260        if (qmsg.isTranslatableMouseEvent)
     1261            widget->translateNonClientMouseEvent(qmsg);
    12521262
    12531263        switch(msg) {
     
    13131323}
    13141324
     1325PFNWP QtOldFrameCtlProcs[FID_HORZSCROLL - FID_SYSMENU + 1] = { 0 };
     1326
     1327MRESULT EXPENTRY QtFrameCtlProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     1328{
     1329    // sanity: this procedure is only for standard frame controls
     1330    ULONG id = (ULONG)WinQueryWindowUShort(hwnd, QWS_ID);
     1331    Q_ASSERT(id >= FID_SYSMENU && id <= FID_HORZSCROLL);
     1332    Q_ASSERT(QtOldFrameCtlProcs[id - FID_SYSMENU]);
     1333    if (id < FID_SYSMENU || id > FID_HORZSCROLL ||
     1334        !QtOldFrameCtlProcs[id - FID_SYSMENU])
     1335        return FALSE;
     1336
     1337    do {
     1338        if (!qApp) // unstable app state
     1339            break;
     1340
     1341        HWND hwndF = WinQueryWindow(hwnd, QW_PARENT);
     1342        HWND hwndC = WinWindowFromID(hwndF, FID_CLIENT);
     1343        QETWidget *widget = (QETWidget*)QWidget::find(hwndC);
     1344        if (!widget) // don't know this widget
     1345            break;
     1346
     1347        Q_ASSERT(widget->isWindow());
     1348
     1349        QtQmsg qmsg(hwnd, msg, mp1, mp2);
     1350
     1351#if defined(QT_DEBUGMSGFLOW)
     1352        {
     1353            QDbgStr str = qStrQMSG(qmsg);
     1354            if (!str.isEmpty())
     1355                qDebug() << "*** [FC]" << str;
     1356        }
     1357#endif
     1358
     1359        if (qmsg.isTranslatableMouseEvent)
     1360            widget->translateNonClientMouseEvent(qmsg);
     1361
     1362    } while(0);
     1363
     1364    // call the original window procedure of this frame control
     1365    return QtOldFrameCtlProcs[id - FID_SYSMENU](hwnd, msg, mp1, mp2);
     1366}
     1367
    13151368/*****************************************************************************
    13161369  Modal widgets; We have implemented our own modal widget mechanism
     
    16021655//
    16031656
    1604 static ushort mouseTbl[] = {
     1657static const ushort mouseTbl[] = {
    16051658    WM_MOUSEMOVE,           QEvent::MouseMove,                  0,
    16061659    WM_BUTTON1DOWN,         QEvent::MouseButtonPress,       Qt::LeftButton,
     
    16141667    WM_BUTTON3DBLCLK,   QEvent::MouseButtonDblClick,    Qt::MidButton,
    16151668    WM_CONTEXTMENU,     QEvent::ContextMenu,            0,
     1669    0,                          0,                                              0
     1670};
     1671
     1672static const ushort mouseTblNC[] = {
     1673    WM_MOUSEMOVE,           QEvent::NonClientAreaMouseMove,                     0,
     1674    WM_BUTTON1DOWN,         QEvent::NonClientAreaMouseButtonPress,          Qt::LeftButton,
     1675    WM_BUTTON1UP,           QEvent::NonClientAreaMouseButtonRelease,    Qt::LeftButton,
     1676    WM_BUTTON1DBLCLK,   QEvent::NonClientAreaMouseButtonDblClick,       Qt::LeftButton,
     1677    WM_BUTTON2DOWN,         QEvent::NonClientAreaMouseButtonPress,          Qt::RightButton,
     1678    WM_BUTTON2UP,           QEvent::NonClientAreaMouseButtonRelease,    Qt::RightButton,
     1679    WM_BUTTON2DBLCLK,   QEvent::NonClientAreaMouseButtonDblClick,       Qt::RightButton,
     1680    WM_BUTTON3DOWN,         QEvent::NonClientAreaMouseButtonPress,          Qt::MidButton,
     1681    WM_BUTTON3UP,           QEvent::NonClientAreaMouseButtonRelease,    Qt::MidButton,
     1682    WM_BUTTON3DBLCLK,   QEvent::NonClientAreaMouseButtonDblClick,       Qt::MidButton,
    16161683    0,                          0,                                              0
    16171684};
     
    19692036            res = res && e.isAccepted();
    19702037        }
    1971 
    1972         if (type != QEvent::MouseMove)
    1973             pos.rx() = pos.ry() = -9999;        // init for move compression
    19742038    }
    19752039
    19762040    return res;
     2041}
     2042
     2043void QETWidget::translateNonClientMouseEvent(const QMSG &qmsg)
     2044{
     2045    // this is a greatly simplified version of translateMouseEvent() that
     2046    // only sends informational non-client area mouse messages to the top-level
     2047    // widget
     2048
     2049    Q_ASSERT(isWindow());
     2050    Q_ASSERT(internalWinId() != NULLHANDLE);
     2051
     2052#if !defined (QT_NO_SESSIONMANAGER)
     2053    if (sm_blockUserInput) //block user interaction during session management
     2054        return;
     2055#endif
     2056
     2057    if (qApp->d_func()->inPopupMode()) {
     2058        // don't report non-client area events in popup mode
     2059        // (for compatibility with Windows)
     2060        return;
     2061    }
     2062
     2063    int i;
     2064    for (i = 0; mouseTblNC[i] && (ULONG)mouseTblNC[i] != qmsg.msg; i += 3)
     2065        ;
     2066    if (!mouseTblNC[i])
     2067        return;
     2068
     2069    QEvent::Type type   = (QEvent::Type)mouseTblNC[++i];    // event type
     2070    int button          = mouseTblNC[++i];                  // which button
     2071    int state = translateButtonState(SHORT2FROMMP(qmsg.mp2), type, button); // button state
     2072
     2073    const QPoint globalPos(QPoint(qmsg.ptl.x, qmsg.ptl.y));
     2074    const QPoint widgetPos = mapFromGlobal(globalPos);
     2075
     2076    QMouseEvent e(type, widgetPos, globalPos, Qt::MouseButton(button),
     2077                  Qt::MouseButtons(state & Qt::MouseButtonMask),
     2078                  Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
     2079
     2080    QApplication::sendSpontaneousEvent(this, &e);
    19772081}
    19782082
  • trunk/src/gui/kernel/qwidget_pm.cpp

    r497 r498  
    7171extern PFNWP QtOldFrameProc;
    7272extern MRESULT EXPENTRY QtFrameProc(HWND, ULONG, MPARAM, MPARAM);
     73extern PFNWP QtOldFrameCtlProcs[FID_HORZSCROLL - FID_SYSMENU + 1];
     74extern MRESULT EXPENTRY QtFrameCtlProc(HWND, ULONG, MPARAM, MPARAM);
    7375
    7476#if !defined(QT_NO_SESSIONMANAGER)
     
    11611163                QtOldFrameProc = oldProc;
    11621164
     1165            // subclass all standard frame controls to get non-client mouse events
     1166            // (note: the size of the ctls array must match QtOldFrameCtlProcs)
     1167            HWND ctls[FID_HORZSCROLL - FID_SYSMENU + 1];
     1168            if (WinMultWindowFromIDs(fId, ctls, FID_SYSMENU, FID_HORZSCROLL) > 0) {
     1169                for (size_t i = 0; i < sizeof(ctls)/sizeof(ctls[0]); ++i) {
     1170                    if (ctls[i] != NULLHANDLE) {
     1171                        oldProc = WinSubclassWindow(ctls[i], QtFrameCtlProc);
     1172                        // remember the old proc only once: it's the same for
     1173                        // all standard frame control windows.
     1174                        if (!QtOldFrameCtlProcs[i])
     1175                            QtOldFrameCtlProcs[i] = oldProc;
     1176                    }
     1177                }
     1178            }
     1179
    11631180            removeSysMenuAccels(fId);
    11641181
Note: See TracChangeset for help on using the changeset viewer.