1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qxlibwindow.h"
43 
44 #include "qxlibintegration.h"
45 #include "qxlibscreen.h"
46 #include "qxlibkeyboard.h"
47 #include "qxlibstatic.h"
48 #include "qxlibdisplay.h"
49 
50 #if !defined(QT_NO_OPENGL)
51 #if !defined(QT_OPENGL_ES_2)
52 #include "qglxintegration.h"
53 #include "qglxconvenience.h"
54 #else
55 #include "../eglconvenience/qeglconvenience.h"
56 #include "../eglconvenience/qeglplatformcontext.h"
57 #include "../eglconvenience/qxlibeglintegration.h"
58 #endif  //QT_OPENGL_ES_2
59 #endif //QT_NO_OPENGL
60 
61 
62 #include <QtGui/QWindowSystemInterface>
63 #include <QSocketNotifier>
64 #include <QApplication>
65 #include <QDebug>
66 
67 #include <QtGui/private/qwindowsurface_p.h>
68 #include <QtGui/private/qapplication_p.h>
69 
70 //#define MYX11_DEBUG
71 
72 QT_BEGIN_NAMESPACE
73 
QXlibWindow(QWidget * window)74 QXlibWindow::QXlibWindow(QWidget *window)
75     : QPlatformWindow(window)
76     , mGLContext(0)
77     , mScreen(QXlibScreen::testLiteScreenForWidget(window))
78 {
79     int x = window->x();
80     int y = window->y();
81     int w = window->width();
82     int h = window->height();
83 
84 #if !defined(QT_NO_OPENGL)
85     if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL
86             && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)
87             || window->platformWindowFormat().alpha()) {
88 #if !defined(QT_OPENGL_ES_2)
89         XVisualInfo *visualInfo = qglx_findVisualInfo(mScreen->display()->nativeDisplay(),mScreen->xScreenNumber(),window->platformWindowFormat());
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 
161 
162 
~QXlibWindow()163 QXlibWindow::~QXlibWindow()
164 {
165 #ifdef MYX11_DEBUG
166     qDebug() << "~QTestLiteWindow" << hex << x_window;
167 #endif
168     delete mGLContext;
169     XFreeGC(mScreen->display()->nativeDisplay(), gc);
170     XDestroyWindow(mScreen->display()->nativeDisplay(), x_window);
171 }
172 
173 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
174 // Mouse event stuff
translateMouseButtons(int s)175 static Qt::MouseButtons translateMouseButtons(int s)
176 {
177     Qt::MouseButtons ret = 0;
178     if (s & Button1Mask)
179         ret |= Qt::LeftButton;
180     if (s & Button2Mask)
181         ret |= Qt::MidButton;
182     if (s & Button3Mask)
183         ret |= Qt::RightButton;
184     return ret;
185 }
186 
187 
188 
handleMouseEvent(QEvent::Type type,XButtonEvent * e)189 void QXlibWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e)
190 {
191     static QPoint mousePoint;
192 
193     Qt::MouseButton button = Qt::NoButton;
194     Qt::MouseButtons buttons = translateMouseButtons(e->state);
195     Qt::KeyboardModifiers modifiers = mScreen->keyboard()->translateModifiers(e->state);
196     if (type != QEvent::MouseMove) {
197         switch (e->button) {
198         case Button1: button = Qt::LeftButton; break;
199         case Button2: button = Qt::MidButton; break;
200         case Button3: button = Qt::RightButton; break;
201         case Button4:
202         case Button5:
203         case 6:
204         case 7: {
205             //mouse wheel
206             if (type == QEvent::MouseButtonPress) {
207                 //logic borrowed from qapplication_x11.cpp
208                 int delta = 120 * ((e->button == Button4 || e->button == 6) ? 1 : -1);
209                 bool hor = (((e->button == Button4 || e->button == Button5)
210                              && (modifiers & Qt::AltModifier))
211                             || (e->button == 6 || e->button == 7));
212                 QWindowSystemInterface::handleWheelEvent(widget(), e->time,
213                                                       QPoint(e->x, e->y),
214                                                       QPoint(e->x_root, e->y_root),
215                                                       delta, hor ? Qt::Horizontal : Qt::Vertical);
216             }
217             return;
218         }
219         default: break;
220         }
221     }
222 
223     buttons ^= button; // X event uses state *before*, Qt uses state *after*
224 
225     QWindowSystemInterface::handleMouseEvent(widget(), e->time, QPoint(e->x, e->y),
226                                           QPoint(e->x_root, e->y_root),
227                                           buttons);
228 
229     mousePoint = QPoint(e->x_root, e->y_root);
230 }
231 
handleCloseEvent()232 void QXlibWindow::handleCloseEvent()
233 {
234     QWindowSystemInterface::handleCloseEvent(widget());
235 }
236 
237 
handleEnterEvent()238 void QXlibWindow::handleEnterEvent()
239 {
240     QWindowSystemInterface::handleEnterEvent(widget());
241 }
242 
handleLeaveEvent()243 void QXlibWindow::handleLeaveEvent()
244 {
245     QWindowSystemInterface::handleLeaveEvent(widget());
246 }
247 
handleFocusInEvent()248 void QXlibWindow::handleFocusInEvent()
249 {
250     QWindowSystemInterface::handleWindowActivated(widget());
251 }
252 
handleFocusOutEvent()253 void QXlibWindow::handleFocusOutEvent()
254 {
255     QWindowSystemInterface::handleWindowActivated(0);
256 }
257 
258 
259 
setGeometry(const QRect & rect)260 void QXlibWindow::setGeometry(const QRect &rect)
261 {
262     XMoveResizeWindow(mScreen->display()->nativeDisplay(), x_window, rect.x(), rect.y(), rect.width(), rect.height());
263     QPlatformWindow::setGeometry(rect);
264 }
265 
266 
windowFlags() const267 Qt::WindowFlags QXlibWindow::windowFlags() const
268 {
269     return mWindowFlags;
270 }
271 
winId() const272 WId QXlibWindow::winId() const
273 {
274     return x_window;
275 }
276 
setParent(const QPlatformWindow * window)277 void QXlibWindow::setParent(const QPlatformWindow *window)
278 {
279     QPoint topLeft = geometry().topLeft();
280     XReparentWindow(mScreen->display()->nativeDisplay(),x_window,window->winId(),topLeft.x(),topLeft.y());
281 }
282 
raise()283 void QXlibWindow::raise()
284 {
285     XRaiseWindow(mScreen->display()->nativeDisplay(), x_window);
286 }
287 
lower()288 void QXlibWindow::lower()
289 {
290     XLowerWindow(mScreen->display()->nativeDisplay(), x_window);
291 }
292 
setWindowTitle(const QString & title)293 void QXlibWindow::setWindowTitle(const QString &title)
294 {
295     QByteArray ba = title.toLatin1(); //We're not making a general solution here...
296     XTextProperty windowName;
297     windowName.value    = (unsigned char *)ba.constData();
298     windowName.encoding = XA_STRING;
299     windowName.format   = 8;
300     windowName.nitems   = ba.length();
301 
302     XSetWMName(mScreen->display()->nativeDisplay(), x_window, &windowName);
303 }
304 
createGC()305 GC QXlibWindow::createGC()
306 {
307     GC gc;
308 
309     gc = XCreateGC(mScreen->display()->nativeDisplay(), x_window, 0, 0);
310     if (gc < 0) {
311         qWarning("QTestLiteWindow::createGC() could not create GC");
312     }
313     return gc;
314 }
315 
paintEvent()316 void QXlibWindow::paintEvent()
317 {
318 #ifdef MYX11_DEBUG
319 //    qDebug() << "QTestLiteWindow::paintEvent" << shm_img.size() << painted;
320 #endif
321 
322     if (QWindowSurface *surface = widget()->windowSurface())
323         surface->flush(widget(), widget()->geometry(), QPoint());
324 }
325 
requestActivateWindow()326 void QXlibWindow::requestActivateWindow()
327 {
328     XSetInputFocus(mScreen->display()->nativeDisplay(), x_window, XRevertToParent, CurrentTime);
329 }
330 
resizeEvent(XConfigureEvent * e)331 void QXlibWindow::resizeEvent(XConfigureEvent *e)
332 {
333     int xpos = geometry().x();
334     int ypos = geometry().y();
335     if ((e->width != geometry().width() || e->height != geometry().height()) && e->x == 0 && e->y == 0) {
336         //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window;
337     } else {
338         //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window;
339         xpos = e->x;
340         ypos = e->y;
341     }
342 #ifdef MYX11_DEBUG
343     qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height << "geometry" << xpos << ypos << width << height;
344 #endif
345 
346     QRect newRect(xpos, ypos, e->width, e->height);
347     QWindowSystemInterface::handleGeometryChange(widget(), newRect);
348 }
349 
mousePressEvent(XButtonEvent * e)350 void QXlibWindow::mousePressEvent(XButtonEvent *e)
351 {
352     static long prevTime = 0;
353     static Window prevWindow;
354     static int prevX = -999;
355     static int prevY = -999;
356 
357     QEvent::Type type = QEvent::MouseButtonPress;
358 
359     if (e->window == prevWindow && long(e->time) - prevTime < QApplication::doubleClickInterval()
360         && qAbs(e->x - prevX) < 5 && qAbs(e->y - prevY) < 5) {
361         type = QEvent::MouseButtonDblClick;
362         prevTime = e->time - QApplication::doubleClickInterval(); //no double click next time
363     } else {
364         prevTime = e->time;
365     }
366     prevWindow = e->window;
367     prevX = e->x;
368     prevY = e->y;
369 
370     handleMouseEvent(type, e);
371 }
372 
getMWMHints() const373 QXlibMWMHints QXlibWindow::getMWMHints() const
374 {
375     QXlibMWMHints mwmhints;
376 
377     Atom type;
378     int format;
379     ulong nitems, bytesLeft;
380     uchar *data = 0;
381     Atom atomForMotifWmHints = QXlibStatic::atom(QXlibStatic::_MOTIF_WM_HINTS);
382     if ((XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, atomForMotifWmHints, 0, 5, false,
383                             atomForMotifWmHints, &type, &format, &nitems, &bytesLeft,
384                             &data) == Success)
385         && (type == atomForMotifWmHints
386             && format == 32
387             && nitems >= 5)) {
388         mwmhints = *(reinterpret_cast<QXlibMWMHints *>(data));
389     } else {
390         mwmhints.flags = 0L;
391         mwmhints.functions = MWM_FUNC_ALL;
392         mwmhints.decorations = MWM_DECOR_ALL;
393         mwmhints.input_mode = 0L;
394         mwmhints.status = 0L;
395     }
396 
397     if (data)
398         XFree(data);
399 
400     return mwmhints;
401 }
402 
setMWMHints(const QXlibMWMHints & mwmhints)403 void QXlibWindow::setMWMHints(const QXlibMWMHints &mwmhints)
404 {
405     Atom atomForMotifWmHints = QXlibStatic::atom(QXlibStatic::_MOTIF_WM_HINTS);
406     if (mwmhints.flags != 0l) {
407         XChangeProperty(mScreen->display()->nativeDisplay(), x_window,
408                         atomForMotifWmHints, atomForMotifWmHints, 32,
409                         PropModeReplace, (unsigned char *) &mwmhints, 5);
410     } else {
411         XDeleteProperty(mScreen->display()->nativeDisplay(), x_window, atomForMotifWmHints);
412     }
413 }
414 
415 // Returns true if we should set WM_TRANSIENT_FOR on \a w
isTransient(const QWidget * w)416 static inline bool isTransient(const QWidget *w)
417 {
418     return ((w->windowType() == Qt::Dialog
419              || w->windowType() == Qt::Sheet
420              || w->windowType() == Qt::Tool
421              || w->windowType() == Qt::SplashScreen
422              || w->windowType() == Qt::ToolTip
423              || w->windowType() == Qt::Drawer
424              || w->windowType() == Qt::Popup)
425             && !w->testAttribute(Qt::WA_X11BypassTransientForHint));
426 }
427 
getNetWmState() const428 QVector<Atom> QXlibWindow::getNetWmState() const
429 {
430     QVector<Atom> returnValue;
431 
432     // Don't read anything, just get the size of the property data
433     Atom actualType;
434     int actualFormat;
435     ulong propertyLength;
436     ulong bytesLeft;
437     uchar *propertyData = 0;
438     if (XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), 0, 0,
439                            False, XA_ATOM, &actualType, &actualFormat,
440                            &propertyLength, &bytesLeft, &propertyData) == Success
441         && actualType == XA_ATOM && actualFormat == 32) {
442         returnValue.resize(bytesLeft / 4);
443         XFree((char*) propertyData);
444 
445         // fetch all data
446         if (XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), 0,
447                                returnValue.size(), False, XA_ATOM, &actualType, &actualFormat,
448                                &propertyLength, &bytesLeft, &propertyData) != Success) {
449             returnValue.clear();
450         } else if (propertyLength != (ulong)returnValue.size()) {
451             returnValue.resize(propertyLength);
452         }
453 
454         // put it into netWmState
455         if (!returnValue.isEmpty()) {
456             memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
457         }
458         XFree((char*) propertyData);
459     }
460 
461     return returnValue;
462 }
463 
setWindowFlags(Qt::WindowFlags flags)464 Qt::WindowFlags QXlibWindow::setWindowFlags(Qt::WindowFlags flags)
465 {
466 //    Q_ASSERT(flags & Qt::Window);
467     mWindowFlags = flags;
468 
469 #ifdef MYX11_DEBUG
470     qDebug() << "QTestLiteWindow::setWindowFlags" << hex << x_window << "flags" << flags;
471 #endif
472     Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
473 
474     if (type == Qt::ToolTip)
475         flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
476     if (type == Qt::Popup)
477         flags |= Qt::X11BypassWindowManagerHint;
478 
479     bool topLevel = (flags & Qt::Window);
480     bool popup = (type == Qt::Popup);
481     bool dialog = (type == Qt::Dialog
482                    || type == Qt::Sheet);
483     bool desktop = (type == Qt::Desktop);
484     bool tool = (type == Qt::Tool || type == Qt::SplashScreen
485                  || type == Qt::ToolTip || type == Qt::Drawer);
486 
487     Q_UNUSED(topLevel);
488     Q_UNUSED(dialog);
489     Q_UNUSED(desktop);
490 
491     bool tooltip = (type == Qt::ToolTip);
492 
493     XSetWindowAttributes wsa;
494 
495     QXlibMWMHints mwmhints;
496     mwmhints.flags = 0L;
497     mwmhints.functions = 0L;
498     mwmhints.decorations = 0;
499     mwmhints.input_mode = 0L;
500     mwmhints.status = 0L;
501 
502 
503     ulong wsa_mask = 0;
504     if (type != Qt::SplashScreen) { // && customize) {
505         mwmhints.flags |= MWM_HINTS_DECORATIONS;
506 
507         bool customize = flags & Qt::CustomizeWindowHint;
508         if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
509             mwmhints.decorations |= MWM_DECOR_BORDER;
510             mwmhints.decorations |= MWM_DECOR_RESIZEH;
511 
512             if (flags & Qt::WindowTitleHint)
513                 mwmhints.decorations |= MWM_DECOR_TITLE;
514 
515             if (flags & Qt::WindowSystemMenuHint)
516                 mwmhints.decorations |= MWM_DECOR_MENU;
517 
518             if (flags & Qt::WindowMinimizeButtonHint) {
519                 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
520                 mwmhints.functions |= MWM_FUNC_MINIMIZE;
521             }
522 
523             if (flags & Qt::WindowMaximizeButtonHint) {
524                 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
525                 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
526             }
527 
528             if (flags & Qt::WindowCloseButtonHint)
529                 mwmhints.functions |= MWM_FUNC_CLOSE;
530         }
531     } else {
532         // if type == Qt::SplashScreen
533         mwmhints.decorations = MWM_DECOR_ALL;
534     }
535 
536     if (tool) {
537         wsa.save_under = True;
538         wsa_mask |= CWSaveUnder;
539     }
540 
541     if (flags & Qt::X11BypassWindowManagerHint) {
542         wsa.override_redirect = True;
543         wsa_mask |= CWOverrideRedirect;
544     }
545 #if 0
546     if (wsa_mask && initializeWindow) {
547         Q_ASSERT(id);
548         XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
549     }
550 #endif
551     if (mwmhints.functions != 0) {
552         mwmhints.flags |= MWM_HINTS_FUNCTIONS;
553         mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
554     } else {
555         mwmhints.functions = MWM_FUNC_ALL;
556     }
557 
558     if (!(flags & Qt::FramelessWindowHint)
559         && flags & Qt::CustomizeWindowHint
560         && flags & Qt::WindowTitleHint
561         && !(flags &
562              (Qt::WindowMinimizeButtonHint
563               | Qt::WindowMaximizeButtonHint
564               | Qt::WindowCloseButtonHint))) {
565         // a special case - only the titlebar without any button
566         mwmhints.flags = MWM_HINTS_FUNCTIONS;
567         mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
568         mwmhints.decorations = 0;
569     }
570 
571     if (widget()->windowModality() == Qt::WindowModal) {
572         mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
573     } else if (widget()->windowModality() == Qt::ApplicationModal) {
574         mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
575     }
576 
577     setMWMHints(mwmhints);
578 
579     QVector<Atom> netWmState = getNetWmState();
580 
581     if (flags & Qt::WindowStaysOnTopHint) {
582         if (flags & Qt::WindowStaysOnBottomHint)
583             qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
584         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_ABOVE)))
585             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_ABOVE));
586         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_STAYS_ON_TOP)))
587             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_STAYS_ON_TOP));
588     } else if (flags & Qt::WindowStaysOnBottomHint) {
589         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_BELOW)))
590             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_BELOW));
591     }
592     if (widget()->isFullScreen()) {
593         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_FULLSCREEN)))
594             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_FULLSCREEN));
595     }
596     if (widget()->isMaximized()) {
597         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_HORZ)))
598             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_HORZ));
599         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_VERT)))
600             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_VERT));
601     }
602     if (widget()->windowModality() != Qt::NonModal) {
603         if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MODAL)))
604             netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MODAL));
605     }
606 
607     if (!netWmState.isEmpty()) {
608         XChangeProperty(mScreen->display()->nativeDisplay(), x_window,
609                         QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
610                         (unsigned char *) netWmState.data(), netWmState.size());
611     } else {
612         XDeleteProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE));
613     }
614 
615 //##### only if initializeWindow???
616 
617     if (popup || tooltip) {                        // popup widget
618 #ifdef MYX11_DEBUG
619         qDebug() << "Doing XChangeWindowAttributes for popup" << wsa.override_redirect;
620 #endif
621         // set EWMH window types
622         // setNetWmWindowTypes();
623 
624         wsa.override_redirect = True;
625         wsa.save_under = True;
626         XChangeWindowAttributes(mScreen->display()->nativeDisplay(), x_window, CWOverrideRedirect | CWSaveUnder,
627                                 &wsa);
628     } else {
629 #ifdef MYX11_DEBUG
630         qDebug() << "Doing XChangeWindowAttributes for non-popup";
631 #endif
632     }
633 
634     return flags;
635 }
636 
setVisible(bool visible)637 void QXlibWindow::setVisible(bool visible)
638 {
639 #ifdef MYX11_DEBUG
640     qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window;
641 #endif
642     if (isTransient(widget())) {
643         Window parentXWindow = x_window;
644         if (widget()->parentWidget()) {
645             QWidget *widgetParent = widget()->parentWidget()->window();
646             if (widgetParent && widgetParent->platformWindow()) {
647                 QXlibWindow *parentWidnow = static_cast<QXlibWindow *>(widgetParent->platformWindow());
648                 parentXWindow = parentWidnow->x_window;
649             }
650         }
651         XSetTransientForHint(mScreen->display()->nativeDisplay(),x_window,parentXWindow);
652     }
653 
654     if (visible) {
655         //ensure that the window is viewed in correct position.
656         doSizeHints();
657         XMapWindow(mScreen->display()->nativeDisplay(), x_window);
658     } else {
659         XUnmapWindow(mScreen->display()->nativeDisplay(), x_window);
660     }
661 }
662 
setCursor(const Cursor & cursor)663 void QXlibWindow::setCursor(const Cursor &cursor)
664 {
665     XDefineCursor(mScreen->display()->nativeDisplay(), x_window, cursor);
666     mScreen->display()->flush();
667 }
668 
glContext() const669 QPlatformGLContext *QXlibWindow::glContext() const
670 {
671     if (!QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
672         return 0;
673     if (!mGLContext) {
674         QXlibWindow *that = const_cast<QXlibWindow *>(this);
675 #if !defined(QT_NO_OPENGL)
676 #if !defined(QT_OPENGL_ES_2)
677         that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat());
678 #else
679         EGLDisplay display = mScreen->eglDisplay();
680 
681         QPlatformWindowFormat windowFormat = correctColorBuffers(widget()->platformWindowFormat());
682 
683         EGLConfig config = q_configFromQPlatformWindowFormat(display,windowFormat);
684         QVector<EGLint> eglContextAttrs;
685         eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
686         eglContextAttrs.append(2);
687         eglContextAttrs.append(EGL_NONE);
688 
689         EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)x_window,0);
690         that->mGLContext = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API, static_cast<QEGLPlatformContext *>(windowFormat.sharedGLContext()));
691 #endif
692 #endif
693     }
694     return mGLContext;
695 }
696 
xWindow() const697 Window QXlibWindow::xWindow() const
698 {
699     return x_window;
700 }
701 
graphicsContext() const702 GC QXlibWindow::graphicsContext() const
703 {
704     return gc;
705 }
706 
doSizeHints()707 void QXlibWindow::doSizeHints()
708 {
709     Q_ASSERT(widget()->testAttribute(Qt::WA_WState_Created));
710     XSizeHints s;
711     s.flags = 0;
712     QRect g = geometry();
713     s.x = g.x();
714     s.y = g.y();
715     s.width = g.width();
716     s.height = g.height();
717     s.flags |= USPosition;
718     s.flags |= PPosition;
719     s.flags |= USSize;
720     s.flags |= PSize;
721     s.flags |= PWinGravity;
722     s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
723     XSetWMNormalHints(mScreen->display()->nativeDisplay(), x_window, &s);
724 }
725 
correctColorBuffers(const QPlatformWindowFormat & platformWindowFormat) const726 QPlatformWindowFormat QXlibWindow::correctColorBuffers(const QPlatformWindowFormat &platformWindowFormat) const
727 {
728     // I have only tested this setup on a dodgy intel setup, where I didn't use standard libs,
729     // so this might be not what we want to do :)
730     if ( !(platformWindowFormat.redBufferSize() == -1   &&
731            platformWindowFormat.greenBufferSize() == -1 &&
732            platformWindowFormat.blueBufferSize() == -1))
733         return platformWindowFormat;
734 
735     QPlatformWindowFormat windowFormat = platformWindowFormat;
736     if (mScreen->depth() == 16) {
737         windowFormat.setRedBufferSize(5);
738         windowFormat.setGreenBufferSize(6);
739         windowFormat.setBlueBufferSize(5);
740     } else {
741         windowFormat.setRedBufferSize(8);
742         windowFormat.setGreenBufferSize(8);
743         windowFormat.setBlueBufferSize(8);
744     }
745 
746     return windowFormat;
747 }
748 
749 QT_END_NAMESPACE
750