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