4#include <QtGui/private/qguiapplication_p.h>
5#include <QtCore/QDebug>
6#include <QtCore/QCoreApplication>
12#if QT_CONFIG(draganddrop)
25#include <QAbstractEventDispatcher>
27#include <QScopedPointer>
32#include <xcb/xfixes.h>
33#define explicit dont_use_cxx_explicit
36#include <xcb/xinput.h>
38#if QT_CONFIG(xcb_xlib)
59 , m_duringSystemMoveResize(
false)
60 , m_canGrabServer(canGrabServer)
61 , m_defaultVisualId(defaultVisualId)
62 , m_nativeInterface(nativeInterface)
72 initializeScreens(
false);
76 xi2SelectStateEvents();
81#ifndef QT_NO_CLIPBOARD
84#if QT_CONFIG(draganddrop)
88 setStartupId(
qgetenv(
"DESKTOP_STARTUP_ID"));
89 if (!startupId().isNull())
92 const int focusInDelay = 100;
93 m_focusInTimer.setSingleShot(
true);
94 m_focusInTimer.setInterval(focusInDelay);
95 m_focusInTimer.callOnTimeout(
this, []() {
105#ifndef QT_NO_CLIPBOARD
108#if QT_CONFIG(draganddrop)
118 while (!m_virtualDesktops.
isEmpty())
119 delete m_virtualDesktops.
takeLast();
121 delete m_glIntegration;
130 return m_screens.
first();
138 m_mapper.
insert(
id, eventListener);
148 return m_mapper.
value(
id,
nullptr);
159#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
161 auto e = reinterpret_cast<event_t *>(event); \
162 if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \
163 if (eventListener->handleNativeEvent(event)) \
165 eventListener->handler(e); \
170#define HANDLE_KEYBOARD_EVENT(event_t, handler) \
172 auto e = reinterpret_cast<event_t *>(event); \
173 if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
174 if (eventListener->handleNativeEvent(event)) \
176 m_keyboard->handler(e); \
182 xcb_generic_event_t *
event)
const
184 quint8 response_type =
event->response_type & ~0x80;
185 quint16 sequence =
event->sequence;
187#define PRINT_AND_RETURN(name) { \
188 qCDebug(log, "%s | %s(%d) | sequence: %d", message, name, response_type, sequence); \
191#define CASE_PRINT_AND_RETURN(name) case name : PRINT_AND_RETURN(#name);
193#define XI_PRINT_AND_RETURN(name) { \
194 qCDebug(log, "%s | XInput Event(%s) | sequence: %d", message, name, sequence); \
197#define XI_CASE_PRINT_AND_RETURN(name) case name : XI_PRINT_AND_RETURN(#name);
199 switch (response_type) {
233 case XCB_GE_GENERIC: {
235 auto *xiDeviceEvent =
reinterpret_cast<const xcb_input_button_press_event_t*
>(
event);
236 switch (xiDeviceEvent->event_type) {
263 qCDebug(log,
"%s | XInput Event(other type) | sequence: %d",
message, sequence);
267 qCDebug(log,
"%s | %s(%d) | sequence: %d",
message,
"XCB_GE_GENERIC", response_type, sequence);
273 if (
isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY))
279 if (
isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY))
287 qCDebug(log,
"%s | unknown(%d) | sequence: %d",
message, response_type, sequence);
289#undef PRINT_AND_RETURN
290#undef CASE_PRINT_AND_RETURN
320 "ChangeWindowAttributes",
321 "GetWindowAttributes",
348 "ChangeActivePointerGrab",
398 "CopyColormapAndFree",
401 "ListInstalledColormaps",
418 "ChangeKeyboardMapping",
419 "GetKeyboardMapping",
420 "ChangeKeyboardControl",
421 "GetKeyboardControl",
423 "ChangePointerControl",
436 "SetModifierMapping",
437 "GetModifierMapping",
456 qCDebug(lcQpaXcb,
"%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
459 int(
error->sequence),
int(
error->resource_id),
461 int(
error->minor_code));
466 Qt::MouseButtons
ret;
467 if (
s & XCB_BUTTON_MASK_1)
469 if (
s & XCB_BUTTON_MASK_2)
471 if (
s & XCB_BUTTON_MASK_3)
478 m_buttonState.setFlag(
button, down);
521 uint8_t response_type;
524 xcb_timestamp_t
time;
527 xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify;
528 xcb_xkb_map_notify_event_t map_notify;
529 xcb_xkb_state_notify_event_t state_notify;
535 if (
Q_UNLIKELY(lcQpaEvents().isDebugEnabled()))
544 uint response_type =
event->response_type & ~0x80;
547 switch (response_type) {
550 case XCB_BUTTON_PRESS: {
551 auto ev =
reinterpret_cast<xcb_button_press_event_t *
>(
event);
558 if (
Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
559 qCDebug(lcQpaXInputEvents,
"legacy mouse press, button %d state %X",
560 ev->detail,
static_cast<unsigned int>(m_buttonState));
563 case XCB_BUTTON_RELEASE: {
564 auto ev =
reinterpret_cast<xcb_button_release_event_t *
>(
event);
566 if (m_duringSystemMoveResize && ev->root != XCB_NONE)
571 if (
Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
572 qCDebug(lcQpaXInputEvents,
"legacy mouse release, button %d state %X",
573 ev->detail,
static_cast<unsigned int>(m_buttonState));
576 case XCB_MOTION_NOTIFY: {
577 auto ev =
reinterpret_cast<xcb_motion_notify_event_t *
>(
event);
581 if (
Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
582 qCDebug(lcQpaXInputEvents,
"legacy mouse move %d,%d button %d state %X",
583 ev->event_x, ev->event_y, ev->detail,
static_cast<unsigned int>(m_buttonState));
586 case XCB_CONFIGURE_NOTIFY: {
588 auto ev =
reinterpret_cast<xcb_configure_notify_event_t *
>(
event);
590 initializeScreens(
true);
596 case XCB_UNMAP_NOTIFY:
598 case XCB_DESTROY_NOTIFY:
600 case XCB_CLIENT_MESSAGE: {
601 auto clientMessage =
reinterpret_cast<xcb_client_message_event_t *
>(
event);
602 if (clientMessage->format != 32)
604#if QT_CONFIG(draganddrop)
606 drag()->handleStatus(clientMessage);
608 drag()->handleFinished(clientMessage);
614 case XCB_ENTER_NOTIFY:
621 case XCB_LEAVE_NOTIFY:
627 auto ev =
reinterpret_cast<xcb_leave_notify_event_t *
>(
event);
638 auto keyPress =
reinterpret_cast<xcb_key_press_event_t *
>(
event);
644 case XCB_KEY_RELEASE:
646 auto keyRelease =
reinterpret_cast<xcb_key_release_event_t *
>(
event);
651 case XCB_MAPPING_NOTIFY:
654 case XCB_SELECTION_REQUEST:
656#if QT_CONFIG(draganddrop) || QT_CONFIG(clipboard)
657 auto selectionRequest =
reinterpret_cast<xcb_selection_request_event_t *
>(
event);
658 setTime(selectionRequest->time);
660#if QT_CONFIG(draganddrop)
662 m_drag->handleSelectionRequest(selectionRequest);
666#ifndef QT_NO_CLIPBOARD
672 case XCB_SELECTION_CLEAR:
674#ifndef QT_NO_CLIPBOARD
678 case XCB_SELECTION_NOTIFY:
681 case XCB_PROPERTY_NOTIFY:
683 auto propertyNotify =
reinterpret_cast<xcb_property_notify_event_t *
>(
event);
685#ifndef QT_NO_CLIPBOARD
690 QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
694 m_wmSupport->updateNetWMAtoms();
703 xi2HandleEvent(
reinterpret_cast<xcb_ge_event_t *
>(
event));
714 if (
isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY)) {
715 auto notify_event =
reinterpret_cast<xcb_xfixes_selection_notify_event_t *
>(
event);
716 setTime(notify_event->timestamp);
717#ifndef QT_NO_CLIPBOARD
721 virtualDesktop->handleXFixesSelectionNotify(notify_event);
722 }
else if (
isXRandrType(response_type, XCB_RANDR_NOTIFY)) {
724 updateScreens(
reinterpret_cast<xcb_randr_notify_event_t *
>(
event));
725 }
else if (
isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY)) {
727 auto change_event =
reinterpret_cast<xcb_randr_screen_change_notify_event_t *
>(
event);
728 if (
auto virtualDesktop = virtualDesktopForRootWindow(change_event->root))
729 virtualDesktop->handleScreenChange(change_event);
732 auto xkb_event =
reinterpret_cast<_xkb_event *
>(
event);
733 if (xkb_event->any.deviceID == m_keyboard->
coreDeviceId()) {
734 switch (xkb_event->any.xkbType) {
737 case XCB_XKB_STATE_NOTIFY:
740 case XCB_XKB_MAP_NOTIFY:
743 case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
744 xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
745 if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
766 m_focusWindow =
w ?
static_cast<QXcbWindow *
>(
w->handle()) :
nullptr;
771 m_mousePressWindow =
nullptr;
775 m_mousePressWindow =
w;
785 if (m_clientLeader) {
788 XCB_PROP_MODE_REPLACE,
827 XCB_ATOM_INTEGER, 32, 0,
nullptr);
831 xcb_generic_event_t *
event =
nullptr;
839 if (
type != XCB_PROPERTY_NOTIFY)
841 auto propertyNotify =
reinterpret_cast<xcb_property_notify_event_t *
>(
event);
842 return propertyNotify->window ==
window && propertyNotify->atom == dummyAtom;
851 return XCB_CURRENT_TIME;
854 xcb_property_notify_event_t *pn =
reinterpret_cast<xcb_property_notify_event_t *
>(
event);
855 xcb_timestamp_t timestamp = pn->time;
865 qCDebug(lcQpaXcb) <<
"failed to query selection owner";
874 if (!m_qtSelectionOwner) {
876 int16_t
x = 0,
y = 0;
877 uint16_t
w = 3,
h = 3;
880 XCB_COPY_FROM_PARENT,
885 XCB_WINDOW_CLASS_INPUT_OUTPUT,
886 xcbScreen->root_visual,
893 return m_qtSelectionOwner;
899 return s ?
s->root() : 0;
904 if (m_clientLeader == 0) {
908 XCB_COPY_FROM_PARENT,
913 XCB_WINDOW_CLASS_INPUT_OUTPUT,
914 screen->screen()->root_visual,
922 XCB_PROP_MODE_REPLACE,
935 XCB_PROP_MODE_REPLACE,
947 return m_clientLeader;
962bool QXcbConnection::compressEvent(xcb_generic_event_t *
event)
const
967 uint responseType =
event->response_type & ~0x80;
969 if (responseType == XCB_MOTION_NOTIFY) {
972 [](xcb_generic_event_t *,
int type) {
973 return type == XCB_MOTION_NOTIFY;
978 if (responseType == XCB_GE_GENERIC) {
984#if QT_CONFIG(tabletevent)
985 auto xdev =
reinterpret_cast<xcb_input_motion_event_t *
>(
event);
987 const_cast<QXcbConnection *
>(
this)->tabletDataForDevice(xdev->sourceid))
991 [
this](xcb_generic_event_t *
next,
int) {
998 auto touchUpdateEvent =
reinterpret_cast<xcb_input_touch_update_event_t *
>(
event);
999 uint32_t
id = touchUpdateEvent->detail % INT_MAX;
1002 [
this, &
id](xcb_generic_event_t *
next,
int) {
1005 auto touchUpdateNextEvent =
reinterpret_cast<xcb_input_touch_update_event_t *
>(
next);
1006 return id == touchUpdateNextEvent->detail % INT_MAX;
1013 if (responseType == XCB_CONFIGURE_NOTIFY) {
1017 if (
type != XCB_CONFIGURE_NOTIFY)
1019 auto currentEvent =
reinterpret_cast<xcb_configure_notify_event_t *
>(
event);
1020 auto nextEvent =
reinterpret_cast<xcb_configure_notify_event_t *
>(
next);
1021 return currentEvent->event == nextEvent->event;
1030 auto eventType =
event->response_type & ~0x80;
1031 bool isInputEvent = eventType == XCB_BUTTON_PRESS ||
1032 eventType == XCB_BUTTON_RELEASE ||
1033 eventType == XCB_KEY_PRESS ||
1034 eventType == XCB_KEY_RELEASE ||
1035 eventType == XCB_MOTION_NOTIFY ||
1036 eventType == XCB_ENTER_NOTIFY ||
1037 eventType == XCB_LEAVE_NOTIFY;
1056 if (eventType == XCB_CLIENT_MESSAGE) {
1057 auto clientMessage =
reinterpret_cast<const xcb_client_message_event_t *
>(
event);
1060 isInputEvent =
true;
1063 return isInputEvent;
1068 int connection_error = xcb_connection_has_error(
xcb_connection());
1069 if (connection_error) {
1070 qWarning(
"The X11 connection broke (error %d). Did the X11 server die?", connection_error);
1079 if (!(
event->response_type & ~0x80)) {
1084 if (compressEvent(
event))
1095#if QT_CONFIG(xcb_xlib)
1104 xcb_format_iterator_t iterator =
1105 xcb_setup_pixmap_formats_iterator(
setup());
1107 while (iterator.rem) {
1108 xcb_format_t *
format = iterator.data;
1111 xcb_format_next(&iterator);
1114 qWarning() <<
"XCB failed to find an xcb_format_t for depth:" <<
depth;
1121 xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus(
xcb_connection());
1122 free(xcb_get_input_focus_reply(
xcb_connection(), cookie,
nullptr));
1127 if (!m_systemTrayTracker) {
1134 return m_systemTrayTracker;
1153 if (m_glIntegrationInitialized)
1154 return m_glIntegration;
1159 if (!glIntegrationName.
isEmpty()) {
1160 qCDebug(lcQpaGl) <<
"QT_XCB_GL_INTEGRATION is set to" << glIntegrationName;
1161 if (glIntegrationName !=
"none"_L1) {
1162 glIntegrationNames.removeAll(glIntegrationName);
1163 glIntegrationNames.prepend(glIntegrationName);
1165 glIntegrationNames.clear();
1169 if (!glIntegrationNames.isEmpty()) {
1170 qCDebug(lcQpaGl) <<
"Choosing xcb gl-integration based on following priority\n" << glIntegrationNames;
1171 for (
int i = 0;
i < glIntegrationNames.size() && !m_glIntegration;
i++) {
1174 qCDebug(lcQpaGl) <<
"Failed to initialize xcb gl-integration" << glIntegrationNames.at(
i);
1175 delete m_glIntegration;
1176 m_glIntegration =
nullptr;
1179 if (!m_glIntegration)
1180 qCDebug(lcQpaGl) <<
"Failed to create xcb gl-integration";
1183 m_glIntegrationInitialized =
true;
1184 return m_glIntegration;
1225 m_connection =
nullptr;
1231#include "moc_qxcbconnection.cpp"
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
Sends message through the event filters that were set by installNativeEventFilter().
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
QString applicationName
the name of this application
static QPlatformNativeInterface * platformNativeInterface()
QString applicationDisplayName
the user-visible name of this application
bool remove(const Key &key)
Removes the item that has the key from the hash.
T value(const Key &key) const noexcept
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
bool isEmpty() const noexcept
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
The QScreen class is used to query screen properties. \inmodule QtGui.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString toLower() const &
static void handleScreenRemoved(QPlatformScreen *screen)
Should be called by the implementation whenever a screen is removed.
static void handleWindowActivated(QWindow *window, Qt::FocusReason r=Qt::OtherFocusReason)
bool isXIEvent(xcb_generic_event_t *event) const
bool isAtLeastXRandR15() const
int primaryScreenNumber() const
xcb_connection_t * xcb_connection() const
const xcb_setup_t * setup() const
bool isXRandrType(uint responseType, int eventType) const
bool isXkbType(uint responseType) const
bool isXIType(xcb_generic_event_t *event, uint16_t type) const
xcb_atom_t atom(QXcbAtom::Atom qatom) const
bool isXFixesType(uint responseType, int eventType) const
void handleSelectionClearRequest(xcb_selection_clear_event_t *event)
bool handlePropertyNotify(const xcb_generic_event_t *event)
void handleSelectionRequest(xcb_selection_request_event_t *event)
void handleXFixesSelectionRequest(xcb_xfixes_selection_notify_event_t *event)
Q_NODISCARD_CTOR QXcbConnectionGrabber(QXcbConnection *connection)
xcb_window_t selectionOwner(xcb_atom_t atom) const
xcb_window_t rootWindow()
bool isUserInputEvent(xcb_generic_event_t *event) const
void setMousePressWindow(QXcbWindow *)
Qt::MouseButton translateMouseButton(xcb_button_t s)
QXcbKeyboard * keyboard() const
void printXcbEvent(const QLoggingCategory &log, const char *message, xcb_generic_event_t *event) const
QXcbGlIntegration * glIntegration() const
void setMouseGrabber(QXcbWindow *)
void setTime(xcb_timestamp_t t)
void setButtonState(Qt::MouseButton button, bool down)
QString windowManagerName() const
QXcbConnection * connection() const
void processXcbEvents(QEventLoop::ProcessEventsFlags flags)
void printXcbError(const char *message, xcb_generic_error_t *error)
xcb_timestamp_t time() const
QXcbScreen * primaryScreen() const
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
xcb_window_t qtSelectionOwner()
void handleXcbError(xcb_generic_error_t *error)
QXcbVirtualDesktop * primaryVirtualDesktop() const
void setFocusWindow(QWindow *)
Qt::MouseButtons queryMouseButtons() const
void abortSystemMoveResize(xcb_window_t window)
QXcbEventQueue * eventQueue() const
xcb_window_t clientLeader()
void setStartupId(const QByteArray &nextId)
QXcbWindowEventListener * windowEventListenerFromId(xcb_window_t id)
Qt::MouseButton button() const
QByteArray startupId() const
const xcb_format_t * formatForDepth(uint8_t depth) const
QXcbWindow * platformWindowFromId(xcb_window_t id)
Qt::KeyboardModifiers queryKeyboardModifiers() const
void addWindowEventListener(xcb_window_t id, QXcbWindowEventListener *eventListener)
xcb_timestamp_t getTimestamp()
void handleXcbEvent(xcb_generic_event_t *event)
QXcbSystemTrayTracker * systemTrayTracker() const
void removeWindowEventListener(xcb_window_t id)
static void queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask=nullptr)
xcb_generic_event_t * takeFirst(QEventLoop::ProcessEventsFlags flags)
xcb_generic_event_t * peek(Peeker &&peeker)
void flushBufferedEvents()
static QXcbGlIntegration * create(const QString &name)
virtual bool initialize(QXcbConnection *connection)=0
virtual bool handleXcbEvent(xcb_generic_event_t *event, uint responseType)
void updateKeymap(xcb_mapping_notify_event_t *event)
void updateXKBState(xcb_xkb_state_notify_event_t *state)
Qt::KeyboardModifiers translateModifiers(int s) const
void updateXKBStateFromCore(quint16 state)
const QByteArray & nativeEventType() const
QXcbWindow * window() const
static QXcbSystemTrayTracker * create(QXcbConnection *connection)
void notifyManagerClientMessageEvent(const xcb_client_message_event_t *)
QString windowManagerName() const
xcb_screen_t * screen() const
virtual QXcbWindow * toWindow()
void updateSyncRequestCounter()
void clearSyncWindowRequest()
void setWindowTitle(const QString &title) override
Reimplement to set the window title to title.
Combined button and popup list for selecting options.
@ AA_CompressTabletEvents
@ AA_CompressHighFrequencyEvents
@ ActiveWindowFocusReason
static QString displayName(CGDirectDisplayID displayID)
DBusConnection const char DBusError * error
DBusConnection * connection
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLfloat GLfloat GLfloat w
[0]
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLenum GLenum GLenum input
#define QStringLiteral(str)
void qt_XFlush(Display *dpy)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qunsetenv(const char *varName)
#define HANDLE_KEYBOARD_EVENT(event_t, handler)
#define CASE_PRINT_AND_RETURN(name)
const char * xcb_protocol_request_codes[]
static Qt::MouseButtons translateMouseButtons(int s)
#define PRINT_AND_RETURN(name)
#define XI_CASE_PRINT_AND_RETURN(name)
#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler)
const char * xcb_errors[]
#define Q_XCB_REPLY(call,...)