70eb061c13c7da4671ec1b4982be5b7967afb1c0
[profile/ivi/qtbase.git] / src / plugins / platforms / xlib / qxlibwindow.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 plugins of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtGui/private/qguiapplication_p.h>
43 #include "qxlibwindow.h"
44
45 #include "qxlibintegration.h"
46 #include "qxlibscreen.h"
47 #include "qxlibkeyboard.h"
48 #include "qxlibstatic.h"
49 #include "qxlibdisplay.h"
50
51 #if !defined(QT_NO_OPENGL)
52 #if !defined(QT_OPENGL_ES_2)
53 #include "qglxintegration.h"
54 #include "private/qglxconvenience_p.h"
55 #else
56 #include "../eglconvenience/qeglconvenience.h"
57 #include "../eglconvenience/qeglplatformcontext.h"
58 #include "../eglconvenience/qxlibeglintegration.h"
59 #endif  //QT_OPENGL_ES_2
60 #endif //QT_NO_OPENGL
61
62
63 #include <QtGui/QWindowSystemInterface>
64 #include <QSocketNotifier>
65 #include <QApplication>
66 #include <QDebug>
67
68 //#define MYX11_DEBUG
69
70 QT_BEGIN_NAMESPACE
71
72 QHash<Window, QXlibWindow *> QXlibWindow::windowMap;
73
74
75 QXlibWindow::QXlibWindow(QWindow *window)
76     : QPlatformWindow(window)
77     , mGLContext(0)
78     , mScreen(QXlibScreen::testLiteScreenForWidget(window))
79 {
80     int x = window->x();
81     int y = window->y();
82     int w = window->width();
83     int h = window->height();
84
85 #if !defined(QT_NO_OPENGL)
86     if(window->surfaceType() == QWindow::OpenGLSurface) {
87 #if !defined(QT_OPENGL_ES_2)
88         XVisualInfo *visualInfo = qglx_findVisualInfo(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber(),
89                                                       window->format());
90 #else
91         QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat());
92
93         EGLDisplay eglDisplay = mScreen->eglDisplay();
94         EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat);
95         VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(), eglDisplay, eglConfig);
96
97         XVisualInfo visualInfoTemplate;
98         memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
99         visualInfoTemplate.visualid = id;
100
101         XVisualInfo *visualInfo;
102         int matchingCount = 0;
103         visualInfo = XGetVisualInfo(mScreen->display()->nativeDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount);
104 #endif //!defined(QT_OPENGL_ES_2)
105         if (visualInfo) {
106             mDepth = visualInfo->depth;
107             mFormat = (mDepth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
108             mVisual = visualInfo->visual;
109             Colormap cmap = XCreateColormap(mScreen->display()->nativeDisplay(), mScreen->rootWindow(), visualInfo->visual, AllocNone);
110
111             XSetWindowAttributes a;
112             a.background_pixel = WhitePixel(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber());
113             a.border_pixel = BlackPixel(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber());
114             a.colormap = cmap;
115             x_window = XCreateWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(),x, y, w, h,
116                                      0, visualInfo->depth, InputOutput, visualInfo->visual,
117                                      CWBackPixel|CWBorderPixel|CWColormap, &a);
118         } else {
119             qFatal("no window!");
120         }
121     } else
122 #endif //!defined(QT_NO_OPENGL)
123     {
124         mDepth = mScreen->depth();
125         mFormat = (mDepth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
126         mVisual = mScreen->defaultVisual();
127
128         x_window = XCreateSimpleWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(),
129                                        x, y, w, h, 0 /*border_width*/,
130                                        mScreen->blackPixel(), mScreen->whitePixel());
131     }
132
133 #ifdef MYX11_DEBUG
134     qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window;
135 #endif
136
137     XSetWindowBackgroundPixmap(mScreen->display()->nativeDisplay(), x_window, XNone);
138
139     XSelectInput(mScreen->display()->nativeDisplay(), x_window,
140                  ExposureMask | KeyPressMask | KeyReleaseMask |
141                  EnterWindowMask | LeaveWindowMask | FocusChangeMask |
142                  PointerMotionMask | ButtonPressMask |  ButtonReleaseMask |
143                  ButtonMotionMask | PropertyChangeMask |
144                  StructureNotifyMask);
145
146     gc = createGC();
147
148     Atom protocols[5];
149     int n = 0;
150     protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW);        // support del window protocol
151     protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_TAKE_FOCUS);                // support take focus window protocol
152 //    protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING);                // support _NET_WM_PING protocol
153 #ifndef QT_NO_XSYNC
154     protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_SYNC_REQUEST);        // support _NET_WM_SYNC_REQUEST protocol
155 #endif // QT_NO_XSYNC
156     if (window->windowFlags() & Qt::WindowContextHelpButtonHint)
157         protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_CONTEXT_HELP);
158     XSetWMProtocols(mScreen->display()->nativeDisplay(), x_window, protocols, n);
159
160     windowMap.insert(x_window, this);
161 }
162
163
164
165 QXlibWindow::~QXlibWindow()
166 {
167 #ifdef MYX11_DEBUG
168     qDebug() << "~QTestLiteWindow" << hex << x_window;
169 #endif
170
171     windowMap.remove(x_window);
172
173     delete mGLContext;
174     XFreeGC(mScreen->display()->nativeDisplay(), gc);
175     XDestroyWindow(mScreen->display()->nativeDisplay(), x_window);
176 }
177
178 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179 // Mouse event stuff
180 static Qt::MouseButtons translateMouseButtons(int s)
181 {
182     Qt::MouseButtons ret = 0;
183     if (s & Button1Mask)
184         ret |= Qt::LeftButton;
185     if (s & Button2Mask)
186         ret |= Qt::MidButton;
187     if (s & Button3Mask)
188         ret |= Qt::RightButton;
189     return ret;
190 }
191
192
193
194 void QXlibWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e)
195 {
196     static QPoint mousePoint;
197
198     Qt::MouseButton button = Qt::NoButton;
199     Qt::MouseButtons buttons = translateMouseButtons(e->state);
200     Qt::KeyboardModifiers modifiers = mScreen->keyboard()->translateModifiers(e->state);
201     if (type != QEvent::MouseMove) {
202         switch (e->button) {
203         case Button1: button = Qt::LeftButton; break;
204         case Button2: button = Qt::MidButton; break;
205         case Button3: button = Qt::RightButton; break;
206         case Button4:
207         case Button5:
208         case 6:
209         case 7: {
210             //mouse wheel
211             if (type == QEvent::MouseButtonPress) {
212                 //logic borrowed from qapplication_x11.cpp
213                 int delta = 120 * ((e->button == Button4 || e->button == 6) ? 1 : -1);
214                 bool hor = (((e->button == Button4 || e->button == Button5)
215                              && (modifiers & Qt::AltModifier))
216                             || (e->button == 6 || e->button == 7));
217                 QWindowSystemInterface::handleWheelEvent(window(), e->time,
218                                                       QPoint(e->x, e->y),
219                                                       QPoint(e->x_root, e->y_root),
220                                                       delta, hor ? Qt::Horizontal : Qt::Vertical);
221             }
222             return;
223         }
224         case 8: button = Qt::BackButton; break;      // Also known as Qt::ExtraButton1
225         case 9: button = Qt::ForwardButton; break;   // Also known as Qt::ExtraButton2
226         case 10: button = Qt::ExtraButton3; break;
227         case 11: button = Qt::ExtraButton4; break;
228         case 12: button = Qt::ExtraButton5; break;
229         case 13: button = Qt::ExtraButton6; break;
230         case 14: button = Qt::ExtraButton7; break;
231         case 15: button = Qt::ExtraButton8; break;
232         case 16: button = Qt::ExtraButton9; break;
233         case 17: button = Qt::ExtraButton10; break;
234         case 18: button = Qt::ExtraButton11; break;
235         case 19: button = Qt::ExtraButton12; break;
236         case 20: button = Qt::ExtraButton13; break;
237         case 21: button = Qt::ExtraButton14; break;
238         case 22: button = Qt::ExtraButton15; break;
239         case 23: button = Qt::ExtraButton16; break;
240         case 24: button = Qt::ExtraButton17; break;
241         case 25: button = Qt::ExtraButton18; break;
242         case 26: button = Qt::ExtraButton19; break;
243         case 27: button = Qt::ExtraButton20; break;
244         case 28: button = Qt::ExtraButton21; break;
245         case 29: button = Qt::ExtraButton22; break;
246         case 30: button = Qt::ExtraButton23; break;
247         case 31: button = Qt::ExtraButton24; break;
248         default: break;
249         }
250     }
251
252     buttons ^= button; // X event uses state *before*, Qt uses state *after*
253
254     QWindowSystemInterface::handleMouseEvent(window(), e->time, QPoint(e->x, e->y),
255                                           QPoint(e->x_root, e->y_root),
256                                           buttons);
257
258     mousePoint = QPoint(e->x_root, e->y_root);
259 }
260
261 void QXlibWindow::handleCloseEvent()
262 {
263     QWindowSystemInterface::handleCloseEvent(window());
264 }
265
266
267 void QXlibWindow::handleEnterEvent()
268 {
269     QWindowSystemInterface::handleEnterEvent(window());
270 }
271
272 void QXlibWindow::handleLeaveEvent()
273 {
274     QWindowSystemInterface::handleLeaveEvent(window());
275 }
276
277 void QXlibWindow::handleFocusInEvent()
278 {
279     QWindowSystemInterface::handleWindowActivated(window());
280 }
281
282 void QXlibWindow::handleFocusOutEvent()
283 {
284     QWindowSystemInterface::handleWindowActivated(0);
285 }
286
287
288
289 void QXlibWindow::setGeometry(const QRect &rect)
290 {
291     XMoveResizeWindow(mScreen->display()->nativeDisplay(), x_window, rect.x(), rect.y(), rect.width(), rect.height());
292     QPlatformWindow::setGeometry(rect);
293 }
294
295
296 Qt::WindowFlags QXlibWindow::windowFlags() const
297 {
298     return mWindowFlags;
299 }
300
301 WId QXlibWindow::winId() const
302 {
303     return x_window;
304 }
305
306 void QXlibWindow::setParent(const QPlatformWindow *parent)
307 {
308     QPoint topLeft = geometry().topLeft();
309     WId parentWinId = parent ? parent->winId() : mScreen->rootWindow();
310     XReparentWindow(mScreen->display()->nativeDisplay(),x_window,parentWinId,topLeft.x(),topLeft.y());
311 }
312
313 void QXlibWindow::raise()
314 {
315     XRaiseWindow(mScreen->display()->nativeDisplay(), x_window);
316 }
317
318 void QXlibWindow::lower()
319 {
320     XLowerWindow(mScreen->display()->nativeDisplay(), x_window);
321 }
322
323 void QXlibWindow::setWindowTitle(const QString &title)
324 {
325     QByteArray ba = title.toLatin1(); //We're not making a general solution here...
326     XTextProperty windowName;
327     windowName.value    = (unsigned char *)ba.constData();
328     windowName.encoding = XA_STRING;
329     windowName.format   = 8;
330     windowName.nitems   = ba.length();
331
332     XSetWMName(mScreen->display()->nativeDisplay(), x_window, &windowName);
333 }
334
335 GC QXlibWindow::createGC()
336 {
337     GC gc;
338
339     gc = XCreateGC(mScreen->display()->nativeDisplay(), x_window, 0, 0);
340     if (gc < 0) {
341         qWarning("QTestLiteWindow::createGC() could not create GC");
342     }
343     return gc;
344 }
345
346 void QXlibWindow::requestActivateWindow()
347 {
348     XSetInputFocus(mScreen->display()->nativeDisplay(), x_window, XRevertToParent, CurrentTime);
349 }
350
351 void QXlibWindow::resizeEvent(XConfigureEvent *e)
352 {
353     int xpos = geometry().x();
354     int ypos = geometry().y();
355     if ((e->width != geometry().width() || e->height != geometry().height()) && e->x == 0 && e->y == 0) {
356         //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window;
357     } else {
358         //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window;
359         xpos = e->x;
360         ypos = e->y;
361     }
362 #ifdef MYX11_DEBUG
363     qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height <<
364                 "geometry" << xpos << ypos << e->width << e->height;
365 #endif
366
367     QRect newRect(xpos, ypos, e->width, e->height);
368     QWindowSystemInterface::handleGeometryChange(window(), newRect);
369 }
370
371 void QXlibWindow::mousePressEvent(XButtonEvent *e)
372 {
373     static long prevTime = 0;
374     static Window prevWindow;
375     static int prevX = -999;
376     static int prevY = -999;
377
378     QEvent::Type type = QEvent::MouseButtonPress;
379
380     if (e->window == prevWindow && long(e->time) - prevTime < QApplication::doubleClickInterval()
381         && qAbs(e->x - prevX) < 5 && qAbs(e->y - prevY) < 5) {
382         type = QEvent::MouseButtonDblClick;
383         prevTime = e->time - QApplication::doubleClickInterval(); //no double click next time
384     } else {
385         prevTime = e->time;
386     }
387     prevWindow = e->window;
388     prevX = e->x;
389     prevY = e->y;
390
391     handleMouseEvent(type, e);
392 }
393
394 QXlibMWMHints QXlibWindow::getMWMHints() const
395 {
396     QXlibMWMHints mwmhints;
397
398     Atom type;
399     int format;
400     ulong nitems, bytesLeft;
401     uchar *data = 0;
402     Atom atomForMotifWmHints = QXlibStatic::atom(QXlibStatic::_MOTIF_WM_HINTS);
403     if ((XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, atomForMotifWmHints, 0, 5, false,
404                             atomForMotifWmHints, &type, &format, &nitems, &bytesLeft,
405                             &data) == Success)
406         && (type == atomForMotifWmHints
407             && format == 32
408             && nitems >= 5)) {
409         mwmhints = *(reinterpret_cast<QXlibMWMHints *>(data));
410     } else {
411         mwmhints.flags = 0L;
412         mwmhints.functions = MWM_FUNC_ALL;
413         mwmhints.decorations = MWM_DECOR_ALL;
414         mwmhints.input_mode = 0L;
415         mwmhints.status = 0L;
416     }
417
418     if (data)
419         XFree(data);
420
421     return mwmhints;
422 }
423
424 void QXlibWindow::setMWMHints(const QXlibMWMHints &mwmhints)
425 {
426     Atom atomForMotifWmHints = QXlibStatic::atom(QXlibStatic::_MOTIF_WM_HINTS);
427     if (mwmhints.flags != 0l) {
428         XChangeProperty(mScreen->display()->nativeDisplay(), x_window,
429                         atomForMotifWmHints, atomForMotifWmHints, 32,
430                         PropModeReplace, (unsigned char *) &mwmhints, 5);
431     } else {
432         XDeleteProperty(mScreen->display()->nativeDisplay(), x_window, atomForMotifWmHints);
433     }
434 }
435
436 // Returns true if we should set WM_TRANSIENT_FOR on \a w
437 static inline bool isTransient(const QWindow *w)
438 {
439     return (w->windowType() == Qt::Dialog
440              || w->windowType() == Qt::Sheet
441              || w->windowType() == Qt::Tool
442              || w->windowType() == Qt::SplashScreen
443              || w->windowType() == Qt::ToolTip
444              || w->windowType() == Qt::Drawer
445              || w->windowType() == Qt::Popup);
446 }
447
448 QVector<Atom> QXlibWindow::getNetWmState() const
449 {
450     QVector<Atom> returnValue;
451
452     // Don't read anything, just get the size of the property data
453     Atom actualType;
454     int actualFormat;
455     ulong propertyLength;
456     ulong bytesLeft;
457     uchar *propertyData = 0;
458     if (XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), 0, 0,
459                            False, XA_ATOM, &actualType, &actualFormat,
460                            &propertyLength, &bytesLeft, &propertyData) == Success
461         && actualType == XA_ATOM && actualFormat == 32) {
462         returnValue.resize(bytesLeft / 4);
463         XFree((char*) propertyData);
464
465         // fetch all data
466         if (XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), 0,
467                                returnValue.size(), False, XA_ATOM, &actualType, &actualFormat,
468                                &propertyLength, &bytesLeft, &propertyData) != Success) {
469             returnValue.clear();
470         } else if (propertyLength != (ulong)returnValue.size()) {
471             returnValue.resize(propertyLength);
472         }
473
474         // put it into netWmState
475         if (!returnValue.isEmpty()) {
476             memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
477         }
478         XFree((char*) propertyData);
479     }
480
481     return returnValue;
482 }
483
484 Qt::WindowFlags QXlibWindow::setWindowFlags(Qt::WindowFlags flags)
485 {
486 //    Q_ASSERT(flags & Qt::Window);
487     mWindowFlags = flags;
488
489 #ifdef MYX11_DEBUG
490     qDebug() << "QTestLiteWindow::setWindowFlags" << hex << x_window << "flags" << flags;
491 #endif
492     Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
493
494     if (type == Qt::ToolTip)
495         flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
496     if (type == Qt::Popup)
497         flags |= Qt::X11BypassWindowManagerHint;
498
499     bool topLevel = (flags & Qt::Window);
500     bool popup = (type == Qt::Popup);
501     bool dialog = (type == Qt::Dialog
502                    || type == Qt::Sheet);
503     bool desktop = (type == Qt::Desktop);
504     bool tool = (type == Qt::Tool || type == Qt::SplashScreen
505                  || type == Qt::ToolTip || type == Qt::Drawer);
506
507     Q_UNUSED(topLevel);
508     Q_UNUSED(dialog);
509     Q_UNUSED(desktop);
510
511     bool tooltip = (type == Qt::ToolTip);
512
513     XSetWindowAttributes wsa;
514
515     QXlibMWMHints mwmhints;
516     mwmhints.flags = 0L;
517     mwmhints.functions = 0L;
518     mwmhints.decorations = 0;
519     mwmhints.input_mode = 0L;
520     mwmhints.status = 0L;
521
522
523     ulong wsa_mask = 0;
524     if (type != Qt::SplashScreen) { // && customize) {
525         mwmhints.flags |= MWM_HINTS_DECORATIONS;
526
527         bool customize = flags & Qt::CustomizeWindowHint;
528         if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
529             mwmhints.decorations |= MWM_DECOR_BORDER;
530             mwmhints.decorations |= MWM_DECOR_RESIZEH;
531
532             if (flags & Qt::WindowTitleHint)
533                 mwmhints.decorations |= MWM_DECOR_TITLE;
534
535             if (flags & Qt::WindowSystemMenuHint)
536                 mwmhints.decorations |= MWM_DECOR_MENU;
537
538             if (flags & Qt::WindowMinimizeButtonHint) {
539                 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
540                 mwmhints.functions |= MWM_FUNC_MINIMIZE;
541             }
542
543             if (flags & Qt::WindowMaximizeButtonHint) {
544                 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
545                 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
546             }
547
548             if (flags & Qt::WindowCloseButtonHint)
549                 mwmhints.functions |= MWM_FUNC_CLOSE;
550         }
551     } else {
552         // if type == Qt::SplashScreen
553         mwmhints.decorations = MWM_DECOR_ALL;
554     }
555
556     if (tool) {
557         wsa.save_under = True;
558         wsa_mask |= CWSaveUnder;
559     }
560
561     if (flags & Qt::X11BypassWindowManagerHint) {
562         wsa.override_redirect = True;
563         wsa_mask |= CWOverrideRedirect;
564     }
565 #if 0
566     if (wsa_mask && initializeWindow) {
567         Q_ASSERT(id);
568         XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
569     }
570 #endif
571     if (mwmhints.functions != 0) {
572         mwmhints.flags |= MWM_HINTS_FUNCTIONS;
573         mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
574     } else {
575         mwmhints.functions = MWM_FUNC_ALL;
576     }
577
578     if (!(flags & Qt::FramelessWindowHint)
579         && flags & Qt::CustomizeWindowHint
580         && flags & Qt::WindowTitleHint
581         && !(flags &
582              (Qt::WindowMinimizeButtonHint
583               | Qt::WindowMaximizeButtonHint
584               | Qt::WindowCloseButtonHint))) {
585         // a special case - only the titlebar without any button
586         mwmhints.flags = MWM_HINTS_FUNCTIONS;
587         mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
588         mwmhints.decorations = 0;
589     }
590
591     if (window()->windowModality() == Qt::WindowModal) {
592         mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
593     } else if (window()->windowModality() == Qt::ApplicationModal) {
594         mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
595     }
596
597     setMWMHints(mwmhints);
598
599     QVector<Atom> netWmState = getNetWmState();
600
601     if (flags & Qt::WindowStaysOnTopHint) {
602         if (flags & Qt::WindowStaysOnBottomHint)
603             qWarning() << "QWindow: Incompatible window flags: the window can't be on top and on bottom at the same time";
604         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_ABOVE)))
605             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_ABOVE));
606         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_STAYS_ON_TOP)))
607             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_STAYS_ON_TOP));
608     } else if (flags & Qt::WindowStaysOnBottomHint) {
609         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_BELOW)))
610             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_BELOW));
611     }
612     if (window()->windowState() & Qt::WindowFullScreen) {
613         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_FULLSCREEN)))
614             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_FULLSCREEN));
615     }
616     if (window()->windowState() & Qt::WindowMaximized) {
617         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_HORZ)))
618             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_HORZ));
619         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_VERT)))
620             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_VERT));
621     }
622     if (window()->windowModality() != Qt::NonModal) {
623         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MODAL)))
624             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MODAL));
625     }
626
627     if (!netWmState.isEmpty()) {
628         XChangeProperty(mScreen->display()->nativeDisplay(), x_window,
629                         QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
630                         (unsigned char *) netWmState.data(), netWmState.size());
631     } else {
632         XDeleteProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE));
633     }
634
635 //##### only if initializeWindow???
636
637     if (popup || tooltip) {                        // popup widget
638 #ifdef MYX11_DEBUG
639         qDebug() << "Doing XChangeWindowAttributes for popup" << wsa.override_redirect;
640 #endif
641         // set EWMH window types
642         // setNetWmWindowTypes();
643
644         wsa.override_redirect = True;
645         wsa.save_under = True;
646         XChangeWindowAttributes(mScreen->display()->nativeDisplay(), x_window, CWOverrideRedirect | CWSaveUnder,
647                                 &wsa);
648     } else {
649 #ifdef MYX11_DEBUG
650         qDebug() << "Doing XChangeWindowAttributes for non-popup";
651 #endif
652     }
653
654     return flags;
655 }
656
657 Qt::WindowState QXlibWindow::setWindowState(Qt::WindowState state)
658 {
659     // ####
660     return state;
661 }
662
663 void QXlibWindow::setVisible(bool visible)
664 {
665 #ifdef MYX11_DEBUG
666     qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window;
667 #endif
668     if (isTransient(window())) {
669         Window parentXWindow = x_window;
670         QWindow *parent = window()->parent();
671         if (parent && parent->handle()) {
672             QXlibWindow *xlibParent = static_cast<QXlibWindow *>(parent->handle());
673             parentXWindow = xlibParent->x_window;
674         }
675         XSetTransientForHint(mScreen->display()->nativeDisplay(),x_window,parentXWindow);
676     }
677
678     if (visible) {
679         qDebug() << ">>> mapping";
680         //ensure that the window is viewed in correct position.
681         doSizeHints();
682         XMapWindow(mScreen->display()->nativeDisplay(), x_window);
683     } else {
684         XUnmapWindow(mScreen->display()->nativeDisplay(), x_window);
685     }
686 }
687
688 void QXlibWindow::setCursor(const Cursor &cursor)
689 {
690     XDefineCursor(mScreen->display()->nativeDisplay(), x_window, cursor);
691     mScreen->display()->flush();
692 }
693
694 QSurfaceFormat QXlibWindow::format() const
695 {
696     return window()->format();
697 }
698
699
700 Window QXlibWindow::xWindow() const
701 {
702     return x_window;
703 }
704
705 GC QXlibWindow::graphicsContext() const
706 {
707     return gc;
708 }
709
710 void QXlibWindow::doSizeHints()
711 {
712 //    Q_ASSERT(window()->testAttribute(Qt::WA_WState_Created));
713     XSizeHints s;
714     s.flags = 0;
715     QRect g = geometry();
716     s.x = g.x();
717     s.y = g.y();
718     s.width = g.width();
719     s.height = g.height();
720     s.flags |= USPosition;
721     s.flags |= PPosition;
722     s.flags |= USSize;
723     s.flags |= PSize;
724     s.flags |= PWinGravity;
725     s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
726     XSetWMNormalHints(mScreen->display()->nativeDisplay(), x_window, &s);
727 }
728
729
730 QXlibWindow *QXlibWindow::platformWindowForXWindow(Window window)
731 {
732     return windowMap.value(window);
733 }
734
735 QT_END_NAMESPACE