Add framestrut mouse events.
- 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 <jorgen.lind@nokia.com>
This commit is contained in:
parent
2b368469c8
commit
f58e046a61
@ -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<QWindowSystemInterfacePrivate::MouseEvent *>(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<ulong>(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);
|
||||
|
@ -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<QPlatformWindowPrivate> d_ptr;
|
||||
private:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -137,6 +137,13 @@ bool QWidgetWindow::event(QEvent *event)
|
||||
handleMouseEvent(static_cast<QMouseEvent *>(event));
|
||||
return true;
|
||||
|
||||
case QEvent::NonClientAreaMouseMove:
|
||||
case QEvent::NonClientAreaMouseButtonPress:
|
||||
case QEvent::NonClientAreaMouseButtonRelease:
|
||||
case QEvent::NonClientAreaMouseButtonDblClick:
|
||||
handleNonClientAreaMouseEvent(static_cast<QMouseEvent *>(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()) {
|
||||
|
@ -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 *);
|
||||
|
@ -48,12 +48,14 @@
|
||||
#include <qdrawutil.h>
|
||||
#include <qevent.h>
|
||||
#include <qfontmetrics.h>
|
||||
#include <qwindow.h>
|
||||
#include <qmainwindow.h>
|
||||
#include <qrubberband.h>
|
||||
#include <qstylepainter.h>
|
||||
#include <qtoolbutton.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <private/qwidgetresizehandler_p.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user