40 #include <QtGui/private/qguiapplication_p.h>
41 #include <QtCore/QDebug>
42 #include <QtCore/QCoreApplication>
48 #if QT_CONFIG(draganddrop)
61 #include <QAbstractEventDispatcher>
63 #include <QScopedPointer>
68 #include <xcb/xfixes.h>
69 #define explicit dont_use_cxx_explicit
89 , m_duringSystemMoveResize(
false)
90 , m_canGrabServer(canGrabServer)
91 , m_defaultVisualId(defaultVisualId)
92 , m_nativeInterface(nativeInterface)
100 xrandrSelectEvents();
102 initializeScreens(
false);
106 xi2SelectStateEvents();
111 #ifndef QT_NO_CLIPBOARD
114 #if QT_CONFIG(draganddrop)
118 m_startupId = qgetenv(
"DESKTOP_STARTUP_ID");
119 if (!m_startupId.isNull())
120 qunsetenv(
"DESKTOP_STARTUP_ID");
122 const int focusInDelay = 100;
123 m_focusInTimer.setSingleShot(
true);
124 m_focusInTimer.setInterval(focusInDelay);
125 m_focusInTimer.callOnTimeout([]() {
135 #ifndef QT_NO_CLIPBOARD
138 #if QT_CONFIG(draganddrop)
148 while (!m_virtualDesktops.
isEmpty())
149 delete m_virtualDesktops.
takeLast();
151 delete m_glIntegration;
160 return m_screens.
first();
168 m_mapper.
insert(
id, eventListener);
178 return m_mapper.
value(
id, 0);
189 #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
191 auto e = reinterpret_cast<event_t *>(event); \
192 if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \
193 if (eventListener->handleNativeEvent(event)) \
195 eventListener->handler(e); \
200 #define HANDLE_KEYBOARD_EVENT(event_t, handler) \
202 auto e = reinterpret_cast<event_t *>(event); \
203 if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
204 if (eventListener->handleNativeEvent(event)) \
206 m_keyboard->handler(e); \
212 xcb_generic_event_t *
event)
const
214 quint8 response_type =
event->response_type & ~0x80;
215 quint16 sequence =
event->sequence;
217 #define PRINT_AND_RETURN(name) { \
218 qCDebug(log, "%s | %s(%d) | sequence: %d", message, name, response_type, sequence); \
221 #define CASE_PRINT_AND_RETURN(name) case name : PRINT_AND_RETURN(#name);
223 #define XI_PRINT_AND_RETURN(name) { \
224 qCDebug(log, "%s | XInput Event(%s) | sequence: %d", message, name, sequence); \
227 #define XI_CASE_PRINT_AND_RETURN(name) case name : XI_PRINT_AND_RETURN(#name);
229 switch (response_type) {
263 case XCB_GE_GENERIC: {
266 switch (xiDeviceEvent->event_type) {
293 qCDebug(log,
"%s | XInput Event(other type) | sequence: %d",
message, sequence);
297 qCDebug(log,
"%s | %s(%d) | sequence: %d",
message,
"XCB_GE_GENERIC", response_type, sequence);
303 if (
isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY))
309 if (
isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY))
317 qCDebug(log,
"%s | unknown(%d) | sequence: %d",
message, response_type, sequence);
319 #undef PRINT_AND_RETURN
320 #undef CASE_PRINT_AND_RETURN
350 "ChangeWindowAttributes",
351 "GetWindowAttributes",
378 "ChangeActivePointerGrab",
428 "CopyColormapAndFree",
431 "ListInstalledColormaps",
448 "ChangeKeyboardMapping",
449 "GetKeyboardMapping",
450 "ChangeKeyboardControl",
451 "GetKeyboardControl",
453 "ChangePointerControl",
466 "SetModifierMapping",
467 "GetModifierMapping",
486 qCWarning(lcQpaXcb,
"%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
489 int(
error->sequence),
int(
error->resource_id),
491 int(
error->minor_code));
494 static Qt::MouseButtons translateMouseButtons(
int s)
496 Qt::MouseButtons
ret;
497 if (
s & XCB_BUTTON_MASK_1)
499 if (
s & XCB_BUTTON_MASK_2)
501 if (
s & XCB_BUTTON_MASK_3)
508 m_buttonState.setFlag(
button, down);
551 uint8_t response_type;
554 xcb_timestamp_t
time;
557 xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify;
558 xcb_xkb_map_notify_event_t map_notify;
559 xcb_xkb_state_notify_event_t state_notify;
565 if (
Q_UNLIKELY(lcQpaEvents().isDebugEnabled()))
574 uint response_type =
event->response_type & ~0x80;
577 switch (response_type) {
580 case XCB_BUTTON_PRESS: {
581 auto ev =
reinterpret_cast<xcb_button_press_event_t *
>(
event);
586 m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
588 if (
Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
589 qCDebug(lcQpaXInputEvents,
"legacy mouse press, button %d state %X",
590 ev->detail,
static_cast<unsigned int>(m_buttonState));
593 case XCB_BUTTON_RELEASE: {
594 auto ev =
reinterpret_cast<xcb_button_release_event_t *
>(
event);
596 if (m_duringSystemMoveResize && ev->root != XCB_NONE)
599 m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
601 if (
Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
602 qCDebug(lcQpaXInputEvents,
"legacy mouse release, button %d state %X",
603 ev->detail,
static_cast<unsigned int>(m_buttonState));
606 case XCB_MOTION_NOTIFY: {
607 auto ev =
reinterpret_cast<xcb_motion_notify_event_t *
>(
event);
610 m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
611 if (
Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
612 qCDebug(lcQpaXInputEvents,
"legacy mouse move %d,%d button %d state %X",
613 ev->event_x, ev->event_y, ev->detail,
static_cast<unsigned int>(m_buttonState));
616 case XCB_CONFIGURE_NOTIFY: {
618 auto ev =
reinterpret_cast<xcb_configure_notify_event_t *
>(
event);
620 initializeScreens(
true);
626 case XCB_UNMAP_NOTIFY:
628 case XCB_DESTROY_NOTIFY:
630 case XCB_CLIENT_MESSAGE: {
631 auto clientMessage =
reinterpret_cast<xcb_client_message_event_t *
>(
event);
632 if (clientMessage->format != 32)
634 #if QT_CONFIG(draganddrop)
636 drag()->handleStatus(clientMessage);
638 drag()->handleFinished(clientMessage);
644 case XCB_ENTER_NOTIFY:
651 case XCB_LEAVE_NOTIFY:
657 auto ev =
reinterpret_cast<xcb_leave_notify_event_t *
>(
event);
668 auto keyPress =
reinterpret_cast<xcb_key_press_event_t *
>(
event);
674 case XCB_KEY_RELEASE:
676 auto keyRelease =
reinterpret_cast<xcb_key_release_event_t *
>(
event);
681 case XCB_MAPPING_NOTIFY:
684 case XCB_SELECTION_REQUEST:
686 #if QT_CONFIG(draganddrop) || QT_CONFIG(clipboard)
687 auto selectionRequest =
reinterpret_cast<xcb_selection_request_event_t *
>(
event);
688 setTime(selectionRequest->time);
690 #if QT_CONFIG(draganddrop)
692 m_drag->handleSelectionRequest(selectionRequest);
696 #ifndef QT_NO_CLIPBOARD
702 case XCB_SELECTION_CLEAR:
704 #ifndef QT_NO_CLIPBOARD
708 case XCB_SELECTION_NOTIFY:
711 case XCB_PROPERTY_NOTIFY:
713 auto propertyNotify =
reinterpret_cast<xcb_property_notify_event_t *
>(
event);
715 #ifndef QT_NO_CLIPBOARD
720 QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
724 m_wmSupport->updateNetWMAtoms();
733 xi2HandleEvent(
reinterpret_cast<xcb_ge_event_t *
>(
event));
744 if (
isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY)) {
745 auto notify_event =
reinterpret_cast<xcb_xfixes_selection_notify_event_t *
>(
event);
746 setTime(notify_event->timestamp);
747 #ifndef QT_NO_CLIPBOARD
751 virtualDesktop->handleXFixesSelectionNotify(notify_event);
752 }
else if (
isXRandrType(response_type, XCB_RANDR_NOTIFY)) {
754 updateScreens(
reinterpret_cast<xcb_randr_notify_event_t *
>(
event));
755 }
else if (
isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY)) {
757 auto change_event =
reinterpret_cast<xcb_randr_screen_change_notify_event_t *
>(
event);
758 if (
auto virtualDesktop = virtualDesktopForRootWindow(change_event->root))
759 virtualDesktop->handleScreenChange(change_event);
762 auto xkb_event =
reinterpret_cast<_xkb_event *
>(
event);
763 if (xkb_event->any.deviceID == m_keyboard->
coreDeviceId()) {
764 switch (xkb_event->any.xkbType) {
767 case XCB_XKB_STATE_NOTIFY:
770 case XCB_XKB_MAP_NOTIFY:
773 case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
774 xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
775 if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
791 m_glIntegration->handleXcbEvent(
event, response_type);
796 m_focusWindow =
w ?
static_cast<QXcbWindow *
>(
w->handle()) :
nullptr;
801 m_mousePressWindow =
nullptr;
805 m_mousePressWindow =
w;
835 XCB_ATOM_INTEGER, 32, 0,
nullptr);
839 xcb_generic_event_t *
event =
nullptr;
847 if (
type != XCB_PROPERTY_NOTIFY)
849 auto propertyNotify =
reinterpret_cast<xcb_property_notify_event_t *
>(
event);
850 return propertyNotify->window ==
window && propertyNotify->atom == dummyAtom;
859 return XCB_CURRENT_TIME;
862 xcb_property_notify_event_t *pn =
reinterpret_cast<xcb_property_notify_event_t *
>(
event);
863 xcb_timestamp_t timestamp = pn->time;
875 qCDebug(lcQpaXcb) <<
"failed to query selection owner";
884 if (!m_qtSelectionOwner) {
886 int16_t
x = 0,
y = 0;
887 uint16_t
w = 3,
h = 3;
890 XCB_COPY_FROM_PARENT,
895 XCB_WINDOW_CLASS_INPUT_OUTPUT,
896 xcbScreen->root_visual,
903 return m_qtSelectionOwner;
909 return s ?
s->root() : 0;
914 if (m_clientLeader == 0) {
918 XCB_COPY_FROM_PARENT,
923 XCB_WINDOW_CLASS_INPUT_OUTPUT,
924 screen->screen()->root_visual,
932 XCB_PROP_MODE_REPLACE,
940 #if QT_CONFIG(xcb_sm)
945 XCB_PROP_MODE_REPLACE,
955 return m_clientLeader;
970 bool QXcbConnection::compressEvent(xcb_generic_event_t *
event)
const
975 uint responseType =
event->response_type & ~0x80;
977 if (responseType == XCB_MOTION_NOTIFY) {
980 [](xcb_generic_event_t *,
int type) {
981 return type == XCB_MOTION_NOTIFY;
986 if (responseType == XCB_GE_GENERIC) {
992 #if QT_CONFIG(tabletevent)
995 const_cast<QXcbConnection *
>(
this)->tabletDataForDevice(xdev->sourceid))
999 [
this](xcb_generic_event_t *
next,
int) {
1007 uint32_t
id = touchUpdateEvent->
detail % INT_MAX;
1010 [
this, &
id](xcb_generic_event_t *
next,
int) {
1014 return id == touchUpdateNextEvent->
detail % INT_MAX;
1021 if (responseType == XCB_CONFIGURE_NOTIFY) {
1025 if (
type != XCB_CONFIGURE_NOTIFY)
1027 auto currentEvent =
reinterpret_cast<xcb_configure_notify_event_t *
>(
event);
1028 auto nextEvent =
reinterpret_cast<xcb_configure_notify_event_t *
>(
next);
1029 return currentEvent->event == nextEvent->event;
1038 auto eventType =
event->response_type & ~0x80;
1039 bool isInputEvent = eventType == XCB_BUTTON_PRESS ||
1040 eventType == XCB_BUTTON_RELEASE ||
1041 eventType == XCB_KEY_PRESS ||
1042 eventType == XCB_KEY_RELEASE ||
1043 eventType == XCB_MOTION_NOTIFY ||
1044 eventType == XCB_ENTER_NOTIFY ||
1045 eventType == XCB_LEAVE_NOTIFY;
1064 if (eventType == XCB_CLIENT_MESSAGE) {
1065 auto clientMessage =
reinterpret_cast<const xcb_client_message_event_t *
>(
event);
1068 isInputEvent =
true;
1071 return isInputEvent;
1076 int connection_error = xcb_connection_has_error(
xcb_connection());
1077 if (connection_error) {
1078 qWarning(
"The X11 connection broke (error %d). Did the X11 server die?", connection_error);
1087 if (!(
event->response_type & ~0x80)) {
1092 if (compressEvent(
event))
1109 xcb_setup_pixmap_formats_iterator(
setup());
1118 qWarning() <<
"XCB failed to find an xcb_format_t for depth:" <<
depth;
1125 xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus(
xcb_connection());
1126 free(xcb_get_input_focus_reply(
xcb_connection(), cookie,
nullptr));
1131 if (!m_systemTrayTracker) {
1138 return m_systemTrayTracker;
1145 return translateMouseButtons(stateMask);
1157 if (m_glIntegrationInitialized)
1158 return m_glIntegration;
1163 if (!glIntegrationName.
isEmpty()) {
1164 qCDebug(lcQpaGl) <<
"QT_XCB_GL_INTEGRATION is set to" << glIntegrationName;
1166 glIntegrationNames.removeAll(glIntegrationName);
1167 glIntegrationNames.prepend(glIntegrationName);
1169 glIntegrationNames.clear();
1173 if (!glIntegrationNames.isEmpty()) {
1174 qCDebug(lcQpaGl) <<
"Choosing xcb gl-integration based on following priority\n" << glIntegrationNames;
1175 for (
int i = 0;
i < glIntegrationNames.size() && !m_glIntegration;
i++) {
1177 if (m_glIntegration && !m_glIntegration->initialize(
const_cast<QXcbConnection *
>(
this))) {
1178 qCDebug(lcQpaGl) <<
"Failed to initialize xcb gl-integration" << glIntegrationNames.at(
i);
1179 delete m_glIntegration;
1180 m_glIntegration =
nullptr;
1183 if (!m_glIntegration)
1184 qCDebug(lcQpaGl) <<
"Failed to create xcb gl-integration";
1187 m_glIntegrationInitialized =
true;
1188 return m_glIntegration;
1229 m_connection =
nullptr;
1235 #include "moc_qxcbconnection.cpp"
small capitals from c petite p scientific i
[1]
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
The QByteArray class provides an array of bytes.
const char * constData() const noexcept
qsizetype length() const noexcept
bool isEmpty() const noexcept
static bool testAttribute(Qt::ApplicationAttribute attribute)
QString applicationName
the name of this application
The QEvent class is the base class of all event classes. Event objects contain event parameters.
static QPlatformNativeInterface * platformNativeInterface()
QString applicationDisplayName
the user-visible name of this application
bool remove(const Key &key)
T value(const Key &key) const noexcept
iterator insert(const Key &key, const T &value)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
bool isEmpty() const noexcept
The QLoggingCategory class represents a category, or 'area' in the logging infrastructure.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
virtual bool event(QEvent *event)
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
The QScreen class is used to query screen properties. \inmodule QtGui.
The QString class provides a Unicode character string.
static QString fromLocal8Bit(QByteArrayView ba)
QString toLower() const &
The QStringList class provides a list of strings.
The QWindow class represents a window in the underlying windowing system.
static void handleScreenRemoved(QPlatformScreen *screen)
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
bool isXRandrType(uint responseType, int eventType) const
bool isXkbType(uint responseType) const
const xcb_setup_t * setup() 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)
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)
void printXcbEvent(const QLoggingCategory &log, const char *message, xcb_generic_event_t *event) const
QXcbEventQueue * eventQueue() const
QXcbGlIntegration * glIntegration() const
void setMouseGrabber(QXcbWindow *)
void setTime(xcb_timestamp_t t)
void setButtonState(Qt::MouseButton button, bool down)
QString windowManagerName() const
void processXcbEvents(QEventLoop::ProcessEventsFlags flags)
QXcbKeyboard * keyboard() const
void printXcbError(const char *message, xcb_generic_error_t *error)
xcb_timestamp_t time() const
QXcbScreen * primaryScreen() const
bool event(QEvent *e) override
xcb_window_t qtSelectionOwner()
void handleXcbError(xcb_generic_error_t *error)
void setFocusWindow(QWindow *)
Qt::MouseButtons queryMouseButtons() const
void abortSystemMoveResize(xcb_window_t window)
xcb_window_t clientLeader()
QXcbVirtualDesktop * primaryVirtualDesktop() const
QXcbWindowEventListener * windowEventListenerFromId(xcb_window_t id)
QXcbConnection * connection() const
Qt::MouseButton button() 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)
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 *)
xcb_screen_t * screen() const
QString windowManagerName() const
virtual QXcbWindow * toWindow()
void updateSyncRequestCounter()
void clearSyncWindowRequest()
void setWindowTitle(const QString &title) override
auto it unsigned count const
typename C::iterator iterator
@ AA_CompressTabletEvents
@ AA_CompressHighFrequencyEvents
@ ActiveWindowFocusReason
QImageReader reader("image.png")
[1]
DBusConnection * connection
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLenum GLuint GLenum GLsizei const GLchar * message
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLenum GLenum GLenum input
#define QStringLiteral(str)
#define HANDLE_KEYBOARD_EVENT(event_t, handler)
#define CASE_PRINT_AND_RETURN(name)
const char * xcb_protocol_request_codes[]
#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,...)