Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qxcbconnection.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#pragma once
6
7#include <xcb/xcb.h>
8#include <xcb/randr.h>
9
10#include <QtCore/QTimer>
11#include <QtGui/qpointingdevice.h>
12#include <QtGui/private/qtguiglobal_p.h>
13#include "qxcbexport.h"
14#include <QHash>
15#include <QList>
16#include <qpa/qwindowsysteminterface.h>
17#include <QtCore/QLoggingCategory>
18#include <QtCore/private/qglobal_p.h>
19
20#include "qxcbeventqueue.h"
22
23#if QT_CONFIG(tabletevent)
24#include <QTabletEvent>
25#endif
26
28
29Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput)
30Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputEvents)
31Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
32Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
33Q_DECLARE_LOGGING_CATEGORY(lcQpaPeeker)
34Q_DECLARE_LOGGING_CATEGORY(lcQpaKeyboard)
35Q_DECLARE_LOGGING_CATEGORY(lcQpaClipboard)
36Q_DECLARE_LOGGING_CATEGORY(lcQpaXDnd)
37Q_DECLARE_LOGGING_CATEGORY(lcQpaEventReader)
38
39class QXcbVirtualDesktop;
40class QXcbScreen;
41class QXcbWindow;
42class QXcbDrag;
43class QXcbKeyboard;
46class QXcbClipboard;
47class QXcbWMSupport;
48class QXcbNativeInterface;
50class QXcbGlIntegration;
51
53{
54public:
56 virtual bool handleNativeEvent(xcb_generic_event_t *) { return false; }
57
58 virtual void handleExposeEvent(const xcb_expose_event_t *) {}
59 virtual void handleClientMessageEvent(const xcb_client_message_event_t *) {}
60 virtual void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *) {}
61 virtual void handleMapNotifyEvent(const xcb_map_notify_event_t *) {}
62 virtual void handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *) {}
63 virtual void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *) {}
64 virtual void handleButtonPressEvent(const xcb_button_press_event_t *) {}
65 virtual void handleButtonReleaseEvent(const xcb_button_release_event_t *) {}
66 virtual void handleMotionNotifyEvent(const xcb_motion_notify_event_t *) {}
67 virtual void handleEnterNotifyEvent(const xcb_enter_notify_event_t *) {}
68 virtual void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *) {}
69 virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {}
70 virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {}
71 virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {}
72 virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource = Qt::MouseEventNotSynthesized) {}
73 virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
74 virtual QXcbWindow *toWindow() { return nullptr; }
75};
76
78
80{
81public:
82 QXcbSyncWindowRequest(QXcbWindow *w) : QEvent(QEvent::Type(QEvent::User + 1)), m_window(w) { }
83
84 QXcbWindow *window() const { return m_window; }
85 void invalidate();
86
87private:
88 QXcbWindow *m_window;
89};
90
91class Q_XCB_EXPORT QXcbConnection : public QXcbBasicConnection
92{
93 Q_OBJECT
94public:
95 QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName = nullptr);
96 ~QXcbConnection();
97
98 QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
99 QXcbEventQueue *eventQueue() const { return m_eventQueue; }
100
101 const QList<QXcbVirtualDesktop *> &virtualDesktops() const { return m_virtualDesktops; }
102 const QList<QXcbScreen *> &screens() const { return m_screens; }
103 QXcbVirtualDesktop *primaryVirtualDesktop() const {
104 return m_virtualDesktops.value(primaryScreenNumber());
105 }
106 QXcbScreen *primaryScreen() const;
107
108 const xcb_format_t *formatForDepth(uint8_t depth) const;
109
110 bool imageNeedsEndianSwap() const
111 {
112 if (!hasShm())
113 return false; // The non-Shm path does its own swapping
114#if Q_BYTE_ORDER == Q_BIG_ENDIAN
115 return setup()->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST;
116#else
117 return setup()->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST;
118#endif
119 }
120
121 QXcbKeyboard *keyboard() const { return m_keyboard; }
122
123#ifndef QT_NO_CLIPBOARD
124 QXcbClipboard *clipboard() const { return m_clipboard; }
125#endif
126#if QT_CONFIG(draganddrop)
127 QXcbDrag *drag() const { return m_drag; }
128#endif
129
130 QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); }
131 xcb_window_t rootWindow();
132 xcb_window_t clientLeader();
133
134 bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; }
135 xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; }
136
137 void sync();
138
139 void handleXcbError(xcb_generic_error_t *error);
140 void printXcbError(const char *message, xcb_generic_error_t *error);
141 void handleXcbEvent(xcb_generic_event_t *event);
142 void printXcbEvent(const QLoggingCategory &log, const char *message,
143 xcb_generic_event_t *event) const;
144
145 void addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener);
146 void removeWindowEventListener(xcb_window_t id);
147 QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id);
148 QXcbWindow *platformWindowFromId(xcb_window_t id);
149
150 inline xcb_timestamp_t time() const { return m_time; }
151 inline void setTime(xcb_timestamp_t t) { if (timeGreaterThan(t, m_time)) m_time = t; }
152
153 inline xcb_timestamp_t netWmUserTime() const { return m_netWmUserTime; }
154 inline void setNetWmUserTime(xcb_timestamp_t t) { if (timeGreaterThan(t, m_netWmUserTime)) m_netWmUserTime = t; }
155
156 xcb_timestamp_t getTimestamp();
157 xcb_window_t selectionOwner(xcb_atom_t atom) const;
158 xcb_window_t qtSelectionOwner();
159
160 void setButtonState(Qt::MouseButton button, bool down);
161 Qt::MouseButtons buttonState() const { return m_buttonState; }
162 Qt::MouseButton button() const { return m_button; }
163 Qt::MouseButton translateMouseButton(xcb_button_t s);
164
165 QXcbWindow *focusWindow() const { return m_focusWindow; }
166 void setFocusWindow(QWindow *);
167 QXcbWindow *mouseGrabber() const { return m_mouseGrabber; }
168 void setMouseGrabber(QXcbWindow *);
169 QXcbWindow *mousePressWindow() const { return m_mousePressWindow; }
170 void setMousePressWindow(QXcbWindow *);
171
172 QByteArray startupId() const;
173 void setStartupId(const QByteArray &nextId);
174
175 void grabServer();
176 void ungrabServer();
177
178 QString windowManagerName() const;
179
180 QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; }
181
182 QXcbSystemTrayTracker *systemTrayTracker() const;
183
184 Qt::MouseButtons queryMouseButtons() const;
185
186 bool isUserInputEvent(xcb_generic_event_t *event) const;
187
188 void xi2SelectStateEvents();
189 void xi2SelectDeviceEvents(xcb_window_t window);
190 bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab);
191
192 Qt::MouseButton xiToQtMouseButton(uint32_t b);
193 void xi2UpdateScrollingDevices();
194 bool isTouchScreen(int id);
195
196 bool startSystemMoveResizeForTouch(xcb_window_t window, int edges);
197 void abortSystemMoveResize(xcb_window_t window);
198 bool isDuringSystemMoveResize() const;
199 void setDuringSystemMoveResize(bool during);
200
201 bool canGrab() const { return m_canGrabServer; }
202
203 QXcbGlIntegration *glIntegration() const;
204
205 void flush() { xcb_flush(xcb_connection()); }
206 void processXcbEvents(QEventLoop::ProcessEventsFlags flags);
207
208 QTimer &focusInTimer() { return m_focusInTimer; }
209
210protected:
211 bool event(QEvent *e) override;
212
213private:
214 void xrandrSelectEvents();
215 QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const;
216 QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const;
217 QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow) const;
218 void updateScreens(const xcb_randr_notify_event_t *event);
219 bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
220 void updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange);
221 QXcbScreen *createScreen(QXcbVirtualDesktop *virtualDesktop,
222 const xcb_randr_output_change_t &outputChange,
223 xcb_randr_get_output_info_reply_t *outputInfo);
224 void destroyScreen(QXcbScreen *screen);
225 void initializeScreens(bool initialized);
226 void initializeScreensWithoutXRandR(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen);
227 void initializeScreensFromOutput(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen);
228
229 QXcbVirtualDesktop* virtualDesktopForNumber(int n) const;
230 QXcbScreen* findScreenForMonitorInfo(const QList<QPlatformScreen *> &screens, xcb_randr_monitor_info_t *monitorInfo);
231 void initializeScreensFromMonitor(xcb_screen_iterator_t *it, int screenNumber, QXcbScreen **primaryScreen, bool initialized);
232
233 bool compressEvent(xcb_generic_event_t *event) const;
234 inline bool timeGreaterThan(xcb_timestamp_t a, xcb_timestamp_t b) const
235 { return static_cast<int32_t>(a - b) > 0 || b == XCB_CURRENT_TIME; }
236
237 void xi2SetupSlavePointerDevice(void *info, bool removeExisting = true, QPointingDevice *master = nullptr);
238 void xi2SetupDevices();
239 // TODO get rid of this: store minimal necessary info in a subclass of QPointingDevicePrivate
240 struct TouchDeviceData {
241 QPointingDevice *qtTouchDevice = nullptr;
242 QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
243 QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed
244 struct ValuatorClassInfo {
245 double min = 0;
246 double max = 0;
247 int number = -1;
248 QXcbAtom::Atom label;
249 };
250 QList<ValuatorClassInfo> valuatorInfo;
251
252 // Stuff that is relevant only for touchpads
253 QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
254 QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
255 QSizeF size; // device size in mm
256 bool providesTouchOrientation = false;
257 };
258 TouchDeviceData *populateTouchDevices(void *info, QXcbScrollingDevicePrivate *scrollingDeviceP, bool *used = nullptr);
259 TouchDeviceData *touchDeviceForId(int id);
260 void xi2HandleEvent(xcb_ge_event_t *event);
261 void xi2HandleGesturePinchEvent(void *event);
262 void xi2HandleGestureSwipeEvent(void *event);
263 void xi2HandleHierarchyEvent(void *event);
264 void xi2HandleDeviceChangedEvent(void *event);
265 void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
266#if QT_CONFIG(tabletevent)
267 // TODO get rid of this: store minimal necessary info in a subclass of QXcbScrollingDevice (some tablets can scroll)
268 struct TabletData {
269 int deviceId = 0;
270 QString name;
271 QPointingDevice::PointerType pointerType = QPointingDevice::PointerType::Unknown;
272 QInputDevice::DeviceType tool = QInputDevice::DeviceType::Stylus;
273 Qt::MouseButtons buttons;
274 qint64 serialId = 0;
275 bool inProximity = false;
276 struct ValuatorClassInfo {
277 double minVal = 0;
278 double maxVal = 0;
279 double curVal = 0;
280 int number = -1;
281 };
282 QHash<int, ValuatorClassInfo> valuatorInfo;
283 };
284 friend class QTypeInfo<TabletData>;
285 friend class QTypeInfo<TabletData::ValuatorClassInfo>;
286 bool xi2HandleTabletEvent(const void *event, TabletData *tabletData);
287 void xi2ReportTabletEvent(const void *event, TabletData *tabletData);
288 QList<TabletData> m_tabletData;
289 TabletData *tabletDataForDevice(int id);
290#endif // QT_CONFIG(tabletevent)
291 void xi2HandleScrollEvent(void *event, const QPointingDevice *scrollingDevice);
292 void xi2UpdateScrollingDevice(QInputDevice *scrollingDevice);
293 QXcbScrollingDevice *scrollingDeviceForId(int id);
294
295 static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
296
297 QHash<int, TouchDeviceData> m_touchDevices;
298
299 struct StartSystemMoveResizeInfo {
300 xcb_window_t window = XCB_NONE;
301 uint16_t deviceid;
302 uint32_t pointid;
303 int edges;
304 } m_startSystemMoveResizeInfo;
305 bool m_duringSystemMoveResize;
306
307 const bool m_canGrabServer;
308 const xcb_visualid_t m_defaultVisualId;
309
310 QList<QXcbVirtualDesktop *> m_virtualDesktops;
311 QList<QXcbScreen *> m_screens;
312
313 xcb_timestamp_t m_time = XCB_CURRENT_TIME;
314 xcb_timestamp_t m_netWmUserTime = XCB_CURRENT_TIME;
315
316 QXcbKeyboard *m_keyboard = nullptr;
317#ifndef QT_NO_CLIPBOARD
318 QXcbClipboard *m_clipboard = nullptr;
319#endif
320#if QT_CONFIG(draganddrop)
321 QXcbDrag *m_drag = nullptr;
322#endif
323 QScopedPointer<QXcbWMSupport> m_wmSupport;
324 QXcbNativeInterface *m_nativeInterface = nullptr;
325
326 QXcbEventQueue *m_eventQueue = nullptr;
327
328 WindowMapper m_mapper;
329
330 Qt::MouseButtons m_buttonState;
331 Qt::MouseButton m_button = Qt::NoButton;
332
333 QXcbWindow *m_focusWindow = nullptr;
334 QXcbWindow *m_mouseGrabber = nullptr;
335 QXcbWindow *m_mousePressWindow = nullptr;
336
337#if QT_CONFIG(gestures)
338 qreal m_lastPinchScale = 0;
339#endif
340
341 xcb_window_t m_clientLeader = 0;
342 QByteArray m_startupId;
343 QXcbSystemTrayTracker *m_systemTrayTracker = nullptr;
344 mutable QXcbGlIntegration *m_glIntegration = nullptr;
345 mutable bool m_glIntegrationInitialized = false;
346 bool m_xiGrab = false;
347 QList<int> m_xiMasterPointerIds;
348 QList<int> m_xiSlavePointerIds;
349
350 xcb_window_t m_qtSelectionOwner = 0;
351
352 friend class QXcbEventQueue;
353
354 QTimer m_focusInTimer;
355
356};
357#if QT_CONFIG(tabletevent)
358Q_DECLARE_TYPEINFO(QXcbConnection::TabletData::ValuatorClassInfo, Q_PRIMITIVE_TYPE);
359Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_RELOCATABLE_TYPE);
360#endif
361
363{
364public:
367 void release();
368private:
369 QXcbConnection *m_connection;
370};
371
372// The xcb_send_event() requires all events to have 32 bytes. It calls memcpy() on the
373// passed in event. If the passed in event is less than 32 bytes, memcpy() reaches into
374// unrelated memory.
375template <typename T>
376struct alignas(32) q_padded_xcb_event : T { };
377
378QT_END_NAMESPACE
\inmodule QtSql
bool isForeignWindow() const override
Definition qxcbwindow.h:273
void create() override
Definition qxcbwindow.h:276
QXcbForeignWindow(QWindow *window, WId nativeHandle)
QXcbConnection * connection() const
Definition qxcbobject.h:17
xcb_connection_t * xcb_connection() const
Definition qxcbobject.h:20
xcb_atom_t atom(QXcbAtom::Atom atom) const
Definition qxcbobject.h:19
void setConnection(QXcbConnection *connection)
Definition qxcbobject.h:16
QXcbObject(QXcbConnection *connection=nullptr)
Definition qxcbobject.h:14
QXcbWindow * window() const
QXcbSyncWindowRequest(QXcbWindow *w)
virtual void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *)
virtual void handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *)
virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource=Qt::MouseEventNotSynthesized)
virtual void handleButtonPressEvent(const xcb_button_press_event_t *)
virtual void handleEnterNotifyEvent(const xcb_enter_notify_event_t *)
virtual void handleMapNotifyEvent(const xcb_map_notify_event_t *)
virtual void handleClientMessageEvent(const xcb_client_message_event_t *)
virtual void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *)
virtual void handleXIEnterLeave(xcb_ge_event_t *)
virtual void handleMotionNotifyEvent(const xcb_motion_notify_event_t *)
virtual void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *)
virtual void handleButtonReleaseEvent(const xcb_button_release_event_t *)
virtual void handleExposeEvent(const xcb_expose_event_t *)
virtual void handleFocusOutEvent(const xcb_focus_out_event_t *)
virtual void handleFocusInEvent(const xcb_focus_in_event_t *)
virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *)
virtual bool handleNativeEvent(xcb_generic_event_t *)
virtual QXcbWindow * toWindow()
QHash< xcb_window_t, QXcbWindowEventListener * > WindowMapper
#define Q_XCB_EXPORT
Definition qxcbexport.h:14
QList< xcb_rectangle_t > qRegionToXcbRectangleList(const QRegion &region)