xcb: Use XCB instead of Xlib for XInput
- Replace xinput2 feature by xcb-xinput, which doesn't depend on xcb-xlib - Remove xi2PrepareXIGenericDeviceEvent() that was used to fix incompatibilty between XCB and libXi structs - Drop XCB_USE_XINPUT21 and XCB_USE_XINPUT22 defines that were needed with libXi Although xcb-xinput was released in version 1.13 of libxcb, it was quite stable in version 1.12, and the parts that we use did not change between versions, so require system xcb-xinput 1.12. [ChangeLog][X11] The xcb plugin was ported to use libxcb-xinput instead of libXi for XInput2 support. The -xinput2 configure option was replaced by -xcb-xinput. Task-number: QTBUG-39624 Change-Id: I37475b09b2bd7057763345c3f33d8c7751a4e831 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
This commit is contained in:
parent
8b16557c35
commit
a692d7cd28
@ -297,7 +297,7 @@ Gui, printing, widget options:
|
||||
-libinput .......... Enable libinput support [auto]
|
||||
-mtdev ............. Enable mtdev support [auto]
|
||||
-tslib ............. Enable tslib support [auto]
|
||||
-xinput2 ........... Enable XInput2 support [auto]
|
||||
-xcb-xinput ........ Enable XInput2 support [auto]
|
||||
-xkbcommon-x11 ..... Select xkbcommon used in combination with xcb
|
||||
[system/qt/no]
|
||||
-xkbcommon-evdev ... Enable X-less xkbcommon in combination with libinput
|
||||
|
@ -44,7 +44,7 @@
|
||||
"xcb": { "type": "enum", "values": [ "no", "yes", "qt", "system" ] },
|
||||
"xcb-native-painting": "boolean",
|
||||
"xcb-xlib": "boolean",
|
||||
"xinput2": "boolean",
|
||||
"xcb-xinput": "boolean",
|
||||
"xkb": "boolean",
|
||||
"xkbcommon": { "type": "enum", "values": [ "no", "qt", "system" ] },
|
||||
"xkbcommon-evdev": "boolean",
|
||||
@ -566,33 +566,22 @@
|
||||
"-lxcb-glx -lxcb"
|
||||
]
|
||||
},
|
||||
"xinput2": {
|
||||
"label": "Xinput2",
|
||||
"xcb_xinput": {
|
||||
"label": "XCB XInput",
|
||||
"test": {
|
||||
"include": [ "X11/Xlib.h", "X11/extensions/XInput2.h", "X11/extensions/Xge.h" ],
|
||||
"tail": [
|
||||
"#ifndef XInput_2_0",
|
||||
"# error Missing XInput_2_0 #define",
|
||||
"#endif"
|
||||
],
|
||||
"include": [ "xcb/xcb.h", "xcb/xinput.h" ],
|
||||
"main": [
|
||||
"// need XGenericEventCookie for XInput2 to work",
|
||||
"Display *dpy = 0;",
|
||||
"XEvent xevent;",
|
||||
"XIEvent *xievent = 0;",
|
||||
"XIDeviceEvent *xideviceevent = 0;",
|
||||
"XIHierarchyEvent *xihierarchyevent = 0;",
|
||||
"int deviceid = 0;",
|
||||
"int len = 0;",
|
||||
"(void) XGetEventData(dpy, &xevent.xcookie);",
|
||||
"XFreeEventData(dpy, &xevent.xcookie);",
|
||||
"(void) XIListProperties(dpy, deviceid, &len);"
|
||||
],
|
||||
"qmake": "CONFIG += x11"
|
||||
"int primaryScreen = 0;",
|
||||
"xcb_connection_t *connection = xcb_connect(\"\", &primaryScreen);",
|
||||
"xcb_generic_error_t *error = 0;",
|
||||
"xcb_input_xi_query_version_cookie_t xinput_query_cookie = xcb_input_xi_query_version(",
|
||||
" connection, XCB_INPUT_MAJOR_VERSION, XCB_INPUT_MINOR_VERSION);",
|
||||
"xcb_input_xi_query_version_reply(connection, xinput_query_cookie, &error);"
|
||||
]
|
||||
},
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "xi" },
|
||||
"-lXi"
|
||||
{ "type": "pkgConfig", "args": "xcb-xinput >= 1.12 xcb" },
|
||||
"-lxcb-xinput -lxcb"
|
||||
]
|
||||
},
|
||||
"xkbcommon": {
|
||||
@ -1352,10 +1341,10 @@
|
||||
"condition": "features.sessionmanager && libs.x11sm",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"xinput2": {
|
||||
"label": "Xinput2",
|
||||
"xcb-xinput": {
|
||||
"label": "XCB XInput",
|
||||
"emitIf": "features.xcb",
|
||||
"condition": "features.xcb-xlib && libs.xinput2",
|
||||
"condition": "!features.system-xcb || libs.xcb_xinput",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"xkbcommon-evdev": {
|
||||
@ -1726,7 +1715,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
|
||||
"section": "X11",
|
||||
"condition": "features.xcb",
|
||||
"entries": [
|
||||
"system-xcb", "egl_x11", "xinput2", "xkb", "xlib", "xcb-render", "xcb-glx", "xcb-xlib", "xkbcommon-system", "xcb-native-painting"
|
||||
"system-xcb", "egl_x11", "xkb", "xlib", "xcb-render", "xcb-glx", "xcb-xinput", "xcb-xlib", "xkbcommon-system", "xcb-native-painting"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -3,7 +3,7 @@ Requires libxcb >= 1.5.
|
||||
PACKAGE DEPENDENCIES
|
||||
|
||||
Required packages:
|
||||
libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev
|
||||
libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev libxcb-xinput0-dev
|
||||
|
||||
On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available:
|
||||
libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev
|
||||
@ -21,12 +21,3 @@ REDUCING RUNTIME DEPENDENCIES
|
||||
The '-qt-xcb' configure option can be used to get rid of most xcb- dependencies. Only libxcb will
|
||||
still be linked dynamically, since it will be most likely be pulled in via other dependencies anyway.
|
||||
This should allow for binaries that are portable across most modern Linux distributions.
|
||||
|
||||
PACKAGE VERSION REQUIREMENTS
|
||||
|
||||
When using touch input via XInput 2.2 or higher, there is a potential issue on systems that ship with
|
||||
a libXi older than 1.7.5. This is because XIAllowTouchEvents can deadlock with libXi 1.7.4 and earlier.
|
||||
When touch events are never received, this is not an issue, so plain mouse/keyboard systems are not affected.
|
||||
Qt versions before 5.8 attempted to recognize this scenario based on the pkg-config package version and skip
|
||||
the call. This has been removed starting from 5.8 since relying on pkg-config package versions is unsafe given
|
||||
that Qt must also support systems with limited or incomplete pkg-config setups.
|
||||
|
@ -76,8 +76,8 @@
|
||||
#include <X11/Xutil.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#include <X11/extensions/XI2proto.h>
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#include <xcb/xinput.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xcb_render)
|
||||
@ -120,7 +120,7 @@ Q_LOGGING_CATEGORY(lcQpaKeyboard, "qt.qpa.xkeyboard")
|
||||
#define XCB_GE_GENERIC 35
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
|
||||
// - "pad0" became "extension"
|
||||
// - "pad1" and "pad" became "pad0"
|
||||
@ -138,7 +138,7 @@ static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
|
||||
qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
|
||||
return e->extension == opCode;
|
||||
}
|
||||
#endif // QT_CONFIG(xinput2)
|
||||
#endif // QT_CONFIG(xcb_xinput)
|
||||
|
||||
#if QT_CONFIG(xcb_xlib)
|
||||
static const char * const xcbConnectionErrors[] = {
|
||||
@ -572,6 +572,9 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_render)
|
||||
&xcb_render_id,
|
||||
#endif
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
&xcb_input_id,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
@ -592,7 +595,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
|
||||
initializeScreens();
|
||||
|
||||
initializeXRender();
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (!qEnvironmentVariableIsSet("QT_XCB_NO_XI2"))
|
||||
initializeXInput2();
|
||||
#endif
|
||||
@ -1105,13 +1108,13 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
||||
handleClientMessageEvent((xcb_client_message_event_t *)event);
|
||||
break;
|
||||
case XCB_ENTER_NOTIFY:
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (hasXInput2() && !xi2MouseEventsDisabled())
|
||||
break;
|
||||
#endif
|
||||
HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
|
||||
case XCB_LEAVE_NOTIFY:
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (hasXInput2() && !xi2MouseEventsDisabled())
|
||||
break;
|
||||
#endif
|
||||
@ -1174,7 +1177,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
case XCB_GE_GENERIC:
|
||||
// Here the windowEventListener is invoked from xi2HandleEvent()
|
||||
if (hasXInput2() && isXIEvent(event, m_xiOpCode))
|
||||
@ -1630,16 +1633,14 @@ void *QXcbConnection::createVisualInfoForDefaultVisualId() const
|
||||
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
// it is safe to cast XI_* events here as long as we are only touching the first 32 bytes,
|
||||
// after that position event needs memmove, see xi2PrepareXIGenericDeviceEvent
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
static inline bool isXIType(xcb_generic_event_t *event, int opCode, uint16_t type)
|
||||
{
|
||||
if (!isXIEvent(event, opCode))
|
||||
return false;
|
||||
|
||||
xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
|
||||
return xiEvent->evtype == type;
|
||||
auto *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
|
||||
return e->event_type == type;
|
||||
}
|
||||
#endif
|
||||
static inline bool isValid(xcb_generic_event_t *event)
|
||||
@ -1675,16 +1676,16 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
// compress XI_* events
|
||||
if (responseType == XCB_GE_GENERIC) {
|
||||
if (!hasXInput2())
|
||||
return false;
|
||||
|
||||
// compress XI_Motion, but not from tablet devices
|
||||
if (isXIType(event, m_xiOpCode, XI_Motion)) {
|
||||
if (isXIType(event, m_xiOpCode, XCB_INPUT_MOTION)) {
|
||||
#if QT_CONFIG(tabletevent)
|
||||
xXIDeviceEvent *xdev = reinterpret_cast<xXIDeviceEvent *>(event);
|
||||
auto *xdev = reinterpret_cast<xcb_input_motion_event_t *>(event);
|
||||
if (!QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents) &&
|
||||
const_cast<QXcbConnection *>(this)->tabletDataForDevice(xdev->sourceid))
|
||||
return false;
|
||||
@ -1693,29 +1694,27 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
|
||||
xcb_generic_event_t *next = eventqueue->at(j);
|
||||
if (!isValid(next))
|
||||
continue;
|
||||
if (isXIType(next, m_xiOpCode, XI_Motion))
|
||||
if (isXIType(next, m_xiOpCode, XCB_INPUT_MOTION))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
// compress XI_TouchUpdate for the same touch point id
|
||||
if (isXIType(event, m_xiOpCode, XI_TouchUpdate)) {
|
||||
xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
|
||||
uint32_t id = xiDeviceEvent->detail % INT_MAX;
|
||||
if (isXIType(event, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE)) {
|
||||
auto *touchUpdateEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(event);
|
||||
uint32_t id = touchUpdateEvent->detail % INT_MAX;
|
||||
for (int j = nextIndex; j < eventqueue->size(); ++j) {
|
||||
xcb_generic_event_t *next = eventqueue->at(j);
|
||||
if (!isValid(next))
|
||||
continue;
|
||||
if (isXIType(next, m_xiOpCode, XI_TouchUpdate)) {
|
||||
xXIDeviceEvent *xiDeviceNextEvent = reinterpret_cast<xXIDeviceEvent *>(next);
|
||||
if (id == xiDeviceNextEvent->detail % INT_MAX)
|
||||
if (isXIType(next, m_xiOpCode, XCB_INPUT_TOUCH_UPDATE)) {
|
||||
auto *touchUpdateNextEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(next);
|
||||
if (id == touchUpdateNextEvent->detail % INT_MAX)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -71,16 +71,6 @@
|
||||
#include <QTabletEvent>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#include <X11/extensions/XI2.h>
|
||||
#ifdef XIScrollClass
|
||||
#define XCB_USE_XINPUT21 // XI 2.1 adds smooth scrolling support
|
||||
#ifdef XI_TouchBeginMask
|
||||
#define XCB_USE_XINPUT22 // XI 2.2 adds multi-point touch support
|
||||
#endif
|
||||
#endif
|
||||
#endif // QT_CONFIG(xinput2)
|
||||
|
||||
struct xcb_randr_get_output_info_reply_t;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -359,7 +349,7 @@ 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 *) {}
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource = Qt::MouseEventNotSynthesized) {}
|
||||
virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
|
||||
#endif
|
||||
@ -511,7 +501,7 @@ public:
|
||||
static bool xEmbedSystemTrayAvailable();
|
||||
static bool xEmbedSystemTrayVisualHasAlphaChannel();
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
void xi2SelectStateEvents();
|
||||
void xi2SelectDeviceEvents(xcb_window_t window);
|
||||
void xi2SelectDeviceEventsCompatibility(xcb_window_t window);
|
||||
@ -520,13 +510,9 @@ public:
|
||||
bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
|
||||
bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
|
||||
Qt::MouseButton xiToQtMouseButton(uint32_t b);
|
||||
#ifdef XCB_USE_XINPUT21
|
||||
void xi2UpdateScrollingDevices();
|
||||
#endif
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
|
||||
bool isTouchScreen(int id);
|
||||
#endif
|
||||
#endif
|
||||
QXcbEventReader *eventReader() const { return m_reader; }
|
||||
|
||||
@ -568,7 +554,7 @@ private:
|
||||
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
|
||||
|
||||
bool m_xi2Enabled = false;
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
int m_xi2Minor = -1;
|
||||
void initializeXInput2();
|
||||
void xi2SetupDevice(void *info, bool removeExisting = true);
|
||||
@ -596,10 +582,8 @@ private:
|
||||
void xi2HandleEvent(xcb_ge_event_t *event);
|
||||
void xi2HandleHierarchyEvent(void *event);
|
||||
void xi2HandleDeviceChangedEvent(void *event);
|
||||
int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
int m_xiOpCode;
|
||||
void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
|
||||
#endif // XCB_USE_XINPUT22
|
||||
#if QT_CONFIG(tabletevent)
|
||||
struct TabletData {
|
||||
int deviceId = 0;
|
||||
@ -634,14 +618,11 @@ private:
|
||||
QPointF lastScrollPosition;
|
||||
};
|
||||
QHash<int, ScrollingDevice> m_scrollingDevices;
|
||||
#ifdef XCB_USE_XINPUT21
|
||||
void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
|
||||
void xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice);
|
||||
ScrollingDevice *scrollingDeviceForId(int id);
|
||||
#endif
|
||||
|
||||
static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
|
||||
static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event);
|
||||
#endif
|
||||
|
||||
xcb_connection_t *m_connection = nullptr;
|
||||
@ -675,16 +656,14 @@ private:
|
||||
#endif
|
||||
QXcbEventReader *m_reader = nullptr;
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
QHash<int, TouchDeviceData> m_touchDevices;
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
struct StartSystemMoveResizeInfo {
|
||||
xcb_window_t window = XCB_NONE;
|
||||
uint16_t deviceid;
|
||||
uint32_t pointid;
|
||||
int corner;
|
||||
} m_startSystemMoveResizeInfo;
|
||||
#endif
|
||||
#endif
|
||||
WindowMapper m_mapper;
|
||||
|
||||
@ -693,6 +672,9 @@ private:
|
||||
uint32_t xfixes_first_event = 0;
|
||||
uint32_t xrandr_first_event = 0;
|
||||
uint32_t xkb_first_event = 0;
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
uint32_t xinput_first_event = 0;
|
||||
#endif
|
||||
|
||||
bool has_xfixes = false;
|
||||
bool has_xinerama_extension = false;
|
||||
@ -726,7 +708,7 @@ private:
|
||||
QHash<qint32, qint32> m_peekerToCachedIndex;
|
||||
friend class QXcbEventReader;
|
||||
};
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#if QT_CONFIG(tabletevent)
|
||||
Q_DECLARE_TYPEINFO(QXcbConnection::TabletData::ValuatorClassInfo, Q_PRIMITIVE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -52,10 +52,8 @@
|
||||
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#include <X11/extensions/XI2proto.h>
|
||||
#undef KeyPress
|
||||
#undef KeyRelease
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#include <xcb/xinput.h>
|
||||
#endif
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -824,20 +822,20 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
|
||||
{
|
||||
if (m_config && !connection()->hasXKB()) {
|
||||
xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
|
||||
xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
|
||||
auto *mods = static_cast<xcb_input_modifier_info_t *>(modInfo);
|
||||
auto *group = static_cast<xcb_input_group_info_t *>(groupInfo);
|
||||
const xkb_state_component changedComponents
|
||||
= xkb_state_update_mask(m_xkbState.get(),
|
||||
mods->base_mods,
|
||||
mods->latched_mods,
|
||||
mods->locked_mods,
|
||||
group->base_group,
|
||||
group->latched_group,
|
||||
group->locked_group);
|
||||
mods->base,
|
||||
mods->latched,
|
||||
mods->locked,
|
||||
group->base,
|
||||
group->latched,
|
||||
group->locked);
|
||||
|
||||
handleStateChanges(changedComponents);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
void updateXKBMods();
|
||||
xkb_mod_mask_t xkbModMask(quint16 state);
|
||||
void updateXKBStateFromCore(quint16 state);
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
void updateXKBStateFromXI(void *modInfo, void *groupInfo);
|
||||
#endif
|
||||
#if QT_CONFIG(xkb)
|
||||
|
@ -68,6 +68,9 @@
|
||||
#undef class
|
||||
#include <xcb/xfixes.h>
|
||||
#include <xcb/shape.h>
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
#include <xcb/xinput.h>
|
||||
#endif
|
||||
|
||||
// xcb-icccm 3.8 support
|
||||
#ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
|
||||
@ -105,11 +108,6 @@
|
||||
#include <X11/Xutil.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/extensions/XI2proto.h>
|
||||
#endif
|
||||
|
||||
#define XCOORD_MAX 16383
|
||||
enum {
|
||||
defaultWindowWidth = 160,
|
||||
@ -520,7 +518,7 @@ void QXcbWindow::create()
|
||||
atom(QXcbAtom::_XEMBED_INFO),
|
||||
32, 2, (void *)data);
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (connection()->hasXInput2()) {
|
||||
if (connection()->xi2MouseEventsDisabled())
|
||||
connection()->xi2SelectDeviceEventsCompatibility(m_window);
|
||||
@ -2149,7 +2147,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
|
||||
QPoint global(root_x, root_y);
|
||||
|
||||
if (isWheel) {
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (!connection()->isAtLeastXI21()) {
|
||||
#endif
|
||||
QPoint angleDelta;
|
||||
@ -2164,7 +2162,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
|
||||
if (modifiers & Qt::AltModifier)
|
||||
std::swap(angleDelta.rx(), angleDelta.ry());
|
||||
QWindowSystemInterface::handleWheelEvent(window(), timestamp, local, global, QPoint(), angleDelta, modifiers);
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
@ -2204,7 +2202,7 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
|
||||
if (conn) {
|
||||
|
||||
const bool mouseButtonsPressed = (conn->buttonState() != Qt::NoButton);
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
return mouseButtonsPressed || (conn->hasXInput2() && !conn->xi2MouseEventsDisabled());
|
||||
#else
|
||||
return mouseButtonsPressed;
|
||||
@ -2253,7 +2251,7 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in
|
||||
quint8 mode, quint8 detail, xcb_timestamp_t timestamp)
|
||||
{
|
||||
connection()->setTime(timestamp);
|
||||
#ifdef XCB_USE_XINPUT21
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
// Updates scroll valuators, as user might have done some scrolling outside our X client.
|
||||
connection()->xi2UpdateScrollingDevices();
|
||||
#endif
|
||||
@ -2330,16 +2328,18 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
|
||||
event->time, QEvent::MouseMove);
|
||||
}
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
static inline int fixed1616ToInt(FP1616 val)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
static inline int fixed1616ToInt(xcb_input_fp1616_t val)
|
||||
{
|
||||
return int(qreal(val) / 0x10000);
|
||||
}
|
||||
|
||||
#define qt_xcb_mask_is_set(ptr, event) (((unsigned char*)(ptr))[(event)>>3] & (1 << ((event) & 7)))
|
||||
|
||||
void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource source)
|
||||
{
|
||||
QXcbConnection *conn = connection();
|
||||
xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event);
|
||||
auto *ev = reinterpret_cast<xcb_input_button_press_event_t *>(event);
|
||||
|
||||
if (ev->buttons_len > 0) {
|
||||
unsigned char *buttonMask = (unsigned char *) &ev[1];
|
||||
@ -2347,16 +2347,16 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
|
||||
// XIPointerEmulated being set: https://bugs.freedesktop.org/show_bug.cgi?id=98188
|
||||
// Filter them out by other attributes: when their source device is a touch screen
|
||||
// and the LMB is pressed.
|
||||
if (XIMaskIsSet(buttonMask, 1) && conn->isTouchScreen(ev->sourceid)) {
|
||||
if (qt_xcb_mask_is_set(buttonMask, 1) && conn->isTouchScreen(ev->sourceid)) {
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInput, "XI2 mouse event from touch device %d was ignored", ev->sourceid);
|
||||
return;
|
||||
}
|
||||
for (int i = 1; i <= 15; ++i)
|
||||
conn->setButtonState(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
|
||||
conn->setButtonState(conn->translateMouseButton(i), qt_xcb_mask_is_set(buttonMask, i));
|
||||
}
|
||||
|
||||
const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods);
|
||||
const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective);
|
||||
const int event_x = fixed1616ToInt(ev->event_x);
|
||||
const int event_y = fixed1616ToInt(ev->event_y);
|
||||
const int root_x = fixed1616ToInt(ev->root_x);
|
||||
@ -2373,47 +2373,47 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
|
||||
sourceName = me.valueToKey(source);
|
||||
}
|
||||
|
||||
switch (ev->evtype) {
|
||||
case XI_ButtonPress:
|
||||
switch (ev->event_type) {
|
||||
case XCB_INPUT_BUTTON_PRESS:
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName);
|
||||
conn->setButtonState(button, true);
|
||||
handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonPress, source);
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
case XCB_INPUT_BUTTON_RELEASE:
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName);
|
||||
conn->setButtonState(button, false);
|
||||
handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonRelease, source);
|
||||
break;
|
||||
case XI_Motion:
|
||||
case XCB_INPUT_MOTION:
|
||||
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName);
|
||||
handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, QEvent::MouseMove, source);
|
||||
break;
|
||||
default:
|
||||
qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
|
||||
qWarning() << "Unrecognized XI2 mouse event" << ev->event_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
|
||||
{
|
||||
xXIEnterEvent *ev = reinterpret_cast<xXIEnterEvent *>(event);
|
||||
auto *ev = reinterpret_cast<xcb_input_enter_event_t *>(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())) {
|
||||
&& (ev->event_type != XCB_INPUT_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: {
|
||||
switch (ev->event_type) {
|
||||
case XCB_INPUT_ENTER: {
|
||||
const int event_x = fixed1616ToInt(ev->event_x);
|
||||
const int event_y = fixed1616ToInt(ev->event_y);
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d",
|
||||
@ -2421,7 +2421,7 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
|
||||
handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, ev->detail, ev->time);
|
||||
break;
|
||||
}
|
||||
case XI_Leave:
|
||||
case XCB_INPUT_LEAVE:
|
||||
qCDebug(lcQpaXInputEvents, "XI2 mouse leave, mode %d, detail %d, time %d",
|
||||
ev->mode, ev->detail, ev->time);
|
||||
connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
|
||||
@ -2563,7 +2563,7 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
|
||||
if (grab && !connection()->canGrab())
|
||||
return false;
|
||||
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (connection()->hasXInput2() && !connection()->xi2MouseEventsDisabled()) {
|
||||
bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab);
|
||||
if (grab && result)
|
||||
@ -2654,7 +2654,7 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
|
||||
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
|
||||
return false;
|
||||
const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
|
||||
#ifdef XCB_USE_XINPUT22
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
if (connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner))
|
||||
return true;
|
||||
#endif
|
||||
|
@ -139,7 +139,7 @@ public:
|
||||
void handleFocusInEvent(const xcb_focus_in_event_t *event) override;
|
||||
void handleFocusOutEvent(const xcb_focus_out_event_t *event) override;
|
||||
void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) override;
|
||||
#if QT_CONFIG(xinput2)
|
||||
#if QT_CONFIG(xcb_xinput)
|
||||
void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized) override;
|
||||
void handleXIEnterLeave(xcb_ge_event_t *) override;
|
||||
#endif
|
||||
|
@ -55,11 +55,10 @@ DEFINES += QT_BUILD_XCB_PLUGIN
|
||||
|
||||
qtConfig(xcb-xlib) {
|
||||
QMAKE_USE += xcb_xlib
|
||||
}
|
||||
|
||||
qtConfig(xinput2) {
|
||||
SOURCES += qxcbconnection_xi2.cpp
|
||||
QMAKE_USE += xinput2
|
||||
}
|
||||
qtConfig(xcb-xinput) {
|
||||
SOURCES += qxcbconnection_xi2.cpp
|
||||
}
|
||||
|
||||
qtConfig(xcb-sm) {
|
||||
@ -86,6 +85,7 @@ qtConfig(vulkan) {
|
||||
} else {
|
||||
qtConfig(xkb): QMAKE_USE += xcb_xkb
|
||||
qtConfig(xcb-render): QMAKE_USE += xcb_render
|
||||
qtConfig(xcb-xinput): QMAKE_USE += xcb_xinput
|
||||
QMAKE_USE += xcb_syslibs
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user