1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the plugins of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qxcbwindow.h"
46 #include "qxcbconnection.h"
47 #include "qxcbscreen.h"
49 #include "qdri2context.h"
52 #define class class_name // Yeah, in 2011 ...
53 #include <xcb/xcb_icccm.h>
56 // xcb-icccm 3.8 support
57 #ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
58 #define xcb_wm_hints_t xcb_icccm_wm_hints_t
59 #define xcb_wm_hints_set_iconic xcb_icccm_wm_hints_set_iconic
60 #define xcb_wm_hints_set_normal xcb_icccm_wm_hints_set_normal
61 #define xcb_set_wm_hints xcb_icccm_set_wm_hints
64 #include <private/qapplication_p.h>
65 #include <private/qwindowsurface_p.h>
67 #include <QtGui/QWindowSystemInterface>
73 #include <X11/Xutil.h>
76 #if defined(XCB_USE_GLX)
77 #include "qglxintegration.h"
78 #include "qglxconvenience.h"
79 #elif defined(XCB_USE_EGL)
80 #include "../eglconvenience/qeglplatformcontext.h"
81 #include "../eglconvenience/qeglconvenience.h"
82 #include "../eglconvenience/qxlibeglintegration.h"
85 // Returns true if we should set WM_TRANSIENT_FOR on \a w
86 static inline bool isTransient(const QWidget *w)
88 return ((w->windowType() == Qt::Dialog
89 || w->windowType() == Qt::Sheet
90 || w->windowType() == Qt::Tool
91 || w->windowType() == Qt::SplashScreen
92 || w->windowType() == Qt::ToolTip
93 || w->windowType() == Qt::Drawer
94 || w->windowType() == Qt::Popup)
95 && !w->testAttribute(Qt::WA_X11BypassTransientForHint));
98 QXcbWindow::QXcbWindow(QWidget *tlw)
99 : QPlatformWindow(tlw)
102 m_screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(tlw));
104 setConnection(m_screen->connection());
106 const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK;
107 const quint32 values[] = {
108 // XCB_CW_BACK_PIXMAP
111 XCB_EVENT_MASK_EXPOSURE
112 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
113 | XCB_EVENT_MASK_KEY_PRESS
114 | XCB_EVENT_MASK_KEY_RELEASE
115 | XCB_EVENT_MASK_BUTTON_PRESS
116 | XCB_EVENT_MASK_BUTTON_RELEASE
117 | XCB_EVENT_MASK_BUTTON_MOTION
118 | XCB_EVENT_MASK_ENTER_WINDOW
119 | XCB_EVENT_MASK_LEAVE_WINDOW
120 | XCB_EVENT_MASK_PROPERTY_CHANGE
121 | XCB_EVENT_MASK_FOCUS_CHANGE
124 #if defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
125 if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
126 && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)
127 || tlw->platformWindowFormat().alpha())
129 #if defined(XCB_USE_GLX)
130 XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat());
131 #elif defined(XCB_USE_EGL)
132 EGLDisplay eglDisplay = connection()->egl_display();
133 EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true);
134 VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);
136 XVisualInfo visualInfoTemplate;
137 memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
138 visualInfoTemplate.visualid = id;
140 XVisualInfo *visualInfo;
141 int matchingCount = 0;
142 visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
145 m_depth = visualInfo->depth;
146 m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
147 Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone);
149 XSetWindowAttributes a;
150 a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
151 a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
153 m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(),
154 0, visualInfo->depth, InputOutput, visualInfo->visual,
155 CWBackPixel|CWBorderPixel|CWColormap, &a);
157 printf("created GL window: %d\n", m_window);
159 qFatal("no window!");
162 #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
164 m_window = xcb_generate_id(xcb_connection());
165 m_depth = m_screen->screen()->root_depth;
166 m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
168 Q_XCB_CALL(xcb_create_window(xcb_connection(),
169 XCB_COPY_FROM_PARENT, // depth -- same as root
170 m_window, // window id
171 m_screen->root(), // parent window id
177 XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
178 m_screen->screen()->root_visual, // visual
182 printf("created regular window: %d\n", m_window);
185 Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
187 xcb_atom_t properties[4];
188 int propertyCount = 0;
189 properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW);
190 properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
191 properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
193 if (m_screen->syncRequestSupported())
194 properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
196 if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint)
197 properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);
199 Q_XCB_CALL(xcb_change_property(xcb_connection(),
200 XCB_PROP_MODE_REPLACE,
202 atom(QXcbAtom::WM_PROTOCOLS),
210 if (m_screen->syncRequestSupported()) {
211 m_syncCounter = xcb_generate_id(xcb_connection());
212 Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));
214 Q_XCB_CALL(xcb_change_property(xcb_connection(),
215 XCB_PROP_MODE_REPLACE,
217 atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
224 if (isTransient(tlw) && tlw->parentWidget()) {
226 QWidget *p = tlw->parentWidget()->window();
227 xcb_window_t parentWindow = p->winId();
228 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
229 XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
234 // set the PID to let the WM kill the application if unresponsive
236 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
237 atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
241 QXcbWindow::~QXcbWindow()
244 if (m_screen->syncRequestSupported())
245 Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
246 Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
249 void QXcbWindow::setGeometry(const QRect &rect)
251 QPlatformWindow::setGeometry(rect);
253 const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
254 const quint32 values[] = { rect.x(), rect.y(), rect.width(), rect.height() };
256 Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
259 void QXcbWindow::setVisible(bool visible)
261 xcb_wm_hints_t hints;
263 if (widget()->isMinimized())
264 xcb_wm_hints_set_iconic(&hints);
266 xcb_wm_hints_set_normal(&hints);
267 xcb_set_wm_hints(xcb_connection(), m_window, &hints);
268 Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
269 connection()->sync();
271 Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
273 // send synthetic UnmapNotify event according to icccm 4.1.4
274 xcb_unmap_notify_event_t event;
275 event.response_type = XCB_UNMAP_NOTIFY;
276 event.sequence = 0; // does this matter?
277 event.event = m_screen->root();
278 event.window = m_window;
279 event.from_configure = false;
280 Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(),
281 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
283 xcb_flush(xcb_connection());
288 quint32 flags, functions, decorations;
294 MWM_HINTS_FUNCTIONS = (1L << 0),
296 MWM_FUNC_ALL = (1L << 0),
297 MWM_FUNC_RESIZE = (1L << 1),
298 MWM_FUNC_MOVE = (1L << 2),
299 MWM_FUNC_MINIMIZE = (1L << 3),
300 MWM_FUNC_MAXIMIZE = (1L << 4),
301 MWM_FUNC_CLOSE = (1L << 5),
303 MWM_HINTS_DECORATIONS = (1L << 1),
305 MWM_DECOR_ALL = (1L << 0),
306 MWM_DECOR_BORDER = (1L << 1),
307 MWM_DECOR_RESIZEH = (1L << 2),
308 MWM_DECOR_TITLE = (1L << 3),
309 MWM_DECOR_MENU = (1L << 4),
310 MWM_DECOR_MINIMIZE = (1L << 5),
311 MWM_DECOR_MAXIMIZE = (1L << 6),
313 MWM_HINTS_INPUT_MODE = (1L << 2),
315 MWM_INPUT_MODELESS = 0L,
316 MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
317 MWM_INPUT_FULL_APPLICATION_MODAL = 3L
320 Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
322 Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
324 setNetWmWindowTypes(flags);
326 if (type == Qt::ToolTip)
327 flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
328 if (type == Qt::Popup)
329 flags |= Qt::X11BypassWindowManagerHint;
331 bool topLevel = (flags & Qt::Window);
332 bool popup = (type == Qt::Popup);
333 bool dialog = (type == Qt::Dialog
334 || type == Qt::Sheet);
335 bool desktop = (type == Qt::Desktop);
336 bool tool = (type == Qt::Tool || type == Qt::SplashScreen
337 || type == Qt::ToolTip || type == Qt::Drawer);
344 bool tooltip = (type == Qt::ToolTip);
348 mwmhints.functions = 0L;
349 mwmhints.decorations = 0;
350 mwmhints.input_mode = 0L;
351 mwmhints.status = 0L;
353 if (type != Qt::SplashScreen) {
354 mwmhints.flags |= MWM_HINTS_DECORATIONS;
356 bool customize = flags & Qt::CustomizeWindowHint;
357 if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
358 mwmhints.decorations |= MWM_DECOR_BORDER;
359 mwmhints.decorations |= MWM_DECOR_RESIZEH;
361 if (flags & Qt::WindowTitleHint)
362 mwmhints.decorations |= MWM_DECOR_TITLE;
364 if (flags & Qt::WindowSystemMenuHint)
365 mwmhints.decorations |= MWM_DECOR_MENU;
367 if (flags & Qt::WindowMinimizeButtonHint) {
368 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
369 mwmhints.functions |= MWM_FUNC_MINIMIZE;
372 if (flags & Qt::WindowMaximizeButtonHint) {
373 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
374 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
377 if (flags & Qt::WindowCloseButtonHint)
378 mwmhints.functions |= MWM_FUNC_CLOSE;
381 // if type == Qt::SplashScreen
382 mwmhints.decorations = MWM_DECOR_ALL;
385 if (mwmhints.functions != 0) {
386 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
387 mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
389 mwmhints.functions = MWM_FUNC_ALL;
392 if (!(flags & Qt::FramelessWindowHint)
393 && flags & Qt::CustomizeWindowHint
394 && flags & Qt::WindowTitleHint
396 (Qt::WindowMinimizeButtonHint
397 | Qt::WindowMaximizeButtonHint
398 | Qt::WindowCloseButtonHint)))
400 // a special case - only the titlebar without any button
401 mwmhints.flags = MWM_HINTS_FUNCTIONS;
402 mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
403 mwmhints.decorations = 0;
406 if (mwmhints.flags != 0l) {
407 Q_XCB_CALL(xcb_change_property(xcb_connection(),
408 XCB_PROP_MODE_REPLACE,
410 atom(QXcbAtom::_MOTIF_WM_HINTS),
411 atom(QXcbAtom::_MOTIF_WM_HINTS),
416 Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS)));
419 if (popup || tooltip) {
420 const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER;
421 const quint32 values[] = { true, true };
423 Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
426 return QPlatformWindow::setWindowFlags(flags);
429 void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
431 // in order of decreasing priority
432 QVector<uint> windowTypes;
434 Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
439 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
443 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
446 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
448 case Qt::SplashScreen:
449 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
455 if (flags & Qt::FramelessWindowHint)
456 windowTypes.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
458 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
460 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
461 atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
462 windowTypes.count(), windowTypes.constData()));
465 WId QXcbWindow::winId() const
470 void QXcbWindow::setParent(const QPlatformWindow *parent)
472 QPoint topLeft = geometry().topLeft();
473 Q_XCB_CALL(xcb_reparent_window(xcb_connection(), window(), static_cast<const QXcbWindow *>(parent)->window(), topLeft.x(), topLeft.y()));
476 void QXcbWindow::setWindowTitle(const QString &title)
478 QByteArray ba = title.toUtf8();
479 Q_XCB_CALL(xcb_change_property(xcb_connection(),
480 XCB_PROP_MODE_REPLACE,
482 atom(QXcbAtom::_NET_WM_NAME),
483 atom(QXcbAtom::UTF8_STRING),
489 void QXcbWindow::raise()
491 const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
492 const quint32 values[] = { XCB_STACK_MODE_ABOVE };
493 Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
496 void QXcbWindow::lower()
498 const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
499 const quint32 values[] = { XCB_STACK_MODE_BELOW };
500 Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
503 void QXcbWindow::requestActivateWindow()
505 Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, XCB_TIME_CURRENT_TIME));
506 connection()->sync();
509 QPlatformGLContext *QXcbWindow::glContext() const
511 if (!QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
512 printf("no opengl\n");
516 #if defined(XCB_USE_GLX)
517 QXcbWindow *that = const_cast<QXcbWindow *>(this);
518 that->m_context = new QGLXContext(m_window, m_screen, widget()->platformWindowFormat());
519 #elif defined(XCB_USE_EGL)
520 EGLDisplay display = connection()->egl_display();
521 EGLConfig config = q_configFromQPlatformWindowFormat(display,widget()->platformWindowFormat(),true);
522 QVector<EGLint> eglContextAttrs;
523 eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
524 eglContextAttrs.append(2);
525 eglContextAttrs.append(EGL_NONE);
527 EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)m_window,0);
528 QXcbWindow *that = const_cast<QXcbWindow *>(this);
529 that->m_context = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API);
530 #elif defined(XCB_USE_DRI2)
531 QXcbWindow *that = const_cast<QXcbWindow *>(this);
532 that->m_context = new QDri2Context(that);
538 void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
540 QWindowSurface *surface = widget()->windowSurface();
542 QRect rect(event->x, event->y, event->width, event->height);
544 surface->flush(widget(), rect, QPoint());
548 void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *event)
550 if (event->format == 32 && event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
551 if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
552 QWindowSystemInterface::handleCloseEvent(widget());
553 } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
554 xcb_client_message_event_t reply = *event;
556 reply.response_type = XCB_CLIENT_MESSAGE;
557 reply.window = m_screen->root();
559 xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
560 xcb_flush(xcb_connection());
561 } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
562 if (!m_hasReceivedSyncRequest) {
563 m_hasReceivedSyncRequest = true;
564 printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n");
566 m_syncValue.lo = event->data.data32[2];
567 m_syncValue.hi = event->data.data32[3];
572 void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event)
574 int xpos = geometry().x();
575 int ypos = geometry().y();
577 if ((event->width == geometry().width() && event->height == geometry().height()) || event->x != 0 || event->y != 0) {
582 QRect rect(xpos, ypos, event->width, event->height);
584 if (rect == geometry())
587 QPlatformWindow::setGeometry(rect);
588 QWindowSystemInterface::handleGeometryChange(widget(), rect);
592 static_cast<QDri2Context *>(m_context)->resize(rect.size());
596 static Qt::MouseButtons translateMouseButtons(int s)
598 Qt::MouseButtons ret = 0;
599 if (s & XCB_BUTTON_MASK_1)
600 ret |= Qt::LeftButton;
601 if (s & XCB_BUTTON_MASK_2)
602 ret |= Qt::MidButton;
603 if (s & XCB_BUTTON_MASK_3)
604 ret |= Qt::RightButton;
608 static Qt::MouseButton translateMouseButton(xcb_button_t s)
612 return Qt::LeftButton;
614 return Qt::MidButton;
616 return Qt::RightButton;
622 void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
624 QPoint local(event->event_x, event->event_y);
625 QPoint global(event->root_x, event->root_y);
627 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
629 if (event->detail >= 4 && event->detail <= 7) {
630 //logic borrowed from qapplication_x11.cpp
631 int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
632 bool hor = (((event->detail == 4 || event->detail == 5)
633 && (modifiers & Qt::AltModifier))
634 || (event->detail == 6 || event->detail == 7));
636 QWindowSystemInterface::handleWheelEvent(widget(), event->time,
637 local, global, delta, hor ? Qt::Horizontal : Qt::Vertical);
641 handleMouseEvent(event->detail, event->state, event->time, local, global);
644 void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
646 QPoint local(event->event_x, event->event_y);
647 QPoint global(event->root_x, event->root_y);
649 handleMouseEvent(event->detail, event->state, event->time, local, global);
652 void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
654 QPoint local(event->event_x, event->event_y);
655 QPoint global(event->root_x, event->root_y);
657 handleMouseEvent(event->detail, event->state, event->time, local, global);
660 void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global)
662 Qt::MouseButtons buttons = translateMouseButtons(state);
663 Qt::MouseButton button = translateMouseButton(detail);
665 buttons ^= button; // X event uses state *before*, Qt uses state *after*
667 QWindowSystemInterface::handleMouseEvent(widget(), time, local, global, buttons);
670 void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *)
672 QWindowSystemInterface::handleEnterEvent(widget());
675 void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *)
677 QWindowSystemInterface::handleLeaveEvent(widget());
680 void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *)
682 QWindowSystemInterface::handleWindowActivated(widget());
685 void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *)
687 QWindowSystemInterface::handleWindowActivated(0);
690 void QXcbWindow::updateSyncRequestCounter()
692 if (m_screen->syncRequestSupported() && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
693 Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue));
694 xcb_flush(xcb_connection());
695 connection()->sync();