forked from pool/libqt5-qtbase
26d10f1197
Update to 5.6.0 + xcb fixes OBS-URL: https://build.opensuse.org/request/show/391423 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libqt5-qtbase?expand=0&rev=53
555 lines
21 KiB
Diff
555 lines
21 KiB
Diff
From e4c22c34fb105fc9c30be855048692d95b31c760 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= <spaz16@wp.pl>
|
|
Date: Fri, 8 Jan 2016 19:37:52 +0100
|
|
Subject: [PATCH 01/16] xcb: XInput2 fixes, enter/leave event fixes
|
|
|
|
Added enter/leave event handling in XInput2 to avoid problems with
|
|
those events when the mouse is grabbed.
|
|
|
|
This commit amends: 53d289ec4c0f512a3475da4bbf1f940cd6838ace
|
|
This commit amends: ed2e15780385f7cf0a0d3aedc9cb2059d470bd58
|
|
|
|
Task-number: QTBUG-50340
|
|
Change-Id: I7a120b46daa4f8fa4c218346273ae90b6abfa156
|
|
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
|
|
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
|
|
(cherry picked from commit e4fb521b3f3b9e59146b7569b72aee08dbaeb268)
|
|
---
|
|
src/plugins/platforms/xcb/qxcbconnection.cpp | 16 +-
|
|
src/plugins/platforms/xcb/qxcbconnection.h | 12 +-
|
|
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 54 +++++--
|
|
src/plugins/platforms/xcb/qxcbkeyboard.cpp | 8 +-
|
|
src/plugins/platforms/xcb/qxcbkeyboard.h | 2 +
|
|
src/plugins/platforms/xcb/qxcbwindow.cpp | 177 ++++++++++++++---------
|
|
src/plugins/platforms/xcb/qxcbwindow.h | 9 ++
|
|
7 files changed, 183 insertions(+), 95 deletions(-)
|
|
|
|
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
|
index 9cedd296e1e9ad870900a09f2d955e3460484205..aeb730670d62b3ce2239fba48b58ccb4752e912d 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
|
|
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
|
@@ -613,8 +613,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
|
initializeScreens();
|
|
|
|
initializeXRender();
|
|
- m_xi2Enabled = false;
|
|
#if defined(XCB_USE_XINPUT2)
|
|
+ m_xi2Enabled = false;
|
|
initializeXInput2();
|
|
#endif
|
|
initializeXShape();
|
|
@@ -1133,8 +1133,16 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
|
handleClientMessageEvent((xcb_client_message_event_t *)event);
|
|
break;
|
|
case XCB_ENTER_NOTIFY:
|
|
+#ifdef XCB_USE_XINPUT22
|
|
+ if (isAtLeastXI22() && xi2MouseEvents())
|
|
+ break;
|
|
+#endif
|
|
HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
|
|
case XCB_LEAVE_NOTIFY:
|
|
+#ifdef XCB_USE_XINPUT22
|
|
+ if (isAtLeastXI22() && xi2MouseEvents())
|
|
+ break;
|
|
+#endif
|
|
m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state);
|
|
HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
|
|
case XCB_FOCUS_IN:
|
|
@@ -2216,13 +2224,15 @@ void QXcbConnection::initializeXKB()
|
|
#endif
|
|
}
|
|
|
|
+#if defined(XCB_USE_XINPUT22)
|
|
bool QXcbConnection::xi2MouseEvents() const
|
|
{
|
|
static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
|
|
- // Don't use XInput2 when Xinerama extension is enabled,
|
|
- // because it causes problems with multi-monitor setup.
|
|
+ // FIXME: Don't use XInput2 mouse events when Xinerama extension
|
|
+ // is enabled, because it causes problems with multi-monitor setup.
|
|
return mouseViaXI2 && !has_xinerama_extension;
|
|
}
|
|
+#endif
|
|
|
|
#if defined(XCB_USE_XINPUT2)
|
|
static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number)
|
|
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
|
|
index a6a7b9e7ca1898fe2add7a51107bfc9e535d9b44..6c2b8583af24e9abd7a087144fb33504ec36fbf8 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbconnection.h
|
|
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
|
|
@@ -347,8 +347,10 @@ public:
|
|
virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {}
|
|
virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {}
|
|
virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {}
|
|
+#ifdef XCB_USE_XINPUT22
|
|
virtual void handleXIMouseEvent(xcb_ge_event_t *) {}
|
|
-
|
|
+ virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
|
|
+#endif
|
|
virtual QXcbWindow *toWindow() { return 0; }
|
|
};
|
|
|
|
@@ -485,8 +487,8 @@ public:
|
|
static bool xEmbedSystemTrayAvailable();
|
|
static bool xEmbedSystemTrayVisualHasAlphaChannel();
|
|
|
|
-#ifdef XCB_USE_XINPUT2
|
|
- void handleEnterEvent(const xcb_enter_notify_event_t *);
|
|
+#ifdef XCB_USE_XINPUT21
|
|
+ void handleEnterEvent();
|
|
#endif
|
|
|
|
#ifdef XCB_USE_XINPUT22
|
|
@@ -500,7 +502,9 @@ public:
|
|
|
|
QXcbGlIntegration *glIntegration() const { return m_glIntegration; }
|
|
|
|
+#ifdef XCB_USE_XINPUT22
|
|
bool xi2MouseEvents() const;
|
|
+#endif
|
|
|
|
protected:
|
|
bool event(QEvent *e) Q_DECL_OVERRIDE;
|
|
@@ -534,9 +538,9 @@ private:
|
|
void initializeScreens();
|
|
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
|
|
|
|
+#ifdef XCB_USE_XINPUT2
|
|
bool m_xi2Enabled;
|
|
int m_xi2Minor;
|
|
-#ifdef XCB_USE_XINPUT2
|
|
void initializeXInput2();
|
|
void finalizeXInput2();
|
|
void xi2SetupDevices();
|
|
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
|
index e055ad1424f9ec51a5f4e814babd85601c920c90..0c78c0e0d2bc9d05e9f6768ead72cad4a51d03a7 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
|
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
|
|
@@ -293,6 +293,11 @@ void QXcbConnection::xi2Select(xcb_window_t window)
|
|
bitMask |= XI_ButtonPressMask;
|
|
bitMask |= XI_ButtonReleaseMask;
|
|
bitMask |= XI_MotionMask;
|
|
+
|
|
+ // There is a check for enter/leave events in plain xcb enter/leave event handler
|
|
+ bitMask |= XI_EnterMask;
|
|
+ bitMask |= XI_LeaveMask;
|
|
+
|
|
qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion events in addition to touch");
|
|
}
|
|
XIEventMask mask;
|
|
@@ -307,9 +312,12 @@ void QXcbConnection::xi2Select(xcb_window_t window)
|
|
if (result != Success)
|
|
qCDebug(lcQpaXInput, "XInput 2.2: failed to select pointer/touch events, window %x, result %d", window, result);
|
|
}
|
|
-#endif // XCB_USE_XINPUT22
|
|
|
|
const bool pointerSelected = isAtLeastXI22() && xi2MouseEvents();
|
|
+#else
|
|
+ const bool pointerSelected = false;
|
|
+#endif // XCB_USE_XINPUT22
|
|
+
|
|
QSet<int> tabletDevices;
|
|
#ifndef QT_NO_TABLETEVENT
|
|
if (!m_tabletData.isEmpty()) {
|
|
@@ -474,6 +482,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
|
xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
|
|
int sourceDeviceId = xiEvent->deviceid; // may be the master id
|
|
xXIDeviceEvent *xiDeviceEvent = 0;
|
|
+ xXIEnterEvent *xiEnterEvent = 0;
|
|
QXcbWindowEventListener *eventListener = 0;
|
|
|
|
switch (xiEvent->evtype) {
|
|
@@ -488,14 +497,16 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
|
{
|
|
xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
|
|
eventListener = windowEventListenerFromId(xiDeviceEvent->event);
|
|
- if (eventListener) {
|
|
- long result = 0;
|
|
- if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
|
|
- return;
|
|
- }
|
|
sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
|
|
break;
|
|
}
|
|
+ case XI_Enter:
|
|
+ case XI_Leave: {
|
|
+ xiEnterEvent = reinterpret_cast<xXIEnterEvent *>(event);
|
|
+ eventListener = windowEventListenerFromId(xiEnterEvent->event);
|
|
+ sourceDeviceId = xiEnterEvent->sourceid; // use the actual device id instead of the master
|
|
+ break;
|
|
+ }
|
|
case XI_HierarchyChanged:
|
|
xi2HandleHierachyEvent(xiEvent);
|
|
return;
|
|
@@ -506,11 +517,19 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
|
break;
|
|
}
|
|
|
|
+ if (eventListener) {
|
|
+ long result = 0;
|
|
+ if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
|
|
+ return;
|
|
+ }
|
|
+
|
|
#ifndef QT_NO_TABLETEVENT
|
|
- for (int i = 0; i < m_tabletData.count(); ++i) {
|
|
- if (m_tabletData.at(i).deviceId == sourceDeviceId) {
|
|
- if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
|
|
- return;
|
|
+ if (!xiEnterEvent) {
|
|
+ for (int i = 0; i < m_tabletData.count(); ++i) {
|
|
+ if (m_tabletData.at(i).deviceId == sourceDeviceId) {
|
|
+ if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
|
|
+ return;
|
|
+ }
|
|
}
|
|
}
|
|
#endif // QT_NO_TABLETEVENT
|
|
@@ -543,6 +562,13 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
|
|
xi2ProcessTouch(xiDeviceEvent, platformWindow);
|
|
break;
|
|
}
|
|
+ } else if (xiEnterEvent && xi2MouseEvents() && eventListener) {
|
|
+ switch (xiEnterEvent->evtype) {
|
|
+ case XI_Enter:
|
|
+ case XI_Leave:
|
|
+ eventListener->handleXIEnterLeave(event);
|
|
+ break;
|
|
+ }
|
|
}
|
|
#endif // XCB_USE_XINPUT22
|
|
}
|
|
@@ -718,6 +744,8 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
|
|
XISetMask(mask, XI_ButtonPress);
|
|
XISetMask(mask, XI_ButtonRelease);
|
|
XISetMask(mask, XI_Motion);
|
|
+ XISetMask(mask, XI_Enter);
|
|
+ XISetMask(mask, XI_Leave);
|
|
XISetMask(mask, XI_TouchBegin);
|
|
XISetMask(mask, XI_TouchUpdate);
|
|
XISetMask(mask, XI_TouchEnd);
|
|
@@ -827,9 +855,9 @@ void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int
|
|
#endif
|
|
}
|
|
|
|
-void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
|
|
-{
|
|
#ifdef XCB_USE_XINPUT21
|
|
+void QXcbConnection::handleEnterEvent()
|
|
+{
|
|
QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin();
|
|
const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end();
|
|
while (it != end) {
|
|
@@ -845,8 +873,8 @@ void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
|
|
XIFreeDeviceInfo(xiDeviceInfo);
|
|
++it;
|
|
}
|
|
-#endif
|
|
}
|
|
+#endif
|
|
|
|
void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice)
|
|
{
|
|
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
|
|
index 2e088d3ca51dfff7fcf41f476b4f8db7c8f40543..631dd17908f458533f413409773b6c078b743d98 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
|
|
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
|
|
@@ -797,9 +797,9 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
|
|
}
|
|
}
|
|
|
|
+#ifdef XCB_USE_XINPUT22
|
|
void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
|
|
{
|
|
-#ifdef XCB_USE_XINPUT22
|
|
if (m_config && !connection()->hasXKB()) {
|
|
xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
|
|
xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
|
|
@@ -815,12 +815,8 @@ void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
|
|
//qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
|
|
}
|
|
}
|
|
-#else
|
|
- Q_UNUSED(modInfo);
|
|
- Q_UNUSED(groupInfo);
|
|
- Q_ASSERT(false); // this can't be
|
|
-#endif
|
|
}
|
|
+#endif
|
|
|
|
quint32 QXcbKeyboard::xkbModMask(quint16 state)
|
|
{
|
|
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
|
|
index d2e37d624cfe5960bf50d8f18f2a82756824fa4d..457a27affb166e2a3e54c78761361ff3713a4d18 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
|
|
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
|
|
@@ -68,7 +68,9 @@ public:
|
|
void updateXKBMods();
|
|
quint32 xkbModMask(quint16 state);
|
|
void updateXKBStateFromCore(quint16 state);
|
|
+#ifdef XCB_USE_XINPUT22
|
|
void updateXKBStateFromXI(void *modInfo, void *groupInfo);
|
|
+#endif
|
|
#ifndef QT_NO_XKB
|
|
// when XKEYBOARD is present on the X server
|
|
int coreDeviceId() const { return core_device_id; }
|
|
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
|
index f97f570831a099c7d1d87cb12ed3c44baa7237eb..91c5eadf3456e15467ba94dd72a886a365aa6a7d 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
|
|
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
|
@@ -2157,6 +2157,78 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x,
|
|
handleMouseEvent(timestamp, local, global, modifiers);
|
|
}
|
|
|
|
+static bool ignoreLeaveEvent(quint8 mode, quint8 detail)
|
|
+{
|
|
+ return (mode == XCB_NOTIFY_MODE_GRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
|
|
+ || detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
|
+ || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL;
|
|
+}
|
|
+
|
|
+static bool ignoreEnterEvent(quint8 mode, quint8 detail)
|
|
+{
|
|
+ return ((mode == XCB_NOTIFY_MODE_UNGRAB && detail == XCB_NOTIFY_DETAIL_ANCESTOR) // Check for AwesomeWM
|
|
+ || (mode != XCB_NOTIFY_MODE_NORMAL && mode != XCB_NOTIFY_MODE_UNGRAB)
|
|
+ || detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
|
+ || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
|
|
+}
|
|
+
|
|
+class EnterEventChecker
|
|
+{
|
|
+public:
|
|
+ bool checkEvent(xcb_generic_event_t *event)
|
|
+ {
|
|
+ if (!event)
|
|
+ return false;
|
|
+ if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY)
|
|
+ return false;
|
|
+
|
|
+ xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
|
|
+ if (ignoreEnterEvent(enter->mode, enter->detail))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+};
|
|
+
|
|
+void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y,
|
|
+ quint8 mode, quint8 detail, xcb_timestamp_t timestamp)
|
|
+{
|
|
+ connection()->setTime(timestamp);
|
|
+#ifdef XCB_USE_XINPUT21
|
|
+ connection()->handleEnterEvent();
|
|
+#endif
|
|
+
|
|
+ if (ignoreEnterEvent(mode, detail))
|
|
+ return;
|
|
+
|
|
+ const QPoint local(event_x, event_y);
|
|
+ QPoint global = QPoint(root_x, root_y);
|
|
+ QWindowSystemInterface::handleEnterEvent(window(), local, global);
|
|
+}
|
|
+
|
|
+void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
|
|
+ quint8 mode, quint8 detail, xcb_timestamp_t timestamp)
|
|
+{
|
|
+ connection()->setTime(timestamp);
|
|
+
|
|
+ if (ignoreLeaveEvent(mode, detail))
|
|
+ return;
|
|
+
|
|
+ EnterEventChecker checker;
|
|
+ xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker);
|
|
+ QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0;
|
|
+
|
|
+ if (enterWindow) {
|
|
+ QPoint local(enter->event_x, enter->event_y);
|
|
+ QPoint global = QPoint(root_x, root_y);
|
|
+ QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
|
|
+ } else {
|
|
+ QWindowSystemInterface::handleLeaveEvent(window());
|
|
+ }
|
|
+
|
|
+ free(enter);
|
|
+}
|
|
+
|
|
void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
|
|
Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
|
|
{
|
|
@@ -2191,12 +2263,10 @@ static inline int fixed1616ToInt(FP1616 val)
|
|
{
|
|
return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF);
|
|
}
|
|
-#endif
|
|
|
|
// With XI 2.2+ press/release/motion comes here instead of the above handlers.
|
|
void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
|
|
{
|
|
-#ifdef XCB_USE_XINPUT22
|
|
QXcbConnection *conn = connection();
|
|
xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event);
|
|
const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods);
|
|
@@ -2234,12 +2304,41 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
|
|
qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
|
|
break;
|
|
}
|
|
-#else
|
|
- Q_UNUSED(event);
|
|
- Q_ASSERT(false); // this can't be
|
|
-#endif
|
|
}
|
|
|
|
+// With XI 2.2+ enter/leave comes here and are blocked in plain xcb events
|
|
+void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
|
|
+{
|
|
+ xXIEnterEvent *ev = reinterpret_cast<xXIEnterEvent *>(event);
|
|
+
|
|
+ // Compare the window with current mouse grabber to prevent deliver events to any other windows.
|
|
+ // If leave event occurs and the window is under mouse - allow to deliver the leave event.
|
|
+ QXcbWindow *mouseGrabber = connection()->mouseGrabber();
|
|
+ if (mouseGrabber && mouseGrabber != this
|
|
+ && (ev->evtype != XI_Leave || QGuiApplicationPrivate::currentMouseWindow != window())) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ const int root_x = fixed1616ToInt(ev->root_x);
|
|
+ const int root_y = fixed1616ToInt(ev->root_y);
|
|
+
|
|
+ switch (ev->evtype) {
|
|
+ case XI_Enter: {
|
|
+ const int event_x = fixed1616ToInt(ev->event_x);
|
|
+ const int event_y = fixed1616ToInt(ev->event_y);
|
|
+ qCDebug(lcQpaXInput, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d", event_x, event_y, ev->mode, ev->detail, ev->time);
|
|
+ handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, ev->detail, ev->time);
|
|
+ break;
|
|
+ }
|
|
+ case XI_Leave:
|
|
+ qCDebug(lcQpaXInput, "XI2 mouse leave, mode %d, detail %d, time %d", ev->mode, ev->detail, ev->time);
|
|
+ connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
|
|
+ handleLeaveNotifyEvent(root_x, root_y, ev->mode, ev->detail, ev->time);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
QXcbWindow *QXcbWindow::toWindow() { return this; }
|
|
|
|
void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global, Qt::KeyboardModifiers modifiers)
|
|
@@ -2248,74 +2347,14 @@ void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, con
|
|
QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttons(), modifiers);
|
|
}
|
|
|
|
-static bool ignoreLeaveEvent(const xcb_leave_notify_event_t *event)
|
|
-{
|
|
- return event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
|
- || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL
|
|
- || event->mode == XCB_NOTIFY_MODE_GRAB;
|
|
-}
|
|
-
|
|
-static bool ignoreEnterEvent(const xcb_enter_notify_event_t *event)
|
|
-{
|
|
- return (event->mode != XCB_NOTIFY_MODE_NORMAL
|
|
- || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
|
|
- || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
|
|
-}
|
|
-
|
|
-class EnterEventChecker
|
|
-{
|
|
-public:
|
|
- bool checkEvent(xcb_generic_event_t *event)
|
|
- {
|
|
- if (!event)
|
|
- return false;
|
|
- if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY)
|
|
- return false;
|
|
-
|
|
- xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
|
|
- if (ignoreEnterEvent(enter))
|
|
- return false;
|
|
-
|
|
- return true;
|
|
- }
|
|
-};
|
|
-
|
|
void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
|
|
{
|
|
- connection()->setTime(event->time);
|
|
-#ifdef XCB_USE_XINPUT2
|
|
- connection()->handleEnterEvent(event);
|
|
-#endif
|
|
-
|
|
- if (ignoreEnterEvent(event))
|
|
- return;
|
|
-
|
|
- const QPoint local(event->event_x, event->event_y);
|
|
- QPoint global = QPoint(event->root_x, event->root_y);
|
|
- QWindowSystemInterface::handleEnterEvent(window(), local, global);
|
|
+ handleEnterNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->mode, event->detail, event->time);
|
|
}
|
|
|
|
void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
|
|
{
|
|
- connection()->setTime(event->time);
|
|
-
|
|
- if (ignoreLeaveEvent(event))
|
|
- return;
|
|
-
|
|
- EnterEventChecker checker;
|
|
- xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker);
|
|
- QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0;
|
|
-
|
|
- if (enterWindow) {
|
|
- QPoint local(enter->event_x, enter->event_y);
|
|
- QPoint global = QPoint(event->root_x, event->root_y);
|
|
-
|
|
- QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
|
|
- } else {
|
|
- QWindowSystemInterface::handleLeaveEvent(window());
|
|
- }
|
|
-
|
|
- free(enter);
|
|
+ handleLeaveNotifyEvent(event->root_x, event->root_y, event->mode, event->detail, event->time);
|
|
}
|
|
|
|
void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event)
|
|
@@ -2419,7 +2458,7 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
|
|
if (!grab && connection()->mouseGrabber() == this)
|
|
connection()->setMouseGrabber(Q_NULLPTR);
|
|
#ifdef XCB_USE_XINPUT22
|
|
- if (connection()->xi2MouseEvents()) {
|
|
+ if (connection()->isAtLeastXI22() && connection()->xi2MouseEvents()) {
|
|
bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab);
|
|
if (grab && result)
|
|
connection()->setMouseGrabber(this);
|
|
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
|
|
index d2c02fe3df4e0d0667711dfa9bfc10fed30d9554..69790f29ae098bbfcc5aa6edec75e3d0fea8ea75 100644
|
|
--- a/src/plugins/platforms/xcb/qxcbwindow.h
|
|
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
|
|
@@ -132,7 +132,10 @@ public:
|
|
void handleFocusInEvent(const xcb_focus_in_event_t *event) Q_DECL_OVERRIDE;
|
|
void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE;
|
|
void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE;
|
|
+#ifdef XCB_USE_XINPUT22
|
|
void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE;
|
|
+ void handleXIEnterLeave(xcb_ge_event_t *) Q_DECL_OVERRIDE;
|
|
+#endif
|
|
|
|
QXcbWindow *toWindow() Q_DECL_OVERRIDE;
|
|
|
|
@@ -212,6 +215,12 @@ protected:
|
|
void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
|
|
Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
|
|
|
|
+ void handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y,
|
|
+ quint8 mode, quint8 detail, xcb_timestamp_t timestamp);
|
|
+
|
|
+ void handleLeaveNotifyEvent(int root_x, int root_y,
|
|
+ quint8 mode, quint8 detail, xcb_timestamp_t timestamp);
|
|
+
|
|
xcb_window_t m_window;
|
|
|
|
uint m_depth;
|
|
--
|
|
2.6.6
|
|
|