Fixes warnings about unused variables
[profile/ivi/qtbase.git] / src / gui / kernel / qwidget_x11.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
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
14 ** this package.
15 **
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.
23 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qevent.h"
43 #include "qwidget.h"
44 #include "qdesktopwidget.h"
45 #include "qapplication.h"
46 #include "qapplication_p.h"
47 #include "qnamespace.h"
48 #include "qpainter.h"
49 #include "qbitmap.h"
50 #include "qlayout.h"
51 #include "qtextcodec.h"
52 #include "qelapsedtimer.h"
53 #include "qcursor.h"
54 #include "qstack.h"
55 #include "qcolormap.h"
56 #include "qdebug.h"
57 #include "qmenu.h"
58 #include "private/qmenu_p.h"
59 #include "private/qbackingstore_p.h"
60 #include "private/qwindowsurface_x11_p.h"
61
62 //extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp
63
64 #include <private/qpixmap_x11_p.h>
65 #include <private/qpaintengine_x11_p.h>
66 #include "qt_x11_p.h"
67 #include "qx11info_x11.h"
68
69 #include <stdlib.h>
70
71 //#define ALIEN_DEBUG
72
73 // defined in qapplication_x11.cpp
74 //bool qt_wstate_iconified(WId);
75 //void qt_updated_rootinfo();
76
77
78 #if !defined(QT_NO_IM)
79 #include "qinputcontext.h"
80 #include "qinputcontextfactory.h"
81 #endif
82
83 #include "qwidget_p.h"
84
85 #define XCOORD_MAX 16383
86 #define WRECT_MAX 8191
87
88 QT_BEGIN_NAMESPACE
89
90 extern bool qt_nograb();
91
92 QWidget *QWidgetPrivate::mouseGrabber = 0;
93 QWidget *QWidgetPrivate::keyboardGrabber = 0;
94
95 void qt_net_remove_user_time(QWidget *tlw);
96 void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
97
98 int qt_x11_create_desktop_on_screen = -1;
99
100 extern void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
101
102 // MWM support
103 struct QtMWMHints {
104     ulong flags, functions, decorations;
105     long input_mode;
106     ulong status;
107 };
108
109 enum {
110     MWM_HINTS_FUNCTIONS   = (1L << 0),
111
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),
118
119     MWM_HINTS_DECORATIONS = (1L << 1),
120
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),
128
129     MWM_HINTS_INPUT_MODE = (1L << 2),
130
131     MWM_INPUT_MODELESS                  = 0L,
132     MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
133     MWM_INPUT_FULL_APPLICATION_MODAL    = 3L
134 };
135
136
137 static QtMWMHints GetMWMHints(Display *display, Window window)
138 {
139     QtMWMHints mwmhints;
140
141     Atom type;
142     int format;
143     ulong nitems, bytesLeft;
144     uchar *data = 0;
145     if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
146                             ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
147                             &data) == Success)
148         && (type == ATOM(_MOTIF_WM_HINTS)
149             && format == 32
150             && nitems >= 5)) {
151         mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
152     } else {
153         mwmhints.flags = 0L;
154         mwmhints.functions = MWM_FUNC_ALL;
155         mwmhints.decorations = MWM_DECOR_ALL;
156         mwmhints.input_mode = 0L;
157         mwmhints.status = 0L;
158     }
159
160     if (data)
161         XFree(data);
162
163     return mwmhints;
164 }
165
166 static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints)
167 {
168     if (mwmhints.flags != 0l) {
169         XChangeProperty(display, window, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
170                         PropModeReplace, (unsigned char *) &mwmhints, 5);
171     } else {
172         XDeleteProperty(display, window, ATOM(_MOTIF_WM_HINTS));
173     }
174 }
175
176 // Returns true if we should set WM_TRANSIENT_FOR on \a w
177 static inline bool isTransient(const QWidget *w)
178 {
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));
187 }
188
189 static void do_size_hints(QWidget* widget, QWExtra *x);
190
191 /*****************************************************************************
192   QWidget member functions
193  *****************************************************************************/
194
195 const uint stdWidgetEventMask =                        // X event mask
196         (uint)(
197             KeyPressMask | KeyReleaseMask |
198             ButtonPressMask | ButtonReleaseMask |
199             KeymapStateMask |
200             ButtonMotionMask | PointerMotionMask |
201             EnterWindowMask | LeaveWindowMask |
202             FocusChangeMask |
203             ExposureMask |
204             PropertyChangeMask |
205             StructureNotifyMask
206        );
207
208 const uint stdDesktopEventMask =                        // X event mask
209        (uint)(
210            KeymapStateMask |
211            EnterWindowMask | LeaveWindowMask |
212            PropertyChangeMask
213       );
214
215
216 /*
217   The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
218 */
219
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);
232
233
234 static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
235 {
236     if (!scrolled_widget->isWindow() && !scrolled_widget->internalWinId())
237         return;
238     QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
239     X11->sip_list.append(sip);
240
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;
247
248     XSendEvent(X11->display, scrolled_widget->internalWinId(), False, NoEventMask,
249         (XEvent*)&client_message);
250 }
251
252 static int qt_sip_count(QWidget* scrolled_widget)
253 {
254     int sips=0;
255
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)
259             sips++;
260     }
261
262     return sips;
263 }
264
265 static void create_wm_client_leader()
266 {
267     if (X11->wm_client_leader) return;
268
269     X11->wm_client_leader =
270         XCreateSimpleWindow(X11->display,
271                              QX11Info::appRootWindow(),
272                              0, 0, 1, 1, 0, 0, 0);
273
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);
279
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());
288     }
289 #endif
290 }
291
292 /*!
293    \internal
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.
297  */
298 void qt_x11_enforce_cursor(QWidget * w, bool force)
299 {
300     if (!w->testAttribute(Qt::WA_WState_Created))
301         return;
302
303     static QPointer<QWidget> lastUnderMouse = 0;
304     if (force) {
305         lastUnderMouse = w;
306     } else if (lastUnderMouse && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) {
307         w = lastUnderMouse;
308     } else if (!w->internalWinId()) {
309         return; //the mouse is not under this widget, and it's not native, so don't change it
310     }
311
312     while (!w->internalWinId() && w->parentWidget() && !w->isWindow() && !w->testAttribute(Qt::WA_SetCursor))
313         w = w->parentWidget();
314
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())
323         return;
324     WId winid = nativeParent->internalWinId();
325
326     if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) {
327 #ifndef QT_NO_CURSOR
328         QCursor *oc = QApplication::overrideCursor();
329         if (oc) {
330             XDefineCursor(X11->display, winid, oc->handle());
331         } else if (w->isEnabled()) {
332             XDefineCursor(X11->display, winid, w->cursor().handle());
333         } else {
334             // enforce the windows behavior of clearing the cursor on
335             // disabled widgets
336             XDefineCursor(X11->display, winid, XNone);
337         }
338 #endif
339     } else {
340         XDefineCursor(X11->display, winid, XNone);
341     }
342 }
343
344 Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
345 {
346     qt_x11_enforce_cursor(w, false);
347 }
348
349 void qt_x11_wait_for_window_manager(QWidget *w, bool sendPostedEvents)
350 {
351     if (!w || (!w->isWindow() && !w->internalWinId()))
352         return;
353     QApplication::flush();
354     XEvent ev;
355     QElapsedTimer t;
356     t.start();
357     static const int maximumWaitTime = 2000;
358     if (!w->testAttribute(Qt::WA_WState_Created))
359         return;
360
361     WId winid = w->internalWinId();
362
363     // first deliver events that are already in the local queue
364     if (sendPostedEvents)
365         QApplication::sendPostedEvents();
366
367     // the normal sequence is:
368     //  ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
369     // with X11BypassWindowManagerHint:
370     //  ConfigureNotify ... MapNotify ... Expose
371
372     enum State {
373         Initial, Mapped
374     } state = Initial;
375
376     do {
377         if (XEventsQueued(X11->display, QueuedAlready)) {
378             XNextEvent(X11->display, &ev);
379             qApp->x11ProcessEvent(&ev);
380
381             switch (state) {
382             case Initial:
383                 if (ev.type == MapNotify && ev.xany.window == winid)
384                     state = Mapped;
385                 break;
386             case Mapped:
387                 if (ev.type == Expose && ev.xany.window == winid)
388                     return;
389                 break;
390             }
391         } else {
392             if (!XEventsQueued(X11->display, QueuedAfterFlush))
393                 qApp->syncX(); // non-busy wait
394         }
395         if (t.elapsed() > maximumWaitTime)
396             return;
397     } while(1);
398 }
399
400 Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget *w)
401 {
402     qt_x11_wait_for_window_manager(w, true);
403 }
404
405 void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
406 {
407     if (!w->isVisible()) // not managed by the window manager
408         return;
409
410     XEvent e;
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);
423 }
424
425 struct QX11WindowAttributes {
426     const XWindowAttributes *att;
427 };
428
429 void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a)
430 {
431     QX11WindowAttributes att;
432     att.att = &a;
433     qt_x11_getX11InfoForWindow(xinfo,att);
434 }
435
436
437 static QVector<Atom> getNetWmState(QWidget *w)
438 {
439     QVector<Atom> returnValue;
440
441     // Don't read anything, just get the size of the property data
442     Atom actualType;
443     int actualFormat;
444     ulong propertyLength;
445     ulong bytesLeft;
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);
453         propertyData = 0;
454
455         // fetch all data
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) {
459             returnValue.clear();
460         } else if (propertyLength != (ulong)returnValue.size()) {
461             returnValue.resize(propertyLength);
462         }
463
464         // put it into netWmState
465         if (!returnValue.isEmpty()) {
466             memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
467         }
468         if (propertyData)
469             XFree((char*) propertyData);
470     }
471
472     return returnValue;
473 }
474
475 void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
476 {
477     Q_Q(QWidget);
478     Qt::WindowType type = q->windowType();
479     Qt::WindowFlags &flags = data.window_flags;
480     QWidget *parentWidget = q->parentWidget();
481
482     if (type == Qt::ToolTip)
483         flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
484     if (type == Qt::Popup)
485         flags |= Qt::X11BypassWindowManagerHint;
486
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);
492
493 #ifdef ALIEN_DEBUG
494     qDebug() << "QWidgetPrivate::create_sys START:" << q << "topLevel?" << topLevel << "WId:"
495              << window << "initializeWindow:" << initializeWindow << "destroyOldWindow" << destroyOldWindow;
496 #endif
497     if (topLevel) {
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;
502         }
503
504         if (type == Qt::SplashScreen) {
505             if (X11->isSupportedByWM(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
506                 flags &= ~Qt::X11BypassWindowManagerHint;
507             } else {
508                 flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
509             }
510         }
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;
516     }
517
518
519     Window parentw, destroyw = 0;
520     WId id = 0;
521
522     // always initialize
523     if (!window)
524         initializeWindow = true;
525
526     QX11Info *parentXinfo = parentWidget ? &parentWidget->d_func()->xinfo : 0;
527
528     if (desktop &&
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"))))
537     {
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;
543     }
544
545     //get display, screen number, root window and desktop geometry for
546     //the current screen
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);
552
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();
560             sw = r.width();
561             sh = r.height();
562         }
563
564         int width = sw / 2;
565         int height = 4 * sh / 10;
566         if (extra) {
567             width = qMax(qMin(width, extra->maxw), extra->minw);
568             height = qMax(qMin(height, extra->maxh), extra->minh);
569         }
570         data.crect.setSize(QSize(width, height));
571     }
572
573     parentw = topLevel ? root_win : parentWidget->effectiveWinId();
574
575     XSetWindowAttributes wsa;
576
577     if (window) {                                // override the old window
578         if (destroyOldWindow) {
579             if (topLevel)
580                 X11->dndEnable(q, false);
581             destroyw = data.winid;
582         }
583         id = window;
584         setWinId(window);
585         XWindowAttributes a;
586         XGetWindowAttributes(dpy, window, &a);
587         data.crect.setRect(a.x, a.y, a.width, a.height);
588
589         if (a.map_state == IsUnmapped)
590             q->setAttribute(Qt::WA_WState_Visible, false);
591         else
592             q->setAttribute(Qt::WA_WState_Visible);
593
594         qt_x11_getX11InfoForWindow(&xinfo,a);
595
596     } else if (desktop) {                        // desktop widget
597 #ifdef QWIDGET_EXTRA_DEBUG
598         qDebug() << "create desktop";
599 #endif
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
606 //         } else {
607         setWinId(id);
608 //         }
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;
615         else
616             qDebug() << "create child" << ++children;
617 #endif
618         QRect safeRect = data.crect; //##### must handle huge sizes as well.... i.e. wrect
619         if (safeRect.width() < 1|| safeRect.height() < 1) {
620             if (topLevel) {
621                 // top-levels must be at least 1x1
622                 safeRect.setSize(safeRect.size().expandedTo(QSize(1, 1)));
623             } else {
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);
627             }
628         }
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))
634         {
635             QX11InfoData *xd = xinfo.getX11Data(true);
636
637             xd->screen = screen;
638             xd->visual = X11->argbVisuals[screen];
639             xd->colormap = X11->argbColormaps[screen];
640             xd->depth = 32;
641             xd->defaultVisual = false;
642             xd->defaultColormap = false;
643             xd->cells = xd->visual->map_entries;
644             xinfo.setX11Data(xd);
645         }
646 #endif
647         if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
648             id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
649                                              safeRect.left(), safeRect.top(),
650                                              safeRect.width(), safeRect.height(),
651                                              0,
652                                              BlackPixel(dpy, xinfo.screen()),
653                                              WhitePixel(dpy, xinfo.screen()));
654         } else {
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,
664                                        &wsa);
665         }
666
667         setWinId(id);                                // set widget id/handle + hd
668     }
669
670 #ifndef QT_NO_XRENDER
671     if (picture) {
672         XRenderFreePicture(X11->display, picture);
673         picture = 0;
674     }
675
676     if (X11->use_xrender && !desktop && q->internalWinId()) {
677         XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual());
678         if (format)
679             picture = XRenderCreatePicture(dpy, id, format, 0, 0);
680     }
681 #endif // QT_NO_XRENDER
682
683     QtMWMHints mwmhints;
684     mwmhints.flags = 0L;
685     mwmhints.functions = 0L;
686     mwmhints.decorations = 0;
687     mwmhints.input_mode = 0L;
688     mwmhints.status = 0L;
689
690     if (topLevel) {
691         ulong wsa_mask = 0;
692         if (type != Qt::SplashScreen) { // && customize) {
693             mwmhints.flags |= MWM_HINTS_DECORATIONS;
694
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;
699
700                 if (flags & Qt::WindowTitleHint)
701                     mwmhints.decorations |= MWM_DECOR_TITLE;
702
703                 if (flags & Qt::WindowSystemMenuHint)
704                     mwmhints.decorations |= MWM_DECOR_MENU;
705
706                 if (flags & Qt::WindowMinimizeButtonHint) {
707                     mwmhints.decorations |= MWM_DECOR_MINIMIZE;
708                     mwmhints.functions |= MWM_FUNC_MINIMIZE;
709                 }
710
711                 if (flags & Qt::WindowMaximizeButtonHint) {
712                     mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
713                     mwmhints.functions |= MWM_FUNC_MAXIMIZE;
714                 }
715
716                 if (flags & Qt::WindowCloseButtonHint)
717                      mwmhints.functions |= MWM_FUNC_CLOSE;
718             }
719         } else {
720             // if type == Qt::SplashScreen
721             mwmhints.decorations = MWM_DECOR_ALL;
722         }
723
724         if (tool) {
725             wsa.save_under = True;
726             wsa_mask |= CWSaveUnder;
727         }
728
729         if (flags & Qt::X11BypassWindowManagerHint) {
730             wsa.override_redirect = True;
731             wsa_mask |= CWOverrideRedirect;
732         }
733
734         if (wsa_mask && initializeWindow) {
735             Q_ASSERT(id);
736             XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
737         }
738
739         if (mwmhints.functions != 0) {
740             mwmhints.flags |= MWM_HINTS_FUNCTIONS;
741             mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
742         } else {
743             mwmhints.functions = MWM_FUNC_ALL;
744         }
745
746         if (!(flags & Qt::FramelessWindowHint)
747             && flags & Qt::CustomizeWindowHint
748             && flags & Qt::WindowTitleHint
749             && !(flags &
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;
757         }
758     }
759
760     if (!initializeWindow) {
761         // do no initialization
762     } else if (popup) {                        // popup widget
763         // set EWMH window types
764         setNetWmWindowTypes();
765
766         wsa.override_redirect = True;
767         wsa.save_under = True;
768         Q_ASSERT(id);
769         XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
770                                 &wsa);
771     } else if (topLevel && !desktop) {        // top-level widget
772         if (!X11->wm_client_leader)
773             create_wm_client_leader();
774
775         // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys()
776
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;
785
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;
792
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
797
798         XSetWMProperties(dpy, id, 0, 0,
799                          qApp->d_func()->argv, qApp->d_func()->argc,
800                          &size_hints, &wm_hints, &class_hint);
801
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());
806         Atom protocols[5];
807         int n = 0;
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
811 #ifndef QT_NO_XSYNC
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);
817
818         // set mwm hints
819         SetMWMHints(dpy, id, mwmhints);
820
821         // set EWMH window types
822         setNetWmWindowTypes();
823
824         // set _NET_WM_PID
825         long curr_pid = getpid();
826         XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
827                         (unsigned char *) &curr_pid, 1);
828
829         // when we create a toplevel widget, the frame strut should be dirty
830         data.fstrut_dirty = 1;
831
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());
839             }
840         }
841
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);
846     } else {
847         // non-toplevel widgets don't have a frame, so no need to
848         // update the strut
849         data.fstrut_dirty = 0;
850     }
851
852     if (initializeWindow && q->internalWinId()) {
853         // don't erase when resizing
854         wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
855         Q_ASSERT(id);
856         XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
857     }
858
859     // set X11 event mask
860     if (desktop) {
861 //         QWidget* main_desktop = find(id);
862 //         if (main_desktop->testWFlags(Qt::WPaintDesktop))
863 //             XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
864 //         else
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),
874                                               tablet.eventCount);
875             }
876         }
877 #endif
878     }
879
880     if (desktop) {
881         q->setAttribute(Qt::WA_WState_Visible);
882     } else if (topLevel) {                        // set X cursor
883         if (initializeWindow) {
884             qt_x11_enforce_cursor(q);
885
886             if (QTLWExtra *topData = maybeTopData())
887                 if (!topData->caption.isEmpty())
888                     setWindowTitle_helper(topData->caption);
889
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);
893
894             if (maybeTopData() && maybeTopData()->opacity != 255)
895                 q->setWindowOpacity(maybeTopData()->opacity/255.);
896
897         }
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);
902     }
903
904     if (extra && !extra->mask.isEmpty() && q->internalWinId())
905         XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
906                             extra->mask.handle(), ShapeSet);
907
908     if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
909         QInputContext *inputContext = q->inputContext();
910         if (inputContext)
911             inputContext->setFocusWidget(q);
912     }
913
914     if (destroyw) {
915         qt_XDestroyWindow(q, dpy, destroyw);
916         if (QTLWExtra *topData = maybeTopData()) {
917 #ifndef QT_NO_XSYNC
918             if (topData->syncUpdateCounter)
919                 XSyncDestroyCounter(dpy, topData->syncUpdateCounter);
920 #endif
921             // we destroyed our old window - reset the top-level state
922             createTLSysExtra();
923         }
924     }
925
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
929     // system position
930     if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
931         setWSGeometry();
932     else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0))
933         q->setAttribute(Qt::WA_OutsideWSRange, true);
934
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()));
941     }
942
943 #ifdef ALIEN_DEBUG
944     qDebug() << "QWidgetPrivate::create_sys END:" << q;
945 #endif
946 }
947
948 static void qt_x11_recreateWidget(QWidget *widget)
949 {
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);
957     } else {
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();
962         if (visible)
963             widget->hide();
964
965         widget->setParent(widget->parentWidget(), widget->windowFlags());
966         widget->move(pos);
967         if (visible)
968             widget->show();
969     }
970 }
971
972 static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget)
973 {
974     if (widget->internalWinId())
975         qt_x11_recreateWidget(widget);
976
977     const QObjectList &children = widget->children();
978     for (int i = 0; i < children.size(); ++i) {
979         QWidget *child = qobject_cast<QWidget*>(children.at(i));
980         if (child)
981             qt_x11_recreateNativeWidgetsRecursive(child);
982     }
983 }
984
985 void QWidgetPrivate::x11UpdateIsOpaque()
986 {
987 #ifndef QT_NO_XRENDER
988     Q_Q(QWidget);
989     if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
990         return;
991
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)
996     {
997         qt_x11_recreateNativeWidgetsRecursive(q);
998     }
999 #endif
1000 }
1001
1002 /*
1003   Returns true if the background is inherited; otherwise returns
1004   false.
1005
1006   Mainly used in the paintOnScreen case.
1007 */
1008 bool QWidgetPrivate::isBackgroundInherited() const
1009 {
1010     Q_Q(const QWidget);
1011
1012     // windows do not inherit their background
1013     if (q->isWindow() || q->windowType() == Qt::SubWindow)
1014         return false;
1015
1016     if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
1017         return false;
1018
1019     const QPalette &pal = q->palette();
1020     QPalette::ColorRole bg = q->backgroundRole();
1021     QBrush brush = pal.brush(bg);
1022
1023     // non opaque brushes leaves us no choice, we must inherit
1024     if (!q->autoFillBackground() || !brush.isOpaque())
1025         return true;
1026
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())
1034             return false;
1035     }
1036
1037     return true;
1038 }
1039
1040 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
1041 {
1042     Q_D(QWidget);
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,
1054                                                     destroySubWindows);
1055         }
1056         if (QWidgetPrivate::mouseGrabber == this)
1057             releaseMouse();
1058         if (QWidgetPrivate::keyboardGrabber == this)
1059             releaseKeyboard();
1060         if (isWindow())
1061             X11->deferred_map.removeAll(this);
1062         if (isModal()) {
1063             // just be sure we leave modal
1064             QApplicationPrivate::leaveModal(this);
1065         }
1066         else if ((windowType() == Qt::Popup))
1067             qApp->d_func()->closePopup(this);
1068
1069 #ifndef QT_NO_XRENDER
1070         if (d->picture) {
1071             if (destroyWindow)
1072                 XRenderFreePicture(X11->display, d->picture);
1073             d->picture = 0;
1074         }
1075 #endif // QT_NO_XRENDER
1076
1077         // delete the _NET_WM_USER_TIME_WINDOW
1078         qt_net_remove_user_time(this);
1079
1080         if ((windowType() == Qt::Desktop)) {
1081             if (acceptDrops())
1082                 X11->dndEnable(this, false);
1083         } else {
1084             if (isWindow())
1085                 X11->dndEnable(this, false);
1086             if (destroyWindow)
1087                 qt_XDestroyWindow(this, X11->display, data->winid);
1088         }
1089         QT_TRY {
1090             d->setWinId(0);
1091         } QT_CATCH (const std::bad_alloc &) {
1092             // swallow - destructors must not throw
1093         }
1094
1095         extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
1096         if (testAttribute(Qt::WA_WState_Reparented))
1097             qPRCleanup(this);
1098
1099         if(d->ic) {
1100             delete d->ic;
1101         } else {
1102             // release previous focus information participating with
1103             // preedit preservation of qic
1104             QInputContext *qic = QApplicationPrivate::inputContext;
1105             if (qic)
1106                 qic->widgetDestroyed(this);
1107         }
1108     }
1109 }
1110
1111 void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
1112 {
1113     Q_Q(QWidget);
1114 #ifdef ALIEN_DEBUG
1115     qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent;
1116 #endif
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;
1122         parent = 0;
1123     }
1124
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
1131     QCursor oldcurs;
1132 #endif
1133
1134     // dnd unregister (we will register again below)
1135     if (q->testAttribute(Qt::WA_DropSiteRegistered))
1136         q->setAttribute(Qt::WA_DropSiteRegistered, false);
1137
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);
1142
1143     if (topData)
1144         qt_net_remove_user_time(q);
1145
1146 //     QWidget *oldparent = q->parentWidget();
1147     WId old_winid = wasCreated ? data.winid : 0;
1148     if ((q->windowType() == Qt::Desktop))
1149         old_winid = 0;
1150     setWinId(0);
1151
1152 #ifndef QT_NO_XRENDER
1153     if (picture) {
1154         XRenderFreePicture(X11->display, picture);
1155         picture = 0;
1156     }
1157 #endif
1158
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);
1165     }
1166     if (topData) {
1167         topData->parentWinId = 0;
1168         // zero the frame strut and mark it dirty
1169         topData->frameStrut.setCoords(0, 0, 0, 0);
1170
1171         // reparenting from top-level, make sure show() works again
1172         topData->waitingForMapNotify = 0;
1173         topData->validWMState = 0;
1174     }
1175     data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
1176
1177     QObjectPrivate::setParent_helper(parent);
1178     bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
1179
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)
1187     if (wasCreated)
1188         createWinId();
1189     if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
1190         q->setAttribute(Qt::WA_WState_Hidden);
1191     q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
1192
1193     if (wasCreated) {
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))
1200                     continue;
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);
1209                     w->setParent(q);
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,
1219                                             w->internalWinId(),
1220                                             nativeParentWidget->internalWinId(),
1221                                             p.x(), p.y());
1222                         } else {
1223                             w->d_func()->setParent_sys(q, w->data->window_flags);
1224                         }
1225                     }
1226                 } else if (isTransient(w)) {
1227                     /*
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 :)
1234
1235                       note that the WM_TRANSIENT_FOR hint is actually updated in
1236                       QWidgetPrivate::show_sys()
1237                     */
1238                     if (w->internalWinId())
1239                         XUnmapWindow(X11->display, w->internalWinId());
1240                     QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
1241                 }
1242             }
1243         }
1244         qPRCreate(q, old_winid);
1245         updateSystemBackground();
1246
1247         if (old_winid) {
1248             Window *cmwret;
1249             int count;
1250             if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) {
1251                 Window *cmw;
1252                 int cmw_size = sizeof(Window)*count;
1253                 cmw = new Window[count];
1254                 memcpy((char *)cmw, (char *)cmwret, cmw_size);
1255                 XFree((char *)cmwret);
1256                 int i;
1257                 for (i=0; i<count; i++) {
1258                     if (cmw[i] == old_winid) {
1259                         cmw[i] = q->internalWinId();
1260                         break;
1261                     }
1262                 }
1263                 int top_count;
1264                 if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(),
1265                                           &cmwret, &top_count))
1266                 {
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);
1270                     delete [] cmw;
1271                     XFree((char *)cmwret);
1272                     cmw = merged_cmw;
1273                     count += top_count;
1274                 }
1275
1276                 XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count);
1277                 delete [] cmw;
1278             }
1279
1280             qt_XDestroyWindow(q, X11->display, old_winid);
1281         }
1282     }
1283
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);
1288     }
1289 #if !defined(QT_NO_IM)
1290     ic = 0;
1291 #endif
1292     invalidateBuffer(q->rect());
1293 #ifdef ALIEN_DEBUG
1294     qDebug() << "QWidgetPrivate::setParent_sys END" << q;
1295 #endif
1296 }
1297
1298 QPoint QWidgetPrivate::mapToGlobal(const QPoint &pos) const
1299 {
1300     Q_Q(const QWidget);
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);
1305     }
1306     int x, y;
1307     Window child;
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);
1313 }
1314
1315 QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const
1316 {
1317     Q_Q(const QWidget);
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();
1322     }
1323     int x, y;
1324     Window child;
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));
1329 }
1330
1331 QPoint QWidget::mapToGlobal(const QPoint &pos) const
1332 {
1333     Q_D(const QWidget);
1334     QPoint offset = data->crect.topLeft();
1335     const QWidget *w = this;
1336     const QWidget *p = w->parentWidget();
1337     while (!w->isWindow() && p) {
1338         w = p;
1339         p = p->parentWidget();
1340         offset += w->data->crect.topLeft();
1341     }
1342
1343     const QWidgetPrivate *wd = w->d_func();
1344     QTLWExtra *tlw = wd->topData();
1345     if (!tlw->embedded)
1346         return pos + offset;
1347
1348     return d->mapToGlobal(pos);
1349 }
1350
1351 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
1352 {
1353     Q_D(const QWidget);
1354     QPoint offset = data->crect.topLeft();
1355     const QWidget *w = this;
1356     const QWidget *p = w->parentWidget();
1357     while (!w->isWindow() && p) {
1358         w = p;
1359         p = p->parentWidget();
1360         offset += w->data->crect.topLeft();
1361     }
1362
1363     const QWidgetPrivate *wd = w->d_func();
1364     QTLWExtra *tlw = wd->topData();
1365     if (!tlw->embedded)
1366         return pos - offset;
1367
1368     return d->mapFromGlobal(pos);
1369 }
1370
1371 void QWidgetPrivate::updateSystemBackground()
1372 {
1373     Q_Q(QWidget);
1374     if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId())
1375         return;
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)
1384                 && !(q->parent()))
1385                 XSetWindowBackground(X11->display, q->internalWinId(),
1386                                      QColormap::instance(xinfo.screen()).pixel(Qt::transparent));
1387             else
1388                 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
1389         }
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());
1399     } else
1400         XSetWindowBackground(X11->display, q->internalWinId(),
1401                              QColormap::instance(xinfo.screen()).pixel(brush.color()));
1402 }
1403
1404 #ifndef QT_NO_CURSOR
1405 void QWidgetPrivate::setCursor_sys(const QCursor &)
1406 {
1407     Q_Q(QWidget);
1408     qt_x11_enforce_cursor(q);
1409     XFlush(X11->display);
1410 }
1411
1412 void QWidgetPrivate::unsetCursor_sys()
1413 {
1414     Q_Q(QWidget);
1415     qt_x11_enforce_cursor(q);
1416     XFlush(X11->display);
1417 }
1418 #endif
1419
1420 static XTextProperty*
1421 qstring_to_xtp(const QString& s)
1422 {
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.
1426     if (tp.value) {
1427         if (free_prop)
1428             XFree(tp.value);
1429         tp.value = 0;
1430         free_prop = true;
1431     }
1432
1433     static const QTextCodec* mapper = QTextCodec::codecForLocale();
1434     int errCode = 0;
1435     if (mapper) {
1436         QByteArray mapped = mapper->fromUnicode(s);
1437         char* tl[2];
1438         tl[0] = mapped.data();
1439         tl[1] = 0;
1440         errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
1441 #if defined(QT_DEBUG)
1442         if (errCode < 0)
1443             qDebug("qstring_to_xtp result code %d", errCode);
1444 #endif
1445     }
1446     if (!mapper || errCode < 0) {
1447         static QByteArray qcs;
1448         qcs = s.toAscii();
1449         tp.value = (uchar*)qcs.data();
1450         tp.encoding = XA_STRING;
1451         tp.format = 8;
1452         tp.nitems = qcs.length();
1453         free_prop = false;
1454     }
1455
1456     // ### If we knew WM could understand unicode, we could use
1457     // ### a much simpler, cheaper encoding...
1458     /*
1459         tp.value = (XChar2b*)s.unicode();
1460         tp.encoding = XA_UNICODE; // wish
1461         tp.format = 16;
1462         tp.nitems = s.length();
1463     */
1464
1465     return &tp;
1466 }
1467
1468 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
1469 {
1470     Q_Q(QWidget);
1471     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1472     if (!q->internalWinId())
1473         return;
1474     XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
1475
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());
1479 }
1480
1481 void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
1482 {
1483     Q_Q(QWidget);
1484     if (!q->testAttribute(Qt::WA_WState_Created))
1485         return;
1486     QTLWExtra *topData = this->topData();
1487     if (topData->iconPixmap && !forceReset)
1488         // already been set
1489         return;
1490
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));
1503         }
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());
1515                 } else {
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];
1520                     }
1521                 }
1522             }
1523         }
1524         if (!icon_data.isEmpty()) {
1525             extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
1526             /*
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)
1531             */
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();
1539             } else {
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();
1545             }
1546         }
1547     }
1548
1549     if (!q->internalWinId())
1550         return;
1551
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(),
1555                         icon_data.size());
1556     } else {
1557         XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
1558     }
1559
1560     XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1561     XWMHints wm_hints;
1562     if (!h) {
1563         memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1564         h = &wm_hints;
1565     }
1566
1567     if (pixmap_handle) {
1568         h->icon_pixmap = pixmap_handle;
1569         h->flags |= IconPixmapHint;
1570     } else {
1571         h->icon_pixmap = 0;
1572         h->flags &= ~(IconPixmapHint | IconMaskHint);
1573     }
1574
1575     XSetWMHints(X11->display, q->internalWinId(), h);
1576     if (h != &wm_hints)
1577         XFree((char *)h);
1578 }
1579
1580 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
1581 {
1582     Q_Q(QWidget);
1583     if (!q->internalWinId())
1584         return;
1585     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1586     XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
1587
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());
1591 }
1592
1593
1594 void QWidget::grabMouse()
1595 {
1596     if (isVisible() && !qt_nograb()) {
1597         if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1598             QWidgetPrivate::mouseGrabber->releaseMouse();
1599         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1600 #ifndef QT_NO_DEBUG
1601         int status =
1602 #endif
1603             XGrabPointer(X11->display, effectiveWinId(), False,
1604                           (uint)(ButtonPressMask | ButtonReleaseMask |
1605                                   PointerMotionMask | EnterWindowMask |
1606                                   LeaveWindowMask),
1607                           GrabModeAsync, GrabModeAsync,
1608                           XNone, XNone, X11->time);
1609 #ifndef QT_NO_DEBUG
1610         if (status) {
1611             const char *s =
1612                 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1613                 status == AlreadyGrabbed  ? "\"AlreadyGrabbed\"" :
1614                 status == GrabFrozen      ? "\"GrabFrozen\"" :
1615                 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1616                 "<?>";
1617             qWarning("QWidget::grabMouse: Failed with %s", s);
1618         }
1619 #endif
1620         QWidgetPrivate::mouseGrabber = this;
1621     }
1622 }
1623
1624
1625 #ifndef QT_NO_CURSOR
1626 void QWidget::grabMouse(const QCursor &cursor)
1627 {
1628     if (!qt_nograb()) {
1629         if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1630             QWidgetPrivate::mouseGrabber->releaseMouse();
1631         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1632 #ifndef QT_NO_DEBUG
1633         int status =
1634 #endif
1635         XGrabPointer(X11->display, effectiveWinId(), False,
1636                       (uint)(ButtonPressMask | ButtonReleaseMask |
1637                              PointerMotionMask | EnterWindowMask | LeaveWindowMask),
1638                       GrabModeAsync, GrabModeAsync,
1639                       XNone, cursor.handle(), X11->time);
1640 #ifndef QT_NO_DEBUG
1641         if (status) {
1642             const char *s =
1643                 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1644                 status == AlreadyGrabbed  ? "\"AlreadyGrabbed\"" :
1645                 status == GrabFrozen      ? "\"GrabFrozen\"" :
1646                 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1647                                             "<?>";
1648             qWarning("QWidget::grabMouse: Failed with %s", s);
1649         }
1650 #endif
1651         QWidgetPrivate::mouseGrabber = this;
1652     }
1653 }
1654 #endif
1655
1656
1657 void QWidget::releaseMouse()
1658 {
1659     if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
1660         XUngrabPointer(X11->display, X11->time);
1661         XFlush(X11->display);
1662         QWidgetPrivate::mouseGrabber = 0;
1663     }
1664 }
1665
1666
1667 void QWidget::grabKeyboard()
1668 {
1669     if (!qt_nograb()) {
1670         if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
1671             QWidgetPrivate::keyboardGrabber->releaseKeyboard();
1672         XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync,
1673                       X11->time);
1674         QWidgetPrivate::keyboardGrabber = this;
1675     }
1676 }
1677
1678
1679 void QWidget::releaseKeyboard()
1680 {
1681     if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
1682         XUngrabKeyboard(X11->display, X11->time);
1683         QWidgetPrivate::keyboardGrabber = 0;
1684     }
1685 }
1686
1687
1688 QWidget *QWidget::mouseGrabber()
1689 {
1690     return QWidgetPrivate::mouseGrabber;
1691 }
1692
1693
1694 QWidget *QWidget::keyboardGrabber()
1695 {
1696     return QWidgetPrivate::keyboardGrabber;
1697 }
1698
1699 void QWidget::activateWindow()
1700 {
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);
1706
1707         if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW))
1708             && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) {
1709             XEvent e;
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();
1719             else
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);
1725         } else {
1726             if (!qt_widget_private(tlw)->topData()->waitingForMapNotify)
1727                 XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
1728         }
1729     }
1730 }
1731
1732 void QWidget::setWindowState(Qt::WindowStates newstate)
1733 {
1734     Q_D(QWidget);
1735     bool needShow = false;
1736     Qt::WindowStates oldstate = windowState();
1737     if (oldstate == newstate)
1738         return;
1739     if (isWindow()) {
1740         // Ensure the initial size is valid, since we store it as normalGeometry below.
1741         if (!testAttribute(Qt::WA_Resized) && !isVisible())
1742             adjustSize();
1743
1744         QTLWExtra *top = d->topData();
1745
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();
1758
1759                     if (isVisible()) {
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;
1769                     }
1770
1771                     if (top->normalGeometry.width() < 0)
1772                         top->normalGeometry = normalGeometry;
1773                 } else {
1774                     // restore original geometry
1775                     setGeometry(top->normalGeometry);
1776                 }
1777             }
1778         }
1779
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();
1785                 }
1786                 qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
1787                                        ATOM(_NET_WM_STATE_FULLSCREEN));
1788             } else {
1789                 needShow = isVisible();
1790
1791                 if (newstate & Qt::WindowFullScreen) {
1792                     data->fstrut_dirty = true;
1793                     const QRect normalGeometry = geometry();
1794                     const QPoint fullScreenOffset = d->frameStrut().topLeft();
1795
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;
1801
1802                     if (top->normalGeometry.width() < 0) {
1803                         top->normalGeometry = normalGeometry;
1804                         top->fullScreenOffset = fullScreenOffset;
1805                     }
1806                 } else {
1807                     setParent(0, top->savedFlags);
1808
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;
1820                     } else {
1821                         // restore original geometry
1822                         setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
1823                                                                  -top->fullScreenOffset.y(),
1824                                                                  -top->fullScreenOffset.x(),
1825                                                                  -top->fullScreenOffset.y()));
1826                     }
1827                 }
1828             }
1829         }
1830
1831         createWinId();
1832         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1833         if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
1834             if (isVisible()) {
1835                 if (newstate & Qt::WindowMinimized) {
1836                     XEvent e;
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);
1850                 } else {
1851                     setAttribute(Qt::WA_Mapped);
1852                     XMapWindow(X11->display, effectiveWinId());
1853                 }
1854             }
1855
1856             needShow = false;
1857         }
1858     }
1859
1860     data->window_state = newstate;
1861
1862     if (needShow)
1863         show();
1864
1865     if (newstate & Qt::WindowActive)
1866         activateWindow();
1867
1868     QWindowStateChangeEvent e(oldstate);
1869     QApplication::sendEvent(this, &e);
1870 }
1871
1872 /*!
1873   \internal
1874   Platform-specific part of QWidget::show().
1875 */
1876
1877 void QWidgetPrivate::show_sys()
1878 {
1879     Q_Q(QWidget);
1880     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1881
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;
1887         return;
1888     }
1889
1890     if (q->isWindow()) {
1891         XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1892         XWMHints  wm_hints;
1893         bool got_hints = h != 0;
1894         if (!got_hints) {
1895             memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1896             h = &wm_hints;
1897         }
1898         h->initial_state = q->isMinimized() ? IconicState : NormalState;
1899         h->flags |= StateHint;
1900         XSetWMHints(X11->display, q->internalWinId(), h);
1901         if (got_hints)
1902             XFree((char *)h);
1903
1904         // update WM_NORMAL_HINTS
1905         do_size_hints(q, extra);
1906
1907         // udpate WM_TRANSIENT_FOR
1908         if (isTransient(q)) {
1909             QWidget *p = q->parentWidget();
1910
1911 #ifndef QT_NO_MENU
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;
1915                 if (!p)
1916                     p = q->parentWidget();
1917                 if (!p)
1918                     p = QApplication::widgetAt(q->pos());
1919                 if (!p)
1920                     p = qApp->activeWindow();
1921             }
1922 #endif
1923             if (p)
1924                 p = p->window();
1925             if (p) {
1926                 // transient for window
1927                 XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
1928             } else {
1929                 // transient for group
1930                 XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
1931             }
1932         }
1933
1934         // update _MOTIF_WM_HINTS
1935         QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
1936
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;
1941                 break;
1942             case Qt::ApplicationModal:
1943             default:
1944                 mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
1945                 break;
1946             }
1947             mwmhints.flags |= MWM_HINTS_INPUT_MODE;
1948         } else {
1949             mwmhints.input_mode = MWM_INPUT_MODELESS;
1950             mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
1951         }
1952
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;
1959             } else {
1960                 mwmhints.functions &= ~MWM_FUNC_RESIZE;
1961             }
1962
1963             if (mwmhints.decorations == MWM_DECOR_ALL) {
1964                 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1965                 mwmhints.decorations = (MWM_DECOR_BORDER
1966                                         | MWM_DECOR_TITLE
1967                                         | MWM_DECOR_MENU);
1968             } else {
1969                 mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
1970             }
1971
1972             if (q->windowFlags() & Qt::WindowMinimizeButtonHint) {
1973                 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1974                 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
1975                 mwmhints.functions |= MWM_FUNC_MINIMIZE;
1976             }
1977             if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
1978                 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1979                 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
1980                 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
1981             }
1982             if (q->windowFlags() & Qt::WindowCloseButtonHint)
1983                 mwmhints.functions |= MWM_FUNC_CLOSE;
1984         }
1985
1986         SetMWMHints(X11->display, q->internalWinId(), mwmhints);
1987
1988         // update _NET_WM_STATE
1989         QVector<Atom> netWmState = getNetWmState(q);
1990
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));
2002         }
2003         if (q->isFullScreen()) {
2004             if (!netWmState.contains(ATOM(_NET_WM_STATE_FULLSCREEN)))
2005                 netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN));
2006         }
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));
2012         }
2013         if (data.window_modality != Qt::NonModal) {
2014             if (!netWmState.contains(ATOM(_NET_WM_STATE_MODAL)))
2015                 netWmState.append(ATOM(_NET_WM_STATE_MODAL));
2016         }
2017
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());
2022         } else {
2023             XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
2024         }
2025
2026         // set _NET_WM_USER_TIME
2027         Time userTime = X11->userTime;
2028         bool setUserTime = false;
2029         if (q->testAttribute(Qt::WA_ShowWithoutActivating)) {
2030             userTime = 0;
2031             setUserTime = true;
2032         } else if (userTime != CurrentTime) {
2033             setUserTime = true;
2034         }
2035         if (setUserTime)
2036             qt_net_update_user_time(q, userTime);
2037
2038 #ifndef QT_NO_XSYNC
2039         if (!topData()->syncUpdateCounter) {
2040             XSyncValue value;
2041             XSyncIntToValue(&value, 0);
2042             topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
2043
2044             XChangeProperty(X11->display, q->internalWinId(),
2045                             ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
2046                             XA_CARDINAL,
2047                             32, PropModeReplace,
2048                             (uchar *) &topData()->syncUpdateCounter, 1);
2049
2050             topData()->newCounterValueHi = 0;
2051             topData()->newCounterValueLo = 0;
2052         }
2053 #endif
2054
2055         if (!topData()->embedded
2056             && (topData()->validWMState || topData()->waitingForMapNotify)
2057             && !q->isMinimized()) {
2058             X11->deferred_map.append(q);
2059             return;
2060         }
2061
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);
2068
2069             // if the wm was not smart enough to adjust our size, do that manually
2070             QRect maxRect = QApplication::desktop()->availableGeometry(q);
2071
2072             QTLWExtra *top = topData();
2073             QRect normalRect = top->normalGeometry;
2074             const QRect fs = frameStrut();
2075
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());
2080
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);
2086             return;
2087         }
2088
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);
2093             return;
2094         }
2095     }
2096
2097     invalidateBuffer(q->rect());
2098
2099     if (q->testAttribute(Qt::WA_OutsideWSRange))
2100         return;
2101     q->setAttribute(Qt::WA_Mapped);
2102     if (q->isWindow())
2103         topData()->waitingForMapNotify = 1;
2104
2105     if (!q->isWindow()
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();
2112         }
2113         return;
2114     }
2115
2116     if (q->internalWinId())
2117         XMapWindow(X11->display, q->internalWinId());
2118
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());
2124         X11->startupId = 0;
2125     }
2126 }
2127
2128 /*!
2129   \internal
2130   Platform-specific part of QWidget::show().
2131 */
2132
2133 void QWidgetPrivate::sendStartupMessage(const char *message) const
2134 {
2135     Q_Q(const QWidget);
2136
2137     if (!message)
2138         return;
2139
2140     XEvent xevent;
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;
2146
2147     Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
2148     uint sent = 0;
2149     uint length = strlen(message) + 1;
2150     do {
2151         if (sent == 20)
2152             xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
2153
2154         for (uint i = 0; i < 20 && i + sent <= length; i++)
2155             xevent.xclient.data.b[i] = message[i + sent++];
2156
2157         XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
2158     } while (sent <= length);
2159 }
2160
2161 void QWidgetPrivate::setNetWmWindowTypes()
2162 {
2163     Q_Q(QWidget);
2164     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2165
2166     if (!q->isWindow()) {
2167         if (q->internalWinId())
2168             XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE));
2169         return;
2170     }
2171
2172     QVector<long> windowTypes;
2173
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));
2181
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));
2191
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));
2207
2208     // automatic selection
2209     switch (q->windowType()) {
2210     case Qt::Dialog:
2211     case Qt::Sheet:
2212         // dialog netwm type
2213         windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2214         break;
2215
2216     case Qt::Tool:
2217     case Qt::Drawer:
2218         // utility netwm type
2219         windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2220         break;
2221
2222     case Qt::ToolTip:
2223         // tooltip netwm type
2224         windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2225         break;
2226
2227     case Qt::SplashScreen:
2228         // splash netwm type
2229         windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2230         break;
2231
2232     default:
2233         break;
2234     }
2235
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));
2239     }
2240
2241     // normal netwm type - default
2242     windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL));
2243
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());
2248     } else {
2249         XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE));
2250     }
2251 }
2252
2253 /*!
2254   \internal
2255   Platform-specific part of QWidget::hide().
2256 */
2257
2258 void QWidgetPrivate::hide_sys()
2259 {
2260     Q_Q(QWidget);
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);
2268     } else {
2269         invalidateBuffer(q->rect());
2270         if (q->internalWinId()) // in nsplugin, may be 0
2271             XUnmapWindow(X11->display, q->internalWinId());
2272     }
2273     q->setAttribute(Qt::WA_Mapped, false);
2274 }
2275
2276 void QWidgetPrivate::setFocus_sys()
2277 {
2278
2279 }
2280
2281
2282 void QWidgetPrivate::raise_sys()
2283 {
2284     Q_Q(QWidget);
2285     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2286     if (q->internalWinId())
2287         XRaiseWindow(X11->display, q->internalWinId());
2288 }
2289
2290 void QWidgetPrivate::lower_sys()
2291 {
2292     Q_Q(QWidget);
2293     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2294     if (q->internalWinId())
2295         XLowerWindow(X11->display, q->internalWinId());
2296     if(!q->isWindow())
2297         invalidateBuffer(q->rect());
2298 }
2299
2300 void QWidgetPrivate::stackUnder_sys(QWidget* w)
2301 {
2302     Q_Q(QWidget);
2303     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2304     if (q->internalWinId() && w->internalWinId()) {
2305         Window stack[2];
2306         stack[0] = w->internalWinId();;
2307         stack[1] = q->internalWinId();
2308         XRestackWindows(X11->display, stack, 2);
2309     }
2310     if(!q->isWindow() || !w->internalWinId())
2311         invalidateBuffer(q->rect());
2312 }
2313
2314
2315 static void do_size_hints(QWidget* widget, QWExtra *x)
2316 {
2317     Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
2318     XSizeHints s;
2319     s.flags = 0;
2320     if (x) {
2321         QRect g = widget->geometry();
2322         s.x = g.x();
2323         s.y = g.y();
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);
2331         }
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);
2337         }
2338         if (x->topextra &&
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;
2346         }
2347     }
2348     if (widget->testAttribute(Qt::WA_Moved)) {
2349         // user (i.e. command-line) specified position
2350         s.flags |= USPosition;
2351         s.flags |= PPosition;
2352     }
2353     if (widget->testAttribute(Qt::WA_Resized)) {
2354         // user (i.e. command-line) specified size
2355         s.flags |= USSize;
2356         s.flags |= PSize;
2357     }
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;
2363     } else {
2364         // position came from move()
2365         s.x = widget->x();
2366         s.y = widget->y();
2367         s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
2368     }
2369     if (widget->internalWinId())
2370         XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
2371 }
2372
2373
2374 /*
2375   Helper function for non-toplevel widgets. Helps to map Qt's 32bit
2376   coordinate system to X11's 16bit coordinate system.
2377
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
2380   valid range.
2381
2382   Maintains data.wrect, which is the geometry of the X widget,
2383   measured in this widget's coordinate system.
2384
2385   if the parent is not clipped, parentWRect is empty, otherwise
2386   parentWRect is the geometry of the parent's X rect, measured in
2387   parent's coord sys
2388  */
2389 void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
2390 {
2391     Q_Q(QWidget);
2392     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2393
2394     /*
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).
2400      */
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);
2404     QRect wrect;
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;
2407
2408     const QWidget *const parent = q->parentWidget();
2409     QRect parentWRect = parent->data->wrect;
2410
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;
2415             wrect = xrect;
2416             //translate from parent's to my Qt coord sys
2417             wrect.translate(-data.crect.topLeft());
2418         }
2419         //translate from parent's Qt coords to parent's X coords
2420         xrect.translate(-parentWRect.topLeft());
2421
2422     } else {
2423         // parent is not clipped, we may or may not have to clip
2424
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
2429             // children
2430
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)) {
2434                 xrect = data.wrect;
2435                 xrect.translate(data.crect.topLeft());
2436                 if (data.winid)
2437                     XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
2438                 return;
2439             }
2440         }
2441
2442         if (!validRange.contains(xrect)) {
2443             // we are too big, and must clip
2444             xrect &=wrectRange;
2445             wrect = xrect;
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.
2449         }
2450
2451     }
2452
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);
2458         if (outsideRange) {
2459             if (data.winid)
2460                 XUnmapWindow(dpy, data.winid);
2461             q->setAttribute(Qt::WA_Mapped, false);
2462         } else if (!q->isHidden()) {
2463             mapWindow = true;
2464         }
2465     }
2466
2467     if (outsideRange)
2468         return;
2469
2470     bool jump = (data.wrect != wrect);
2471     data.wrect = wrect;
2472
2473
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);
2482         }
2483     }
2484
2485     if (data.winid) {
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());
2494     }
2495
2496     //to avoid flicker, we have to show children after the helper widget has moved
2497     if (jump) {
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);
2506                 }
2507             }
2508         }
2509     }
2510
2511
2512     if  (jump && data.winid)
2513         XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
2514
2515     if (mapWindow && !dontShow) {
2516         q->setAttribute(Qt::WA_Mapped);
2517         if (data.winid)
2518             XMapWindow(dpy, data.winid);
2519     }
2520 }
2521
2522 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
2523 {
2524     Q_Q(QWidget);
2525     Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2526     Display *dpy = X11->display;
2527
2528     if ((q->windowType() == Qt::Desktop))
2529         return;
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);
2538     } else {
2539         uint s = data.window_state;
2540         s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
2541         data.window_state = s;
2542     }
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);
2548     }
2549     QPoint oldPos(q->pos());
2550     QSize oldSize(q->size());
2551     QRect oldGeom(data.crect);
2552     QRect  r(x, y, w, h);
2553
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)
2557         return;
2558
2559     data.crect = r;
2560     bool isResize = q->size() != oldSize;
2561
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))
2566                 hide_sys();
2567         } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
2568             q->setAttribute(Qt::WA_OutsideWSRange, false);
2569
2570             // put the window in its place and show it
2571             if (data.winid)
2572                 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2573             topData()->posFromMove = false; // force StaticGravity
2574             do_size_hints(q, extra);
2575             show_sys();
2576         } else {
2577             q->setAttribute(Qt::WA_OutsideWSRange, false);
2578             if (!q->isVisible())
2579                 do_size_hints(q, extra);
2580             if (isMove) {
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) {
2584                     if (data.winid)
2585                         XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2586                 } else if (q->isVisible()
2587                            && topData()->validWMState
2588                            && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) {
2589                     XEvent e;
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);
2605                 }
2606             } else if (isResize && data.winid) {
2607                 if (!q->isVisible()
2608                     && topData()->validWMState
2609                     && !q->testAttribute(Qt::WA_PendingMoveEvent)) {
2610                     /*
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
2616                        right place
2617                     */
2618                     topData()->posFromMove = false;
2619                 }
2620                 XResizeWindow(dpy, data.winid, w, h);
2621             }
2622         }
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);
2625
2626     } else {
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;
2634         }
2635
2636         if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) {
2637             moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
2638         }
2639         if (q->testAttribute(Qt::WA_WState_Created))
2640             setWSGeometry();
2641
2642         if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible())
2643             invalidateBuffer_resizeHelper(oldPos, oldSize);
2644
2645         if (disableInTopLevelResize)
2646             tlwExtra->inTopLevelResize = true;
2647     }
2648
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);
2655             } else {
2656                 // work around 4Dwm's incompliance with ICCCM 4.1.5
2657                 QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
2658                 QApplication::sendEvent(q, &e);
2659             }
2660         }
2661         if (isResize) {
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;
2677         }
2678     } else {
2679         if (isMove && q->pos() != oldPos)
2680             q->setAttribute(Qt::WA_PendingMoveEvent, true);
2681         if (isResize)
2682             q->setAttribute(Qt::WA_PendingResizeEvent, true);
2683     }
2684 }
2685
2686 void QWidgetPrivate::setConstraints_sys()
2687 {
2688     Q_Q(QWidget);
2689 #ifdef ALIEN_DEBUG
2690     qDebug() << "QWidgetPrivate::setConstraints_sys START" << q;
2691 #endif
2692     if (q->testAttribute(Qt::WA_WState_Created))
2693         do_size_hints(q, extra);
2694 #ifdef ALIEN_DEBUG
2695     qDebug() << "QWidgetPrivate::setConstraints_sys END" << q;
2696 #endif
2697 }
2698
2699 void QWidgetPrivate::scroll_sys(int dx, int dy)
2700 {
2701     Q_Q(QWidget);
2702
2703     scrollChildren(dx, dy);
2704     if (!paintOnScreen()) {
2705         scrollRect(q->rect(), dx, dy);
2706     } else {
2707         scroll_sys(dx, dy, QRect());
2708     }
2709 }
2710
2711 void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
2712 {
2713     Q_Q(QWidget);
2714
2715     if (!paintOnScreen()) {
2716         scrollRect(r, dx, dy);
2717         return;
2718     }
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();
2722     if (just_update)
2723         q->update();
2724     else if (!valid_rect)
2725         dirty.translate(dx, dy);
2726
2727     int x1, y1, x2, y2, w = sr.width(), h = sr.height();
2728     if (dx > 0) {
2729         x1 = sr.x();
2730         x2 = x1+dx;
2731         w -= dx;
2732     } else {
2733         x2 = sr.x();
2734         x1 = x2-dx;
2735         w += dx;
2736     }
2737     if (dy > 0) {
2738         y1 = sr.y();
2739         y2 = y1+dy;
2740         h -= dy;
2741     } else {
2742         y2 = sr.y();
2743         y1 = y2-dy;
2744         h += dy;
2745     }
2746
2747     if (dx == 0 && dy == 0)
2748         return;
2749
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);
2756         XFreeGC(dpy, gc);
2757     }
2758
2759     if (!valid_rect && !children.isEmpty()) {        // scroll children
2760         QPoint pd(dx, dy);
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);
2765                 if (!w->isWindow())
2766                     w->move(w->pos() + pd);
2767             }
2768         }
2769     }
2770
2771     if (just_update)
2772         return;
2773
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));
2776
2777     if (dx) {
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);
2783     }
2784     if (dy) {
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);
2790     }
2791
2792     qt_insert_sip(q, dx, dy); // #### ignores r
2793 }
2794
2795 int QWidget::metric(PaintDeviceMetric m) const
2796 {
2797     Q_D(const QWidget);
2798     int val;
2799     if (m == PdmWidth) {
2800         val = data->crect.width();
2801     } else if (m == PdmHeight) {
2802         val = data->crect.height();
2803     } else {
2804         Display *dpy = X11->display;
2805         int scr = d->xinfo.screen();
2806         switch (m) {
2807             case PdmDpiX:
2808             case PdmPhysicalDpiX:
2809                 if (d->extra && d->extra->customDpiX)
2810                     val = d->extra->customDpiX;
2811                 else if (d->parent)
2812                     val = static_cast<QWidget *>(d->parent)->metric(m);
2813                 else
2814                     val = QX11Info::appDpiX(scr);
2815                 break;
2816             case PdmDpiY:
2817             case PdmPhysicalDpiY:
2818                 if (d->extra && d->extra->customDpiY)
2819                     val = d->extra->customDpiY;
2820                 else if (d->parent)
2821                     val = static_cast<QWidget *>(d->parent)->metric(m);
2822                 else
2823                     val = QX11Info::appDpiY(scr);
2824                 break;
2825             case PdmWidthMM:
2826                 val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
2827                       DisplayWidth(dpy,scr);
2828                 break;
2829             case PdmHeightMM:
2830                 val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
2831                       DisplayHeight(dpy,scr);
2832                 break;
2833             case PdmNumColors:
2834                 val = d->xinfo.cells();
2835                 break;
2836             case PdmDepth:
2837                 val = d->xinfo.depth();
2838                 break;
2839             default:
2840                 val = 0;
2841                 qWarning("QWidget::metric: Invalid metric command");
2842         }
2843     }
2844     return val;
2845 }
2846
2847 void QWidgetPrivate::createSysExtra()
2848 {
2849     extra->compress_events = true;
2850     extra->xDndProxy = 0;
2851 }
2852
2853 void QWidgetPrivate::deleteSysExtra()
2854 {
2855 }
2856
2857 void QWidgetPrivate::createTLSysExtra()
2858 {
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;
2865 #ifndef QT_NO_XSYNC
2866     extra->topextra->syncUpdateCounter = 0;
2867     extra->topextra->syncRequestTimestamp = 0;
2868     extra->topextra->newCounterValueHi = 0;
2869     extra->topextra->newCounterValueLo = 0;
2870 #endif
2871 }
2872
2873 void QWidgetPrivate::deleteTLSysExtra()
2874 {
2875     // don't destroy input context here. it will be destroyed in
2876     // QWidget::destroy() destroyInputContext();
2877 }
2878
2879 void QWidgetPrivate::registerDropSite(bool on)
2880 {
2881     Q_UNUSED(on);
2882 }
2883
2884 void QWidgetPrivate::setMask_sys(const QRegion &region)
2885 {
2886     Q_Q(QWidget);
2887     if (!q->internalWinId())
2888         return;
2889
2890     if (region.isEmpty()) {
2891         XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2892                           XNone, ShapeSet);
2893     } else {
2894         XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2895                             region.handle(), ShapeSet);
2896     }
2897 }
2898
2899 /*!
2900   \internal
2901
2902   Computes the frame rectangle when needed.  This is an internal function, you
2903   should never call this.
2904 */
2905
2906 void QWidgetPrivate::updateFrameStrut()
2907 {
2908     Q_Q(QWidget);
2909
2910     QTLWExtra *top = topData();
2911     if (!top->validWMState) {
2912         return;
2913     }
2914     if (!q->isWindow() && !q->internalWinId()) {
2915         data.fstrut_dirty = false;
2916         return;
2917     }
2918
2919     Atom type_ret;
2920     Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root
2921     Window *c;
2922     int i_unused;
2923     unsigned int nc;
2924     unsigned char *data_ret;
2925     unsigned long l_unused;
2926
2927     while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
2928         if (c && nc > 0)
2929             XFree(c);
2930
2931         if (! p) {
2932             qWarning("QWidget::updateFrameStrut: No parent");
2933             return;
2934         }
2935
2936         // if the parent window is the root window, an Enlightenment virtual root or
2937         // a NET WM virtual root window, stop here
2938         data_ret = 0;
2939         if (p == r ||
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)) {
2945             if (data_ret)
2946                 XFree(data_ret);
2947
2948             break;
2949         } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
2950             int i = 0;
2951             while (X11->net_virtual_root_list[i] != 0) {
2952                 if (X11->net_virtual_root_list[i++] == p)
2953                     break;
2954             }
2955         }
2956
2957         l = w;
2958         w = p;
2959     }
2960
2961     // we have our window
2962     int transx, transy;
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,
2968                                   transy,
2969                                   wattr.width - data.crect.width() - transx,
2970                                   wattr.height - data.crect.height() - transy);
2971
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).
2977         // - Brad
2978         top->frameStrut.adjust(wattr.border_width,
2979                                wattr.border_width,
2980                                wattr.border_width,
2981                                wattr.border_width);
2982     }
2983
2984    data.fstrut_dirty = false;
2985 }
2986
2987 void QWidgetPrivate::setWindowOpacity_sys(qreal opacity)
2988 {
2989     Q_Q(QWidget);
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);
2993 }
2994
2995 const QX11Info &QWidget::x11Info() const
2996 {
2997     Q_D(const QWidget);
2998     return d->xinfo;
2999 }
3000
3001 void QWidgetPrivate::setWindowRole()
3002 {
3003     Q_Q(QWidget);
3004     if (!q->internalWinId())
3005         return;
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());
3010 }
3011
3012 Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
3013 QPaintEngine *QWidget::paintEngine() const
3014 {
3015     Q_D(const QWidget);
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;
3022     }
3023     return qt_widget_paintengine();
3024 }
3025
3026 QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
3027 {
3028     return new QX11WindowSurface(q_func());
3029 }
3030
3031 Qt::HANDLE QWidget::x11PictureHandle() const
3032 {
3033 #ifndef QT_NO_XRENDER
3034     Q_D(const QWidget);
3035     if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
3036         (void)winId(); // enforce native window
3037     return d->picture;
3038 #else
3039     return 0;
3040 #endif // QT_NO_XRENDER
3041 }
3042
3043 #ifndef QT_NO_XRENDER
3044 XRenderColor QX11Data::preMultiply(const QColor &c)
3045 {
3046     XRenderColor color;
3047     const uint A = c.alpha(),
3048                R = c.red(),
3049                G = c.green(),
3050                B = c.blue();
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;
3055     return color;
3056 }
3057 Picture QX11Data::getSolidFill(int screen, const QColor &c)
3058 {
3059     if (!X11->use_xrender)
3060         return XNone;
3061
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;
3070     }
3071     // none found, replace one
3072     int i = qrand() % 16;
3073
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;
3077     }
3078
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),
3085                                                             CPRepeat, &attrs);
3086         XFreePixmap (X11->display, pixmap);
3087     }
3088
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;
3093 }
3094 #endif
3095
3096 void QWidgetPrivate::setModal_sys()
3097 {
3098 }
3099
3100 void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att)
3101 {
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 :)
3106     int i;
3107     for (i = 0; i < ScreenCount(X11->display); i++) {
3108         if (RootWindow(X11->display, i) == a.root) {
3109             xd->screen = i;
3110             break;
3111         }
3112     }
3113
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);
3122 }
3123
3124 void QWidgetPrivate::updateX11AcceptFocus()
3125 {
3126     Q_Q(QWidget);
3127     if (!q->isWindow() || !q->internalWinId())
3128         return;
3129
3130     XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
3131     XWMHints wm_hints;
3132     if (!h) {
3133         memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
3134         h = &wm_hints;
3135     }
3136     h->flags |= InputHint;
3137     h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
3138
3139     XSetWMHints(X11->display, q->internalWinId(), h);
3140     if (h != &wm_hints)
3141         XFree((char *)h);
3142 }
3143
3144 QT_END_NAMESPACE