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"
47 #include "qxcbconnection.h"
48 #include "qxcbscreen.h"
50 #include "qxcbwmsupport.h"
53 #include "qdri2context.h"
56 // FIXME This workaround can be removed for xcb-icccm > 3.8
57 #define class class_name
58 #include <xcb/xcb_icccm.h>
60 #include <xcb/xfixes.h>
62 // xcb-icccm 3.8 support
63 #ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
64 #define xcb_get_wm_hints_reply xcb_icccm_get_wm_hints_reply
65 #define xcb_get_wm_hints xcb_icccm_get_wm_hints
66 #define xcb_set_wm_hints xcb_icccm_set_wm_hints
67 #define xcb_set_wm_normal_hints xcb_icccm_set_wm_normal_hints
68 #define xcb_size_hints_set_base_size xcb_icccm_size_hints_set_base_size
69 #define xcb_size_hints_set_max_size xcb_icccm_size_hints_set_max_size
70 #define xcb_size_hints_set_min_size xcb_icccm_size_hints_set_min_size
71 #define xcb_size_hints_set_position xcb_icccm_size_hints_set_position
72 #define xcb_size_hints_set_resize_inc xcb_icccm_size_hints_set_resize_inc
73 #define xcb_size_hints_set_size xcb_icccm_size_hints_set_size
74 #define xcb_size_hints_set_win_gravity xcb_icccm_size_hints_set_win_gravity
75 #define xcb_wm_hints_set_iconic xcb_icccm_wm_hints_set_iconic
76 #define xcb_wm_hints_set_normal xcb_icccm_wm_hints_set_normal
77 #define xcb_wm_hints_t xcb_icccm_wm_hints_t
78 #define XCB_WM_STATE_ICONIC XCB_ICCCM_WM_STATE_ICONIC
81 #include <private/qguiapplication_p.h>
82 #include <private/qwindow_p.h>
84 #include <QtGui/QPlatformBackingStore>
85 #include <QtGui/QWindowSystemInterface>
91 #include <X11/Xutil.h>
94 #if defined(XCB_USE_GLX)
95 #include "qglxintegration.h"
96 #include <QtPlatformSupport/private/qglxconvenience_p.h>
97 #elif defined(XCB_USE_EGL)
98 #include "qxcbeglsurface.h"
99 #include <QtPlatformSupport/private/qeglconvenience_p.h>
100 #include <QtPlatformSupport/private/qxlibeglintegration_p.h>
103 #define XCOORD_MAX 16383
105 //#ifdef NET_WM_STATE_DEBUG
109 // Returns true if we should set WM_TRANSIENT_FOR on \a w
110 static inline bool isTransient(const QWindow *w)
112 return w->windowType() == Qt::Dialog
113 || w->windowType() == Qt::Sheet
114 || w->windowType() == Qt::Tool
115 || w->windowType() == Qt::SplashScreen
116 || w->windowType() == Qt::ToolTip
117 || w->windowType() == Qt::Drawer
118 || w->windowType() == Qt::Popup;
121 static inline QImage::Format imageFormatForDepth(int depth)
124 case 32: return QImage::Format_ARGB32_Premultiplied;
125 case 24: return QImage::Format_RGB32;
126 case 16: return QImage::Format_RGB16;
129 qFatal("Unsupported display depth %d", depth);
130 return QImage::Format_Invalid;
133 QXcbWindow::QXcbWindow(QWindow *window)
134 : QPlatformWindow(window)
138 , m_transparent(false)
139 , m_netWmUserTimeWindow(XCB_NONE)
140 #if defined(XCB_USE_EGL)
144 m_screen = static_cast<QXcbScreen *>(window->screen()->handle());
146 setConnection(m_screen->connection());
151 void QXcbWindow::create()
155 m_windowState = Qt::WindowNoState;
157 Qt::WindowType type = window()->windowType();
159 if (type == Qt::Desktop) {
160 m_window = m_screen->root();
161 m_depth = m_screen->screen()->root_depth;
162 m_imageFormat = imageFormatForDepth(m_depth);
163 connection()->addWindow(m_window, this);
167 const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK;
168 const quint32 values[] = {
169 // XCB_CW_BACK_PIXMAP
171 // XCB_CW_OVERRIDE_REDIRECT
172 type == Qt::Popup || type == Qt::ToolTip,
174 type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
176 XCB_EVENT_MASK_EXPOSURE
177 | XCB_EVENT_MASK_STRUCTURE_NOTIFY
178 | XCB_EVENT_MASK_KEY_PRESS
179 | XCB_EVENT_MASK_KEY_RELEASE
180 | XCB_EVENT_MASK_BUTTON_PRESS
181 | XCB_EVENT_MASK_BUTTON_RELEASE
182 | XCB_EVENT_MASK_BUTTON_MOTION
183 | XCB_EVENT_MASK_ENTER_WINDOW
184 | XCB_EVENT_MASK_LEAVE_WINDOW
185 | XCB_EVENT_MASK_POINTER_MOTION
186 | XCB_EVENT_MASK_PROPERTY_CHANGE
187 | XCB_EVENT_MASK_FOCUS_CHANGE
190 QRect rect = window()->geometry();
191 QPlatformWindow::setGeometry(rect);
193 rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
194 rect.setHeight(qBound(1, rect.height(), XCOORD_MAX));
196 xcb_window_t xcb_parent_id = m_screen->root();
198 xcb_parent_id = static_cast<QXcbWindow *>(parent())->xcb_window();
200 m_requestedFormat = window()->format();
202 #if (defined(XCB_USE_GLX) || defined(XCB_USE_EGL)) && defined(XCB_USE_XLIB)
203 if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)
204 || window()->format().hasAlpha())
206 #if defined(XCB_USE_GLX)
207 XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), window()->format());
209 #elif defined(XCB_USE_EGL)
210 EGLDisplay eglDisplay = connection()->egl_display();
211 EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, window()->format(), true);
212 VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);
214 XVisualInfo visualInfoTemplate;
215 memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
216 visualInfoTemplate.visualid = id;
218 XVisualInfo *visualInfo;
219 int matchingCount = 0;
220 visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount);
223 m_depth = visualInfo->depth;
224 m_imageFormat = imageFormatForDepth(m_depth);
225 Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
227 XSetWindowAttributes a;
228 a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
229 a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber());
231 m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, rect.x(), rect.y(), rect.width(), rect.height(),
232 0, visualInfo->depth, InputOutput, visualInfo->visual,
233 CWBackPixel|CWBorderPixel|CWColormap, &a);
235 qFatal("no window!");
238 #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
240 m_window = xcb_generate_id(xcb_connection());
241 m_depth = m_screen->screen()->root_depth;
242 m_imageFormat = imageFormatForDepth(m_depth);
244 Q_XCB_CALL(xcb_create_window(xcb_connection(),
245 XCB_COPY_FROM_PARENT, // depth -- same as root
246 m_window, // window id
247 xcb_parent_id, // parent window id
253 XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
254 m_screen->screen()->root_visual, // visual
259 connection()->addWindow(m_window, this);
261 Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
263 propagateSizeHints();
265 xcb_atom_t properties[4];
266 int propertyCount = 0;
267 properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW);
268 properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
269 properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
271 if (m_screen->syncRequestSupported())
272 properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
274 if (window()->windowFlags() & Qt::WindowContextHelpButtonHint)
275 properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);
277 Q_XCB_CALL(xcb_change_property(xcb_connection(),
278 XCB_PROP_MODE_REPLACE,
280 atom(QXcbAtom::WM_PROTOCOLS),
288 if (m_screen->syncRequestSupported()) {
289 m_syncCounter = xcb_generate_id(xcb_connection());
290 Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));
292 Q_XCB_CALL(xcb_change_property(xcb_connection(),
293 XCB_PROP_MODE_REPLACE,
295 atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
302 // set the PID to let the WM kill the application if unresponsive
304 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
305 atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
308 xcb_wm_hints_t hints;
309 memset(&hints, 0, sizeof(hints));
310 xcb_wm_hints_set_normal(&hints);
312 xcb_set_wm_hints(xcb_connection(), m_window, &hints);
314 xcb_window_t leader = m_screen->clientLeader();
315 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
316 atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
319 setWindowFlags(window()->windowFlags());
320 setWindowTitle(window()->windowTitle());
321 setWindowState(window()->windowState());
323 if (window()->windowFlags() & Qt::WindowTransparentForInput)
324 setTransparentForMouseEvents(true);
326 connection()->drag()->dndEnable(this, true);
329 QXcbWindow::~QXcbWindow()
334 void QXcbWindow::destroy()
336 if (m_syncCounter && m_screen->syncRequestSupported())
337 Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
339 connection()->removeWindow(m_window);
340 Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
344 #if defined(XCB_USE_EGL)
350 void QXcbWindow::setGeometry(const QRect &rect)
352 QPlatformWindow::setGeometry(rect);
354 propagateSizeHints();
356 const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
357 const quint32 values[] = { rect.x(),
359 qBound(1, rect.width(), XCOORD_MAX),
360 qBound(1, rect.height(), XCOORD_MAX) };
362 Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
364 xcb_flush(xcb_connection());
367 QMargins QXcbWindow::frameMargins() const
369 if (m_dirtyFrameMargins) {
370 xcb_window_t window = m_window;
371 xcb_window_t parent = m_window;
373 bool foundRoot = false;
375 const QVector<xcb_window_t> &virtualRoots =
376 connection()->wmSupport()->virtualRoots();
379 xcb_query_tree_cookie_t cookie = xcb_query_tree(xcb_connection(), parent);
381 xcb_generic_error_t *error;
382 xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, &error);
384 if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1) {
388 parent = reply->parent;
394 connection()->handleXcbError(error);
398 m_dirtyFrameMargins = false;
399 m_frameMargins = QMargins();
400 return m_frameMargins;
406 xcb_generic_error_t *error;
407 xcb_translate_coordinates_reply_t *reply =
408 xcb_translate_coordinates_reply(
410 xcb_translate_coordinates(xcb_connection(), window, parent, 0, 0),
414 offset = QPoint(reply->dst_x, reply->dst_y);
420 xcb_get_geometry_reply_t *geom =
421 xcb_get_geometry_reply(
423 xcb_get_geometry(xcb_connection(), parent),
428 // add the border_width for the window managers frame... some window managers
429 // do not use a border_width of zero for their frames, and if we the left and
430 // top strut, we ensure that pos() is absolutely correct. frameGeometry()
431 // will still be incorrect though... perhaps i should have foffset as well, to
432 // indicate the frame offset (equal to the border_width on X).
434 // -- copied from qwidget_x11.cpp
436 int left = offset.x() + geom->border_width;
437 int top = offset.y() + geom->border_width;
438 int right = geom->width + geom->border_width - geometry().width() - offset.x();
439 int bottom = geom->height + geom->border_width - geometry().height() - offset.y();
441 m_frameMargins = QMargins(left, top, right, bottom);
448 m_dirtyFrameMargins = false;
451 return m_frameMargins;
454 void QXcbWindow::setVisible(bool visible)
462 void QXcbWindow::show()
464 if (window()->isTopLevel()) {
465 xcb_get_property_cookie_t cookie = xcb_get_wm_hints(xcb_connection(), m_window);
467 xcb_generic_error_t *error;
469 xcb_wm_hints_t hints;
470 xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, &error);
473 connection()->handleXcbError(error);
477 if (window()->windowState() & Qt::WindowMinimized)
478 xcb_wm_hints_set_iconic(&hints);
480 xcb_wm_hints_set_normal(&hints);
482 xcb_set_wm_hints(xcb_connection(), m_window, &hints);
484 // update WM_NORMAL_HINTS
485 propagateSizeHints();
487 // update WM_TRANSIENT_FOR
488 if (window()->transientParent() && isTransient(window())) {
489 QXcbWindow *transientXcbParent = static_cast<QXcbWindow *>(window()->transientParent()->handle());
490 if (transientXcbParent) {
492 xcb_window_t parentWindow = transientXcbParent->xcb_window();
494 // todo: set transient for group (wm_client_leader) if no parent, a la qwidget_x11.cpp
495 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
496 XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
501 // update _MOTIF_WM_HINTS
502 updateMotifWmHintsBeforeMap();
504 // update _NET_WM_STATE
505 updateNetWmStateBeforeMap();
508 Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
509 xcb_flush(xcb_connection());
511 connection()->sync();
514 void QXcbWindow::hide()
516 Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
518 // send synthetic UnmapNotify event according to icccm 4.1.4
519 xcb_unmap_notify_event_t event;
520 event.response_type = XCB_UNMAP_NOTIFY;
521 event.event = m_screen->root();
522 event.window = m_window;
523 event.from_configure = false;
524 Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_screen->root(),
525 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
527 xcb_flush(xcb_connection());
532 struct QtMotifWmHints {
533 quint32 flags, functions, decorations;
539 MWM_HINTS_FUNCTIONS = (1L << 0),
541 MWM_FUNC_ALL = (1L << 0),
542 MWM_FUNC_RESIZE = (1L << 1),
543 MWM_FUNC_MOVE = (1L << 2),
544 MWM_FUNC_MINIMIZE = (1L << 3),
545 MWM_FUNC_MAXIMIZE = (1L << 4),
546 MWM_FUNC_CLOSE = (1L << 5),
548 MWM_HINTS_DECORATIONS = (1L << 1),
550 MWM_DECOR_ALL = (1L << 0),
551 MWM_DECOR_BORDER = (1L << 1),
552 MWM_DECOR_RESIZEH = (1L << 2),
553 MWM_DECOR_TITLE = (1L << 3),
554 MWM_DECOR_MENU = (1L << 4),
555 MWM_DECOR_MINIMIZE = (1L << 5),
556 MWM_DECOR_MAXIMIZE = (1L << 6),
558 MWM_HINTS_INPUT_MODE = (1L << 2),
560 MWM_INPUT_MODELESS = 0L,
561 MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
562 MWM_INPUT_FULL_APPLICATION_MODAL = 3L
565 static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window)
567 QtMotifWmHints hints;
569 xcb_get_property_cookie_t get_cookie =
570 xcb_get_property(c->xcb_connection(), 0, window, c->atom(QXcbAtom::_MOTIF_WM_HINTS),
571 c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20);
573 xcb_generic_error_t *error;
575 xcb_get_property_reply_t *reply =
576 xcb_get_property_reply(c->xcb_connection(), get_cookie, &error);
578 if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) {
579 hints = *((QtMotifWmHints *)xcb_get_property_value(reply));
581 c->handleXcbError(error);
585 hints.functions = MWM_FUNC_ALL;
586 hints.decorations = MWM_DECOR_ALL;
587 hints.input_mode = 0L;
596 static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints)
598 if (hints.flags != 0l) {
599 Q_XCB_CALL2(xcb_change_property(c->xcb_connection(),
600 XCB_PROP_MODE_REPLACE,
602 c->atom(QXcbAtom::_MOTIF_WM_HINTS),
603 c->atom(QXcbAtom::_MOTIF_WM_HINTS),
608 Q_XCB_CALL2(xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)), c);
612 void QXcbWindow::printNetWmState(const QVector<xcb_atom_t> &state)
614 printf("_NET_WM_STATE (%d): ", state.size());
615 for (int i = 0; i < state.size(); ++i) {
616 #define CHECK_WM_STATE(state_atom) \
617 if (state.at(i) == atom(QXcbAtom::state_atom))\
618 printf(#state_atom " ");
619 CHECK_WM_STATE(_NET_WM_STATE_ABOVE)
620 CHECK_WM_STATE(_NET_WM_STATE_BELOW)
621 CHECK_WM_STATE(_NET_WM_STATE_FULLSCREEN)
622 CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_HORZ)
623 CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_VERT)
624 CHECK_WM_STATE(_NET_WM_STATE_MODAL)
625 CHECK_WM_STATE(_NET_WM_STATE_STAYS_ON_TOP)
626 CHECK_WM_STATE(_NET_WM_STATE_DEMANDS_ATTENTION)
627 #undef CHECK_WM_STATE
632 QVector<xcb_atom_t> QXcbWindow::getNetWmState()
634 QVector<xcb_atom_t> result;
636 xcb_get_property_cookie_t get_cookie =
637 xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
638 XCB_ATOM_ATOM, 0, 1024);
640 xcb_generic_error_t *error;
642 xcb_get_property_reply_t *reply =
643 xcb_get_property_reply(xcb_connection(), get_cookie, &error);
645 if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
646 result.resize(reply->length);
648 memcpy(result.data(), xcb_get_property_value(reply), reply->length * sizeof(xcb_atom_t));
650 #ifdef NET_WM_STATE_DEBUG
651 printf("getting net wm state (%x)\n", m_window);
652 printNetWmState(result);
657 connection()->handleXcbError(error);
660 #ifdef NET_WM_STATE_DEBUG
661 printf("getting net wm state (%x), empty\n", m_window);
668 void QXcbWindow::setNetWmState(const QVector<xcb_atom_t> &atoms)
670 if (atoms.isEmpty()) {
671 Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE)));
673 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
674 atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
675 atoms.count(), atoms.constData()));
677 xcb_flush(xcb_connection());
681 Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
683 Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
685 if (type == Qt::ToolTip)
686 flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
687 if (type == Qt::Popup)
688 flags |= Qt::X11BypassWindowManagerHint;
690 if (flags & Qt::WindowTransparentForInput) {
691 uint32_t mask = XCB_EVENT_MASK_NO_EVENT;
692 xcb_change_window_attributes(xcb_connection(), xcb_window(), XCB_CW_EVENT_MASK, &mask);
695 setNetWmWindowFlags(flags);
696 setMotifWindowFlags(flags);
698 setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
703 void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags)
705 Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
707 QtMotifWmHints mwmhints;
709 mwmhints.functions = 0L;
710 mwmhints.decorations = 0;
711 mwmhints.input_mode = 0L;
712 mwmhints.status = 0L;
714 if (type != Qt::SplashScreen) {
715 mwmhints.flags |= MWM_HINTS_DECORATIONS;
717 bool customize = flags & Qt::CustomizeWindowHint;
718 if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
719 mwmhints.decorations |= MWM_DECOR_BORDER;
720 mwmhints.decorations |= MWM_DECOR_RESIZEH;
722 if (flags & Qt::WindowTitleHint)
723 mwmhints.decorations |= MWM_DECOR_TITLE;
725 if (flags & Qt::WindowSystemMenuHint)
726 mwmhints.decorations |= MWM_DECOR_MENU;
728 if (flags & Qt::WindowMinimizeButtonHint) {
729 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
730 mwmhints.functions |= MWM_FUNC_MINIMIZE;
733 if (flags & Qt::WindowMaximizeButtonHint) {
734 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
735 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
738 if (flags & Qt::WindowCloseButtonHint)
739 mwmhints.functions |= MWM_FUNC_CLOSE;
742 // if type == Qt::SplashScreen
743 mwmhints.decorations = MWM_DECOR_ALL;
746 if (mwmhints.functions != 0) {
747 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
748 mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
750 mwmhints.functions = MWM_FUNC_ALL;
753 if (!(flags & Qt::FramelessWindowHint)
754 && flags & Qt::CustomizeWindowHint
755 && flags & Qt::WindowTitleHint
757 (Qt::WindowMinimizeButtonHint
758 | Qt::WindowMaximizeButtonHint
759 | Qt::WindowCloseButtonHint)))
761 // a special case - only the titlebar without any button
762 mwmhints.flags = MWM_HINTS_FUNCTIONS;
763 mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
764 mwmhints.decorations = 0;
767 setMotifWmHints(connection(), m_window, mwmhints);
770 void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
772 xcb_client_message_event_t event;
774 event.response_type = XCB_CLIENT_MESSAGE;
776 event.window = m_window;
777 event.type = atom(QXcbAtom::_NET_WM_STATE);
778 event.data.data32[0] = set ? 1 : 0;
779 event.data.data32[1] = one;
780 event.data.data32[2] = two;
781 event.data.data32[3] = 0;
782 event.data.data32[4] = 0;
784 Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
787 Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
789 if (state == m_windowState)
793 switch (m_windowState) {
794 case Qt::WindowMinimized:
795 Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
797 case Qt::WindowMaximized:
798 changeNetWmState(false,
799 atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
800 atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
802 case Qt::WindowFullScreen:
803 changeNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
811 case Qt::WindowMinimized:
813 xcb_client_message_event_t event;
815 event.response_type = XCB_CLIENT_MESSAGE;
817 event.window = m_window;
818 event.type = atom(QXcbAtom::WM_CHANGE_STATE);
819 event.data.data32[0] = XCB_WM_STATE_ICONIC;
820 event.data.data32[1] = 0;
821 event.data.data32[2] = 0;
822 event.data.data32[3] = 0;
823 event.data.data32[4] = 0;
825 Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
828 case Qt::WindowMaximized:
829 changeNetWmState(true,
830 atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
831 atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
833 case Qt::WindowFullScreen:
834 changeNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
836 case Qt::WindowNoState:
842 connection()->sync();
844 m_windowState = state;
845 return m_windowState;
848 void QXcbWindow::setNetWmWindowFlags(Qt::WindowFlags flags)
850 // in order of decreasing priority
851 QVector<uint> windowTypes;
853 Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
858 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
862 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
865 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
867 case Qt::SplashScreen:
868 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
874 if (flags & Qt::FramelessWindowHint)
875 windowTypes.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
877 windowTypes.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
879 Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
880 atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
881 windowTypes.count(), windowTypes.constData()));
884 void QXcbWindow::updateMotifWmHintsBeforeMap()
886 QtMotifWmHints mwmhints = getMotifWmHints(connection(), m_window);
888 if (window()->windowModality() != Qt::NonModal) {
889 switch (window()->windowModality()) {
890 case Qt::WindowModal:
891 mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
893 case Qt::ApplicationModal:
895 mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
898 mwmhints.flags |= MWM_HINTS_INPUT_MODE;
900 mwmhints.input_mode = MWM_INPUT_MODELESS;
901 mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
904 if (window()->minimumSize() == window()->maximumSize()) {
905 // fixed size, remove the resize handle (since mwm/dtwm
906 // isn't smart enough to do it itself)
907 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
908 if (mwmhints.functions == MWM_FUNC_ALL) {
909 mwmhints.functions = MWM_FUNC_MOVE;
911 mwmhints.functions &= ~MWM_FUNC_RESIZE;
914 if (mwmhints.decorations == MWM_DECOR_ALL) {
915 mwmhints.flags |= MWM_HINTS_DECORATIONS;
916 mwmhints.decorations = (MWM_DECOR_BORDER
920 mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
924 if (window()->windowFlags() & Qt::WindowMinimizeButtonHint) {
925 mwmhints.flags |= MWM_HINTS_DECORATIONS;
926 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
927 mwmhints.functions |= MWM_FUNC_MINIMIZE;
929 if (window()->windowFlags() & Qt::WindowMaximizeButtonHint) {
930 mwmhints.flags |= MWM_HINTS_DECORATIONS;
931 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
932 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
934 if (window()->windowFlags() & Qt::WindowCloseButtonHint)
935 mwmhints.functions |= MWM_FUNC_CLOSE;
937 setMotifWmHints(connection(), m_window, mwmhints);
940 void QXcbWindow::updateNetWmStateBeforeMap()
942 QVector<xcb_atom_t> netWmState;
944 Qt::WindowFlags flags = window()->windowFlags();
945 if (flags & Qt::WindowStaysOnTopHint) {
946 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
947 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
948 } else if (flags & Qt::WindowStaysOnBottomHint) {
949 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_BELOW));
952 if (window()->windowState() & Qt::WindowFullScreen) {
953 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
956 if (window()->windowState() & Qt::WindowMaximized) {
957 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
958 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
961 if (window()->windowModality() != Qt::NonModal) {
962 netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MODAL));
965 setNetWmState(netWmState);
968 void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
970 xcb_window_t wid = m_window;
972 const bool isSupportedByWM = connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
973 if (m_netWmUserTimeWindow || isSupportedByWM) {
974 if (!m_netWmUserTimeWindow) {
975 m_netWmUserTimeWindow = xcb_generate_id(xcb_connection());
976 Q_XCB_CALL(xcb_create_window(xcb_connection(),
977 XCB_COPY_FROM_PARENT, // depth -- same as root
978 m_netWmUserTimeWindow, // window id
979 m_window, // parent window id
982 XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
983 m_screen->screen()->root_visual, // visual
986 wid = m_netWmUserTimeWindow;
987 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW),
988 XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow);
989 xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME));
990 } else if (!isSupportedByWM) {
991 // WM no longer supports it, then we should remove the
992 // _NET_WM_USER_TIME_WINDOW atom.
993 xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
994 xcb_destroy_window(xcb_connection(), m_netWmUserTimeWindow);
995 m_netWmUserTimeWindow = XCB_NONE;
997 wid = m_netWmUserTimeWindow;
1000 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, wid, atom(QXcbAtom::_NET_WM_USER_TIME),
1001 XCB_ATOM_CARDINAL, 32, 1, ×tamp);
1004 void QXcbWindow::setTransparentForMouseEvents(bool transparent)
1006 if (transparent == m_transparent)
1009 xcb_rectangle_t rectangle;
1011 xcb_rectangle_t *rect = 0;
1017 rectangle.width = geometry().width();
1018 rectangle.height = geometry().height();
1023 xcb_xfixes_region_t region = xcb_generate_id(xcb_connection());
1024 xcb_xfixes_create_region(xcb_connection(), region, nrect, rect);
1025 xcb_xfixes_set_window_shape_region_checked(xcb_connection(), m_window, XCB_SHAPE_SK_INPUT, 0, 0, region);
1026 xcb_xfixes_destroy_region(xcb_connection(), region);
1028 m_transparent = transparent;
1032 WId QXcbWindow::winId() const
1037 void QXcbWindow::setParent(const QPlatformWindow *parent)
1039 // re-create for compatibility
1042 QPoint topLeft = geometry().topLeft();
1044 xcb_window_t xcb_parent_id = parent ? static_cast<const QXcbWindow *>(parent)->xcb_window() : m_screen->root();
1045 Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y()));
1048 void QXcbWindow::setWindowTitle(const QString &title)
1050 QByteArray ba = title.toUtf8();
1051 Q_XCB_CALL(xcb_change_property(xcb_connection(),
1052 XCB_PROP_MODE_REPLACE,
1054 atom(QXcbAtom::_NET_WM_NAME),
1055 atom(QXcbAtom::UTF8_STRING),
1061 void QXcbWindow::raise()
1063 const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
1064 const quint32 values[] = { XCB_STACK_MODE_ABOVE };
1065 Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
1068 void QXcbWindow::lower()
1070 const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
1071 const quint32 values[] = { XCB_STACK_MODE_BELOW };
1072 Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
1075 void QXcbWindow::propagateSizeHints()
1077 // update WM_NORMAL_HINTS
1078 xcb_size_hints_t hints;
1079 memset(&hints, 0, sizeof(hints));
1081 QRect rect = geometry();
1083 QWindow *win = window();
1085 xcb_size_hints_set_position(&hints, true, rect.x(), rect.y());
1086 xcb_size_hints_set_size(&hints, true, rect.width(), rect.height());
1087 xcb_size_hints_set_win_gravity(&hints, qt_window_private(win)->positionPolicy == QWindowPrivate::WindowFrameInclusive
1088 ? XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC);
1090 QSize minimumSize = win->minimumSize();
1091 QSize maximumSize = win->maximumSize();
1092 QSize baseSize = win->baseSize();
1093 QSize sizeIncrement = win->sizeIncrement();
1095 if (minimumSize.width() > 0 || minimumSize.height() > 0)
1096 xcb_size_hints_set_min_size(&hints, minimumSize.width(), minimumSize.height());
1098 if (maximumSize.width() < QWINDOWSIZE_MAX || maximumSize.height() < QWINDOWSIZE_MAX)
1099 xcb_size_hints_set_max_size(&hints,
1100 qMin(XCOORD_MAX, maximumSize.width()),
1101 qMin(XCOORD_MAX, maximumSize.height()));
1103 if (sizeIncrement.width() > 0 || sizeIncrement.height() > 0) {
1104 xcb_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height());
1105 xcb_size_hints_set_resize_inc(&hints, sizeIncrement.width(), sizeIncrement.height());
1108 xcb_set_wm_normal_hints(xcb_connection(), m_window, &hints);
1111 void QXcbWindow::requestActivateWindow()
1114 updateNetWmUserTime(connection()->time());
1115 Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()));
1117 connection()->sync();
1120 QSurfaceFormat QXcbWindow::format() const
1122 // ### return actual format
1123 return m_requestedFormat;
1126 #if defined(XCB_USE_EGL)
1127 QXcbEGLSurface *QXcbWindow::eglSurface() const
1129 if (!m_eglSurface) {
1130 EGLDisplay display = connection()->egl_display();
1131 EGLConfig config = q_configFromGLFormat(display, window()->format(), true);
1132 EGLSurface surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_window, 0);
1134 m_eglSurface = new QXcbEGLSurface(display, surface);
1137 return m_eglSurface;
1141 void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
1143 QRect rect(event->x, event->y, event->width, event->height);
1145 if (m_exposeRegion.isEmpty())
1146 m_exposeRegion = rect;
1148 m_exposeRegion |= rect;
1150 // if count is non-zero there are more expose events pending
1151 if (event->count == 0) {
1152 QWindowSystemInterface::handleSynchronousExposeEvent(window(), m_exposeRegion);
1153 m_exposeRegion = QRegion();
1157 void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *event)
1159 if (event->format != 32)
1162 if (event->type == atom(QXcbAtom::WM_PROTOCOLS)) {
1163 if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) {
1164 QWindowSystemInterface::handleCloseEvent(window());
1165 } else if (event->data.data32[0] == atom(QXcbAtom::WM_TAKE_FOCUS)) {
1166 connection()->setTime(event->data.data32[1]);
1167 } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_PING)) {
1168 xcb_client_message_event_t reply = *event;
1170 reply.response_type = XCB_CLIENT_MESSAGE;
1171 reply.window = m_screen->root();
1173 xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply);
1174 xcb_flush(xcb_connection());
1175 } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) {
1176 connection()->setTime(event->data.data32[1]);
1177 m_syncValue.lo = event->data.data32[2];
1178 m_syncValue.hi = event->data.data32[3];
1180 qWarning() << "unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]);
1182 } else if (event->type == atom(QXcbAtom::XdndEnter)) {
1183 connection()->drag()->handleEnter(window(), event);
1184 } else if (event->type == atom(QXcbAtom::XdndPosition)) {
1185 connection()->drag()->handlePosition(window(), event, false);
1186 } else if (event->type == atom(QXcbAtom::XdndLeave)) {
1187 connection()->drag()->handleLeave(window(), event, false);
1188 } else if (event->type == atom(QXcbAtom::XdndDrop)) {
1189 connection()->drag()->handleDrop(window(), event, false);
1191 qWarning() << "unhandled client message:" << connection()->atomName(event->type);
1195 void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event)
1197 QRect rect(event->x, event->y, event->width, event->height);
1199 QPlatformWindow::setGeometry(rect);
1200 QWindowSystemInterface::handleGeometryChange(window(), rect);
1202 m_dirtyFrameMargins = true;
1206 static_cast<QDri2Context *>(m_context)->resize(rect.size());
1210 void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event)
1212 if (event->window == m_window) {
1214 QWindowSystemInterface::handleMapEvent(window());
1218 void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
1220 if (event->window == m_window) {
1222 QWindowSystemInterface::handleUnmapEvent(window());
1226 static Qt::MouseButtons translateMouseButtons(int s)
1228 Qt::MouseButtons ret = 0;
1229 if (s & XCB_BUTTON_MASK_1)
1230 ret |= Qt::LeftButton;
1231 if (s & XCB_BUTTON_MASK_2)
1232 ret |= Qt::MidButton;
1233 if (s & XCB_BUTTON_MASK_3)
1234 ret |= Qt::RightButton;
1238 static Qt::MouseButton translateMouseButton(xcb_button_t s)
1242 return Qt::LeftButton;
1244 return Qt::MidButton;
1246 return Qt::RightButton;
1248 return Qt::NoButton;
1252 void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
1254 updateNetWmUserTime(event->time);
1256 QPoint local(event->event_x, event->event_y);
1257 QPoint global(event->root_x, event->root_y);
1259 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
1261 if (event->detail >= 4 && event->detail <= 7) {
1262 //logic borrowed from qapplication_x11.cpp
1263 int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
1264 bool hor = (((event->detail == 4 || event->detail == 5)
1265 && (modifiers & Qt::AltModifier))
1266 || (event->detail == 6 || event->detail == 7));
1268 QWindowSystemInterface::handleWheelEvent(window(), event->time,
1269 local, global, delta, hor ? Qt::Horizontal : Qt::Vertical);
1273 handleMouseEvent(event->detail, event->state, event->time, local, global);
1276 void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
1278 QPoint local(event->event_x, event->event_y);
1279 QPoint global(event->root_x, event->root_y);
1281 handleMouseEvent(event->detail, event->state, event->time, local, global);
1284 void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
1286 QPoint local(event->event_x, event->event_y);
1287 QPoint global(event->root_x, event->root_y);
1289 handleMouseEvent(event->detail, event->state, event->time, local, global);
1292 void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global)
1294 connection()->setTime(time);
1296 Qt::MouseButtons buttons = translateMouseButtons(state);
1297 Qt::MouseButton button = translateMouseButton(detail);
1299 buttons ^= button; // X event uses state *before*, Qt uses state *after*
1301 QWindowSystemInterface::handleMouseEvent(window(), time, local, global, buttons);
1304 void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
1306 connection()->setTime(event->time);
1308 if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
1309 || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
1310 || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL)
1315 QWindowSystemInterface::handleEnterEvent(window());
1318 void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
1320 connection()->setTime(event->time);
1322 if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
1323 || event->detail == XCB_NOTIFY_DETAIL_INFERIOR)
1328 QWindowSystemInterface::handleLeaveEvent(window());
1331 void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *)
1333 QWindowSystemInterface::handleWindowActivated(window());
1336 static bool focusInPeeker(xcb_generic_event_t *event)
1339 // FocusIn event is not in the queue, proceed with FocusOut normally.
1340 QWindowSystemInterface::handleWindowActivated(0);
1343 uint response_type = event->response_type & ~0x80;
1344 return response_type == XCB_FOCUS_IN;
1347 void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *)
1349 // Do not set the active window to 0 if there is a FocusIn coming.
1350 // There is however no equivalent for XPutBackEvent so register a
1351 // callback for QXcbConnection instead.
1352 connection()->addPeekFunc(focusInPeeker);
1355 void QXcbWindow::updateSyncRequestCounter()
1357 if (m_screen->syncRequestSupported() && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
1358 Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue));
1359 xcb_flush(xcb_connection());
1360 connection()->sync();
1367 bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
1370 xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME);
1373 xcb_grab_keyboard_cookie_t cookie = xcb_grab_keyboard(xcb_connection(), false,
1374 m_window, XCB_TIME_CURRENT_TIME,
1375 XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
1376 xcb_generic_error_t *err;
1377 xcb_grab_keyboard_reply_t *reply = xcb_grab_keyboard_reply(xcb_connection(), cookie, &err);
1378 bool result = !(err || !reply || reply->status != XCB_GRAB_STATUS_SUCCESS);
1384 bool QXcbWindow::setMouseGrabEnabled(bool grab)
1387 xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME);
1390 xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(xcb_connection(), false, m_window,
1391 (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
1392 | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW
1393 | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION),
1394 XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
1395 XCB_WINDOW_NONE, XCB_CURSOR_NONE,
1396 XCB_TIME_CURRENT_TIME);
1397 xcb_generic_error_t *err;
1398 xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, &err);
1399 bool result = !(err || !reply || reply->status != XCB_GRAB_STATUS_SUCCESS);
1405 void QXcbWindow::setCursor(xcb_cursor_t cursor)
1407 xcb_change_window_attributes(xcb_connection(), m_window, XCB_CW_CURSOR, &cursor);
1408 xcb_flush(xcb_connection());