From f58e046a611118a6349ee617a98dbb24280ef183 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 27 Jun 2012 16:20:18 +0200 Subject: Add framestrut mouse events. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add infrastructure to QWindowSystemInterface. - Add a setter for enabling framestrut events to QPlatformWindow. - Add Windows implementation, pass keyboard modifiers. QDockWidget relies on it for docking. Task-number: QTBUG-26296 Change-Id: I9d84b356e9a5eb341f57b6f51f34b6b494ff7f87 Reviewed-by: Jørgen Lind --- src/gui/kernel/qguiapplication.cpp | 17 ++++++---- src/gui/kernel/qplatformwindow.h | 3 ++ src/gui/kernel/qplatformwindow_qpa.cpp | 23 ++++++++++++++ src/gui/kernel/qwindowsysteminterface_qpa.cpp | 15 +++++++++ src/gui/kernel/qwindowsysteminterface_qpa.h | 2 ++ src/gui/kernel/qwindowsysteminterface_qpa_p.h | 4 +++ src/plugins/platforms/windows/qwindowscontext.cpp | 5 ++- .../platforms/windows/qwindowsmousehandler.cpp | 37 ++++++++++++++++++---- .../platforms/windows/qwindowsmousehandler.h | 1 + src/plugins/platforms/windows/qwindowswindow.cpp | 9 ++++++ src/plugins/platforms/windows/qwindowswindow.h | 6 +++- src/widgets/kernel/qwidgetwindow_qpa.cpp | 12 +++++++ src/widgets/kernel/qwidgetwindow_qpa_p.h | 1 + src/widgets/widgets/qdockwidget.cpp | 7 ++++ 14 files changed, 128 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index a3d9c1f2ab..a27a8558cd 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1098,6 +1098,7 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) { switch(e->type) { + case QWindowSystemInterfacePrivate::FrameStrutMouse: case QWindowSystemInterfacePrivate::Mouse: QGuiApplicationPrivate::processMouseEvent(static_cast(e)); break; @@ -1179,9 +1180,10 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo QEvent::Type type; // move first Qt::MouseButtons stateChange = e->buttons ^ buttons; + const bool frameStrut = e->type == QWindowSystemInterfacePrivate::FrameStrutMouse; if (e->globalPos != QGuiApplicationPrivate::lastCursorPosition && (stateChange != Qt::NoButton)) { QWindowSystemInterfacePrivate::MouseEvent * newMouseEvent = - new QWindowSystemInterfacePrivate::MouseEvent(e->window.data(), e->timestamp, e->localPos, e->globalPos, e->buttons, e->modifiers); + new QWindowSystemInterfacePrivate::MouseEvent(e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers); QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(newMouseEvent); // just in case the move triggers a new event loop stateChange = Qt::NoButton; } @@ -1204,7 +1206,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo bool doubleClick = false; if (QGuiApplicationPrivate::lastCursorPosition != globalPoint) { - type = QEvent::MouseMove; + type = frameStrut ? QEvent::NonClientAreaMouseMove : QEvent::MouseMove; QGuiApplicationPrivate::lastCursorPosition = globalPoint; if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance|| qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance) @@ -1226,14 +1228,14 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (button & e->buttons) { ulong doubleClickInterval = static_cast(qApp->styleHints()->mouseDoubleClickInterval()); doubleClick = e->timestamp - mousePressTime < doubleClickInterval && button == mousePressButton; - type = QEvent::MouseButtonPress; + type = frameStrut ? QEvent::NonClientAreaMouseButtonPress : QEvent::MouseButtonPress; mousePressTime = e->timestamp; mousePressButton = button; const QPoint point = QGuiApplicationPrivate::lastCursorPosition.toPoint(); mousePressX = point.x(); mousePressY = point.y(); } else { - type = QEvent::MouseButtonRelease; + type = frameStrut ? QEvent::NonClientAreaMouseButtonRelease : QEvent::MouseButtonRelease; } } @@ -1253,7 +1255,9 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo cursor->pointerEvent(ev); #endif QGuiApplication::sendSpontaneousEvent(window, &ev); - if (!e->synthetic && !ev.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) { + if (!e->synthetic && !ev.isAccepted() + && !frameStrut + && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) { if (!m_fakeTouchDevice) { m_fakeTouchDevice = new QTouchDevice; QWindowSystemInterface::registerTouchDevice(m_fakeTouchDevice); @@ -1287,7 +1291,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo } if (doubleClick) { mousePressButton = Qt::NoButton; - QMouseEvent dblClickEvent(QEvent::MouseButtonDblClick, localPoint, localPoint, globalPoint, + const QEvent::Type doubleClickType = frameStrut ? QEvent::NonClientAreaMouseButtonDblClick : QEvent::MouseButtonDblClick; + QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint, button, buttons, e->modifiers); dblClickEvent.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent); diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index cded1fe316..a6a519e6fd 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -122,6 +122,9 @@ public: virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner); + virtual void setFrameStrutEventsEnabled(bool enabled); + virtual bool frameStrutEventsEnabled() const; + protected: QScopedPointer d_ptr; private: diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp index d2ec6833b0..3c2246cf00 100644 --- a/src/gui/kernel/qplatformwindow_qpa.cpp +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -373,6 +373,29 @@ bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) return false; } +/*! + Reimplement this method to set whether frame strut events + should be sent to \a enabled. + + \sa frameStrutEventsEnabled +*/ + +void QPlatformWindow::setFrameStrutEventsEnabled(bool enabled) +{ + if (enabled) + qWarning("This plugin does not support frame strut events."); +} + +/*! + Reimplement this method to return whether + frame strut events are enabled. +*/ + +bool QPlatformWindow::frameStrutEventsEnabled() const +{ + return false; +} + /*! \class QPlatformWindow \since 4.8 diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index c707d4eea2..139df98daf 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -149,6 +149,21 @@ void QWindowSystemInterface::handleMouseEvent(QWindow *w, ulong timestamp, const QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } +void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +{ + const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleFrameStrutMouseEvent(w, time, local, global, b, mods); +} + +void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +{ + QWindowSystemInterfacePrivate::MouseEvent * e = + new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, + QWindowSystemInterfacePrivate::FrameStrutMouse, + local, global, b, mods); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + bool QWindowSystemInterface::tryHandleSynchronousShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h index 34587f67d8..b55f3e3f33 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -68,6 +68,8 @@ class Q_GUI_EXPORT QWindowSystemInterface public: static void handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); static void handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); + static void handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); + static void handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier); static bool tryHandleSynchronousShortcutEvent(QWindow *w, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h index 919a7de39b..8fb0652eb6 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -60,6 +60,7 @@ public: ActivatedWindow, WindowStateChanged, Mouse, + FrameStrutMouse, Wheel, Key, Touch, @@ -156,6 +157,9 @@ public: MouseEvent(QWindow * w, ulong time, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) : InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(b) { } + MouseEvent(QWindow * w, ulong time, EventType t, const QPointF & local, const QPointF & global, + Qt::MouseButtons b, Qt::KeyboardModifiers mods) + : InputEvent(w, time, t, mods), localPos(local), globalPos(global), buttons(b) { } QPointF localPos; QPointF globalPos; Qt::MouseButtons buttons; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 891753215d..ba32369c03 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -817,9 +817,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, #endif case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); + case QtWindows::NonClientMouseEvent: + if (platformWindow->frameStrutEventsEnabled()) + return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); + break; case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: - case QtWindows::NonClientMouseEvent: case QtWindows::LeaveEvent: return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::TouchEvent: diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index eb7d2912bb..e9a2b5c19d 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qwindowsmousehandler.h" +#include "qwindowskeymapper.h" #include "qwindowscontext.h" #include "qwindowswindow.h" #include "qwindowsintegration.h" @@ -130,14 +131,37 @@ QWindowsMouseHandler::QWindowsMouseHandler() : { } +Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons() +{ + Qt::MouseButtons result = 0; + const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON); + if (GetAsyncKeyState(VK_LBUTTON) < 0) + result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton; + if (GetAsyncKeyState(VK_RBUTTON) < 0) + result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton; + if (GetAsyncKeyState(VK_MBUTTON) < 0) + result |= Qt::MidButton; + return result; +} + bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) { - if (et & QtWindows::NonClientEventFlag) - return false; if (et == QtWindows::MouseWheelEvent) return translateMouseWheelEvent(window, hwnd, msg, result); + + const QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); + if (et & QtWindows::NonClientEventFlag) { + const QPoint globalPosition = winEventPosition; + const QPoint clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition); + const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons(); + QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, + globalPosition, buttons, + QWindowsKeyMapper::queryKeyboardModifiers()); + return false; // Allow further event processing (dragging of windows). + } + *result = 0; if (msg.message == WM_MOUSELEAVE) { // When moving out of a child, MouseMove within parent is received first @@ -161,7 +185,6 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, return true; } } - const QPoint client(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); // Enter new window: track to generate leave event. if (m_windowUnderMouse != window) { // The tracking on m_windowUnderMouse might still be active and @@ -186,9 +209,11 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, qWarning("TrackMouseEvent failed."); #endif // !Q_OS_WINCE } - QWindowSystemInterface::handleMouseEvent(window, client, - QWindowsGeometryHint::mapToGlobal(hwnd, client), - keyStateToMouseButtons((int)msg.wParam)); + const QPoint clientPosition = winEventPosition; + QWindowSystemInterface::handleMouseEvent(window, clientPosition, + QWindowsGeometryHint::mapToGlobal(hwnd, clientPosition), + keyStateToMouseButtons((int)msg.wParam), + QWindowsKeyMapper::queryKeyboardModifiers()); return true; } diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index a978840d67..e3d329e872 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -70,6 +70,7 @@ public: static inline Qt::KeyboardModifiers keyStateToModifiers(int); static inline int mouseButtonsToKeyState(Qt::MouseButtons); + static Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderMouse.data(); } private: diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 7fa43e03e6..b553c15864 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1489,6 +1489,15 @@ bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner) return true; } +void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled) +{ + if (enabled) { + setFlag(FrameStrutEventsEnabled); + } else { + clearFlag(FrameStrutEventsEnabled); + } +} + #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const { diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 182bef78e4..475982aba4 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -123,7 +123,8 @@ public: OpenGLDoubleBuffered = 0x20, OpenGlPixelFormatInitialized = 0x40, BlockedByModal = 0x80, - SizeGripOperation = 0x100 + SizeGripOperation = 0x100, + FrameStrutEventsEnabled = 0x200 }; struct WindowData @@ -178,6 +179,9 @@ public: virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner); + void setFrameStrutEventsEnabled(bool enabled); + bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); } + Qt::WindowState windowState_sys() const; Qt::WindowStates windowStates_sys() const; diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp index f8a5178be5..1b076d1801 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa.cpp +++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp @@ -137,6 +137,13 @@ bool QWidgetWindow::event(QEvent *event) handleMouseEvent(static_cast(event)); return true; + case QEvent::NonClientAreaMouseMove: + case QEvent::NonClientAreaMouseButtonPress: + case QEvent::NonClientAreaMouseButtonRelease: + case QEvent::NonClientAreaMouseButtonDblClick: + handleNonClientAreaMouseEvent(static_cast(event)); + return true; + case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: @@ -208,6 +215,11 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) } } +void QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent *e) +{ + QApplication::sendSpontaneousEvent(m_widget, e); +} + void QWidgetWindow::handleMouseEvent(QMouseEvent *event) { if (qApp->d_func()->inPopupMode()) { diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h index 8afa3f33cd..5750a05d40 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa_p.h +++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h @@ -74,6 +74,7 @@ protected: void handleEnterLeaveEvent(QEvent *); void handleKeyEvent(QKeyEvent *); void handleMouseEvent(QMouseEvent *); + void handleNonClientAreaMouseEvent(QMouseEvent *); void handleTouchEvent(QTouchEvent *); void handleMoveEvent(QMoveEvent *); void handleResizeEvent(QResizeEvent *); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index be216ecf9f..551549f97e 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -48,12 +48,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include "qdockwidget_p.h" @@ -1052,6 +1054,11 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect } } + if (unplug && floating && nativeDeco) + if (const QWindow *window = q->windowHandle()) + if (QPlatformWindow *platformWindow = window->handle()) + platformWindow->setFrameStrutEventsEnabled(true); + resizer->setActive(QWidgetResizeHandler::Resize, !unplug && floating && !nativeDeco); } -- cgit v1.2.3