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 QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
44 #include "qdesktopwidget.h"
45 #include "qapplication.h"
46 #include "qapplication_p.h"
47 #include "qnamespace.h"
51 #include "qtextcodec.h"
52 #include "qelapsedtimer.h"
55 #include "qcolormap.h"
58 #include "private/qmenu_p.h"
59 #include "private/qbackingstore_p.h"
60 #include "private/qwindowsurface_x11_p.h"
62 //extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp
64 #include <private/qpixmap_x11_p.h>
65 #include <private/qpaintengine_x11_p.h>
67 #include "qx11info_x11.h"
73 // defined in qapplication_x11.cpp
74 //bool qt_wstate_iconified(WId);
75 //void qt_updated_rootinfo();
78 #if !defined(QT_NO_IM)
79 #include "qinputcontext.h"
80 #include "qinputcontextfactory.h"
83 #include "qwidget_p.h"
85 #define XCOORD_MAX 16383
86 #define WRECT_MAX 8191
90 extern bool qt_nograb();
92 QWidget *QWidgetPrivate::mouseGrabber = 0;
93 QWidget *QWidgetPrivate::keyboardGrabber = 0;
95 void qt_net_remove_user_time(QWidget *tlw);
96 void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
98 int qt_x11_create_desktop_on_screen = -1;
100 extern void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
104 ulong flags, functions, decorations;
110 MWM_HINTS_FUNCTIONS = (1L << 0),
112 MWM_FUNC_ALL = (1L << 0),
113 MWM_FUNC_RESIZE = (1L << 1),
114 MWM_FUNC_MOVE = (1L << 2),
115 MWM_FUNC_MINIMIZE = (1L << 3),
116 MWM_FUNC_MAXIMIZE = (1L << 4),
117 MWM_FUNC_CLOSE = (1L << 5),
119 MWM_HINTS_DECORATIONS = (1L << 1),
121 MWM_DECOR_ALL = (1L << 0),
122 MWM_DECOR_BORDER = (1L << 1),
123 MWM_DECOR_RESIZEH = (1L << 2),
124 MWM_DECOR_TITLE = (1L << 3),
125 MWM_DECOR_MENU = (1L << 4),
126 MWM_DECOR_MINIMIZE = (1L << 5),
127 MWM_DECOR_MAXIMIZE = (1L << 6),
129 MWM_HINTS_INPUT_MODE = (1L << 2),
131 MWM_INPUT_MODELESS = 0L,
132 MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
133 MWM_INPUT_FULL_APPLICATION_MODAL = 3L
137 static QtMWMHints GetMWMHints(Display *display, Window window)
143 ulong nitems, bytesLeft;
145 if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
146 ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
148 && (type == ATOM(_MOTIF_WM_HINTS)
151 mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
154 mwmhints.functions = MWM_FUNC_ALL;
155 mwmhints.decorations = MWM_DECOR_ALL;
156 mwmhints.input_mode = 0L;
157 mwmhints.status = 0L;
166 static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints)
168 if (mwmhints.flags != 0l) {
169 XChangeProperty(display, window, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
170 PropModeReplace, (unsigned char *) &mwmhints, 5);
172 XDeleteProperty(display, window, ATOM(_MOTIF_WM_HINTS));
176 // Returns true if we should set WM_TRANSIENT_FOR on \a w
177 static inline bool isTransient(const QWidget *w)
179 return ((w->windowType() == Qt::Dialog
180 || w->windowType() == Qt::Sheet
181 || w->windowType() == Qt::Tool
182 || w->windowType() == Qt::SplashScreen
183 || w->windowType() == Qt::ToolTip
184 || w->windowType() == Qt::Drawer
185 || w->windowType() == Qt::Popup)
186 && !w->testAttribute(Qt::WA_X11BypassTransientForHint));
189 static void do_size_hints(QWidget* widget, QWExtra *x);
191 /*****************************************************************************
192 QWidget member functions
193 *****************************************************************************/
195 const uint stdWidgetEventMask = // X event mask
197 KeyPressMask | KeyReleaseMask |
198 ButtonPressMask | ButtonReleaseMask |
200 ButtonMotionMask | PointerMotionMask |
201 EnterWindowMask | LeaveWindowMask |
208 const uint stdDesktopEventMask = // X event mask
211 EnterWindowMask | LeaveWindowMask |
217 The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
220 Window qt_XCreateWindow(const QWidget *creator,
221 Display *display, Window parent,
222 int x, int y, uint w, uint h,
223 int borderwidth, int depth,
224 uint windowclass, Visual *visual,
225 ulong valuemask, XSetWindowAttributes *attributes);
226 Window qt_XCreateSimpleWindow(const QWidget *creator,
227 Display *display, Window parent,
228 int x, int y, uint w, uint h, int borderwidth,
229 ulong border, ulong background);
230 void qt_XDestroyWindow(const QWidget *destroyer,
231 Display *display, Window window);
234 static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
236 if (!scrolled_widget->isWindow() && !scrolled_widget->internalWinId())
238 QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
239 X11->sip_list.append(sip);
241 XClientMessageEvent client_message;
242 client_message.type = ClientMessage;
243 client_message.window = scrolled_widget->internalWinId();
244 client_message.format = 32;
245 client_message.message_type = ATOM(_QT_SCROLL_DONE);
246 client_message.data.l[0] = sip.id;
248 XSendEvent(X11->display, scrolled_widget->internalWinId(), False, NoEventMask,
249 (XEvent*)&client_message);
252 static int qt_sip_count(QWidget* scrolled_widget)
256 for (int i = 0; i < X11->sip_list.size(); ++i) {
257 const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
258 if (sip.scrolled_widget == scrolled_widget)
265 static void create_wm_client_leader()
267 if (X11->wm_client_leader) return;
269 X11->wm_client_leader =
270 XCreateSimpleWindow(X11->display,
271 QX11Info::appRootWindow(),
272 0, 0, 1, 1, 0, 0, 0);
274 // set client leader property to itself
275 XChangeProperty(X11->display,
276 X11->wm_client_leader, ATOM(WM_CLIENT_LEADER),
277 XA_WINDOW, 32, PropModeReplace,
278 (unsigned char *)&X11->wm_client_leader, 1);
280 #ifndef QT_NO_SESSIONMANAGER
281 // If we are session managed, inform the window manager about it
282 QByteArray session = qApp->sessionId().toLatin1();
283 if (!session.isEmpty()) {
284 XChangeProperty(X11->display,
285 X11->wm_client_leader, ATOM(SM_CLIENT_ID),
286 XA_STRING, 8, PropModeReplace,
287 (unsigned char *)session.data(), session.size());
294 Update the X11 cursor of the widget w.
295 \a force is true if this function is called from dispatchEnterLeave, it means that the
296 mouse is actually directly under this widget.
298 void qt_x11_enforce_cursor(QWidget * w, bool force)
300 if (!w->testAttribute(Qt::WA_WState_Created))
303 static QPointer<QWidget> lastUnderMouse = 0;
306 } else if (lastUnderMouse && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
308 } else if (!w->internalWinId()) {
309 return; //the mouse is not under this widget, and it's not native, so don't change it
312 while (!w->internalWinId() && w->parentWidget() && !w->isWindow() && !w->testAttribute(Qt::WA_SetCursor))
313 w = w->parentWidget();
315 QWidget *nativeParent = w;
316 if (!w->internalWinId())
317 nativeParent = w->nativeParentWidget();
318 // This does the same as effectiveWinId(), but since it is possible
319 // to not have a native parent widget due to a special hack in
320 // qwidget for reparenting widgets to a different X11 screen,
321 // added additional check to make sure native parent widget exists.
322 if (!nativeParent || !nativeParent->internalWinId())
324 WId winid = nativeParent->internalWinId();
326 if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
328 QCursor *oc = QApplication::overrideCursor();
330 XDefineCursor(X11->display, winid, oc->handle());
331 } else if (w->isEnabled()) {
332 XDefineCursor(X11->display, winid, w->cursor().handle());
334 // enforce the windows behavior of clearing the cursor on
336 XDefineCursor(X11->display, winid, XNone);
340 XDefineCursor(X11->display, winid, XNone);
344 Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
346 qt_x11_enforce_cursor(w, false);
349 void qt_x11_wait_for_window_manager(QWidget *w, bool sendPostedEvents)
351 if (!w || (!w->isWindow() && !w->internalWinId()))
353 QApplication::flush();
357 static const int maximumWaitTime = 2000;
358 if (!w->testAttribute(Qt::WA_WState_Created))
361 WId winid = w->internalWinId();
363 // first deliver events that are already in the local queue
364 if (sendPostedEvents)
365 QApplication::sendPostedEvents();
367 // the normal sequence is:
368 // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
369 // with X11BypassWindowManagerHint:
370 // ConfigureNotify ... MapNotify ... Expose
377 if (XEventsQueued(X11->display, QueuedAlready)) {
378 XNextEvent(X11->display, &ev);
379 qApp->x11ProcessEvent(&ev);
383 if (ev.type == MapNotify && ev.xany.window == winid)
387 if (ev.type == Expose && ev.xany.window == winid)
392 if (!XEventsQueued(X11->display, QueuedAfterFlush))
393 qApp->syncX(); // non-busy wait
395 if (t.elapsed() > maximumWaitTime)
400 Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget *w)
402 qt_x11_wait_for_window_manager(w, true);
405 void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
407 if (!w->isVisible()) // not managed by the window manager
411 e.xclient.type = ClientMessage;
412 e.xclient.message_type = ATOM(_NET_WM_STATE);
413 e.xclient.display = X11->display;
414 e.xclient.window = w->internalWinId();
415 e.xclient.format = 32;
416 e.xclient.data.l[0] = set ? 1 : 0;
417 e.xclient.data.l[1] = one;
418 e.xclient.data.l[2] = two;
419 e.xclient.data.l[3] = 0;
420 e.xclient.data.l[4] = 0;
421 XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()),
422 false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
425 struct QX11WindowAttributes {
426 const XWindowAttributes *att;
429 void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a)
431 QX11WindowAttributes att;
433 qt_x11_getX11InfoForWindow(xinfo,att);
437 static QVector<Atom> getNetWmState(QWidget *w)
439 QVector<Atom> returnValue;
441 // Don't read anything, just get the size of the property data
444 ulong propertyLength;
446 uchar *propertyData = 0;
447 if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, 0,
448 False, XA_ATOM, &actualType, &actualFormat,
449 &propertyLength, &bytesLeft, &propertyData) == Success
450 && actualType == XA_ATOM && actualFormat == 32) {
451 returnValue.resize(bytesLeft / 4);
452 XFree((char*) propertyData);
456 if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0,
457 returnValue.size(), False, XA_ATOM, &actualType, &actualFormat,
458 &propertyLength, &bytesLeft, &propertyData) != Success) {
460 } else if (propertyLength != (ulong)returnValue.size()) {
461 returnValue.resize(propertyLength);
464 // put it into netWmState
465 if (!returnValue.isEmpty()) {
466 memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
469 XFree((char*) propertyData);
475 void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
478 Qt::WindowType type = q->windowType();
479 Qt::WindowFlags &flags = data.window_flags;
480 QWidget *parentWidget = q->parentWidget();
482 if (type == Qt::ToolTip)
483 flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
484 if (type == Qt::Popup)
485 flags |= Qt::X11BypassWindowManagerHint;
487 bool topLevel = (flags & Qt::Window);
488 bool popup = (type == Qt::Popup);
489 bool desktop = (type == Qt::Desktop);
490 bool tool = (type == Qt::Tool || type == Qt::SplashScreen
491 || type == Qt::ToolTip || type == Qt::Drawer);
494 qDebug() << "QWidgetPrivate::create_sys START:" << q << "topLevel?" << topLevel << "WId:"
495 << window << "initializeWindow:" << initializeWindow << "destroyOldWindow" << destroyOldWindow;
498 if (parentWidget) { // if our parent stays on top, so must we
499 QWidget *ptl = parentWidget->window();
500 if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
501 flags |= Qt::WindowStaysOnTopHint;
504 if (type == Qt::SplashScreen) {
505 if (X11->isSupportedByWM(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
506 flags &= ~Qt::X11BypassWindowManagerHint;
508 flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
511 // All these buttons depend on the system menu, so we enable it
512 if (flags & (Qt::WindowMinimizeButtonHint
513 | Qt::WindowMaximizeButtonHint
514 | Qt::WindowContextHelpButtonHint))
515 flags |= Qt::WindowSystemMenuHint;
519 Window parentw, destroyw = 0;
524 initializeWindow = true;
526 QX11Info *parentXinfo = parentWidget ? &parentWidget->d_func()->xinfo : 0;
529 qt_x11_create_desktop_on_screen >= 0 &&
530 qt_x11_create_desktop_on_screen != xinfo.screen()) {
531 // desktop on a certain screen other than the default requested
532 QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen];
533 xinfo.setX11Data(xd);
534 } else if (parentXinfo && (parentXinfo->screen() != xinfo.screen()
535 || (parentXinfo->visual() != xinfo.visual()
536 && !q->inherits("QGLWidget"))))
538 // QGLWidgets have to be excluded here as they have a
539 // specially crafted QX11Info structure which can't be swapped
540 // out with the parent widgets QX11Info. The parent visual,
541 // for instance, might not even be GL capable.
542 xinfo = *parentXinfo;
545 //get display, screen number, root window and desktop geometry for
547 Display *dpy = X11->display;
548 int scr = xinfo.screen();
549 Window root_win = RootWindow(dpy, scr);
550 int sw = DisplayWidth(dpy,scr);
551 int sh = DisplayHeight(dpy,scr);
553 if (desktop) { // desktop widget
554 popup = false; // force these flags off
555 data.crect.setRect(0, 0, sw, sh);
556 } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
557 QDesktopWidget *desktopWidget = qApp->desktop();
558 if (desktopWidget->isVirtualDesktop()) {
559 QRect r = desktopWidget->screenGeometry();
565 int height = 4 * sh / 10;
567 width = qMax(qMin(width, extra->maxw), extra->minw);
568 height = qMax(qMin(height, extra->maxh), extra->minh);
570 data.crect.setSize(QSize(width, height));
573 parentw = topLevel ? root_win : parentWidget->effectiveWinId();
575 XSetWindowAttributes wsa;
577 if (window) { // override the old window
578 if (destroyOldWindow) {
580 X11->dndEnable(q, false);
581 destroyw = data.winid;
586 XGetWindowAttributes(dpy, window, &a);
587 data.crect.setRect(a.x, a.y, a.width, a.height);
589 if (a.map_state == IsUnmapped)
590 q->setAttribute(Qt::WA_WState_Visible, false);
592 q->setAttribute(Qt::WA_WState_Visible);
594 qt_x11_getX11InfoForWindow(&xinfo,a);
596 } else if (desktop) { // desktop widget
597 #ifdef QWIDGET_EXTRA_DEBUG
598 qDebug() << "create desktop";
600 id = (WId)parentw; // id = root window
601 // QWidget *otherDesktop = find(id); // is there another desktop?
602 // if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
603 // otherDesktop->d->setWinId(0); // remove id from widget mapper
604 // d->setWinId(id); // make sure otherDesktop is
605 // otherDesktop->d->setWinId(id); // found first
609 } else if (topLevel || q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) {
610 #ifdef QWIDGET_EXTRA_DEBUG
611 static int topLevels = 0;
612 static int children = 0;
613 if (parentw == root_win)
614 qDebug() << "create toplevel" << ++topLevels;
616 qDebug() << "create child" << ++children;
618 QRect safeRect = data.crect; //##### must handle huge sizes as well.... i.e. wrect
619 if (safeRect.width() < 1|| safeRect.height() < 1) {
621 // top-levels must be at least 1x1
622 safeRect.setSize(safeRect.size().expandedTo(QSize(1, 1)));
624 // create it way off screen, and rely on
625 // setWSGeometry() to do the right thing with it later
626 safeRect = QRect(-1000,-1000,1,1);
629 #ifndef QT_NO_XRENDER
630 int screen = xinfo.screen();
631 if (topLevel && X11->use_xrender
632 && xinfo.depth() != 32 && X11->argbVisuals[screen]
633 && q->testAttribute(Qt::WA_TranslucentBackground))
635 QX11InfoData *xd = xinfo.getX11Data(true);
638 xd->visual = X11->argbVisuals[screen];
639 xd->colormap = X11->argbColormaps[screen];
641 xd->defaultVisual = false;
642 xd->defaultColormap = false;
643 xd->cells = xd->visual->map_entries;
644 xinfo.setX11Data(xd);
647 if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
648 id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
649 safeRect.left(), safeRect.top(),
650 safeRect.width(), safeRect.height(),
652 BlackPixel(dpy, xinfo.screen()),
653 WhitePixel(dpy, xinfo.screen()));
655 wsa.background_pixel = WhitePixel(dpy, xinfo.screen());
656 wsa.border_pixel = BlackPixel(dpy, xinfo.screen());
657 wsa.colormap = xinfo.colormap();
658 id = (WId)qt_XCreateWindow(q, dpy, parentw,
659 safeRect.left(), safeRect.top(),
660 safeRect.width(), safeRect.height(),
661 0, xinfo.depth(), InputOutput,
662 (Visual *) xinfo.visual(),
663 CWBackPixel|CWBorderPixel|CWColormap,
667 setWinId(id); // set widget id/handle + hd
670 #ifndef QT_NO_XRENDER
672 XRenderFreePicture(X11->display, picture);
676 if (X11->use_xrender && !desktop && q->internalWinId()) {
677 XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual());
679 picture = XRenderCreatePicture(dpy, id, format, 0, 0);
681 #endif // QT_NO_XRENDER
685 mwmhints.functions = 0L;
686 mwmhints.decorations = 0;
687 mwmhints.input_mode = 0L;
688 mwmhints.status = 0L;
692 if (type != Qt::SplashScreen) { // && customize) {
693 mwmhints.flags |= MWM_HINTS_DECORATIONS;
695 bool customize = flags & Qt::CustomizeWindowHint;
696 if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
697 mwmhints.decorations |= MWM_DECOR_BORDER;
698 mwmhints.decorations |= MWM_DECOR_RESIZEH;
700 if (flags & Qt::WindowTitleHint)
701 mwmhints.decorations |= MWM_DECOR_TITLE;
703 if (flags & Qt::WindowSystemMenuHint)
704 mwmhints.decorations |= MWM_DECOR_MENU;
706 if (flags & Qt::WindowMinimizeButtonHint) {
707 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
708 mwmhints.functions |= MWM_FUNC_MINIMIZE;
711 if (flags & Qt::WindowMaximizeButtonHint) {
712 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
713 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
716 if (flags & Qt::WindowCloseButtonHint)
717 mwmhints.functions |= MWM_FUNC_CLOSE;
720 // if type == Qt::SplashScreen
721 mwmhints.decorations = MWM_DECOR_ALL;
725 wsa.save_under = True;
726 wsa_mask |= CWSaveUnder;
729 if (flags & Qt::X11BypassWindowManagerHint) {
730 wsa.override_redirect = True;
731 wsa_mask |= CWOverrideRedirect;
734 if (wsa_mask && initializeWindow) {
736 XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
739 if (mwmhints.functions != 0) {
740 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
741 mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
743 mwmhints.functions = MWM_FUNC_ALL;
746 if (!(flags & Qt::FramelessWindowHint)
747 && flags & Qt::CustomizeWindowHint
748 && flags & Qt::WindowTitleHint
750 (Qt::WindowMinimizeButtonHint
751 | Qt::WindowMaximizeButtonHint
752 | Qt::WindowCloseButtonHint))) {
753 // a special case - only the titlebar without any button
754 mwmhints.flags = MWM_HINTS_FUNCTIONS;
755 mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
756 mwmhints.decorations = 0;
760 if (!initializeWindow) {
761 // do no initialization
762 } else if (popup) { // popup widget
763 // set EWMH window types
764 setNetWmWindowTypes();
766 wsa.override_redirect = True;
767 wsa.save_under = True;
769 XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
771 } else if (topLevel && !desktop) { // top-level widget
772 if (!X11->wm_client_leader)
773 create_wm_client_leader();
775 // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys()
777 XSizeHints size_hints;
778 size_hints.flags = USSize | PSize | PWinGravity;
779 size_hints.x = data.crect.left();
780 size_hints.y = data.crect.top();
781 size_hints.width = data.crect.width();
782 size_hints.height = data.crect.height();
783 size_hints.win_gravity =
784 QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
786 XWMHints wm_hints; // window manager hints
787 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
788 wm_hints.flags = InputHint | StateHint | WindowGroupHint;
789 wm_hints.input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
790 wm_hints.initial_state = NormalState;
791 wm_hints.window_group = X11->wm_client_leader;
793 XClassHint class_hint;
794 QByteArray appName = qAppName().toLatin1();
795 class_hint.res_name = appName.data(); // application name
796 class_hint.res_class = const_cast<char *>(QX11Info::appClass()); // application class
798 XSetWMProperties(dpy, id, 0, 0,
799 qApp->d_func()->argv, qApp->d_func()->argc,
800 &size_hints, &wm_hints, &class_hint);
802 XResizeWindow(dpy, id,
803 qBound(1, data.crect.width(), XCOORD_MAX),
804 qBound(1, data.crect.height(), XCOORD_MAX));
805 XStoreName(dpy, id, appName.data());
808 protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
809 protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
810 protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
812 protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
813 #endif // QT_NO_XSYNC
814 if (flags & Qt::WindowContextHelpButtonHint)
815 protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
816 XSetWMProtocols(dpy, id, protocols, n);
819 SetMWMHints(dpy, id, mwmhints);
821 // set EWMH window types
822 setNetWmWindowTypes();
825 long curr_pid = getpid();
826 XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
827 (unsigned char *) &curr_pid, 1);
829 // when we create a toplevel widget, the frame strut should be dirty
830 data.fstrut_dirty = 1;
832 // declare the widget's window role
833 if (QTLWExtra *topData = maybeTopData()) {
834 if (!topData->role.isEmpty()) {
835 QByteArray windowRole = topData->role.toUtf8();
836 XChangeProperty(dpy, id,
837 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
838 (unsigned char *)windowRole.constData(), windowRole.length());
842 // set client leader property
843 XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
844 XA_WINDOW, 32, PropModeReplace,
845 (unsigned char *)&X11->wm_client_leader, 1);
847 // non-toplevel widgets don't have a frame, so no need to
849 data.fstrut_dirty = 0;
852 if (initializeWindow && q->internalWinId()) {
853 // don't erase when resizing
854 wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
856 XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
859 // set X11 event mask
861 // QWidget* main_desktop = find(id);
862 // if (main_desktop->testWFlags(Qt::WPaintDesktop))
863 // XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
865 XSelectInput(dpy, id, stdDesktopEventMask);
866 } else if (q->internalWinId()) {
867 XSelectInput(dpy, id, stdWidgetEventMask);
868 #if !defined (QT_NO_TABLET)
869 QTabletDeviceDataList *tablet_list = qt_tablet_devices();
870 if (X11->ptrXSelectExtensionEvent) {
871 for (int i = 0; i < tablet_list->size(); ++i) {
872 QTabletDeviceData tablet = tablet_list->at(i);
873 X11->ptrXSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList),
881 q->setAttribute(Qt::WA_WState_Visible);
882 } else if (topLevel) { // set X cursor
883 if (initializeWindow) {
884 qt_x11_enforce_cursor(q);
886 if (QTLWExtra *topData = maybeTopData())
887 if (!topData->caption.isEmpty())
888 setWindowTitle_helper(topData->caption);
890 //always enable dnd: it's not worth the effort to maintain the state
891 // NOTE: this always creates topData()
892 X11->dndEnable(q, true);
894 if (maybeTopData() && maybeTopData()->opacity != 255)
895 q->setWindowOpacity(maybeTopData()->opacity/255.);
898 } else if (q->internalWinId()) {
899 qt_x11_enforce_cursor(q);
900 if (QWidget *p = q->parentWidget()) // reset the cursor on the native parent
901 qt_x11_enforce_cursor(p);
904 if (extra && !extra->mask.isEmpty() && q->internalWinId())
905 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
906 extra->mask.handle(), ShapeSet);
908 if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
909 QInputContext *inputContext = q->inputContext();
911 inputContext->setFocusWidget(q);
915 qt_XDestroyWindow(q, dpy, destroyw);
916 if (QTLWExtra *topData = maybeTopData()) {
918 if (topData->syncUpdateCounter)
919 XSyncDestroyCounter(dpy, topData->syncUpdateCounter);
921 // we destroyed our old window - reset the top-level state
926 // newly created windows are positioned at the window system's
927 // (0,0) position. If the parent uses wrect mapping to expand the
928 // coordinate system, we must also adjust this widget's window
930 if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
932 else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0))
933 q->setAttribute(Qt::WA_OutsideWSRange, true);
935 if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
936 Q_ASSERT(q->internalWinId());
937 XMapWindow(X11->display, q->internalWinId());
938 // Ensure that mapped alien widgets are flushed immediately when re-created as native widgets.
939 if (QWindowSurface *surface = q->windowSurface())
940 surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint()));
944 qDebug() << "QWidgetPrivate::create_sys END:" << q;
948 static void qt_x11_recreateWidget(QWidget *widget)
950 if (widget->inherits("QGLWidget")) {
951 // We send QGLWidgets a ParentChange event which causes them to
952 // recreate their GL context, which in turn causes them to choose
953 // their visual again. Now that WA_TranslucentBackground is set,
954 // QGLContext::chooseVisual will select an ARGB visual.
955 QEvent e(QEvent::ParentChange);
956 QApplication::sendEvent(widget, &e);
958 // For regular widgets, reparent them with their parent which
959 // also triggers a recreation of the native window
960 QPoint pos = widget->pos();
961 bool visible = widget->isVisible();
965 widget->setParent(widget->parentWidget(), widget->windowFlags());
972 static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget)
974 if (widget->internalWinId())
975 qt_x11_recreateWidget(widget);
977 const QObjectList &children = widget->children();
978 for (int i = 0; i < children.size(); ++i) {
979 QWidget *child = qobject_cast<QWidget*>(children.at(i));
981 qt_x11_recreateNativeWidgetsRecursive(child);
985 void QWidgetPrivate::x11UpdateIsOpaque()
987 #ifndef QT_NO_XRENDER
989 if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
992 bool topLevel = (data.window_flags & Qt::Window);
993 int screen = xinfo.screen();
994 if (topLevel && X11->use_xrender
995 && X11->argbVisuals[screen] && xinfo.depth() != 32)
997 qt_x11_recreateNativeWidgetsRecursive(q);
1003 Returns true if the background is inherited; otherwise returns
1006 Mainly used in the paintOnScreen case.
1008 bool QWidgetPrivate::isBackgroundInherited() const
1012 // windows do not inherit their background
1013 if (q->isWindow() || q->windowType() == Qt::SubWindow)
1016 if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
1019 const QPalette &pal = q->palette();
1020 QPalette::ColorRole bg = q->backgroundRole();
1021 QBrush brush = pal.brush(bg);
1023 // non opaque brushes leaves us no choice, we must inherit
1024 if (!q->autoFillBackground() || !brush.isOpaque())
1027 if (brush.style() == Qt::SolidPattern) {
1028 // the background is just a solid color. If there is no
1029 // propagated contents, then we claim as performance
1030 // optimization that it was not inheritet. This is the normal
1031 // case in standard Windows or Motif style.
1032 const QWidget *w = q->parentWidget();
1033 if (!w->d_func()->isBackgroundInherited())
1040 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
1043 d->aboutToDestroy();
1044 if (!isWindow() && parentWidget())
1045 parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
1046 d->deactivateWidgetCleanup();
1047 if (testAttribute(Qt::WA_WState_Created)) {
1048 setAttribute(Qt::WA_WState_Created, false);
1049 QObjectList childList = children();
1050 for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
1051 register QObject *obj = childList.at(i);
1052 if (obj->isWidgetType())
1053 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
1056 if (QWidgetPrivate::mouseGrabber == this)
1058 if (QWidgetPrivate::keyboardGrabber == this)
1061 X11->deferred_map.removeAll(this);
1063 // just be sure we leave modal
1064 QApplicationPrivate::leaveModal(this);
1066 else if ((windowType() == Qt::Popup))
1067 qApp->d_func()->closePopup(this);
1069 #ifndef QT_NO_XRENDER
1072 XRenderFreePicture(X11->display, d->picture);
1075 #endif // QT_NO_XRENDER
1077 // delete the _NET_WM_USER_TIME_WINDOW
1078 qt_net_remove_user_time(this);
1080 if ((windowType() == Qt::Desktop)) {
1082 X11->dndEnable(this, false);
1085 X11->dndEnable(this, false);
1087 qt_XDestroyWindow(this, X11->display, data->winid);
1091 } QT_CATCH (const std::bad_alloc &) {
1092 // swallow - destructors must not throw
1095 extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
1096 if (testAttribute(Qt::WA_WState_Reparented))
1102 // release previous focus information participating with
1103 // preedit preservation of qic
1104 QInputContext *qic = QApplicationPrivate::inputContext;
1106 qic->widgetDestroyed(this);
1111 void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
1115 qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent;
1117 QX11Info old_xinfo = xinfo;
1118 if (parent && parent->windowType() == Qt::Desktop) {
1119 // make sure the widget is created on the same screen as the
1120 // programmer specified desktop widget
1121 xinfo = parent->d_func()->xinfo;
1125 QTLWExtra *topData = maybeTopData();
1126 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
1127 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
1128 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
1129 extern void qPRCreate(const QWidget *, Window);
1130 #ifndef QT_NO_CURSOR
1134 // dnd unregister (we will register again below)
1135 if (q->testAttribute(Qt::WA_DropSiteRegistered))
1136 q->setAttribute(Qt::WA_DropSiteRegistered, false);
1138 // if we are a top then remove our dnd prop for now
1139 // it will get rest later
1140 if (q->isWindow() && wasCreated)
1141 X11->dndEnable(q, false);
1144 qt_net_remove_user_time(q);
1146 // QWidget *oldparent = q->parentWidget();
1147 WId old_winid = wasCreated ? data.winid : 0;
1148 if ((q->windowType() == Qt::Desktop))
1152 #ifndef QT_NO_XRENDER
1154 XRenderFreePicture(X11->display, picture);
1159 // hide and reparent our own window away. Otherwise we might get
1160 // destroyed when emitting the child remove event below. See QWorkspace.
1161 if (wasCreated && old_winid) {
1162 XUnmapWindow(X11->display, old_winid);
1163 if (!old_xinfo.screen() != xinfo.screen())
1164 XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
1167 topData->parentWinId = 0;
1168 // zero the frame strut and mark it dirty
1169 topData->frameStrut.setCoords(0, 0, 0, 0);
1171 // reparenting from top-level, make sure show() works again
1172 topData->waitingForMapNotify = 0;
1173 topData->validWMState = 0;
1175 data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
1177 QObjectPrivate::setParent_helper(parent);
1178 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
1180 data.window_flags = f;
1181 q->setAttribute(Qt::WA_WState_Created, false);
1182 q->setAttribute(Qt::WA_WState_Visible, false);
1183 q->setAttribute(Qt::WA_WState_Hidden, false);
1184 adjustFlags(data.window_flags, q);
1185 // keep compatibility with previous versions, we need to preserve the created state
1186 // (but we recreate the winId for the widget being reparented, again for compatibility)
1189 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
1190 q->setAttribute(Qt::WA_WState_Hidden);
1191 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
1194 QObjectList chlist = q->children();
1195 for (int i = 0; i < chlist.size(); ++i) { // reparent children
1196 QObject *obj = chlist.at(i);
1197 if (obj->isWidgetType()) {
1198 QWidget *w = (QWidget *)obj;
1199 if (!w->testAttribute(Qt::WA_WState_Created))
1201 if (xinfo.screen() != w->d_func()->xinfo.screen()) {
1202 // ### force setParent() to not shortcut out (because
1203 // ### we're setting the parent to the current parent)
1204 // ### setParent will add child back to the list
1205 // ### of children so we need to make sure the
1206 // ### widget won't be added twice.
1207 w->d_func()->parent = 0;
1208 this->children.removeOne(w);
1210 } else if (!w->isWindow()) {
1211 w->d_func()->invalidateBuffer(w->rect());
1212 if (w->internalWinId()) {
1213 if (w->testAttribute(Qt::WA_NativeWindow)) {
1214 QWidget *nativeParentWidget = w->nativeParentWidget();
1215 // Qt::WA_NativeWindow ensures that we always have a nativeParentWidget
1216 Q_ASSERT(nativeParentWidget != 0);
1217 QPoint p = w->mapTo(nativeParentWidget, QPoint());
1218 XReparentWindow(X11->display,
1220 nativeParentWidget->internalWinId(),
1223 w->d_func()->setParent_sys(q, w->data->window_flags);
1226 } else if (isTransient(w)) {
1228 when reparenting toplevel windows with toplevel-transient children,
1229 we need to make sure that the window manager gets the updated
1230 WM_TRANSIENT_FOR information... unfortunately, some window managers
1231 don't handle changing WM_TRANSIENT_FOR before the toplevel window is
1232 visible, so we unmap and remap all toplevel-transient children *after*
1233 the toplevel parent has been mapped. thankfully, this is easy in Qt :)
1235 note that the WM_TRANSIENT_FOR hint is actually updated in
1236 QWidgetPrivate::show_sys()
1238 if (w->internalWinId())
1239 XUnmapWindow(X11->display, w->internalWinId());
1240 QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
1244 qPRCreate(q, old_winid);
1245 updateSystemBackground();
1250 if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) {
1252 int cmw_size = sizeof(Window)*count;
1253 cmw = new Window[count];
1254 memcpy((char *)cmw, (char *)cmwret, cmw_size);
1255 XFree((char *)cmwret);
1257 for (i=0; i<count; i++) {
1258 if (cmw[i] == old_winid) {
1259 cmw[i] = q->internalWinId();
1264 if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(),
1265 &cmwret, &top_count))
1267 Window *merged_cmw = new Window[count + top_count];
1268 memcpy((char *)merged_cmw, (char *)cmw, cmw_size);
1269 memcpy((char *)merged_cmw + cmw_size, (char *)cmwret, sizeof(Window)*top_count);
1271 XFree((char *)cmwret);
1276 XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count);
1280 qt_XDestroyWindow(q, X11->display, old_winid);
1284 // check if we need to register our dropsite
1285 if (q->testAttribute(Qt::WA_AcceptDrops)
1286 || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) {
1287 q->setAttribute(Qt::WA_DropSiteRegistered, true);
1289 #if !defined(QT_NO_IM)
1292 invalidateBuffer(q->rect());
1294 qDebug() << "QWidgetPrivate::setParent_sys END" << q;
1298 QPoint QWidgetPrivate::mapToGlobal(const QPoint &pos) const
1301 if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) {
1302 QPoint p = pos + q->data->crect.topLeft();
1303 //cannot trust that !isWindow() implies parentWidget() before create
1304 return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p);
1308 QPoint p = mapToWS(pos);
1309 XTranslateCoordinates(X11->display, q->internalWinId(),
1310 QApplication::desktop()->screen(xinfo.screen())->internalWinId(),
1311 p.x(), p.y(), &x, &y, &child);
1312 return QPoint(x, y);
1315 QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const
1318 if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) {
1319 //cannot trust that !isWindow() implies parentWidget() before create
1320 QPoint p = (q->isWindow() || !q->parentWidget()) ? pos : q->parentWidget()->d_func()->mapFromGlobal(pos);
1321 return p - q->data->crect.topLeft();
1325 XTranslateCoordinates(X11->display,
1326 QApplication::desktop()->screen(xinfo.screen())->internalWinId(),
1327 q->internalWinId(), pos.x(), pos.y(), &x, &y, &child);
1328 return mapFromWS(QPoint(x, y));
1331 QPoint QWidget::mapToGlobal(const QPoint &pos) const
1334 QPoint offset = data->crect.topLeft();
1335 const QWidget *w = this;
1336 const QWidget *p = w->parentWidget();
1337 while (!w->isWindow() && p) {
1339 p = p->parentWidget();
1340 offset += w->data->crect.topLeft();
1343 const QWidgetPrivate *wd = w->d_func();
1344 QTLWExtra *tlw = wd->topData();
1346 return pos + offset;
1348 return d->mapToGlobal(pos);
1351 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
1354 QPoint offset = data->crect.topLeft();
1355 const QWidget *w = this;
1356 const QWidget *p = w->parentWidget();
1357 while (!w->isWindow() && p) {
1359 p = p->parentWidget();
1360 offset += w->data->crect.topLeft();
1363 const QWidgetPrivate *wd = w->d_func();
1364 QTLWExtra *tlw = wd->topData();
1366 return pos - offset;
1368 return d->mapFromGlobal(pos);
1371 void QWidgetPrivate::updateSystemBackground()
1374 if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId())
1376 QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole());
1377 Qt::WindowType type = q->windowType();
1378 if (brush.style() == Qt::NoBrush
1379 || q->testAttribute(Qt::WA_NoSystemBackground)
1380 || q->testAttribute(Qt::WA_UpdatesDisabled)
1381 || type == Qt::Popup || type == Qt::ToolTip) {
1382 if (QX11Info::isCompositingManagerRunning()
1383 && q->testAttribute(Qt::WA_TranslucentBackground)
1385 XSetWindowBackground(X11->display, q->internalWinId(),
1386 QColormap::instance(xinfo.screen()).pixel(Qt::transparent));
1388 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
1390 else if (brush.style() == Qt::SolidPattern && brush.isOpaque())
1391 XSetWindowBackground(X11->display, q->internalWinId(),
1392 QColormap::instance(xinfo.screen()).pixel(brush.color()));
1393 else if (isBackgroundInherited())
1394 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative);
1395 else if (brush.style() == Qt::TexturePattern) {
1396 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
1397 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
1398 static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth());
1400 XSetWindowBackground(X11->display, q->internalWinId(),
1401 QColormap::instance(xinfo.screen()).pixel(brush.color()));
1404 #ifndef QT_NO_CURSOR
1405 void QWidgetPrivate::setCursor_sys(const QCursor &)
1408 qt_x11_enforce_cursor(q);
1409 XFlush(X11->display);
1412 void QWidgetPrivate::unsetCursor_sys()
1415 qt_x11_enforce_cursor(q);
1416 XFlush(X11->display);
1420 static XTextProperty*
1421 qstring_to_xtp(const QString& s)
1423 static XTextProperty tp = { 0, 0, 0, 0 };
1424 static bool free_prop = true; // we can't free tp.value in case it references
1425 // the data of the static QCString below.
1433 static const QTextCodec* mapper = QTextCodec::codecForLocale();
1436 QByteArray mapped = mapper->fromUnicode(s);
1438 tl[0] = mapped.data();
1440 errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
1441 #if defined(QT_DEBUG)
1443 qDebug("qstring_to_xtp result code %d", errCode);
1446 if (!mapper || errCode < 0) {
1447 static QByteArray qcs;
1449 tp.value = (uchar*)qcs.data();
1450 tp.encoding = XA_STRING;
1452 tp.nitems = qcs.length();
1456 // ### If we knew WM could understand unicode, we could use
1457 // ### a much simpler, cheaper encoding...
1459 tp.value = (XChar2b*)s.unicode();
1460 tp.encoding = XA_UNICODE; // wish
1462 tp.nitems = s.length();
1468 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
1471 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1472 if (!q->internalWinId())
1474 XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
1476 QByteArray net_wm_name = caption.toUtf8();
1477 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
1478 PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
1481 void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
1484 if (!q->testAttribute(Qt::WA_WState_Created))
1486 QTLWExtra *topData = this->topData();
1487 if (topData->iconPixmap && !forceReset)
1491 // preparing images to set the _NET_WM_ICON property
1492 QIcon icon = q->windowIcon();
1493 QVector<long> icon_data;
1494 Qt::HANDLE pixmap_handle = 0;
1495 if (!icon.isNull()) {
1496 QList<QSize> availableSizes = icon.availableSizes();
1497 if(availableSizes.isEmpty()) {
1498 // try to use default sizes since the icon can be a scalable image like svg.
1499 availableSizes.push_back(QSize(16,16));
1500 availableSizes.push_back(QSize(32,32));
1501 availableSizes.push_back(QSize(64,64));
1502 availableSizes.push_back(QSize(128,128));
1504 for(int i = 0; i < availableSizes.size(); ++i) {
1505 QSize size = availableSizes.at(i);
1506 QPixmap pixmap = icon.pixmap(size);
1507 if (!pixmap.isNull()) {
1508 QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
1509 int pos = icon_data.size();
1510 icon_data.resize(pos + 2 + image.width()*image.height());
1511 icon_data[pos++] = image.width();
1512 icon_data[pos++] = image.height();
1513 if (sizeof(long) == sizeof(quint32)) {
1514 memcpy(icon_data.data() + pos, image.scanLine(0), image.byteCount());
1516 for (int y = 0; y < image.height(); ++y) {
1517 uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y));
1518 for (int x = 0; x < image.width(); ++x)
1519 icon_data[pos + y*image.width() + x] = scanLine[x];
1524 if (!icon_data.isEmpty()) {
1525 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
1527 if the app is running on an unknown desktop, or it is not
1528 using the default visual, convert the icon to 1bpp as stated
1529 in the ICCCM section 4.1.2.4; otherwise, create the icon pixmap
1530 in the default depth (even though this violates the ICCCM)
1532 if (X11->desktopEnvironment == DE_UNKNOWN
1533 || !QX11Info::appDefaultVisual(xinfo.screen())
1534 || !QX11Info::appDefaultColormap(xinfo.screen())) {
1535 // unknown DE or non-default visual/colormap, use 1bpp bitmap
1536 if (!forceReset || !topData->iconPixmap)
1537 topData->iconPixmap = new QPixmap(qt_toX11Pixmap(QBitmap(icon.pixmap(QSize(64,64)))));
1538 pixmap_handle = topData->iconPixmap->handle();
1540 // default depth, use a normal pixmap (even though this
1541 // violates the ICCCM), since this works on all DEs known to Qt
1542 if (!forceReset || !topData->iconPixmap)
1543 topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
1544 pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth();
1549 if (!q->internalWinId())
1552 if (!icon_data.isEmpty()) {
1553 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
1554 PropModeReplace, (unsigned char *) icon_data.data(),
1557 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
1560 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1563 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1567 if (pixmap_handle) {
1568 h->icon_pixmap = pixmap_handle;
1569 h->flags |= IconPixmapHint;
1572 h->flags &= ~(IconPixmapHint | IconMaskHint);
1575 XSetWMHints(X11->display, q->internalWinId(), h);
1580 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
1583 if (!q->internalWinId())
1585 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1586 XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
1588 QByteArray icon_name = iconText.toUtf8();
1589 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
1590 PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
1594 void QWidget::grabMouse()
1596 if (isVisible() && !qt_nograb()) {
1597 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1598 QWidgetPrivate::mouseGrabber->releaseMouse();
1599 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1603 XGrabPointer(X11->display, effectiveWinId(), False,
1604 (uint)(ButtonPressMask | ButtonReleaseMask |
1605 PointerMotionMask | EnterWindowMask |
1607 GrabModeAsync, GrabModeAsync,
1608 XNone, XNone, X11->time);
1612 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1613 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1614 status == GrabFrozen ? "\"GrabFrozen\"" :
1615 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1617 qWarning("QWidget::grabMouse: Failed with %s", s);
1620 QWidgetPrivate::mouseGrabber = this;
1625 #ifndef QT_NO_CURSOR
1626 void QWidget::grabMouse(const QCursor &cursor)
1629 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1630 QWidgetPrivate::mouseGrabber->releaseMouse();
1631 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1635 XGrabPointer(X11->display, effectiveWinId(), False,
1636 (uint)(ButtonPressMask | ButtonReleaseMask |
1637 PointerMotionMask | EnterWindowMask | LeaveWindowMask),
1638 GrabModeAsync, GrabModeAsync,
1639 XNone, cursor.handle(), X11->time);
1643 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1644 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1645 status == GrabFrozen ? "\"GrabFrozen\"" :
1646 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1648 qWarning("QWidget::grabMouse: Failed with %s", s);
1651 QWidgetPrivate::mouseGrabber = this;
1657 void QWidget::releaseMouse()
1659 if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
1660 XUngrabPointer(X11->display, X11->time);
1661 XFlush(X11->display);
1662 QWidgetPrivate::mouseGrabber = 0;
1667 void QWidget::grabKeyboard()
1670 if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
1671 QWidgetPrivate::keyboardGrabber->releaseKeyboard();
1672 XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync,
1674 QWidgetPrivate::keyboardGrabber = this;
1679 void QWidget::releaseKeyboard()
1681 if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
1682 XUngrabKeyboard(X11->display, X11->time);
1683 QWidgetPrivate::keyboardGrabber = 0;
1688 QWidget *QWidget::mouseGrabber()
1690 return QWidgetPrivate::mouseGrabber;
1694 QWidget *QWidget::keyboardGrabber()
1696 return QWidgetPrivate::keyboardGrabber;
1699 void QWidget::activateWindow()
1701 QWidget *tlw = window();
1702 if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
1703 if (X11->userTime == 0)
1704 X11->userTime = X11->time;
1705 qt_net_update_user_time(tlw, X11->userTime);
1707 if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW))
1708 && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) {
1710 e.xclient.type = ClientMessage;
1711 e.xclient.message_type = ATOM(_NET_ACTIVE_WINDOW);
1712 e.xclient.display = X11->display;
1713 e.xclient.window = tlw->internalWinId();
1714 e.xclient.format = 32;
1715 e.xclient.data.l[0] = 1; // 1 == application
1716 e.xclient.data.l[1] = X11->userTime;
1717 if (QWidget *aw = QApplication::activeWindow())
1718 e.xclient.data.l[2] = aw->internalWinId();
1720 e.xclient.data.l[2] = XNone;
1721 e.xclient.data.l[3] = 0;
1722 e.xclient.data.l[4] = 0;
1723 XSendEvent(X11->display, RootWindow(X11->display, tlw->x11Info().screen()),
1724 false, SubstructureNotifyMask | SubstructureRedirectMask, &e);
1726 if (!qt_widget_private(tlw)->topData()->waitingForMapNotify)
1727 XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
1732 void QWidget::setWindowState(Qt::WindowStates newstate)
1735 bool needShow = false;
1736 Qt::WindowStates oldstate = windowState();
1737 if (oldstate == newstate)
1740 // Ensure the initial size is valid, since we store it as normalGeometry below.
1741 if (!testAttribute(Qt::WA_Resized) && !isVisible())
1744 QTLWExtra *top = d->topData();
1746 if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
1747 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
1748 && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
1749 if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
1750 top->normalGeometry = geometry();
1751 qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
1752 ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
1753 ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
1754 } else if (! (newstate & Qt::WindowFullScreen)) {
1755 if (newstate & Qt::WindowMaximized) {
1756 // save original geometry
1757 const QRect normalGeometry = geometry();
1760 data->fstrut_dirty = true;
1761 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
1762 const QRect r = top->normalGeometry;
1763 const QRect fs = d->frameStrut();
1764 setGeometry(maxRect.x() + fs.left(),
1765 maxRect.y() + fs.top(),
1766 maxRect.width() - fs.left() - fs.right(),
1767 maxRect.height() - fs.top() - fs.bottom());
1768 top->normalGeometry = r;
1771 if (top->normalGeometry.width() < 0)
1772 top->normalGeometry = normalGeometry;
1774 // restore original geometry
1775 setGeometry(top->normalGeometry);
1780 if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
1781 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
1782 if (newstate & Qt::WindowFullScreen) {
1783 top->normalGeometry = geometry();
1784 top->fullScreenOffset = d->frameStrut().topLeft();
1786 qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
1787 ATOM(_NET_WM_STATE_FULLSCREEN));
1789 needShow = isVisible();
1791 if (newstate & Qt::WindowFullScreen) {
1792 data->fstrut_dirty = true;
1793 const QRect normalGeometry = geometry();
1794 const QPoint fullScreenOffset = d->frameStrut().topLeft();
1796 top->savedFlags = windowFlags();
1797 setParent(0, Qt::Window | Qt::FramelessWindowHint);
1798 const QRect r = top->normalGeometry;
1799 setGeometry(qApp->desktop()->screenGeometry(this));
1800 top->normalGeometry = r;
1802 if (top->normalGeometry.width() < 0) {
1803 top->normalGeometry = normalGeometry;
1804 top->fullScreenOffset = fullScreenOffset;
1807 setParent(0, top->savedFlags);
1809 if (newstate & Qt::WindowMaximized) {
1810 // from fullscreen to maximized
1811 data->fstrut_dirty = true;
1812 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
1813 const QRect r = top->normalGeometry;
1814 const QRect fs = d->frameStrut();
1815 setGeometry(maxRect.x() + fs.left(),
1816 maxRect.y() + fs.top(),
1817 maxRect.width() - fs.left() - fs.right(),
1818 maxRect.height() - fs.top() - fs.bottom());
1819 top->normalGeometry = r;
1821 // restore original geometry
1822 setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
1823 -top->fullScreenOffset.y(),
1824 -top->fullScreenOffset.x(),
1825 -top->fullScreenOffset.y()));
1832 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1833 if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
1835 if (newstate & Qt::WindowMinimized) {
1837 e.xclient.type = ClientMessage;
1838 e.xclient.message_type = ATOM(WM_CHANGE_STATE);
1839 e.xclient.display = X11->display;
1840 e.xclient.window = data->winid;
1841 e.xclient.format = 32;
1842 e.xclient.data.l[0] = IconicState;
1843 e.xclient.data.l[1] = 0;
1844 e.xclient.data.l[2] = 0;
1845 e.xclient.data.l[3] = 0;
1846 e.xclient.data.l[4] = 0;
1847 XSendEvent(X11->display,
1848 RootWindow(X11->display,d->xinfo.screen()),
1849 False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
1851 setAttribute(Qt::WA_Mapped);
1852 XMapWindow(X11->display, effectiveWinId());
1860 data->window_state = newstate;
1865 if (newstate & Qt::WindowActive)
1868 QWindowStateChangeEvent e(oldstate);
1869 QApplication::sendEvent(this, &e);
1874 Platform-specific part of QWidget::show().
1877 void QWidgetPrivate::show_sys()
1880 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1882 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
1883 invalidateBuffer(q->rect());
1884 q->setAttribute(Qt::WA_Mapped);
1885 if (QTLWExtra *tlwExtra = maybeTopData())
1886 tlwExtra->waitingForMapNotify = 0;
1890 if (q->isWindow()) {
1891 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1893 bool got_hints = h != 0;
1895 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1898 h->initial_state = q->isMinimized() ? IconicState : NormalState;
1899 h->flags |= StateHint;
1900 XSetWMHints(X11->display, q->internalWinId(), h);
1904 // update WM_NORMAL_HINTS
1905 do_size_hints(q, extra);
1907 // udpate WM_TRANSIENT_FOR
1908 if (isTransient(q)) {
1909 QWidget *p = q->parentWidget();
1912 // hackish ... try to find the main window related to this QMenu
1913 if (qobject_cast<QMenu *>(q)) {
1914 p = static_cast<QMenuPrivate*>(this)->causedPopup.widget;
1916 p = q->parentWidget();
1918 p = QApplication::widgetAt(q->pos());
1920 p = qApp->activeWindow();
1926 // transient for window
1927 XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
1929 // transient for group
1930 XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
1934 // update _MOTIF_WM_HINTS
1935 QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
1937 if (data.window_modality != Qt::NonModal) {
1938 switch (data.window_modality) {
1939 case Qt::WindowModal:
1940 mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
1942 case Qt::ApplicationModal:
1944 mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
1947 mwmhints.flags |= MWM_HINTS_INPUT_MODE;
1949 mwmhints.input_mode = MWM_INPUT_MODELESS;
1950 mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
1953 if (q->minimumSize() == q->maximumSize()) {
1954 // fixed size, remove the resize handle (since mwm/dtwm
1955 // isn't smart enough to do it itself)
1956 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
1957 if (mwmhints.functions == MWM_FUNC_ALL) {
1958 mwmhints.functions = MWM_FUNC_MOVE;
1960 mwmhints.functions &= ~MWM_FUNC_RESIZE;
1963 if (mwmhints.decorations == MWM_DECOR_ALL) {
1964 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1965 mwmhints.decorations = (MWM_DECOR_BORDER
1969 mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
1972 if (q->windowFlags() & Qt::WindowMinimizeButtonHint) {
1973 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1974 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
1975 mwmhints.functions |= MWM_FUNC_MINIMIZE;
1977 if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
1978 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1979 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
1980 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
1982 if (q->windowFlags() & Qt::WindowCloseButtonHint)
1983 mwmhints.functions |= MWM_FUNC_CLOSE;
1986 SetMWMHints(X11->display, q->internalWinId(), mwmhints);
1988 // update _NET_WM_STATE
1989 QVector<Atom> netWmState = getNetWmState(q);
1991 Qt::WindowFlags flags = q->windowFlags();
1992 if (flags & Qt::WindowStaysOnTopHint) {
1993 if (flags & Qt::WindowStaysOnBottomHint)
1994 qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
1995 if (!netWmState.contains(ATOM(_NET_WM_STATE_ABOVE)))
1996 netWmState.append(ATOM(_NET_WM_STATE_ABOVE));
1997 if (!netWmState.contains(ATOM(_NET_WM_STATE_STAYS_ON_TOP)))
1998 netWmState.append(ATOM(_NET_WM_STATE_STAYS_ON_TOP));
1999 } else if (flags & Qt::WindowStaysOnBottomHint) {
2000 if (!netWmState.contains(ATOM(_NET_WM_STATE_BELOW)))
2001 netWmState.append(ATOM(_NET_WM_STATE_BELOW));
2003 if (q->isFullScreen()) {
2004 if (!netWmState.contains(ATOM(_NET_WM_STATE_FULLSCREEN)))
2005 netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN));
2007 if (q->isMaximized()) {
2008 if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
2009 netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ));
2010 if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))
2011 netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
2013 if (data.window_modality != Qt::NonModal) {
2014 if (!netWmState.contains(ATOM(_NET_WM_STATE_MODAL)))
2015 netWmState.append(ATOM(_NET_WM_STATE_MODAL));
2018 if (!netWmState.isEmpty()) {
2019 XChangeProperty(X11->display, q->internalWinId(),
2020 ATOM(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
2021 (unsigned char *) netWmState.data(), netWmState.size());
2023 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
2026 // set _NET_WM_USER_TIME
2027 Time userTime = X11->userTime;
2028 bool setUserTime = false;
2029 if (q->testAttribute(Qt::WA_ShowWithoutActivating)) {
2032 } else if (userTime != CurrentTime) {
2036 qt_net_update_user_time(q, userTime);
2039 if (!topData()->syncUpdateCounter) {
2041 XSyncIntToValue(&value, 0);
2042 topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
2044 XChangeProperty(X11->display, q->internalWinId(),
2045 ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
2047 32, PropModeReplace,
2048 (uchar *) &topData()->syncUpdateCounter, 1);
2050 topData()->newCounterValueHi = 0;
2051 topData()->newCounterValueLo = 0;
2055 if (!topData()->embedded
2056 && (topData()->validWMState || topData()->waitingForMapNotify)
2057 && !q->isMinimized()) {
2058 X11->deferred_map.append(q);
2062 if (q->isMaximized() && !q->isFullScreen()
2063 && !(X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
2064 && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
2065 XMapWindow(X11->display, q->internalWinId());
2066 data.fstrut_dirty = true;
2067 qt_x11_wait_for_window_manager(q);
2069 // if the wm was not smart enough to adjust our size, do that manually
2070 QRect maxRect = QApplication::desktop()->availableGeometry(q);
2072 QTLWExtra *top = topData();
2073 QRect normalRect = top->normalGeometry;
2074 const QRect fs = frameStrut();
2076 q->setGeometry(maxRect.x() + fs.left(),
2077 maxRect.y() + fs.top(),
2078 maxRect.width() - fs.left() - fs.right(),
2079 maxRect.height() - fs.top() - fs.bottom());
2081 // restore the original normalGeometry
2082 top->normalGeometry = normalRect;
2083 // internalSetGeometry() clears the maximized flag... make sure we set it back
2084 data.window_state = data.window_state | Qt::WindowMaximized;
2085 q->setAttribute(Qt::WA_Mapped);
2089 if (q->isFullScreen() && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
2090 XMapWindow(X11->display, q->internalWinId());
2091 qt_x11_wait_for_window_manager(q);
2092 q->setAttribute(Qt::WA_Mapped);
2097 invalidateBuffer(q->rect());
2099 if (q->testAttribute(Qt::WA_OutsideWSRange))
2101 q->setAttribute(Qt::WA_Mapped);
2103 topData()->waitingForMapNotify = 1;
2106 && (!q->autoFillBackground()
2107 || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
2108 if (q->internalWinId()) {
2109 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
2110 XMapWindow(X11->display, q->internalWinId());
2111 updateSystemBackground();
2116 if (q->internalWinId())
2117 XMapWindow(X11->display, q->internalWinId());
2119 // Freedesktop.org Startup Notification
2120 if (X11->startupId && q->isWindow()) {
2121 QByteArray message("remove: ID=");
2122 message.append(X11->startupId);
2123 sendStartupMessage(message.constData());
2130 Platform-specific part of QWidget::show().
2133 void QWidgetPrivate::sendStartupMessage(const char *message) const
2141 xevent.xclient.type = ClientMessage;
2142 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN);
2143 xevent.xclient.display = X11->display;
2144 xevent.xclient.window = q->internalWinId();
2145 xevent.xclient.format = 8;
2147 Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
2149 uint length = strlen(message) + 1;
2152 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
2154 for (uint i = 0; i < 20 && i + sent <= length; i++)
2155 xevent.xclient.data.b[i] = message[i + sent++];
2157 XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
2158 } while (sent <= length);
2161 void QWidgetPrivate::setNetWmWindowTypes()
2164 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2166 if (!q->isWindow()) {
2167 if (q->internalWinId())
2168 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE));
2172 QVector<long> windowTypes;
2174 // manual selection 1 (these are never set by Qt and take precedence)
2175 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
2176 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DESKTOP));
2177 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
2178 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DOCK));
2179 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
2180 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NOTIFICATION));
2182 // manual selection 2 (Qt uses these during auto selection);
2183 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
2184 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2185 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
2186 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2187 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
2188 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2189 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
2190 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2192 // manual selection 3 (these can be set by Qt, but don't have a
2193 // corresponding Qt::WindowType). note that order of the *MENU
2194 // atoms is important
2195 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
2196 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_MENU));
2197 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
2198 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
2199 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
2200 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU));
2201 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
2202 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR));
2203 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
2204 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_COMBO));
2205 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
2206 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DND));
2208 // automatic selection
2209 switch (q->windowType()) {
2212 // dialog netwm type
2213 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2218 // utility netwm type
2219 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2223 // tooltip netwm type
2224 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2227 case Qt::SplashScreen:
2228 // splash netwm type
2229 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2236 if (q->windowFlags() & Qt::FramelessWindowHint) {
2237 // override netwm type - quick and easy for KDE noborder
2238 windowTypes.append(ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
2241 // normal netwm type - default
2242 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL));
2244 if (!windowTypes.isEmpty()) {
2245 XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32,
2246 PropModeReplace, (unsigned char *) windowTypes.constData(),
2247 windowTypes.count());
2249 XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE));
2255 Platform-specific part of QWidget::hide().
2258 void QWidgetPrivate::hide_sys()
2261 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2262 deactivateWidgetCleanup();
2263 if (q->isWindow()) {
2264 X11->deferred_map.removeAll(q);
2265 if (q->internalWinId()) // in nsplugin, may be 0
2266 XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen());
2267 XFlush(X11->display);
2269 invalidateBuffer(q->rect());
2270 if (q->internalWinId()) // in nsplugin, may be 0
2271 XUnmapWindow(X11->display, q->internalWinId());
2273 q->setAttribute(Qt::WA_Mapped, false);
2276 void QWidgetPrivate::setFocus_sys()
2282 void QWidgetPrivate::raise_sys()
2285 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2286 if (q->internalWinId())
2287 XRaiseWindow(X11->display, q->internalWinId());
2290 void QWidgetPrivate::lower_sys()
2293 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2294 if (q->internalWinId())
2295 XLowerWindow(X11->display, q->internalWinId());
2297 invalidateBuffer(q->rect());
2300 void QWidgetPrivate::stackUnder_sys(QWidget* w)
2303 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2304 if (q->internalWinId() && w->internalWinId()) {
2306 stack[0] = w->internalWinId();;
2307 stack[1] = q->internalWinId();
2308 XRestackWindows(X11->display, stack, 2);
2310 if(!q->isWindow() || !w->internalWinId())
2311 invalidateBuffer(q->rect());
2315 static void do_size_hints(QWidget* widget, QWExtra *x)
2317 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
2321 QRect g = widget->geometry();
2324 s.width = g.width();
2325 s.height = g.height();
2326 if (x->minw > 0 || x->minh > 0) {
2327 // add minimum size hints
2328 s.flags |= PMinSize;
2329 s.min_width = qMin(XCOORD_MAX, x->minw);
2330 s.min_height = qMin(XCOORD_MAX, x->minh);
2332 if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
2333 // add maximum size hints
2334 s.flags |= PMaxSize;
2335 s.max_width = qMin(XCOORD_MAX, x->maxw);
2336 s.max_height = qMin(XCOORD_MAX, x->maxh);
2339 (x->topextra->incw > 0 || x->topextra->inch > 0)) {
2340 // add resize increment hints
2341 s.flags |= PResizeInc | PBaseSize;
2342 s.width_inc = x->topextra->incw;
2343 s.height_inc = x->topextra->inch;
2344 s.base_width = x->topextra->basew;
2345 s.base_height = x->topextra->baseh;
2348 if (widget->testAttribute(Qt::WA_Moved)) {
2349 // user (i.e. command-line) specified position
2350 s.flags |= USPosition;
2351 s.flags |= PPosition;
2353 if (widget->testAttribute(Qt::WA_Resized)) {
2354 // user (i.e. command-line) specified size
2358 s.flags |= PWinGravity;
2359 if (widget->testAttribute(Qt::WA_Moved) && x && x->topextra && !x->topextra->posFromMove) {
2360 // position came from setGeometry(), tell the WM that we don't
2361 // want our window gravity-shifted
2362 s.win_gravity = StaticGravity;
2364 // position came from move()
2367 s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
2369 if (widget->internalWinId())
2370 XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
2375 Helper function for non-toplevel widgets. Helps to map Qt's 32bit
2376 coordinate system to X11's 16bit coordinate system.
2378 Sets the geometry of the widget to data.crect, but clipped to sizes
2379 that X can handle. Unmaps widgets that are completely outside the
2382 Maintains data.wrect, which is the geometry of the X widget,
2383 measured in this widget's coordinate system.
2385 if the parent is not clipped, parentWRect is empty, otherwise
2386 parentWRect is the geometry of the parent's X rect, measured in
2389 void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
2392 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2395 There are up to four different coordinate systems here:
2396 Qt coordinate system for this widget.
2397 X coordinate system for this widget (relative to wrect).
2398 Qt coordinate system for parent
2399 X coordinate system for parent (relative to parent's wrect).
2401 Display *dpy = xinfo.display();
2402 QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
2403 QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
2405 //xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys)
2406 QRect xrect = data.crect;
2408 const QWidget *const parent = q->parentWidget();
2409 QRect parentWRect = parent->data->wrect;
2411 if (parentWRect.isValid()) {
2412 // parent is clipped, and we have to clip to the same limit as parent
2413 if (!parentWRect.contains(xrect)) {
2414 xrect &= parentWRect;
2416 //translate from parent's to my Qt coord sys
2417 wrect.translate(-data.crect.topLeft());
2419 //translate from parent's Qt coords to parent's X coords
2420 xrect.translate(-parentWRect.topLeft());
2423 // parent is not clipped, we may or may not have to clip
2425 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
2426 // This is where the main optimization is: we are already
2427 // clipped, and if our clip is still valid, we can just
2428 // move our window, and do not need to move or clip
2431 QRect vrect = xrect & parent->rect();
2432 vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
2433 if (data.wrect.contains(vrect)) {
2435 xrect.translate(data.crect.topLeft());
2437 XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
2442 if (!validRange.contains(xrect)) {
2443 // we are too big, and must clip
2446 wrect.translate(-data.crect.topLeft());
2447 //parent's X coord system is equal to parent's Qt coord
2448 //sys, so we don't need to map xrect.
2453 // unmap if we are outside the valid window system coord system
2454 bool outsideRange = !xrect.isValid();
2455 bool mapWindow = false;
2456 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
2457 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
2460 XUnmapWindow(dpy, data.winid);
2461 q->setAttribute(Qt::WA_Mapped, false);
2462 } else if (!q->isHidden()) {
2470 bool jump = (data.wrect != wrect);
2474 // and now recursively for all children...
2475 // ### can be optimized
2476 for (int i = 0; i < children.size(); ++i) {
2477 QObject *object = children.at(i);
2478 if (object->isWidgetType()) {
2479 QWidget *w = static_cast<QWidget *>(object);
2480 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
2481 w->d_func()->setWSGeometry(jump);
2486 // move ourselves to the new position and map (if necessary) after
2487 // the movement. Rationale: moving unmapped windows is much faster
2488 // than moving mapped windows
2489 if (jump) //avoid flicker when jumping
2490 XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
2491 if (!parent->internalWinId())
2492 xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
2493 XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
2496 //to avoid flicker, we have to show children after the helper widget has moved
2498 for (int i = 0; i < children.size(); ++i) {
2499 QObject *object = children.at(i);
2500 if (object->isWidgetType()) {
2501 QWidget *w = static_cast<QWidget *>(object);
2502 if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
2503 w->setAttribute(Qt::WA_Mapped);
2504 if (w->internalWinId())
2505 XMapWindow(dpy, w->data->winid);
2512 if (jump && data.winid)
2513 XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
2515 if (mapWindow && !dontShow) {
2516 q->setAttribute(Qt::WA_Mapped);
2518 XMapWindow(dpy, data.winid);
2522 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
2525 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2526 Display *dpy = X11->display;
2528 if ((q->windowType() == Qt::Desktop))
2530 if (q->isWindow()) {
2531 if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
2532 && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
2533 data.window_state &= ~Qt::WindowMaximized;
2534 if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
2535 data.window_state &= ~Qt::WindowFullScreen;
2536 if (QTLWExtra *topData = maybeTopData())
2537 topData->normalGeometry = QRect(0,0,-1,-1);
2539 uint s = data.window_state;
2540 s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
2541 data.window_state = s;
2543 if (extra) { // any size restrictions?
2544 w = qMin(w,extra->maxw);
2545 h = qMin(h,extra->maxh);
2546 w = qMax(w,extra->minw);
2547 h = qMax(h,extra->minh);
2549 QPoint oldPos(q->pos());
2550 QSize oldSize(q->size());
2551 QRect oldGeom(data.crect);
2552 QRect r(x, y, w, h);
2554 // We only care about stuff that changes the geometry, or may
2555 // cause the window manager to change its state
2556 if (!q->isWindow() && oldGeom == r)
2560 bool isResize = q->size() != oldSize;
2562 if (q->isWindow()) {
2563 if (w == 0 || h == 0) {
2564 q->setAttribute(Qt::WA_OutsideWSRange, true);
2565 if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
2567 } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
2568 q->setAttribute(Qt::WA_OutsideWSRange, false);
2570 // put the window in its place and show it
2572 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2573 topData()->posFromMove = false; // force StaticGravity
2574 do_size_hints(q, extra);
2577 q->setAttribute(Qt::WA_OutsideWSRange, false);
2578 if (!q->isVisible())
2579 do_size_hints(q, extra);
2581 if ((data.window_flags & Qt::X11BypassWindowManagerHint) == Qt::X11BypassWindowManagerHint
2582 // work around 4Dwm's incompliance with ICCCM 4.1.5
2583 || X11->desktopEnvironment == DE_4DWM) {
2585 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2586 } else if (q->isVisible()
2587 && topData()->validWMState
2588 && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) {
2590 e.xclient.type = ClientMessage;
2591 e.xclient.message_type = ATOM(_NET_MOVERESIZE_WINDOW);
2592 e.xclient.display = X11->display;
2593 e.xclient.window = q->internalWinId();
2594 e.xclient.format = 32;
2595 e.xclient.data.l[0] = StaticGravity | 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12;
2596 e.xclient.data.l[1] = x;
2597 e.xclient.data.l[2] = y;
2598 e.xclient.data.l[3] = w;
2599 e.xclient.data.l[4] = h;
2600 XSendEvent(X11->display, RootWindow(X11->display, q->x11Info().screen()),
2601 false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
2602 } else if (data.winid) {
2603 // pos() is right according to ICCCM 4.1.5
2604 XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
2606 } else if (isResize && data.winid) {
2608 && topData()->validWMState
2609 && !q->testAttribute(Qt::WA_PendingMoveEvent)) {
2611 even though we've not visible, we could be in a
2612 race w/ the window manager, and it may ignore
2613 our ConfigureRequest. setting posFromMove to
2614 false makes sure that doDeferredMap() in
2615 qapplication_x11.cpp keeps the window in the
2618 topData()->posFromMove = false;
2620 XResizeWindow(dpy, data.winid, w, h);
2623 if (isResize && !q->testAttribute(Qt::WA_DontShowOnScreen)) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
2624 q->setAttribute(Qt::WA_WState_ConfigPending);
2627 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
2628 const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
2629 const bool disableInTopLevelResize = inTopLevelResize && q->internalWinId();
2630 if (disableInTopLevelResize) {
2631 // Top-level resize optimization does not work for native child widgets;
2632 // disable it for this particular widget.
2633 tlwExtra->inTopLevelResize = false;
2636 if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) {
2637 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
2639 if (q->testAttribute(Qt::WA_WState_Created))
2642 if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible())
2643 invalidateBuffer_resizeHelper(oldPos, oldSize);
2645 if (disableInTopLevelResize)
2646 tlwExtra->inTopLevelResize = true;
2649 if (q->isVisible()) {
2650 if (isMove && q->pos() != oldPos) {
2651 if (X11->desktopEnvironment != DE_4DWM) {
2652 // pos() is right according to ICCCM 4.1.5
2653 QMoveEvent e(q->pos(), oldPos);
2654 QApplication::sendEvent(q, &e);
2656 // work around 4Dwm's incompliance with ICCCM 4.1.5
2657 QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
2658 QApplication::sendEvent(q, &e);
2662 static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
2663 // If we have a backing store with static contents, we have to disable the top-level
2664 // resize optimization in order to get invalidated regions for resized widgets.
2665 // The optimization discards all invalidateBuffer() calls since we're going to
2666 // repaint everything anyways, but that's not the case with static contents.
2667 const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
2668 && !extra->topextra->inTopLevelResize
2669 && (!extra->topextra->backingStore
2670 || !extra->topextra->backingStore->hasStaticContents());
2671 if (setTopLevelResize)
2672 extra->topextra->inTopLevelResize = true;
2673 QResizeEvent e(q->size(), oldSize);
2674 QApplication::sendEvent(q, &e);
2675 if (setTopLevelResize)
2676 extra->topextra->inTopLevelResize = false;
2679 if (isMove && q->pos() != oldPos)
2680 q->setAttribute(Qt::WA_PendingMoveEvent, true);
2682 q->setAttribute(Qt::WA_PendingResizeEvent, true);
2686 void QWidgetPrivate::setConstraints_sys()
2690 qDebug() << "QWidgetPrivate::setConstraints_sys START" << q;
2692 if (q->testAttribute(Qt::WA_WState_Created))
2693 do_size_hints(q, extra);
2695 qDebug() << "QWidgetPrivate::setConstraints_sys END" << q;
2699 void QWidgetPrivate::scroll_sys(int dx, int dy)
2703 scrollChildren(dx, dy);
2704 if (!paintOnScreen()) {
2705 scrollRect(q->rect(), dx, dy);
2707 scroll_sys(dx, dy, QRect());
2711 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
2715 if (!paintOnScreen()) {
2716 scrollRect(r, dx, dy);
2719 bool valid_rect = r.isValid();
2720 bool just_update = qAbs(dx) > q->width() || qAbs(dy) > q->height();
2721 QRect sr = valid_rect ? r : clipRect();
2724 else if (!valid_rect)
2725 dirty.translate(dx, dy);
2727 int x1, y1, x2, y2, w = sr.width(), h = sr.height();
2747 if (dx == 0 && dy == 0)
2750 Display *dpy = X11->display;
2751 // Want expose events
2752 if (w > 0 && h > 0 && !just_update && q->internalWinId()) {
2753 GC gc = XCreateGC(dpy, q->internalWinId(), 0, 0);
2754 XSetGraphicsExposures(dpy, gc, True);
2755 XCopyArea(dpy, q->internalWinId(), q->internalWinId(), gc, x1, y1, w, h, x2, y2);
2759 if (!valid_rect && !children.isEmpty()) { // scroll children
2761 for (int i = 0; i < children.size(); ++i) { // move all children
2762 register QObject *object = children.at(i);
2763 if (object->isWidgetType()) {
2764 QWidget *w = static_cast<QWidget *>(object);
2766 w->move(w->pos() + pd);
2774 // Don't let the server be bogged-down with repaint events
2775 bool repaint_immediately = (qt_sip_count(q) < 3 && !q->testAttribute(Qt::WA_WState_InPaintEvent));
2778 int x = x2 == sr.x() ? sr.x()+w : sr.x();
2779 if (repaint_immediately)
2780 q->repaint(x, sr.y(), qAbs(dx), sr.height());
2781 else if (q->internalWinId())
2782 XClearArea(dpy, data.winid, x, sr.y(), qAbs(dx), sr.height(), True);
2785 int y = y2 == sr.y() ? sr.y()+h : sr.y();
2786 if (repaint_immediately)
2787 q->repaint(sr.x(), y, sr.width(), qAbs(dy));
2788 else if (q->internalWinId())
2789 XClearArea(dpy, data.winid, sr.x(), y, sr.width(), qAbs(dy), True);
2792 qt_insert_sip(q, dx, dy); // #### ignores r
2795 int QWidget::metric(PaintDeviceMetric m) const
2799 if (m == PdmWidth) {
2800 val = data->crect.width();
2801 } else if (m == PdmHeight) {
2802 val = data->crect.height();
2804 Display *dpy = X11->display;
2805 int scr = d->xinfo.screen();
2808 case PdmPhysicalDpiX:
2809 if (d->extra && d->extra->customDpiX)
2810 val = d->extra->customDpiX;
2812 val = static_cast<QWidget *>(d->parent)->metric(m);
2814 val = QX11Info::appDpiX(scr);
2817 case PdmPhysicalDpiY:
2818 if (d->extra && d->extra->customDpiY)
2819 val = d->extra->customDpiY;
2821 val = static_cast<QWidget *>(d->parent)->metric(m);
2823 val = QX11Info::appDpiY(scr);
2826 val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
2827 DisplayWidth(dpy,scr);
2830 val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
2831 DisplayHeight(dpy,scr);
2834 val = d->xinfo.cells();
2837 val = d->xinfo.depth();
2841 qWarning("QWidget::metric: Invalid metric command");
2847 void QWidgetPrivate::createSysExtra()
2849 extra->compress_events = true;
2850 extra->xDndProxy = 0;
2853 void QWidgetPrivate::deleteSysExtra()
2857 void QWidgetPrivate::createTLSysExtra()
2859 extra->topextra->spont_unmapped = 0;
2860 extra->topextra->dnd = 0;
2861 extra->topextra->validWMState = 0;
2862 extra->topextra->waitingForMapNotify = 0;
2863 extra->topextra->parentWinId = 0;
2864 extra->topextra->userTimeWindow = 0;
2866 extra->topextra->syncUpdateCounter = 0;
2867 extra->topextra->syncRequestTimestamp = 0;
2868 extra->topextra->newCounterValueHi = 0;
2869 extra->topextra->newCounterValueLo = 0;
2873 void QWidgetPrivate::deleteTLSysExtra()
2875 // don't destroy input context here. it will be destroyed in
2876 // QWidget::destroy() destroyInputContext();
2879 void QWidgetPrivate::registerDropSite(bool on)
2884 void QWidgetPrivate::setMask_sys(const QRegion ®ion)
2887 if (!q->internalWinId())
2890 if (region.isEmpty()) {
2891 XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2894 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2895 region.handle(), ShapeSet);
2902 Computes the frame rectangle when needed. This is an internal function, you
2903 should never call this.
2906 void QWidgetPrivate::updateFrameStrut()
2910 QTLWExtra *top = topData();
2911 if (!top->validWMState) {
2914 if (!q->isWindow() && !q->internalWinId()) {
2915 data.fstrut_dirty = false;
2920 Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root
2924 unsigned char *data_ret;
2925 unsigned long l_unused;
2927 while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
2932 qWarning("QWidget::updateFrameStrut: No parent");
2936 // if the parent window is the root window, an Enlightenment virtual root or
2937 // a NET WM virtual root window, stop here
2940 (XGetWindowProperty(X11->display, p,
2941 ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
2942 &type_ret, &i_unused, &l_unused, &l_unused,
2943 &data_ret) == Success &&
2944 type_ret == XA_CARDINAL)) {
2949 } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
2951 while (X11->net_virtual_root_list[i] != 0) {
2952 if (X11->net_virtual_root_list[i++] == p)
2961 // we have our window
2963 XWindowAttributes wattr;
2964 if (XTranslateCoordinates(X11->display, l, w,
2965 0, 0, &transx, &transy, &p) &&
2966 XGetWindowAttributes(X11->display, w, &wattr)) {
2967 top->frameStrut.setCoords(transx,
2969 wattr.width - data.crect.width() - transx,
2970 wattr.height - data.crect.height() - transy);
2972 // add the border_width for the window managers frame... some window managers
2973 // do not use a border_width of zero for their frames, and if we the left and
2974 // top strut, we ensure that pos() is absolutely correct. frameGeometry()
2975 // will still be incorrect though... perhaps i should have foffset as well, to
2976 // indicate the frame offset (equal to the border_width on X).
2978 top->frameStrut.adjust(wattr.border_width,
2981 wattr.border_width);
2984 data.fstrut_dirty = false;
2987 void QWidgetPrivate::setWindowOpacity_sys(qreal opacity)
2990 ulong value = ulong(opacity * 0xffffffff);
2991 XChangeProperty(QX11Info::display(), q->internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL,
2992 32, PropModeReplace, (uchar*)&value, 1);
2995 const QX11Info &QWidget::x11Info() const
3001 void QWidgetPrivate::setWindowRole()
3004 if (!q->internalWinId())
3006 QByteArray windowRole = topData()->role.toUtf8();
3007 XChangeProperty(X11->display, q->internalWinId(),
3008 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
3009 (unsigned char *)windowRole.constData(), windowRole.length());
3012 Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
3013 QPaintEngine *QWidget::paintEngine() const
3016 if (qt_widget_paintengine()->isActive()) {
3017 if (d->extraPaintEngine)
3018 return d->extraPaintEngine;
3019 QWidget *self = const_cast<QWidget *>(this);
3020 self->d_func()->extraPaintEngine = new QX11PaintEngine();
3021 return d->extraPaintEngine;
3023 return qt_widget_paintengine();
3026 QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
3028 return new QX11WindowSurface(q_func());
3031 Qt::HANDLE QWidget::x11PictureHandle() const
3033 #ifndef QT_NO_XRENDER
3035 if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
3036 (void)winId(); // enforce native window
3040 #endif // QT_NO_XRENDER
3043 #ifndef QT_NO_XRENDER
3044 XRenderColor QX11Data::preMultiply(const QColor &c)
3047 const uint A = c.alpha(),
3051 color.alpha = (A | A << 8);
3052 color.red = (R | R << 8) * color.alpha / 0x10000;
3053 color.green = (G | G << 8) * color.alpha / 0x10000;
3054 color.blue = (B | B << 8) * color.alpha / 0x10000;
3057 Picture QX11Data::getSolidFill(int screen, const QColor &c)
3059 if (!X11->use_xrender)
3062 XRenderColor color = preMultiply(c);
3063 for (int i = 0; i < X11->solid_fill_count; ++i) {
3064 if (X11->solid_fills[i].screen == screen
3065 && X11->solid_fills[i].color.alpha == color.alpha
3066 && X11->solid_fills[i].color.red == color.red
3067 && X11->solid_fills[i].color.green == color.green
3068 && X11->solid_fills[i].color.blue == color.blue)
3069 return X11->solid_fills[i].picture;
3071 // none found, replace one
3072 int i = qrand() % 16;
3074 if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
3075 XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
3076 X11->solid_fills[i].picture = 0;
3079 if (!X11->solid_fills[i].picture) {
3080 Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
3081 XRenderPictureAttributes attrs;
3082 attrs.repeat = True;
3083 X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
3084 XRenderFindStandardFormat(X11->display, PictStandardARGB32),
3086 XFreePixmap (X11->display, pixmap);
3089 X11->solid_fills[i].color = color;
3090 X11->solid_fills[i].screen = screen;
3091 XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
3092 return X11->solid_fills[i].picture;
3096 void QWidgetPrivate::setModal_sys()
3100 void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att)
3102 QX11InfoData* xd = xinfo->getX11Data(true);
3103 const XWindowAttributes &a = *(att.att);
3104 // find which screen the window is on...
3105 xd->screen = QX11Info::appScreen(); // by default, use the default :)
3107 for (i = 0; i < ScreenCount(X11->display); i++) {
3108 if (RootWindow(X11->display, i) == a.root) {
3114 xd->depth = a.depth;
3115 xd->cells = DisplayCells(X11->display, xd->screen);
3116 xd->visual = a.visual;
3117 xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
3118 XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo->screen())));
3119 xd->colormap = a.colormap;
3120 xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo->screen()));
3121 xinfo->setX11Data(xd);
3124 void QWidgetPrivate::updateX11AcceptFocus()
3127 if (!q->isWindow() || !q->internalWinId())
3130 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
3133 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
3136 h->flags |= InputHint;
3137 h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
3139 XSetWMHints(X11->display, q->internalWinId(), h);