Changeset 108


Ignore:
Timestamp:
Aug 12, 2009, 10:18:10 PM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: Added mouse event translation, various message handling.

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

Legend:

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

    r100 r108  
    5151#include "qcolormap.h"
    5252#include "qpixmapcache.h"
     53#include "qdesktopwidget.h"
    5354
    5455#include "qset.h"
     
    6869static HWND      curWin         = 0;            // current window
    6970static HPS       displayPS      = 0;            // display presentation space
     71
     72#if !defined (QT_NO_SESSIONMANAGER)
     73
     74// Session management
     75static bool     sm_blockUserInput    = FALSE;
     76
     77//#define DEBUG_SESSIONMANAGER
     78
     79#endif
    7080
    7181static bool replayPopupMouseEvent = false; // replay handling when popups close
     
    8292extern QDesktopWidget *qt_desktopWidget;
    8393static QPointer<QWidget> popupButtonFocus;
    84 static bool     qt_try_modal(QWidget *, QMSG *, int& ret);
     94static bool     qt_try_modal(QWidget*, QMSG*, MRESULT&);
    8595
    8696QWidget *qt_button_down = 0; // widget got last button-down
     
    8898
    8999static HWND autoCaptureWnd = NULLHANDLE;
     100static bool autoCaptureReleased = FALSE;
    90101static void setAutoCapture(HWND); // automatic capture
    91102static void releaseAutoCapture();
     
    107118//  QWidgetPrivate *dptr() { return d_func(); }
    108119//  QRect frameStrut() const { return d_func()->frameStrut(); }
    109 //  bool        winEvent(QMSG *m, long *r) { return QWidget::winEvent(m, r); }
     120    bool        pmEvent(QMSG *m, MRESULT *r) { return QWidget::pmEvent(m, r); }
    110121//  void        markFrameStrutDirty() { data->fstrut_dirty = 1; }
    111 //  bool        translateMouseEvent(const MSG &msg);
    112 //  bool        translateWheelEvent(const MSG &msg);
    113 //  bool        translatePaintEvent(const MSG &msg);
     122    bool        translateMouseEvent(const QMSG &qmsg);
     123#ifndef QT_NO_WHEELEVENT
     124    bool        translateWheelEvent(const QMSG &qmsg);
     125#endif
     126    bool        translatePaintEvent(const QMSG &qmsg);
    114127//  bool        translateConfigEvent(const MSG &msg);
    115128//  bool        translateCloseEvent(const MSG &msg);
     
    254267class QGuiEventDispatcherPM : public QEventDispatcherPM
    255268{
    256     Q_DECLARE_PRIVATE(QEventDispatcherPM)
    257269public:
    258270    QGuiEventDispatcherPM(QObject *parent = 0);
     
    424436MRESULT EXPENTRY QtWndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    425437{
    426     // message handling indicators: if handled is true at the end of message
    427     // processing, no default window proc is called but rc is returned.
    428     bool handled = false;
    429     MRESULT rc = (MRESULT) FALSE;
    430     QETWidget *widget = 0;
    431     HWND hwndC = NULLHANDLE;
    432 
    433438    do {
     439        if (!qApp) // unstable app state
     440            break;
     441#if 0
     442        // make sure we show widgets (e.g. scrollbars) when the user resizes
     443        if (qApp->loopLevel())
     444            qApp->sendPostedEvents(0, QEvent::ShowWindowRequest);
     445#endif
     446
     447        MRESULT rc = (MRESULT) FALSE;
     448        QETWidget *widget = 0;
     449
     450        bool isTranslatableMouseEvent =
     451            (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) ||
     452            (msg >= WM_EXTMOUSEFIRST && msg <= WM_EXTMOUSELAST);
     453
     454        QMSG qmsg; // create QMSG structure
     455        qmsg.hwnd = hwnd;
     456        qmsg.msg = msg;
     457        qmsg.mp1 = mp1;
     458        qmsg.mp2 = mp2;
     459        qmsg.time = WinQueryMsgTime(0);
     460
     461        if (isTranslatableMouseEvent || msg == WM_CONTEXTMENU) {
     462            qmsg.ptl.x = (short)SHORT1FROMMP(mp1);
     463            qmsg.ptl.y = (short)SHORT2FROMMP(mp1);
     464            WinMapWindowPoints(qmsg.hwnd, HWND_DESKTOP, &qmsg.ptl, 1);
     465        } else {
     466            WinQueryMsgPos(0, &qmsg.ptl);
     467        }
     468        // flip y coordinate
     469        qmsg.ptl.y = QApplication::desktop()->height() - (qmsg.ptl.y + 1);
     470
     471        // send through app filter
     472        if (qApp->filterEvent(&qmsg, reinterpret_cast<long *>(&rc)))
     473            return rc;
     474
     475        switch(msg) {
     476
     477        case WM_BUTTON1DOWN:
     478        case WM_BUTTON2DOWN:
     479        case WM_BUTTON3DOWN:
     480            if (ignoreNextMouseReleaseEvent)
     481                ignoreNextMouseReleaseEvent = false;
     482            break;
     483        case WM_BUTTON1UP:
     484        case WM_BUTTON2UP:
     485        case WM_BUTTON3UP:
     486            if (ignoreNextMouseReleaseEvent) {
     487                ignoreNextMouseReleaseEvent = false;
     488                if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) {
     489                    releaseAutoCapture();
     490                    qt_button_down = 0;
     491                }
     492                return (MRESULT)TRUE;
     493            }
     494            break;
     495
     496        default:
     497            break;
     498        }
     499
     500        if (!widget)
     501            widget = (QETWidget*)QWidget::find(hwnd);
     502        if (!widget) // don't know this widget
     503            break;
     504
     505        if (app_do_modal) { // modal event handling
     506            if (!qt_try_modal(widget, &qmsg, rc))
     507                return rc;
     508        }
     509
     510        if (widget->pmEvent(&qmsg, &rc)) // send through widget filter
     511            return rc;
     512
     513        if (isTranslatableMouseEvent) {
     514            if (qApp->activePopupWidget() != 0) { // in popup mode
     515                QWidget *w = QApplication::widgetAt(qmsg.ptl.x, qmsg.ptl.y);
     516                if (w) {
     517                    POINTL ptl = { SHORT1FROMMP(qmsg.mp1), SHORT2FROMMP(qmsg.mp1) };
     518                    WinMapWindowPoints(qmsg.hwnd, w->winId(), &ptl, 1);
     519                    qmsg.mp1 = MPFROM2SHORT(ptl.x, ptl.y);
     520                    widget = (QETWidget*)w;
     521                }
     522            }
     523            if (widget->translateMouseEvent(qmsg)) // mouse event
     524                return (MRESULT)TRUE;
     525#ifndef QT_NO_WHEELEVENT
     526        } else if (msg == WM_VSCROLL || msg == WM_HSCROLL) {
     527            if (widget->translateWheelEvent(qmsg))
     528                return (MRESULT)TRUE;
     529#endif
     530#ifndef QT_NO_DRAGANDDROP
     531        } else if (msg >= WM_DRAGFIRST && msg <= WM_DRAGLAST) {
     532            return qt_dispatchDragAndDrop(widget, qmsg);
     533#endif
     534        } else {
     535            switch(msg) {
     536
     537            case WM_SHOW: {
     538                // @todo there is some more processing in Qt4, see
     539                // WM_SHOWWINDOW in Win32 sources
     540                if (!SHORT1FROMMP(mp1) && autoCaptureWnd == widget->internalWinId())
     541                    releaseAutoCapture();
     542                break;
     543            }
     544
     545#ifndef QT_NO_CONTEXTMENU
     546            case WM_CONTEXTMENU: {
     547                if (SHORT2FROMMP(mp2)) {
     548                    // keyboard event
     549                    QWidget *fw = qApp->focusWidget();
     550                    if (fw && fw->isEnabled()) {
     551                        QContextMenuEvent e(QContextMenuEvent::Keyboard,
     552                                            QPoint(5, 5),
     553                                            fw->mapToGlobal(QPoint(5, 5)), 0);
     554                        if (qt_sendSpontaneousEvent(fw, &e))
     555                            return (MRESULT)TRUE;
     556                    }
     557                } else {
     558                    // mouse event
     559                    if (widget->translateMouseEvent(qmsg))
     560                        return (MRESULT)TRUE;
     561                }
     562                break;
     563            }
     564#endif
     565
     566            default:
     567                break;
     568            }
     569        }
     570
     571    } while(0);
     572
     573    return WinDefWindowProc(hwnd, msg, mp1, mp2);
     574}
     575
     576PFNWP QtOldFrameProc = 0;
     577
     578MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     579{
     580    do {
     581        if (!qApp) // unstable app state
     582            break;
     583#if 0
     584        // make sure we show widgets (e.g. scrollbars) when the user resizes
     585        if (qApp->loopLevel())
     586            qApp->sendPostedEvents(0, QEvent::ShowWindowRequest);
     587#endif
     588
     589        HWND hwndC = WinWindowFromID(hwnd, FID_CLIENT);
     590        QETWidget *widget = (QETWidget*)QWidget::find(hwndC);
     591        if (!widget) // don't know this widget
     592            break;
     593
    434594        switch(msg) {
    435595        default:
    436596            break;
    437597        }
    438         if (handled)
    439             return rc;
    440     } while(0);
    441 
    442     return WinDefWindowProc(hwnd, msg, mp1, mp2);
    443 }
    444 
    445 PFNWP QtOldFrameProc = 0;
    446 
    447 MRESULT EXPENTRY QtFrameProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
    448 {
    449     // message handling indicators: if handled is true at the end of message
    450     // processing, no default window proc is called but rc is returned.
    451     bool handled = false;
    452     MRESULT rc = (MRESULT) FALSE;
    453     QETWidget *widget = 0;
    454     HWND hwndC = NULLHANDLE;
    455 
    456     do {
    457         switch(msg) {
    458         default:
    459             break;
    460         }
    461         if (handled)
    462             return rc;
    463598    } while(0);
    464599
     
    499634}
    500635
     636bool qt_try_modal(QWidget *widget, QMSG *qmsg, MRESULT& rc)
     637{
     638    // @todo implement
     639    return false;
     640}
     641
    501642/*****************************************************************************
    502643  Popup widget mechanism
     
    527668 *****************************************************************************/
    528669
     670// State holder for LWIN/RWIN and ALTGr keys
     671// (ALTGr is also necessary since OS/2 doesn't report ALTGr as KC_ALT)
     672static int qt_extraKeyState = 0;
     673
     674static int mouseButtonState()
     675{
     676    int state = 0;
     677
     678    if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
     679        state |= Qt::LeftButton;
     680    if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
     681        state |= Qt::RightButton;
     682    if (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
     683        state |= Qt::MidButton;
     684
     685    return state;
     686}
     687
     688//
     689// Auto-capturing for mouse press and mouse release
     690//
     691
     692static void setAutoCapture(HWND h)
     693{
     694    if (autoCaptureWnd)
     695        releaseAutoCapture();
     696    autoCaptureWnd = h;
     697
     698    if (!mouseButtonState()) {
     699        // all buttons released, we don't actually capture the mouse
     700        // (see QWidget::translateMouseEvent())
     701        autoCaptureReleased = true;
     702    } else {
     703        autoCaptureReleased = false;
     704        WinSetCapture(HWND_DESKTOP, h);
     705    }
     706}
     707
     708static void releaseAutoCapture()
     709{
     710    if (autoCaptureWnd) {
     711        if (!autoCaptureReleased) {
     712            WinSetCapture(HWND_DESKTOP, NULLHANDLE);
     713            autoCaptureReleased = true;
     714        }
     715        autoCaptureWnd = NULLHANDLE;
     716    }
     717}
     718
     719//
     720// Mouse event translation
     721//
     722
     723static ushort mouseTbl[] = {
     724    WM_MOUSEMOVE,           QEvent::MouseMove,                  0,
     725    WM_BUTTON1DOWN,         QEvent::MouseButtonPress,       Qt::LeftButton,
     726    WM_BUTTON1UP,           QEvent::MouseButtonRelease,     Qt::LeftButton,
     727    WM_BUTTON1DBLCLK,   QEvent::MouseButtonDblClick,    Qt::LeftButton,
     728    WM_BUTTON2DOWN,         QEvent::MouseButtonPress,       Qt::RightButton,
     729    WM_BUTTON2UP,           QEvent::MouseButtonRelease,     Qt::RightButton,
     730    WM_BUTTON2DBLCLK,   QEvent::MouseButtonDblClick,    Qt::RightButton,
     731    WM_BUTTON3DOWN,         QEvent::MouseButtonPress,       Qt::MidButton,
     732    WM_BUTTON3UP,           QEvent::MouseButtonRelease,     Qt::MidButton,
     733    WM_BUTTON3DBLCLK,   QEvent::MouseButtonDblClick,    Qt::MidButton,
     734    WM_CONTEXTMENU,     QEvent::ContextMenu,            0,
     735    0,                          0,                                              0
     736};
     737
     738static int translateButtonState(USHORT s, int type, int button)
     739{
     740    Q_UNUSED(button);
     741
     742    int bst = mouseButtonState();
     743
     744    if (type == QEvent::ContextMenu) {
     745        if (WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000)
     746            bst |= Qt::ShiftModifier;
     747        if (WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000)
     748            bst |= Qt::AltModifier;
     749        if (WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)
     750            bst |= Qt::ControlModifier;
     751    } else {
     752        if (s & KC_SHIFT)
     753            bst |= Qt::ShiftModifier;
     754        if ((s & KC_ALT))
     755            bst |= Qt::AltModifier;
     756        if (s & KC_CTRL)
     757            bst |= Qt::ControlModifier;
     758    }
     759    if ((qt_extraKeyState & Qt::AltModifier))
     760        bst |= Qt::AltModifier;
     761    if (qt_extraKeyState & Qt::MetaModifier)
     762        bst |= Qt::MetaModifier;
     763
     764    return bst;
     765}
     766
     767bool QETWidget::translateMouseEvent(const QMSG &qmsg)
     768{
     769#if 0
     770    static const char *msgNames[] = { // 11 items
     771        "WM_MOUSEMOVE",
     772        "WM_BUTTON1DOWN", "WM_BUTTON1UP", "WM_BUTTON1DBLCLK",
     773        "WM_BUTTON2DOWN", "WM_BUTTON2UP", "WM_BUTTON2DBLCLK",
     774        "WM_BUTTON3DOWN", "WM_BUTTON3UP", "WM_BUTTON3DBLCLK",
     775        "WM_???"
     776    };
     777    int msgIdx = qmsg.msg - WM_MOUSEMOVE;
     778    if (msgIdx < 0 || msgIdx > 9)
     779        msgIdx = 10;
     780    qDebug("%s (%04lX): [%08lX/%p:%s] %04hd,%04hd hit=%04hX fl=%04hX",
     781           msgNames[msgIdx], qmsg.msg, qmsg.hwnd, this, widgetName(this),
     782           SHORT1FROMMP(qmsg.mp1), SHORT2FROMMP(qmsg.mp1),
     783           SHORT1FROMMP(qmsg.mp2), SHORT2FROMMP(qmsg.mp2));
     784#endif
     785
     786    if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
     787        Q_ASSERT(internalWinId() != NULLHANDLE);
     788
     789    static QPoint pos;                          // window pos (y flipped)
     790    static POINTL gpos = { -1, -1 };            // global pos (y flipped)
     791    QEvent::Type type;                                      // event parameters
     792    int    button;
     793    int    state;
     794    int    i;
     795
     796    // candidate for the double click event
     797    static HWND dblClickCandidateWin = 0;
     798
     799#if !defined (QT_NO_SESSIONMANAGER)
     800    if (sm_blockUserInput) //block user interaction during session management
     801        return true;
     802#endif
     803
     804    // Compress mouse move events
     805    if (qmsg.msg == WM_MOUSEMOVE) {
     806        QMSG mouseMsg;
     807        mouseMsg.msg = WM_NULL;
     808        while (WinPeekMsg(0, &mouseMsg, qmsg.hwnd, WM_MOUSEMOVE,
     809                          WM_MOUSEMOVE, PM_NOREMOVE)) {
     810                if (mouseMsg.mp2 != qmsg.mp2)
     811                    break; // leave the message in the queue because
     812                           // the key state has changed
     813                // Remove the mouse move message
     814                WinPeekMsg(0, &mouseMsg, qmsg.hwnd, WM_MOUSEMOVE,
     815                           WM_MOUSEMOVE, PM_REMOVE);
     816        }
     817        // Update the passed in QMSG structure with the
     818        // most recent one.
     819        if (mouseMsg.msg != WM_NULL) {
     820            PQMSG pqmsg = (PQMSG)&qmsg;
     821            pqmsg->mp1 = mouseMsg.mp1;
     822            pqmsg->mp2 = mouseMsg.mp2;
     823            pqmsg->time = mouseMsg.time;
     824            pqmsg->ptl.x = (short)SHORT1FROMMP(mouseMsg.mp1);
     825            pqmsg->ptl.y = (short)SHORT2FROMMP(mouseMsg.mp1);
     826            WinMapWindowPoints(pqmsg->hwnd, HWND_DESKTOP, &pqmsg->ptl, 1);
     827            // flip y coordinate
     828            pqmsg->ptl.y = QApplication::desktop()->height() - (pqmsg->ptl.y + 1);
     829        }
     830    }
     831
     832    for (i = 0; mouseTbl[i] && (ULONG)mouseTbl[i] != qmsg.msg; i += 3)
     833        ;
     834    if (!mouseTbl[i])
     835        return true;
     836
     837    type   = (QEvent::Type)mouseTbl[++i];   // event type
     838    button = mouseTbl[++i];                             // which button
     839    state  = translateButtonState(SHORT2FROMMP(qmsg.mp2), type, button); // button state
     840
     841    // It seems, that PM remembers only the WM_BUTTONxDOWN message (instead of
     842    // the WM_BUTTONxDOWN + WM_BUTTONxUP pair) to detect whether the next button
     843    // press should be converted to WM_BUTTONxDBLCLK or not. As a result, the
     844    // window gets WM_BUTTONxDBLCLK even if it didn't receive the preceeding
     845    // WM_BUTTONxUP (this happens if we issue WinSetCapture() on the first
     846    // WM_BUTTONxDOWN), which is obviously wrong and makes problems for QWorkspace
     847    // and QTitleBar system menu handlers that don't expect a double click after
     848    // they opened a popup menu. dblClickCandidateWin is reset to 0 (see a ***
     849    // remmark below) when WinSetCapture is issued that directs messages
     850    // to a window other than one received the first WM_BUTTONxDOWN,
     851    // so we can fix it here.  Note that if there is more than one popup window,
     852    // WinSetCapture is issued only for the first of them, so this code doesn't
     853    // prevent MouseButtonDblClick from being delivered to a popup when another
     854    // popup gets closed on the first WM_BUTTONxDOWN (Qt/Win32 behaves in the
     855    // same way, so it's left for compatibility).
     856    if (type == QEvent::MouseButtonPress) {
     857        dblClickCandidateWin = qmsg.hwnd;
     858    } else if (type == QEvent::MouseButtonDblClick) {
     859        if (dblClickCandidateWin != qmsg.hwnd)
     860            type = QEvent::MouseButtonPress;
     861        dblClickCandidateWin = 0;
     862    }
     863
     864    const QPoint widgetPos = mapFromGlobal(QPoint(qmsg.ptl.x, qmsg.ptl.y));
     865
     866    QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos);
     867    if (alienWidget && alienWidget->internalWinId())
     868        alienWidget = 0;
     869
     870    if (type == QEvent::MouseMove) {
     871        if (!(state & Qt::MouseButtonMask))
     872            qt_button_down = 0;
     873#ifndef QT_NO_CURSOR
     874        QCursor *c = qt_grab_cursor();
     875        if (!c)
     876            c = QApplication::overrideCursor();
     877        if (c) // application cursor defined
     878            WinSetPointer(HWND_DESKTOP, c->handle());
     879        else if (!qt_button_down) {
     880            QWidget *w = alienWidget ? alienWidget : this;
     881            while (!w->isWindow() && !w->isEnabled())
     882                w = w->parentWidget();
     883            WinSetPointer(HWND_DESKTOP, w->cursor().handle());
     884        }
     885#else
     886        // pass the msg to the default proc to let it change the pointer shape
     887        WinDefWindowProc(qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2);
     888#endif
     889
     890        HWND id = effectiveWinId();
     891        QWidget *mouseGrabber = QWidget::mouseGrabber();
     892        QWidget *activePopupWidget = qApp->activePopupWidget();
     893        if (mouseGrabber) {
     894            if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos)))
     895                id = mouseGrabber->effectiveWinId();
     896        } else if (type == QEvent::NonClientAreaMouseMove) {
     897            id = 0;
     898        }
     899
     900        if (curWin != id) { // new current window
     901            // @todo
     902            // add CS_HITTEST to our window classes and handle WM_HITTEST,
     903            // otherwise disabled windows will not get mouse events?
     904            if (id == 0) {
     905                QWidget *leave = qt_last_mouse_receiver;
     906                if (!leave)
     907                    leave = QWidget::find(curWin);
     908                QApplicationPrivate::dispatchEnterLeave(0, leave);
     909                qt_last_mouse_receiver = 0;
     910                curWin = 0;
     911            } else {
     912                QWidget *leave = 0;
     913                if (curWin && qt_last_mouse_receiver)
     914                    leave = qt_last_mouse_receiver;
     915                else
     916                    leave = QWidget::find(curWin);
     917                QWidget *enter = alienWidget ? alienWidget : this;
     918                if (mouseGrabber && activePopupWidget) {
     919                    if (leave != mouseGrabber)
     920                        enter = mouseGrabber;
     921                    else
     922                        enter = activePopupWidget == this ? this : mouseGrabber;
     923                }
     924                QApplicationPrivate::dispatchEnterLeave(enter, leave);
     925                qt_last_mouse_receiver = enter;
     926                curWin = enter ? enter->effectiveWinId() : 0;
     927            }
     928        }
     929
     930        // *** PM posts a dummy WM_MOUSEMOVE message (with the same, uncahnged
     931        // pointer coordinates) after every WinSetCapture that actually changes
     932        // the capture target. I.e., if the argument of WinSetCapture is
     933        // NULLHANDLE, a window under the mouse pointer gets this message,
     934        // otherwise the specified window gets it unless it is already under the
     935        // pointer. We use this info to check whether the window can be a double
     936        // click candidate (see above).
     937        if (qmsg.ptl.x == gpos.x && qmsg.ptl.y == gpos.y) {
     938            if (dblClickCandidateWin != qmsg.hwnd)
     939                dblClickCandidateWin = 0;
     940            return true;
     941        }
     942
     943        gpos = qmsg.ptl;
     944
     945        Q_ASSERT(testAttribute(Qt::WA_WState_Created));
     946
     947        POINTL curPos = gpos;
     948        WinMapWindowPoints(internalWinId(), HWND_DESKTOP, &gpos, 1);
     949
     950        pos.rx() = curPos.x;
     951        pos.ry() = curPos.y;
     952        pos = d_func()->mapFromWS(pos);
     953    } else {
     954        if (type == QEvent::MouseButtonPress && !isActiveWindow())
     955            setActiveWindow();
     956
     957        gpos = qmsg.ptl;
     958        pos = mapFromGlobal(QPoint(gpos.x, gpos.y));
     959
     960        // mouse button pressed
     961        if (!qt_button_down && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)) {
     962            QWidget *tlw = window();
     963            if (QWidget *child = tlw->childAt(mapTo(tlw, pos)))
     964                qt_button_down = child;
     965            else
     966                qt_button_down = this;
     967        }
     968    }
     969
     970    // detect special button states
     971    enum { Other, SinglePressed, AllReleased } btnState = Other;
     972    int bs = state & Qt::MouseButtonMask;
     973    if ((type == QEvent::MouseButtonPress ||
     974         type == QEvent::MouseButtonDblClick) && bs == 0) {
     975        btnState = SinglePressed;
     976    } else if (type == QEvent::MouseButtonRelease && bs == button) {
     977        btnState = AllReleased;
     978    }
     979
     980    bool res = false;
     981
     982    if (qApp->d_func()->inPopupMode()) { // in popup mode
     983        if (!autoCaptureReleased && btnState == AllReleased) {
     984            // in order to give non-Qt windows the opportunity to see mouse
     985            // messages while our popups are active we need to release the
     986            // mouse capture which is absolute in OS/2. we do it directly
     987            // (not through releaseAutoCapture()) in order to keep
     988            // autoCaptureWnd nonzero to keep forwarding mouse move events
     989            // (actually sent to one of Qt widgets) to the active popup.
     990            autoCaptureReleased = true;
     991            WinSetCapture(HWND_DESKTOP, 0);
     992        } else if (autoCaptureReleased && btnState == SinglePressed) {
     993            // set the mouse capture back if a button is pressed.
     994            if ( autoCaptureWnd ) {
     995                autoCaptureReleased = false;
     996                WinSetCapture(HWND_DESKTOP, autoCaptureWnd);
     997            }
     998        }
     999
     1000        replayPopupMouseEvent = false;
     1001        QWidget* activePopupWidget = qApp->activePopupWidget();
     1002        QWidget *target = activePopupWidget;
     1003        const QPoint globalPos(gpos.x, gpos.y);
     1004
     1005        if (target != this) {
     1006            if ((windowType() == Qt::Popup) && rect().contains(pos) && 0)
     1007                target = this;
     1008            else                                // send to last popup
     1009                pos = target->mapFromGlobal(globalPos);
     1010        }
     1011        QWidget *popupChild = target->childAt(pos);
     1012        bool releaseAfter = false;
     1013        switch (type) {
     1014            case QEvent::MouseButtonPress:
     1015            case QEvent::MouseButtonDblClick:
     1016                popupButtonFocus = popupChild;
     1017                break;
     1018            case QEvent::MouseButtonRelease:
     1019                releaseAfter = true;
     1020                break;
     1021            default:
     1022                break;                                // nothing for mouse move
     1023        }
     1024
     1025        if (target->isEnabled()) {
     1026            if (popupButtonFocus) {
     1027                target = popupButtonFocus;
     1028            } else if (popupChild) {
     1029                // forward mouse events to the popup child. mouse move events
     1030                // are only forwarded to popup children that enable mouse tracking.
     1031                if (type != QEvent::MouseMove || popupChild->hasMouseTracking())
     1032                    target = popupChild;
     1033            }
     1034
     1035            pos = target->mapFromGlobal(globalPos);
     1036#ifndef QT_NO_CONTEXTMENU
     1037            if (type == QEvent::ContextMenu) {
     1038                QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, state);
     1039                res = QApplication::sendSpontaneousEvent(target, &e);
     1040                res = res && e.isAccepted();
     1041            }
     1042            else
     1043#endif
     1044            {
     1045                QMouseEvent e(type, pos, globalPos,
     1046                            Qt::MouseButton(button),
     1047                            Qt::MouseButtons(state & Qt::MouseButtonMask),
     1048                            Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
     1049                res = QApplicationPrivate::sendMouseEvent(target, &e, alienWidget, this, &qt_button_down,
     1050                                                          qt_last_mouse_receiver);
     1051                res = res && e.isAccepted();
     1052            }
     1053        } else {
     1054            // close disabled popups when a mouse button is pressed or released
     1055            switch (type) {
     1056            case QEvent::MouseButtonPress:
     1057            case QEvent::MouseButtonDblClick:
     1058            case QEvent::MouseButtonRelease:
     1059                target->close();
     1060                break;
     1061            default:
     1062                break;
     1063            }
     1064        }
     1065
     1066        if (releaseAfter) {
     1067            popupButtonFocus = 0;
     1068            qt_button_down = 0;
     1069        }
     1070
     1071        if (type == QEvent::MouseButtonPress
     1072            && qApp->activePopupWidget() != activePopupWidget
     1073            && replayPopupMouseEvent) {
     1074            // the popup dissappeared. Replay the event
     1075            QWidget* w = QApplication::widgetAt(gpos.x, gpos.y);
     1076            if (w && !QApplicationPrivate::isBlockedByModal(w)) {
     1077                Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
     1078                HWND hwndTarget = w->effectiveWinId();
     1079                if (QWidget::mouseGrabber() == 0)
     1080                    setAutoCapture(hwndTarget);
     1081                if (!w->isActiveWindow())
     1082                    w->activateWindow();
     1083                POINTL pt = gpos;
     1084                WinMapWindowPoints(HWND_DESKTOP, hwndTarget, &pt, 1);
     1085                // flip y coordinate
     1086                pt.y = w->height() - (pt.y + 1);
     1087                WinPostMsg(hwndTarget, qmsg.msg,
     1088                           MPFROM2SHORT(pt.x, pt.y), qmsg.mp2);
     1089            }
     1090        }
     1091    } else { // not popup mode
     1092        if (btnState == SinglePressed && QWidget::mouseGrabber() == 0) {
     1093            Q_ASSERT(testAttribute(Qt::WA_WState_Created));
     1094            setAutoCapture(internalWinId());
     1095        } else if (btnState == AllReleased && QWidget::mouseGrabber() == 0) {
     1096            releaseAutoCapture();
     1097        }
     1098
     1099        const QPoint globalPos(gpos.x,gpos.y);
     1100        QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type,
     1101                                                                 Qt::MouseButtons(bs),
     1102                                                                 qt_button_down, alienWidget);
     1103        if (!widget)
     1104            return false; // don't send event
     1105
     1106#ifndef QT_NO_CONTEXTMENU
     1107        if (type == QEvent::ContextMenu) {
     1108            QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, state);
     1109            res = QApplication::sendSpontaneousEvent(widget, &e);
     1110            res = res && e.isAccepted();
     1111        } else
     1112#endif
     1113        {
     1114            QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button),
     1115                          Qt::MouseButtons(state & Qt::MouseButtonMask),
     1116                          Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask));
     1117
     1118            res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
     1119                                                      qt_last_mouse_receiver);
     1120            res = res && e.isAccepted();
     1121        }
     1122
     1123        if (type != QEvent::MouseMove)
     1124            pos.rx() = pos.ry() = -9999;        // init for move compression
     1125    }
     1126
     1127    return res;
     1128}
     1129
     1130#ifndef QT_NO_WHEELEVENT
     1131bool QETWidget::translateWheelEvent(const QMSG &qmsg)
     1132{
     1133    enum { WHEEL_DELTA = 120 };
     1134
     1135#ifndef QT_NO_SESSIONMANAGER
     1136    if (sm_blockUserInput) // block user interaction during session management
     1137        return true;
     1138#endif
     1139
     1140    // consume duplicate wheel events sent by the AMouse driver to emulate
     1141    // multiline scrolls. we need this since currently Qt (QScrollBar, for
     1142    // instance) maintains the number of lines to scroll per wheel rotation
     1143    // (including the special handling of CTRL and SHIFT modifiers) on its own
     1144    // and doesn't have a setting to tell it to be aware of system settings
     1145    // for the mouse wheel. if we had processed events as they are, we would
     1146    // get a confusing behavior (too many lines scrolled etc.).
     1147    {
     1148        int devh = QApplication::desktop()->height();
     1149        QMSG wheelMsg;
     1150        while (WinPeekMsg(0, &wheelMsg, qmsg.hwnd, qmsg.msg, qmsg.msg, PM_NOREMOVE)) {
     1151            // PM bug: ptl contains SHORT coordinates although fields are LONG
     1152            wheelMsg.ptl.x = (short) wheelMsg.ptl.x;
     1153            wheelMsg.ptl.y = (short) wheelMsg.ptl.y;
     1154            // flip y coordinate
     1155            wheelMsg.ptl.y = devh - (wheelMsg.ptl.y + 1);
     1156            if (wheelMsg.mp1 != qmsg.mp1 ||
     1157                wheelMsg.mp2 != qmsg.mp2 ||
     1158                wheelMsg.ptl.x != qmsg.ptl.x ||
     1159                wheelMsg.ptl.y != qmsg.ptl.y)
     1160                break;
     1161            WinPeekMsg(0, &wheelMsg, qmsg.hwnd, qmsg.msg, qmsg.msg, PM_REMOVE);
     1162        }
     1163    }
     1164
     1165    int delta;
     1166    USHORT cmd = SHORT2FROMMP(qmsg.mp2);
     1167    switch (cmd) {
     1168        case SB_LINEUP:
     1169        case SB_PAGEUP:
     1170            delta = WHEEL_DELTA;
     1171            break;
     1172        case SB_LINEDOWN:
     1173        case SB_PAGEDOWN:
     1174            delta = -WHEEL_DELTA;
     1175            break;
     1176        default:
     1177            return false;
     1178    }
     1179
     1180    int state = 0;
     1181    if (WinGetKeyState(HWND_DESKTOP, VK_SHIFT ) & 0x8000)
     1182        state |= Qt::ShiftModifier;
     1183    if (WinGetKeyState(HWND_DESKTOP, VK_ALT) & 0x8000 ||
     1184        (qt_extraKeyState & Qt::AltModifier))
     1185        state |= Qt::AltModifier;
     1186    if (WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)
     1187        state |= Qt::ControlModifier;
     1188    if (qt_extraKeyState & Qt::MetaModifier)
     1189        state |= Qt::MetaModifier;
     1190
     1191    Qt::Orientation orient;
     1192    // Alt inverts scroll orientation (Qt/Win32 behavior)
     1193    if (state & Qt::AltModifier)
     1194        orient = qmsg.msg == WM_VSCROLL ? Qt::Horizontal : Qt::Vertical;
     1195    else
     1196        orient = qmsg.msg == WM_VSCROLL ? Qt::Vertical : Qt::Horizontal;
     1197
     1198    QPoint globalPos(qmsg.ptl.x, qmsg.ptl.y);
     1199
     1200    // if there is a widget under the mouse and it is not shadowed
     1201    // by modality, we send the event to it first
     1202    MRESULT rc = FALSE;
     1203    QWidget* w = QApplication::widgetAt(globalPos);
     1204    if (!w || !qt_try_modal(w, (QMSG*)&qmsg, rc)) {
     1205        //synaptics touchpad shows its own widget at this position
     1206        //so widgetAt() will fail with that HWND, try child of this widget
     1207        w = this->childAt(this->mapFromGlobal(globalPos));
     1208        if (!w)
     1209            w = this;
     1210    }
     1211
     1212    // send the event to the widget or its ancestors
     1213    {
     1214        QWidget* popup = qApp->activePopupWidget();
     1215        if (popup && w->window() != popup)
     1216            popup->close();
     1217#ifndef QT_NO_WHEELEVENT
     1218        QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta,
     1219                      Qt::MouseButtons(state & Qt::MouseButtonMask),
     1220                      Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient);
     1221
     1222        if (QApplication::sendSpontaneousEvent(w, &e))
     1223#else
     1224        Q_UNUSED(orient);
     1225#endif //QT_NO_WHEELEVENT
     1226            return true;
     1227    }
     1228
     1229    // send the event to the widget that has the focus or its ancestors, if different
     1230    if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
     1231        QWidget* popup = qApp->activePopupWidget();
     1232        if (popup && w->window() != popup)
     1233            popup->close();
     1234#ifndef QT_NO_WHEELEVENT
     1235        QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta,
     1236                      Qt::MouseButtons(state & Qt::MouseButtonMask),
     1237                      Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient);
     1238        if (QApplication::sendSpontaneousEvent(w, &e))
     1239#endif //QT_NO_WHEELEVENT
     1240            return true;
     1241    }
     1242
     1243    return false;
     1244}
     1245#endif
     1246
    5291247QT_END_NAMESPACE
  • TabularUnified trunk/src/gui/kernel/qcursor.h

    r2 r108  
    115115    HCURSOR handle() const;
    116116    QCursor(HCURSOR cursor);
     117#elif defined(Q_WS_PM)
     118    HPOINTER handle() const;
     119    QCursor(HPOINTER handle);
    117120#elif defined(Q_WS_X11)
    118121    Qt::HANDLE handle() const;
  • TabularUnified trunk/src/gui/kernel/qcursor_p.h

    r2 r108  
    9393#if defined (Q_WS_WIN)
    9494    HCURSOR hcurs;
     95#elif defined (Q_WS_PM)
     96    HPOINTER hcurs;
    9597#elif defined (Q_WS_X11)
    9698    XColor fg, bg;
  • TabularUnified trunk/src/gui/kernel/qcursor_pm.cpp

    r95 r108  
    6060
    6161QCursorData::QCursorData(Qt::CursorShape s)
    62   : cshape(s), bm(0), bmm(0), hx(0), hy(0) // @todo, hcurs(0)
     62  : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(NULLHANDLE)
    6363{
    6464    ref = 1;
     
    7979    // @todo implement
    8080    return 0;
     81}
     82
     83HPOINTER QCursor::handle() const
     84{
     85    if (!QCursorData::initialized)
     86        QCursorData::initialize();
     87    if (!d->hcurs)
     88        d->update();
     89    return d->hcurs;
     90}
     91
     92QCursor::QCursor(HPOINTER handle)
     93{
     94    d = new QCursorData(Qt::CustomCursor);
     95    d->hcurs = handle;
    8196}
    8297
  • TabularUnified trunk/src/gui/kernel/qwidget_pm.cpp

    r106 r108  
    857857
    858858    if (flags & Qt::WindowTitleHint) {
    859         title = topLevel ? qAppName().toLocal8Bit() : q->objectName().toLocal8Bit();
     859        QString t = topLevel ? qAppName() : q->objectName();
     860        t = t.left(1).toUpper() + t.mid(1).toLower();
     861        title = t.toLocal8Bit();
    860862    }
    861863
     
    11861188}
    11871189
     1190QCursor *qt_grab_cursor()
     1191{
     1192    return mouseGrbCur;
     1193}
     1194
    11881195void QWidget::grabMouse()
    11891196{
  • TabularUnified trunk/src/gui/kernel/qwindowdefs_pm.h

    r100 r108  
    5959typedef LHANDLE HWND;
    6060typedef LHANDLE HPS;
     61typedef LHANDLE HPOINTER;
    6162typedef struct _QMSG QMSG;
    6263typedef void *MRESULT;
Note: See TracChangeset for help on using the changeset viewer.