source: trunk/src/gui/kernel/qwidget_x11.cpp@ 802

Last change on this file since 802 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 107.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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 "qdatetime.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
88QT_BEGIN_NAMESPACE
89
90extern bool qt_nograb();
91
92QWidget *QWidgetPrivate::mouseGrabber = 0;
93QWidget *QWidgetPrivate::keyboardGrabber = 0;
94
95void qt_net_remove_user_time(QWidget *tlw);
96void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
97
98int qt_x11_create_desktop_on_screen = -1;
99
100extern void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
101
102// MWM support
103struct QtMWMHints {
104 ulong flags, functions, decorations;
105 long input_mode;
106 ulong status;
107};
108
109enum {
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
137static 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
166static 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
177static 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
189static void do_size_hints(QWidget* widget, QWExtra *x);
190
191/*****************************************************************************
192 QWidget member functions
193 *****************************************************************************/
194
195const 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
208const 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
220Window 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);
226Window 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);
230void qt_XDestroyWindow(const QWidget *destroyer,
231 Display *display, Window window);
232
233
234static 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
252static 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
265static 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 */
298void 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
344Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
345{
346 qt_x11_enforce_cursor(w, false);
347}
348
349Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
350{
351 if (!w || (!w->isWindow() && !w->internalWinId()))
352 return;
353 QApplication::flush();
354 XEvent ev;
355 QTime 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 QApplication::sendPostedEvents();
365
366 // the normal sequence is:
367 // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
368 // with X11BypassWindowManagerHint:
369 // ConfigureNotify ... MapNotify ... Expose
370
371 enum State {
372 Initial, Mapped
373 } state = Initial;
374
375 do {
376 if (XEventsQueued(X11->display, QueuedAlready)) {
377 XNextEvent(X11->display, &ev);
378 qApp->x11ProcessEvent(&ev);
379
380 switch (state) {
381 case Initial:
382 if (ev.type == MapNotify && ev.xany.window == winid)
383 state = Mapped;
384 break;
385 case Mapped:
386 if (ev.type == Expose && ev.xany.window == winid)
387 return;
388 break;
389 }
390 } else {
391 if (!XEventsQueued(X11->display, QueuedAfterFlush))
392 qApp->syncX(); // non-busy wait
393 }
394 if (t.elapsed() > maximumWaitTime)
395 return;
396 } while(1);
397}
398
399void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
400{
401 if (!w->isVisible()) // not managed by the window manager
402 return;
403
404 XEvent e;
405 e.xclient.type = ClientMessage;
406 e.xclient.message_type = ATOM(_NET_WM_STATE);
407 e.xclient.display = X11->display;
408 e.xclient.window = w->internalWinId();
409 e.xclient.format = 32;
410 e.xclient.data.l[0] = set ? 1 : 0;
411 e.xclient.data.l[1] = one;
412 e.xclient.data.l[2] = two;
413 e.xclient.data.l[3] = 0;
414 e.xclient.data.l[4] = 0;
415 XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()),
416 false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
417}
418
419struct QX11WindowAttributes {
420 const XWindowAttributes *att;
421};
422
423void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a)
424{
425 QX11WindowAttributes att;
426 att.att = &a;
427 qt_x11_getX11InfoForWindow(xinfo,att);
428}
429
430
431static QVector<Atom> getNetWmState(QWidget *w)
432{
433 QVector<Atom> returnValue;
434
435 // Don't read anything, just get the size of the property data
436 Atom actualType;
437 int actualFormat;
438 ulong propertyLength;
439 ulong bytesLeft;
440 uchar *propertyData = 0;
441 if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, 0,
442 False, XA_ATOM, &actualType, &actualFormat,
443 &propertyLength, &bytesLeft, &propertyData) == Success
444 && actualType == XA_ATOM && actualFormat == 32) {
445 returnValue.resize(bytesLeft / 4);
446 XFree((char*) propertyData);
447
448 // fetch all data
449 if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0,
450 returnValue.size(), False, XA_ATOM, &actualType, &actualFormat,
451 &propertyLength, &bytesLeft, &propertyData) != Success) {
452 returnValue.clear();
453 } else if (propertyLength != (ulong)returnValue.size()) {
454 returnValue.resize(propertyLength);
455 }
456
457 // put it into netWmState
458 if (!returnValue.isEmpty()) {
459 memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom));
460 }
461 XFree((char*) propertyData);
462 }
463
464 return returnValue;
465}
466
467void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
468{
469 Q_Q(QWidget);
470 Qt::WindowType type = q->windowType();
471 Qt::WindowFlags &flags = data.window_flags;
472 QWidget *parentWidget = q->parentWidget();
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#ifdef ALIEN_DEBUG
488 qDebug() << "QWidgetPrivate::create_sys START:" << q << "topLevel?" << topLevel << "WId:"
489 << window << "initializeWindow:" << initializeWindow << "destroyOldWindow" << destroyOldWindow;
490#endif
491 if (topLevel) {
492 if (parentWidget) { // if our parent stays on top, so must we
493 QWidget *ptl = parentWidget->window();
494 if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
495 flags |= Qt::WindowStaysOnTopHint;
496 }
497
498 if (type == Qt::SplashScreen) {
499 if (X11->isSupportedByWM(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
500 flags &= ~Qt::X11BypassWindowManagerHint;
501 } else {
502 flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
503 }
504 }
505 // All these buttons depend on the system menu, so we enable it
506 if (flags & (Qt::WindowMinimizeButtonHint
507 | Qt::WindowMaximizeButtonHint
508 | Qt::WindowContextHelpButtonHint))
509 flags |= Qt::WindowSystemMenuHint;
510 }
511
512
513 Window parentw, destroyw = 0;
514 WId id = 0;
515
516 // always initialize
517 if (!window)
518 initializeWindow = true;
519
520 QX11Info *parentXinfo = parentWidget ? &parentWidget->d_func()->xinfo : 0;
521
522 if (desktop &&
523 qt_x11_create_desktop_on_screen >= 0 &&
524 qt_x11_create_desktop_on_screen != xinfo.screen()) {
525 // desktop on a certain screen other than the default requested
526 QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen];
527 xinfo.setX11Data(xd);
528 } else if (parentXinfo && (parentXinfo->screen() != xinfo.screen()
529 || (parentXinfo->visual() != xinfo.visual()
530 && !q->inherits("QGLWidget"))))
531 {
532 // QGLWidgets have to be excluded here as they have a
533 // specially crafted QX11Info structure which can't be swapped
534 // out with the parent widgets QX11Info. The parent visual,
535 // for instance, might not even be GL capable.
536 xinfo = *parentXinfo;
537 }
538
539 //get display, screen number, root window and desktop geometry for
540 //the current screen
541 Display *dpy = X11->display;
542 int scr = xinfo.screen();
543 Window root_win = RootWindow(dpy, scr);
544 int sw = DisplayWidth(dpy,scr);
545 int sh = DisplayHeight(dpy,scr);
546
547 if (desktop) { // desktop widget
548 dialog = popup = false; // force these flags off
549 data.crect.setRect(0, 0, sw, sh);
550 } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
551 QDesktopWidget *desktopWidget = qApp->desktop();
552 if (desktopWidget->isVirtualDesktop()) {
553 QRect r = desktopWidget->screenGeometry();
554 sw = r.width();
555 sh = r.height();
556 }
557
558 int width = sw / 2;
559 int height = 4 * sh / 10;
560 if (extra) {
561 width = qMax(qMin(width, extra->maxw), extra->minw);
562 height = qMax(qMin(height, extra->maxh), extra->minh);
563 }
564 data.crect.setSize(QSize(width, height));
565 }
566
567 parentw = topLevel ? root_win : parentWidget->effectiveWinId();
568
569 XSetWindowAttributes wsa;
570
571 if (window) { // override the old window
572 if (destroyOldWindow) {
573 if (topLevel)
574 X11->dndEnable(q, false);
575 destroyw = data.winid;
576 }
577 id = window;
578 setWinId(window);
579 XWindowAttributes a;
580 XGetWindowAttributes(dpy, window, &a);
581 data.crect.setRect(a.x, a.y, a.width, a.height);
582
583 if (a.map_state == IsUnmapped)
584 q->setAttribute(Qt::WA_WState_Visible, false);
585 else
586 q->setAttribute(Qt::WA_WState_Visible);
587
588 qt_x11_getX11InfoForWindow(&xinfo,a);
589
590 } else if (desktop) { // desktop widget
591#ifdef QWIDGET_EXTRA_DEBUG
592 qDebug() << "create desktop";
593#endif
594 id = (WId)parentw; // id = root window
595// QWidget *otherDesktop = find(id); // is there another desktop?
596// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
597// otherDesktop->d->setWinId(0); // remove id from widget mapper
598// d->setWinId(id); // make sure otherDesktop is
599// otherDesktop->d->setWinId(id); // found first
600// } else {
601 setWinId(id);
602// }
603 } else if (topLevel || q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) {
604#ifdef QWIDGET_EXTRA_DEBUG
605 static int topLevels = 0;
606 static int children = 0;
607 if (parentw == root_win)
608 qDebug() << "create toplevel" << ++topLevels;
609 else
610 qDebug() << "create child" << ++children;
611#endif
612 QRect safeRect = data.crect; //##### must handle huge sizes as well.... i.e. wrect
613 if (safeRect.width() < 1|| safeRect.height() < 1) {
614 if (topLevel) {
615 // top-levels must be at least 1x1
616 safeRect.setSize(safeRect.size().expandedTo(QSize(1, 1)));
617 } else {
618 // create it way off screen, and rely on
619 // setWSGeometry() to do the right thing with it later
620 safeRect = QRect(-1000,-1000,1,1);
621 }
622 }
623#ifndef QT_NO_XRENDER
624 int screen = xinfo.screen();
625 if (topLevel && X11->use_xrender
626 && xinfo.depth() != 32 && X11->argbVisuals[screen]
627 && q->testAttribute(Qt::WA_TranslucentBackground))
628 {
629 QX11InfoData *xd = xinfo.getX11Data(true);
630
631 xd->screen = screen;
632 xd->visual = X11->argbVisuals[screen];
633 xd->colormap = X11->argbColormaps[screen];
634 xd->depth = 32;
635 xd->defaultVisual = false;
636 xd->defaultColormap = false;
637 xd->cells = xd->visual->map_entries;
638 xinfo.setX11Data(xd);
639 }
640#endif
641 if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
642 id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
643 safeRect.left(), safeRect.top(),
644 safeRect.width(), safeRect.height(),
645 0,
646 BlackPixel(dpy, xinfo.screen()),
647 WhitePixel(dpy, xinfo.screen()));
648 } else {
649 wsa.background_pixel = WhitePixel(dpy, xinfo.screen());
650 wsa.border_pixel = BlackPixel(dpy, xinfo.screen());
651 wsa.colormap = xinfo.colormap();
652 id = (WId)qt_XCreateWindow(q, dpy, parentw,
653 safeRect.left(), safeRect.top(),
654 safeRect.width(), safeRect.height(),
655 0, xinfo.depth(), InputOutput,
656 (Visual *) xinfo.visual(),
657 CWBackPixel|CWBorderPixel|CWColormap,
658 &wsa);
659 }
660
661 setWinId(id); // set widget id/handle + hd
662 }
663
664#ifndef QT_NO_XRENDER
665 if (picture) {
666 XRenderFreePicture(X11->display, picture);
667 picture = 0;
668 }
669
670 if (X11->use_xrender && !desktop && q->internalWinId()) {
671 XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual());
672 if (format)
673 picture = XRenderCreatePicture(dpy, id, format, 0, 0);
674 }
675#endif // QT_NO_XRENDER
676
677 QtMWMHints mwmhints;
678 mwmhints.flags = 0L;
679 mwmhints.functions = 0L;
680 mwmhints.decorations = 0;
681 mwmhints.input_mode = 0L;
682 mwmhints.status = 0L;
683
684 if (topLevel) {
685 ulong wsa_mask = 0;
686 if (type != Qt::SplashScreen) { // && customize) {
687 mwmhints.flags |= MWM_HINTS_DECORATIONS;
688
689 bool customize = flags & Qt::CustomizeWindowHint;
690 if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
691 mwmhints.decorations |= MWM_DECOR_BORDER;
692 mwmhints.decorations |= MWM_DECOR_RESIZEH;
693
694 if (flags & Qt::WindowTitleHint)
695 mwmhints.decorations |= MWM_DECOR_TITLE;
696
697 if (flags & Qt::WindowSystemMenuHint)
698 mwmhints.decorations |= MWM_DECOR_MENU;
699
700 if (flags & Qt::WindowMinimizeButtonHint) {
701 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
702 mwmhints.functions |= MWM_FUNC_MINIMIZE;
703 }
704
705 if (flags & Qt::WindowMaximizeButtonHint) {
706 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
707 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
708 }
709
710 if (flags & Qt::WindowCloseButtonHint)
711 mwmhints.functions |= MWM_FUNC_CLOSE;
712 }
713 } else {
714 // if type == Qt::SplashScreen
715 mwmhints.decorations = MWM_DECOR_ALL;
716 }
717
718 if (tool) {
719 wsa.save_under = True;
720 wsa_mask |= CWSaveUnder;
721 }
722
723 if (flags & Qt::X11BypassWindowManagerHint) {
724 wsa.override_redirect = True;
725 wsa_mask |= CWOverrideRedirect;
726 }
727
728 if (wsa_mask && initializeWindow) {
729 Q_ASSERT(id);
730 XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
731 }
732
733 if (mwmhints.functions != 0) {
734 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
735 mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
736 } else {
737 mwmhints.functions = MWM_FUNC_ALL;
738 }
739
740 if (!(flags & Qt::FramelessWindowHint)
741 && flags & Qt::CustomizeWindowHint
742 && flags & Qt::WindowTitleHint
743 && !(flags &
744 (Qt::WindowMinimizeButtonHint
745 | Qt::WindowMaximizeButtonHint
746 | Qt::WindowCloseButtonHint))) {
747 // a special case - only the titlebar without any button
748 mwmhints.flags = MWM_HINTS_FUNCTIONS;
749 mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE;
750 mwmhints.decorations = 0;
751 }
752 }
753
754 if (!initializeWindow) {
755 // do no initialization
756 } else if (popup) { // popup widget
757 // set EWMH window types
758 setNetWmWindowTypes();
759
760 wsa.override_redirect = True;
761 wsa.save_under = True;
762 Q_ASSERT(id);
763 XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
764 &wsa);
765 } else if (topLevel && !desktop) { // top-level widget
766 if (!X11->wm_client_leader)
767 create_wm_client_leader();
768
769 // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys()
770
771 XSizeHints size_hints;
772 size_hints.flags = USSize | PSize | PWinGravity;
773 size_hints.x = data.crect.left();
774 size_hints.y = data.crect.top();
775 size_hints.width = data.crect.width();
776 size_hints.height = data.crect.height();
777 size_hints.win_gravity =
778 QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
779
780 XWMHints wm_hints; // window manager hints
781 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
782 wm_hints.flags = InputHint | StateHint | WindowGroupHint;
783 wm_hints.input = True;
784 wm_hints.initial_state = NormalState;
785 wm_hints.window_group = X11->wm_client_leader;
786
787 XClassHint class_hint;
788 QByteArray appName = qAppName().toLatin1();
789 class_hint.res_name = appName.data(); // application name
790 class_hint.res_class = const_cast<char *>(QX11Info::appClass()); // application class
791
792 XSetWMProperties(dpy, id, 0, 0,
793 qApp->d_func()->argv, qApp->d_func()->argc,
794 &size_hints, &wm_hints, &class_hint);
795
796 XResizeWindow(dpy, id,
797 qBound(1, data.crect.width(), XCOORD_MAX),
798 qBound(1, data.crect.height(), XCOORD_MAX));
799 XStoreName(dpy, id, appName.data());
800 Atom protocols[5];
801 int n = 0;
802 protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
803 protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
804 protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
805#ifndef QT_NO_XSYNC
806 protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
807#endif // QT_NO_XSYNC
808 if (flags & Qt::WindowContextHelpButtonHint)
809 protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
810 XSetWMProtocols(dpy, id, protocols, n);
811
812 // set mwm hints
813 SetMWMHints(dpy, id, mwmhints);
814
815 // set EWMH window types
816 setNetWmWindowTypes();
817
818 // set _NET_WM_PID
819 long curr_pid = getpid();
820 XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
821 (unsigned char *) &curr_pid, 1);
822
823 // when we create a toplevel widget, the frame strut should be dirty
824 data.fstrut_dirty = 1;
825
826 // declare the widget's window role
827 if (QTLWExtra *topData = maybeTopData()) {
828 if (!topData->role.isEmpty()) {
829 QByteArray windowRole = topData->role.toUtf8();
830 XChangeProperty(dpy, id,
831 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
832 (unsigned char *)windowRole.constData(), windowRole.length());
833 }
834 }
835
836 // set client leader property
837 XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
838 XA_WINDOW, 32, PropModeReplace,
839 (unsigned char *)&X11->wm_client_leader, 1);
840 } else {
841 // non-toplevel widgets don't have a frame, so no need to
842 // update the strut
843 data.fstrut_dirty = 0;
844 }
845
846 if (initializeWindow && q->internalWinId()) {
847 // don't erase when resizing
848 wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
849 Q_ASSERT(id);
850 XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
851 }
852
853 // set X11 event mask
854 if (desktop) {
855// QWidget* main_desktop = find(id);
856// if (main_desktop->testWFlags(Qt::WPaintDesktop))
857// XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
858// else
859 XSelectInput(dpy, id, stdDesktopEventMask);
860 } else if (q->internalWinId()) {
861 XSelectInput(dpy, id, stdWidgetEventMask);
862#if !defined (QT_NO_TABLET)
863 QTabletDeviceDataList *tablet_list = qt_tablet_devices();
864 if (X11->ptrXSelectExtensionEvent) {
865 for (int i = 0; i < tablet_list->size(); ++i) {
866 QTabletDeviceData tablet = tablet_list->at(i);
867 X11->ptrXSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList),
868 tablet.eventCount);
869 }
870 }
871#endif
872 }
873
874 if (desktop) {
875 q->setAttribute(Qt::WA_WState_Visible);
876 } else if (topLevel) { // set X cursor
877 if (initializeWindow) {
878 qt_x11_enforce_cursor(q);
879
880 if (QTLWExtra *topData = maybeTopData())
881 if (!topData->caption.isEmpty())
882 setWindowTitle_helper(topData->caption);
883
884 //always enable dnd: it's not worth the effort to maintain the state
885 // NOTE: this always creates topData()
886 X11->dndEnable(q, true);
887
888 if (maybeTopData() && maybeTopData()->opacity != 255)
889 q->setWindowOpacity(maybeTopData()->opacity/255.);
890
891 }
892 } else if (q->testAttribute(Qt::WA_SetCursor) && q->internalWinId()) {
893 qt_x11_enforce_cursor(q);
894 }
895
896 if (extra && !extra->mask.isEmpty() && q->internalWinId())
897 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
898 extra->mask.handle(), ShapeSet);
899
900 if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
901 QInputContext *inputContext = q->inputContext();
902 if (inputContext)
903 inputContext->setFocusWidget(q);
904 }
905
906 if (destroyw)
907 qt_XDestroyWindow(q, dpy, destroyw);
908
909 // newly created windows are positioned at the window system's
910 // (0,0) position. If the parent uses wrect mapping to expand the
911 // coordinate system, we must also adjust this widget's window
912 // system position
913 if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
914 setWSGeometry();
915 else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0))
916 q->setAttribute(Qt::WA_OutsideWSRange, true);
917
918 if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
919 Q_ASSERT(q->internalWinId());
920 XMapWindow(X11->display, q->internalWinId());
921 // Ensure that mapped alien widgets are flushed immediately when re-created as native widgets.
922 if (QWindowSurface *surface = q->windowSurface())
923 surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint()));
924 }
925
926#ifdef ALIEN_DEBUG
927 qDebug() << "QWidgetPrivate::create_sys END:" << q;
928#endif
929}
930
931static void qt_x11_recreateWidget(QWidget *widget)
932{
933 if (widget->inherits("QGLWidget")) {
934 // We send QGLWidgets a ParentChange event which causes them to
935 // recreate their GL context, which in turn causes them to choose
936 // their visual again. Now that WA_TranslucentBackground is set,
937 // QGLContext::chooseVisual will select an ARGB visual.
938 QEvent e(QEvent::ParentChange);
939 QApplication::sendEvent(widget, &e);
940 } else {
941 // For regular widgets, reparent them with their parent which
942 // also triggers a recreation of the native window
943 QPoint pos = widget->pos();
944 bool visible = widget->isVisible();
945 if (visible)
946 widget->hide();
947
948 widget->setParent(widget->parentWidget(), widget->windowFlags());
949 widget->move(pos);
950 if (visible)
951 widget->show();
952 }
953}
954
955static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget)
956{
957 if (widget->internalWinId())
958 qt_x11_recreateWidget(widget);
959
960 const QObjectList &children = widget->children();
961 for (int i = 0; i < children.size(); ++i) {
962 QWidget *child = qobject_cast<QWidget*>(children.at(i));
963 if (child)
964 qt_x11_recreateNativeWidgetsRecursive(child);
965 }
966}
967
968void QWidgetPrivate::x11UpdateIsOpaque()
969{
970#ifndef QT_NO_XRENDER
971 Q_Q(QWidget);
972 if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
973 return;
974
975 bool topLevel = (data.window_flags & Qt::Window);
976 int screen = xinfo.screen();
977 if (topLevel && X11->use_xrender
978 && X11->argbVisuals[screen] && xinfo.depth() != 32)
979 {
980 qt_x11_recreateNativeWidgetsRecursive(q);
981 }
982#endif
983}
984
985/*
986 Returns true if the background is inherited; otherwise returns
987 false.
988
989 Mainly used in the paintOnScreen case.
990*/
991bool QWidgetPrivate::isBackgroundInherited() const
992{
993 Q_Q(const QWidget);
994
995 // windows do not inherit their background
996 if (q->isWindow() || q->windowType() == Qt::SubWindow)
997 return false;
998
999 if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
1000 return false;
1001
1002 const QPalette &pal = q->palette();
1003 QPalette::ColorRole bg = q->backgroundRole();
1004 QBrush brush = pal.brush(bg);
1005
1006 // non opaque brushes leaves us no choice, we must inherit
1007 if (!q->autoFillBackground() || !brush.isOpaque())
1008 return true;
1009
1010 if (brush.style() == Qt::SolidPattern) {
1011 // the background is just a solid color. If there is no
1012 // propagated contents, then we claim as performance
1013 // optimization that it was not inheritet. This is the normal
1014 // case in standard Windows or Motif style.
1015 const QWidget *w = q->parentWidget();
1016 if (!w->d_func()->isBackgroundInherited())
1017 return false;
1018 }
1019
1020 return true;
1021}
1022
1023void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
1024{
1025 Q_D(QWidget);
1026 if (!isWindow() && parentWidget())
1027 parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
1028 d->deactivateWidgetCleanup();
1029 if (testAttribute(Qt::WA_WState_Created)) {
1030 setAttribute(Qt::WA_WState_Created, false);
1031 QObjectList childList = children();
1032 for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
1033 register QObject *obj = childList.at(i);
1034 if (obj->isWidgetType())
1035 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
1036 destroySubWindows);
1037 }
1038 if (QWidgetPrivate::mouseGrabber == this)
1039 releaseMouse();
1040 if (QWidgetPrivate::keyboardGrabber == this)
1041 releaseKeyboard();
1042 if (isWindow())
1043 X11->deferred_map.removeAll(this);
1044 if (isModal()) {
1045 // just be sure we leave modal
1046 QApplicationPrivate::leaveModal(this);
1047 }
1048 else if ((windowType() == Qt::Popup))
1049 qApp->d_func()->closePopup(this);
1050
1051#ifndef QT_NO_XRENDER
1052 if (d->picture) {
1053 if (destroyWindow)
1054 XRenderFreePicture(X11->display, d->picture);
1055 d->picture = 0;
1056 }
1057#endif // QT_NO_XRENDER
1058
1059 // delete the _NET_WM_USER_TIME_WINDOW
1060 qt_net_remove_user_time(this);
1061
1062 if ((windowType() == Qt::Desktop)) {
1063 if (acceptDrops())
1064 X11->dndEnable(this, false);
1065 } else {
1066 if (isWindow())
1067 X11->dndEnable(this, false);
1068 if (destroyWindow)
1069 qt_XDestroyWindow(this, X11->display, data->winid);
1070 }
1071 QT_TRY {
1072 d->setWinId(0);
1073 } QT_CATCH (const std::bad_alloc &) {
1074 // swallow - destructors must not throw
1075 }
1076
1077 extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
1078 if (testAttribute(Qt::WA_WState_Reparented))
1079 qPRCleanup(this);
1080
1081 if(d->ic) {
1082 delete d->ic;
1083 } else {
1084 // release previous focus information participating with
1085 // preedit preservation of qic
1086 QInputContext *qic = QApplicationPrivate::inputContext;
1087 if (qic)
1088 qic->widgetDestroyed(this);
1089 }
1090 }
1091}
1092
1093void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
1094{
1095 Q_Q(QWidget);
1096#ifdef ALIEN_DEBUG
1097 qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent;
1098#endif
1099 QX11Info old_xinfo = xinfo;
1100 if (parent && parent->windowType() == Qt::Desktop) {
1101 // make sure the widget is created on the same screen as the
1102 // programmer specified desktop widget
1103 xinfo = parent->d_func()->xinfo;
1104 parent = 0;
1105 }
1106
1107 QTLWExtra *topData = maybeTopData();
1108 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
1109 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
1110 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
1111 extern void qPRCreate(const QWidget *, Window);
1112#ifndef QT_NO_CURSOR
1113 QCursor oldcurs;
1114#endif
1115
1116 // dnd unregister (we will register again below)
1117 if (q->testAttribute(Qt::WA_DropSiteRegistered))
1118 q->setAttribute(Qt::WA_DropSiteRegistered, false);
1119
1120 // if we are a top then remove our dnd prop for now
1121 // it will get rest later
1122 if (q->isWindow() && wasCreated)
1123 X11->dndEnable(q, false);
1124
1125 if (topData)
1126 qt_net_remove_user_time(q);
1127
1128// QWidget *oldparent = q->parentWidget();
1129 WId old_winid = wasCreated ? data.winid : 0;
1130 if ((q->windowType() == Qt::Desktop))
1131 old_winid = 0;
1132 setWinId(0);
1133
1134#ifndef QT_NO_XRENDER
1135 if (picture) {
1136 XRenderFreePicture(X11->display, picture);
1137 picture = 0;
1138 }
1139#endif
1140
1141 // hide and reparent our own window away. Otherwise we might get
1142 // destroyed when emitting the child remove event below. See QWorkspace.
1143 if (wasCreated && old_winid) {
1144 XUnmapWindow(X11->display, old_winid);
1145 if (!old_xinfo.screen() != xinfo.screen())
1146 XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
1147 }
1148 if (topData) {
1149 topData->parentWinId = 0;
1150 // zero the frame strut and mark it dirty
1151 topData->frameStrut.setCoords(0, 0, 0, 0);
1152
1153 // reparenting from top-level, make sure show() works again
1154 topData->waitingForMapNotify = 0;
1155 topData->validWMState = 0;
1156 }
1157 data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
1158
1159 QObjectPrivate::setParent_helper(parent);
1160 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
1161
1162 data.window_flags = f;
1163 q->setAttribute(Qt::WA_WState_Created, false);
1164 q->setAttribute(Qt::WA_WState_Visible, false);
1165 q->setAttribute(Qt::WA_WState_Hidden, false);
1166 adjustFlags(data.window_flags, q);
1167 // keep compatibility with previous versions, we need to preserve the created state
1168 // (but we recreate the winId for the widget being reparented, again for compatibility)
1169 if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
1170 createWinId();
1171 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
1172 q->setAttribute(Qt::WA_WState_Hidden);
1173 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
1174
1175 if (wasCreated) {
1176 QObjectList chlist = q->children();
1177 for (int i = 0; i < chlist.size(); ++i) { // reparent children
1178 QObject *obj = chlist.at(i);
1179 if (obj->isWidgetType()) {
1180 QWidget *w = (QWidget *)obj;
1181 if (!w->testAttribute(Qt::WA_WState_Created))
1182 continue;
1183 if (xinfo.screen() != w->d_func()->xinfo.screen()) {
1184 // ### force setParent() to not shortcut out (because
1185 // ### we're setting the parent to the current parent)
1186 // ### setParent will add child back to the list
1187 // ### of children so we need to make sure the
1188 // ### widget won't be added twice.
1189 w->d_func()->parent = 0;
1190 this->children.removeOne(w);
1191 w->setParent(q);
1192 } else if (!w->isWindow()) {
1193 w->d_func()->invalidateBuffer(w->rect());
1194 if (w->internalWinId()) {
1195 if (w->testAttribute(Qt::WA_NativeWindow)) {
1196 QWidget *nativeParentWidget = w->nativeParentWidget();
1197 // Qt::WA_NativeWindow ensures that we always have a nativeParentWidget
1198 Q_ASSERT(nativeParentWidget != 0);
1199 QPoint p = w->mapTo(nativeParentWidget, QPoint());
1200 XReparentWindow(X11->display,
1201 w->internalWinId(),
1202 nativeParentWidget->internalWinId(),
1203 p.x(), p.y());
1204 } else {
1205 w->d_func()->setParent_sys(q, w->data->window_flags);
1206 }
1207 }
1208 } else if (isTransient(w)) {
1209 /*
1210 when reparenting toplevel windows with toplevel-transient children,
1211 we need to make sure that the window manager gets the updated
1212 WM_TRANSIENT_FOR information... unfortunately, some window managers
1213 don't handle changing WM_TRANSIENT_FOR before the toplevel window is
1214 visible, so we unmap and remap all toplevel-transient children *after*
1215 the toplevel parent has been mapped. thankfully, this is easy in Qt :)
1216
1217 note that the WM_TRANSIENT_FOR hint is actually updated in
1218 QWidgetPrivate::show_sys()
1219 */
1220 if (w->internalWinId())
1221 XUnmapWindow(X11->display, w->internalWinId());
1222 QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
1223 }
1224 }
1225 }
1226 qPRCreate(q, old_winid);
1227 updateSystemBackground();
1228
1229 if (old_winid) {
1230 Window *cmwret;
1231 int count;
1232 if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) {
1233 Window *cmw;
1234 int cmw_size = sizeof(Window)*count;
1235 cmw = new Window[count];
1236 memcpy((char *)cmw, (char *)cmwret, cmw_size);
1237 XFree((char *)cmwret);
1238 int i;
1239 for (i=0; i<count; i++) {
1240 if (cmw[i] == old_winid) {
1241 cmw[i] = q->internalWinId();
1242 break;
1243 }
1244 }
1245 int top_count;
1246 if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(),
1247 &cmwret, &top_count))
1248 {
1249 Window *merged_cmw = new Window[count + top_count];
1250 memcpy((char *)merged_cmw, (char *)cmw, cmw_size);
1251 memcpy((char *)merged_cmw + cmw_size, (char *)cmwret, sizeof(Window)*top_count);
1252 delete [] cmw;
1253 XFree((char *)cmwret);
1254 cmw = merged_cmw;
1255 count += top_count;
1256 }
1257
1258 XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count);
1259 delete [] cmw;
1260 }
1261
1262 qt_XDestroyWindow(q, X11->display, old_winid);
1263 }
1264 }
1265
1266 // check if we need to register our dropsite
1267 if (q->testAttribute(Qt::WA_AcceptDrops)
1268 || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) {
1269 q->setAttribute(Qt::WA_DropSiteRegistered, true);
1270 }
1271#if !defined(QT_NO_IM)
1272 ic = 0;
1273#endif
1274 invalidateBuffer(q->rect());
1275#ifdef ALIEN_DEBUG
1276 qDebug() << "QWidgetPrivate::setParent_sys END" << q;
1277#endif
1278}
1279
1280
1281QPoint QWidget::mapToGlobal(const QPoint &pos) const
1282{
1283 Q_D(const QWidget);
1284 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
1285 QPoint p = pos + data->crect.topLeft();
1286 //cannot trust that !isWindow() implies parentWidget() before create
1287 return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
1288 }
1289 int x, y;
1290 Window child;
1291 QPoint p = d->mapToWS(pos);
1292 XTranslateCoordinates(X11->display, internalWinId(),
1293 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
1294 p.x(), p.y(), &x, &y, &child);
1295 return QPoint(x, y);
1296}
1297
1298
1299QPoint QWidget::mapFromGlobal(const QPoint &pos) const
1300{
1301 Q_D(const QWidget);
1302 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
1303 //cannot trust that !isWindow() implies parentWidget() before create
1304 QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
1305 return p - data->crect.topLeft();
1306 }
1307 int x, y;
1308 Window child;
1309 XTranslateCoordinates(X11->display,
1310 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
1311 internalWinId(), pos.x(), pos.y(), &x, &y, &child);
1312 return d->mapFromWS(QPoint(x, y));
1313}
1314
1315void QWidgetPrivate::updateSystemBackground()
1316{
1317 Q_Q(QWidget);
1318 if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId())
1319 return;
1320 QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole());
1321 Qt::WindowType type = q->windowType();
1322 if (brush.style() == Qt::NoBrush
1323 || q->testAttribute(Qt::WA_NoSystemBackground)
1324 || q->testAttribute(Qt::WA_UpdatesDisabled)
1325 || type == Qt::Popup || type == Qt::ToolTip
1326 )
1327 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
1328 else if (brush.style() == Qt::SolidPattern && brush.isOpaque())
1329 XSetWindowBackground(X11->display, q->internalWinId(),
1330 QColormap::instance(xinfo.screen()).pixel(brush.color()));
1331 else if (isBackgroundInherited())
1332 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative);
1333 else if (brush.style() == Qt::TexturePattern) {
1334 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
1335 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
1336 static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth());
1337 } else
1338 XSetWindowBackground(X11->display, q->internalWinId(),
1339 QColormap::instance(xinfo.screen()).pixel(brush.color()));
1340}
1341
1342#ifndef QT_NO_CURSOR
1343void QWidgetPrivate::setCursor_sys(const QCursor &)
1344{
1345 Q_Q(QWidget);
1346 qt_x11_enforce_cursor(q);
1347 XFlush(X11->display);
1348}
1349
1350void QWidgetPrivate::unsetCursor_sys()
1351{
1352 Q_Q(QWidget);
1353 qt_x11_enforce_cursor(q);
1354 XFlush(X11->display);
1355}
1356#endif
1357
1358static XTextProperty*
1359qstring_to_xtp(const QString& s)
1360{
1361 static XTextProperty tp = { 0, 0, 0, 0 };
1362 static bool free_prop = true; // we can't free tp.value in case it references
1363 // the data of the static QCString below.
1364 if (tp.value) {
1365 if (free_prop)
1366 XFree(tp.value);
1367 tp.value = 0;
1368 free_prop = true;
1369 }
1370
1371 static const QTextCodec* mapper = QTextCodec::codecForLocale();
1372 int errCode = 0;
1373 if (mapper) {
1374 QByteArray mapped = mapper->fromUnicode(s);
1375 char* tl[2];
1376 tl[0] = mapped.data();
1377 tl[1] = 0;
1378 errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
1379#if defined(QT_DEBUG)
1380 if (errCode < 0)
1381 qDebug("qstring_to_xtp result code %d", errCode);
1382#endif
1383 }
1384 if (!mapper || errCode < 0) {
1385 static QByteArray qcs;
1386 qcs = s.toAscii();
1387 tp.value = (uchar*)qcs.data();
1388 tp.encoding = XA_STRING;
1389 tp.format = 8;
1390 tp.nitems = qcs.length();
1391 free_prop = false;
1392 }
1393
1394 // ### If we knew WM could understand unicode, we could use
1395 // ### a much simpler, cheaper encoding...
1396 /*
1397 tp.value = (XChar2b*)s.unicode();
1398 tp.encoding = XA_UNICODE; // wish
1399 tp.format = 16;
1400 tp.nitems = s.length();
1401 */
1402
1403 return &tp;
1404}
1405
1406void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
1407{
1408 Q_Q(QWidget);
1409 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1410 if (!q->internalWinId())
1411 return;
1412 XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
1413
1414 QByteArray net_wm_name = caption.toUtf8();
1415 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
1416 PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
1417}
1418
1419void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
1420{
1421 Q_Q(QWidget);
1422 if (!q->testAttribute(Qt::WA_WState_Created))
1423 return;
1424 QTLWExtra *topData = this->topData();
1425 if (topData->iconPixmap && !forceReset)
1426 // already been set
1427 return;
1428
1429 // preparing images to set the _NET_WM_ICON property
1430 QIcon icon = q->windowIcon();
1431 QVector<long> icon_data;
1432 Qt::HANDLE pixmap_handle = 0;
1433 if (!icon.isNull()) {
1434 QList<QSize> availableSizes = icon.availableSizes();
1435 if(availableSizes.isEmpty()) {
1436 // try to use default sizes since the icon can be a scalable image like svg.
1437 availableSizes.push_back(QSize(16,16));
1438 availableSizes.push_back(QSize(32,32));
1439 availableSizes.push_back(QSize(64,64));
1440 availableSizes.push_back(QSize(128,128));
1441 }
1442 for(int i = 0; i < availableSizes.size(); ++i) {
1443 QSize size = availableSizes.at(i);
1444 QPixmap pixmap = icon.pixmap(size);
1445 if (!pixmap.isNull()) {
1446 QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
1447 int pos = icon_data.size();
1448 icon_data.resize(pos + 2 + image.width()*image.height());
1449 icon_data[pos++] = image.width();
1450 icon_data[pos++] = image.height();
1451 if (sizeof(long) == sizeof(quint32)) {
1452 memcpy(icon_data.data() + pos, image.scanLine(0), image.byteCount());
1453 } else {
1454 for (int y = 0; y < image.height(); ++y) {
1455 uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y));
1456 for (int x = 0; x < image.width(); ++x)
1457 icon_data[pos + y*image.width() + x] = scanLine[x];
1458 }
1459 }
1460 }
1461 }
1462 if (!icon_data.isEmpty()) {
1463 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
1464 /*
1465 if the app is running on an unknown desktop, or it is not
1466 using the default visual, convert the icon to 1bpp as stated
1467 in the ICCCM section 4.1.2.4; otherwise, create the icon pixmap
1468 in the default depth (even though this violates the ICCCM)
1469 */
1470 if (X11->desktopEnvironment == DE_UNKNOWN
1471 || !QX11Info::appDefaultVisual(xinfo.screen())
1472 || !QX11Info::appDefaultColormap(xinfo.screen())) {
1473 // unknown DE or non-default visual/colormap, use 1bpp bitmap
1474 if (!forceReset || !topData->iconPixmap)
1475 topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
1476 pixmap_handle = topData->iconPixmap->handle();
1477 } else {
1478 // default depth, use a normal pixmap (even though this
1479 // violates the ICCCM), since this works on all DEs known to Qt
1480 if (!forceReset || !topData->iconPixmap)
1481 topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
1482 pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth();
1483 }
1484 }
1485 }
1486
1487 if (!q->internalWinId())
1488 return;
1489
1490 if (!icon_data.isEmpty()) {
1491 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
1492 PropModeReplace, (unsigned char *) icon_data.data(),
1493 icon_data.size());
1494 } else {
1495 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
1496 }
1497
1498 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1499 XWMHints wm_hints;
1500 if (!h) {
1501 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1502 h = &wm_hints;
1503 }
1504
1505 if (pixmap_handle) {
1506 h->icon_pixmap = pixmap_handle;
1507 h->flags |= IconPixmapHint;
1508 } else {
1509 h->icon_pixmap = 0;
1510 h->flags &= ~(IconPixmapHint | IconMaskHint);
1511 }
1512
1513 XSetWMHints(X11->display, q->internalWinId(), h);
1514 if (h != &wm_hints)
1515 XFree((char *)h);
1516}
1517
1518void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
1519{
1520 Q_Q(QWidget);
1521 if (!q->internalWinId())
1522 return;
1523 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1524 XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
1525
1526 QByteArray icon_name = iconText.toUtf8();
1527 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
1528 PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
1529}
1530
1531
1532void QWidget::grabMouse()
1533{
1534 if (isVisible() && !qt_nograb()) {
1535 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1536 QWidgetPrivate::mouseGrabber->releaseMouse();
1537 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1538#ifndef QT_NO_DEBUG
1539 int status =
1540#endif
1541 XGrabPointer(X11->display, effectiveWinId(), False,
1542 (uint)(ButtonPressMask | ButtonReleaseMask |
1543 PointerMotionMask | EnterWindowMask |
1544 LeaveWindowMask),
1545 GrabModeAsync, GrabModeAsync,
1546 XNone, XNone, X11->time);
1547#ifndef QT_NO_DEBUG
1548 if (status) {
1549 const char *s =
1550 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1551 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1552 status == GrabFrozen ? "\"GrabFrozen\"" :
1553 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1554 "<?>";
1555 qWarning("QWidget::grabMouse: Failed with %s", s);
1556 }
1557#endif
1558 QWidgetPrivate::mouseGrabber = this;
1559 }
1560}
1561
1562
1563#ifndef QT_NO_CURSOR
1564void QWidget::grabMouse(const QCursor &cursor)
1565{
1566 if (!qt_nograb()) {
1567 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1568 QWidgetPrivate::mouseGrabber->releaseMouse();
1569 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1570#ifndef QT_NO_DEBUG
1571 int status =
1572#endif
1573 XGrabPointer(X11->display, effectiveWinId(), False,
1574 (uint)(ButtonPressMask | ButtonReleaseMask |
1575 PointerMotionMask | EnterWindowMask | LeaveWindowMask),
1576 GrabModeAsync, GrabModeAsync,
1577 XNone, cursor.handle(), X11->time);
1578#ifndef QT_NO_DEBUG
1579 if (status) {
1580 const char *s =
1581 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1582 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1583 status == GrabFrozen ? "\"GrabFrozen\"" :
1584 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1585 "<?>";
1586 qWarning("QWidget::grabMouse: Failed with %s", s);
1587 }
1588#endif
1589 QWidgetPrivate::mouseGrabber = this;
1590 }
1591}
1592#endif
1593
1594
1595void QWidget::releaseMouse()
1596{
1597 if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
1598 XUngrabPointer(X11->display, X11->time);
1599 XFlush(X11->display);
1600 QWidgetPrivate::mouseGrabber = 0;
1601 }
1602}
1603
1604
1605void QWidget::grabKeyboard()
1606{
1607 if (!qt_nograb()) {
1608 if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
1609 QWidgetPrivate::keyboardGrabber->releaseKeyboard();
1610 XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync,
1611 X11->time);
1612 QWidgetPrivate::keyboardGrabber = this;
1613 }
1614}
1615
1616
1617void QWidget::releaseKeyboard()
1618{
1619 if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
1620 XUngrabKeyboard(X11->display, X11->time);
1621 QWidgetPrivate::keyboardGrabber = 0;
1622 }
1623}
1624
1625
1626QWidget *QWidget::mouseGrabber()
1627{
1628 return QWidgetPrivate::mouseGrabber;
1629}
1630
1631
1632QWidget *QWidget::keyboardGrabber()
1633{
1634 return QWidgetPrivate::keyboardGrabber;
1635}
1636
1637void QWidget::activateWindow()
1638{
1639 QWidget *tlw = window();
1640 if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
1641 if (X11->userTime == 0)
1642 X11->userTime = X11->time;
1643 qt_net_update_user_time(tlw, X11->userTime);
1644 XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
1645 }
1646}
1647
1648void QWidget::setWindowState(Qt::WindowStates newstate)
1649{
1650 Q_D(QWidget);
1651 bool needShow = false;
1652 Qt::WindowStates oldstate = windowState();
1653 if (oldstate == newstate)
1654 return;
1655 if (isWindow()) {
1656 // Ensure the initial size is valid, since we store it as normalGeometry below.
1657 if (!testAttribute(Qt::WA_Resized) && !isVisible())
1658 adjustSize();
1659
1660 QTLWExtra *top = d->topData();
1661
1662 if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
1663 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
1664 && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
1665 if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
1666 top->normalGeometry = geometry();
1667 qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
1668 ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
1669 ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
1670 } else if (! (newstate & Qt::WindowFullScreen)) {
1671 if (newstate & Qt::WindowMaximized) {
1672 // save original geometry
1673 const QRect normalGeometry = geometry();
1674
1675 if (isVisible()) {
1676 data->fstrut_dirty = true;
1677 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
1678 const QRect r = top->normalGeometry;
1679 const QRect fs = d->frameStrut();
1680 setGeometry(maxRect.x() + fs.left(),
1681 maxRect.y() + fs.top(),
1682 maxRect.width() - fs.left() - fs.right(),
1683 maxRect.height() - fs.top() - fs.bottom());
1684 top->normalGeometry = r;
1685 }
1686
1687 if (top->normalGeometry.width() < 0)
1688 top->normalGeometry = normalGeometry;
1689 } else {
1690 // restore original geometry
1691 setGeometry(top->normalGeometry);
1692 }
1693 }
1694 }
1695
1696 if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
1697 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
1698 if (newstate & Qt::WindowFullScreen) {
1699 top->normalGeometry = geometry();
1700 top->fullScreenOffset = d->frameStrut().topLeft();
1701 }
1702 qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
1703 ATOM(_NET_WM_STATE_FULLSCREEN));
1704 } else {
1705 needShow = isVisible();
1706
1707 if (newstate & Qt::WindowFullScreen) {
1708 data->fstrut_dirty = true;
1709 const QRect normalGeometry = geometry();
1710 const QPoint fullScreenOffset = d->frameStrut().topLeft();
1711
1712 top->savedFlags = windowFlags();
1713 setParent(0, Qt::Window | Qt::FramelessWindowHint);
1714 const QRect r = top->normalGeometry;
1715 setGeometry(qApp->desktop()->screenGeometry(this));
1716 top->normalGeometry = r;
1717
1718 if (top->normalGeometry.width() < 0) {
1719 top->normalGeometry = normalGeometry;
1720 top->fullScreenOffset = fullScreenOffset;
1721 }
1722 } else {
1723 setParent(0, top->savedFlags);
1724
1725 if (newstate & Qt::WindowMaximized) {
1726 // from fullscreen to maximized
1727 data->fstrut_dirty = true;
1728 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
1729 const QRect r = top->normalGeometry;
1730 const QRect fs = d->frameStrut();
1731 setGeometry(maxRect.x() + fs.left(),
1732 maxRect.y() + fs.top(),
1733 maxRect.width() - fs.left() - fs.right(),
1734 maxRect.height() - fs.top() - fs.bottom());
1735 top->normalGeometry = r;
1736 } else {
1737 // restore original geometry
1738 setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
1739 -top->fullScreenOffset.y(),
1740 -top->fullScreenOffset.x(),
1741 -top->fullScreenOffset.y()));
1742 }
1743 }
1744 }
1745 }
1746
1747 createWinId();
1748 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1749 if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
1750 if (isVisible()) {
1751 if (newstate & Qt::WindowMinimized) {
1752 XEvent e;
1753 e.xclient.type = ClientMessage;
1754 e.xclient.message_type = ATOM(WM_CHANGE_STATE);
1755 e.xclient.display = X11->display;
1756 e.xclient.window = data->winid;
1757 e.xclient.format = 32;
1758 e.xclient.data.l[0] = IconicState;
1759 e.xclient.data.l[1] = 0;
1760 e.xclient.data.l[2] = 0;
1761 e.xclient.data.l[3] = 0;
1762 e.xclient.data.l[4] = 0;
1763 XSendEvent(X11->display,
1764 RootWindow(X11->display,d->xinfo.screen()),
1765 False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
1766 } else {
1767 setAttribute(Qt::WA_Mapped);
1768 XMapWindow(X11->display, effectiveWinId());
1769 }
1770 }
1771
1772 needShow = false;
1773 }
1774 }
1775
1776 data->window_state = newstate;
1777
1778 if (needShow)
1779 show();
1780
1781 if (newstate & Qt::WindowActive)
1782 activateWindow();
1783
1784 QWindowStateChangeEvent e(oldstate);
1785 QApplication::sendEvent(this, &e);
1786}
1787
1788/*!
1789 \internal
1790 Platform-specific part of QWidget::show().
1791*/
1792
1793void QWidgetPrivate::show_sys()
1794{
1795 Q_Q(QWidget);
1796 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1797
1798 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
1799 invalidateBuffer(q->rect());
1800 q->setAttribute(Qt::WA_Mapped);
1801 if (QTLWExtra *tlwExtra = maybeTopData())
1802 tlwExtra->waitingForMapNotify = 0;
1803 return;
1804 }
1805
1806 if (q->isWindow()) {
1807 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1808 XWMHints wm_hints;
1809 bool got_hints = h != 0;
1810 if (!got_hints) {
1811 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1812 h = &wm_hints;
1813 }
1814 h->initial_state = q->isMinimized() ? IconicState : NormalState;
1815 h->flags |= StateHint;
1816 XSetWMHints(X11->display, q->internalWinId(), h);
1817 if (got_hints)
1818 XFree((char *)h);
1819
1820 // update WM_NORMAL_HINTS
1821 do_size_hints(q, extra);
1822
1823 // udpate WM_TRANSIENT_FOR
1824 if (isTransient(q)) {
1825 QWidget *p = q->parentWidget();
1826
1827#ifndef QT_NO_MENU
1828 // hackish ... try to find the main window related to this QMenu
1829 if (qobject_cast<QMenu *>(q)) {
1830 p = static_cast<QMenuPrivate*>(this)->causedPopup.widget;
1831 if (!p)
1832 p = q->parentWidget();
1833 if (!p)
1834 p = QApplication::widgetAt(q->pos());
1835 if (!p)
1836 p = qApp->activeWindow();
1837 }
1838#endif
1839 if (p)
1840 p = p->window();
1841 if (p) {
1842 // transient for window
1843 XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
1844 } else {
1845 // transient for group
1846 XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
1847 }
1848 }
1849
1850 // update _MOTIF_WM_HINTS
1851 QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
1852
1853 if (data.window_modality != Qt::NonModal) {
1854 switch (data.window_modality) {
1855 case Qt::WindowModal:
1856 mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
1857 break;
1858 case Qt::ApplicationModal:
1859 default:
1860 mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
1861 break;
1862 }
1863 mwmhints.flags |= MWM_HINTS_INPUT_MODE;
1864 } else {
1865 mwmhints.input_mode = MWM_INPUT_MODELESS;
1866 mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
1867 }
1868
1869 if (q->minimumSize() == q->maximumSize()) {
1870 // fixed size, remove the resize handle (since mwm/dtwm
1871 // isn't smart enough to do it itself)
1872 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
1873 if (mwmhints.functions == MWM_FUNC_ALL) {
1874 mwmhints.functions = MWM_FUNC_MOVE;
1875 } else {
1876 mwmhints.functions &= ~MWM_FUNC_RESIZE;
1877 }
1878
1879 if (mwmhints.decorations == MWM_DECOR_ALL) {
1880 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1881 mwmhints.decorations = (MWM_DECOR_BORDER
1882 | MWM_DECOR_TITLE
1883 | MWM_DECOR_MENU);
1884 } else {
1885 mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
1886 }
1887
1888 if (q->windowFlags() & Qt::WindowMinimizeButtonHint) {
1889 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1890 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
1891 mwmhints.functions |= MWM_FUNC_MINIMIZE;
1892 }
1893 if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
1894 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1895 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
1896 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
1897 }
1898 if (q->windowFlags() & Qt::WindowCloseButtonHint)
1899 mwmhints.functions |= MWM_FUNC_CLOSE;
1900 }
1901
1902 SetMWMHints(X11->display, q->internalWinId(), mwmhints);
1903
1904 // update _NET_WM_STATE
1905 QVector<Atom> netWmState = getNetWmState(q);
1906
1907 Qt::WindowFlags flags = q->windowFlags();
1908 if (flags & Qt::WindowStaysOnTopHint) {
1909 if (flags & Qt::WindowStaysOnBottomHint)
1910 qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
1911 netWmState.append(ATOM(_NET_WM_STATE_ABOVE));
1912 netWmState.append(ATOM(_NET_WM_STATE_STAYS_ON_TOP));
1913 } else if (flags & Qt::WindowStaysOnBottomHint) {
1914 netWmState.append(ATOM(_NET_WM_STATE_BELOW));
1915 }
1916 if (q->isFullScreen()) {
1917 netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN));
1918 }
1919 if (q->isMaximized()) {
1920 netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ));
1921 netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
1922 }
1923 if (data.window_modality != Qt::NonModal) {
1924 netWmState.append(ATOM(_NET_WM_STATE_MODAL));
1925 }
1926
1927 if (!netWmState.isEmpty()) {
1928 XChangeProperty(X11->display, q->internalWinId(),
1929 ATOM(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
1930 (unsigned char *) netWmState.data(), netWmState.size());
1931 } else {
1932 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
1933 }
1934
1935 // set _NET_WM_USER_TIME
1936 Time userTime = X11->userTime;
1937 bool setUserTime = false;
1938 if (q->testAttribute(Qt::WA_ShowWithoutActivating)) {
1939 userTime = 0;
1940 setUserTime = true;
1941 } else if (userTime != CurrentTime) {
1942 setUserTime = true;
1943 }
1944 if (setUserTime)
1945 qt_net_update_user_time(q, userTime);
1946
1947#ifndef QT_NO_XSYNC
1948 if (!topData()->syncUpdateCounter) {
1949 XSyncValue value;
1950 XSyncIntToValue(&value, 0);
1951 topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
1952
1953 XChangeProperty(X11->display, q->internalWinId(),
1954 ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
1955 XA_CARDINAL,
1956 32, PropModeReplace,
1957 (uchar *) &topData()->syncUpdateCounter, 1);
1958
1959 topData()->newCounterValueHi = 0;
1960 topData()->newCounterValueLo = 0;
1961 }
1962#endif
1963
1964 if (!topData()->embedded
1965 && (topData()->validWMState || topData()->waitingForMapNotify)
1966 && !q->isMinimized()) {
1967 X11->deferred_map.append(q);
1968 return;
1969 }
1970
1971 if (q->isMaximized() && !q->isFullScreen()
1972 && !(X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
1973 && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
1974 XMapWindow(X11->display, q->internalWinId());
1975 data.fstrut_dirty = true;
1976 qt_x11_wait_for_window_manager(q);
1977
1978 // if the wm was not smart enough to adjust our size, do that manually
1979 QRect maxRect = QApplication::desktop()->availableGeometry(q);
1980
1981 QTLWExtra *top = topData();
1982 QRect normalRect = top->normalGeometry;
1983 const QRect fs = frameStrut();
1984
1985 q->setGeometry(maxRect.x() + fs.left(),
1986 maxRect.y() + fs.top(),
1987 maxRect.width() - fs.left() - fs.right(),
1988 maxRect.height() - fs.top() - fs.bottom());
1989
1990 // restore the original normalGeometry
1991 top->normalGeometry = normalRect;
1992 // internalSetGeometry() clears the maximized flag... make sure we set it back
1993 data.window_state = data.window_state | Qt::WindowMaximized;
1994 q->setAttribute(Qt::WA_Mapped);
1995 return;
1996 }
1997
1998 if (q->isFullScreen() && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
1999 XMapWindow(X11->display, q->internalWinId());
2000 qt_x11_wait_for_window_manager(q);
2001 q->setAttribute(Qt::WA_Mapped);
2002 return;
2003 }
2004 }
2005
2006 invalidateBuffer(q->rect());
2007
2008 if (q->testAttribute(Qt::WA_OutsideWSRange))
2009 return;
2010 q->setAttribute(Qt::WA_Mapped);
2011 if (q->isWindow())
2012 topData()->waitingForMapNotify = 1;
2013
2014 if (!q->isWindow()
2015 && (!q->autoFillBackground()
2016 || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
2017 if (q->internalWinId()) {
2018 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
2019 XMapWindow(X11->display, q->internalWinId());
2020 updateSystemBackground();
2021 }
2022 return;
2023 }
2024
2025 if (q->internalWinId())
2026 XMapWindow(X11->display, q->internalWinId());
2027
2028 // Freedesktop.org Startup Notification
2029 if (X11->startupId && q->isWindow()) {
2030 QByteArray message("remove: ID=");
2031 message.append(X11->startupId);
2032 sendStartupMessage(message.constData());
2033 X11->startupId = 0;
2034 }
2035}
2036
2037/*!
2038 \internal
2039 Platform-specific part of QWidget::show().
2040*/
2041
2042void QWidgetPrivate::sendStartupMessage(const char *message) const
2043{
2044 Q_Q(const QWidget);
2045
2046 if (!message)
2047 return;
2048
2049 XEvent xevent;
2050 xevent.xclient.type = ClientMessage;
2051 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN);
2052 xevent.xclient.display = X11->display;
2053 xevent.xclient.window = q->internalWinId();
2054 xevent.xclient.format = 8;
2055
2056 Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
2057 uint sent = 0;
2058 uint length = strlen(message) + 1;
2059 do {
2060 if (sent == 20)
2061 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
2062
2063 for (uint i = 0; i < 20 && i + sent <= length; i++)
2064 xevent.xclient.data.b[i] = message[i + sent++];
2065
2066 XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
2067 } while (sent <= length);
2068}
2069
2070void QWidgetPrivate::setNetWmWindowTypes()
2071{
2072 Q_Q(QWidget);
2073 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2074
2075 if (!q->isWindow()) {
2076 if (q->internalWinId())
2077 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE));
2078 return;
2079 }
2080
2081 QVector<long> windowTypes;
2082
2083 // manual selection 1 (these are never set by Qt and take precedence)
2084 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
2085 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DESKTOP));
2086 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
2087 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DOCK));
2088 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
2089 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NOTIFICATION));
2090
2091 // manual selection 2 (Qt uses these during auto selection);
2092 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
2093 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2094 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
2095 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2096 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
2097 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2098 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
2099 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2100
2101 // manual selection 3 (these can be set by Qt, but don't have a
2102 // corresponding Qt::WindowType). note that order of the *MENU
2103 // atoms is important
2104 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
2105 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_MENU));
2106 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
2107 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
2108 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
2109 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU));
2110 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
2111 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR));
2112 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
2113 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_COMBO));
2114 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
2115 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DND));
2116
2117 // automatic selection
2118 switch (q->windowType()) {
2119 case Qt::Dialog:
2120 case Qt::Sheet:
2121 // dialog netwm type
2122 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2123 break;
2124
2125 case Qt::Tool:
2126 case Qt::Drawer:
2127 // utility netwm type
2128 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2129 break;
2130
2131 case Qt::ToolTip:
2132 // tooltip netwm type
2133 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2134 break;
2135
2136 case Qt::SplashScreen:
2137 // splash netwm type
2138 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2139 break;
2140
2141 default:
2142 break;
2143 }
2144
2145 if (q->windowFlags() & Qt::FramelessWindowHint) {
2146 // override netwm type - quick and easy for KDE noborder
2147 windowTypes.append(ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
2148 }
2149
2150 // normal netwm type - default
2151 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL));
2152
2153 if (!windowTypes.isEmpty()) {
2154 XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32,
2155 PropModeReplace, (unsigned char *) windowTypes.constData(),
2156 windowTypes.count());
2157 } else {
2158 XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE));
2159 }
2160}
2161
2162/*!
2163 \internal
2164 Platform-specific part of QWidget::hide().
2165*/
2166
2167void QWidgetPrivate::hide_sys()
2168{
2169 Q_Q(QWidget);
2170 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2171 deactivateWidgetCleanup();
2172 if (q->isWindow()) {
2173 X11->deferred_map.removeAll(q);
2174 if (q->internalWinId()) // in nsplugin, may be 0
2175 XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen());
2176 XFlush(X11->display);
2177 } else {
2178 invalidateBuffer(q->rect());
2179 if (q->internalWinId()) // in nsplugin, may be 0
2180 XUnmapWindow(X11->display, q->internalWinId());
2181 }
2182 q->setAttribute(Qt::WA_Mapped, false);
2183}
2184
2185void QWidgetPrivate::setFocus_sys()
2186{
2187
2188}
2189
2190
2191void QWidgetPrivate::raise_sys()
2192{
2193 Q_Q(QWidget);
2194 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2195 if (q->internalWinId())
2196 XRaiseWindow(X11->display, q->internalWinId());
2197}
2198
2199void QWidgetPrivate::lower_sys()
2200{
2201 Q_Q(QWidget);
2202 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2203 if (q->internalWinId())
2204 XLowerWindow(X11->display, q->internalWinId());
2205 if(!q->isWindow())
2206 invalidateBuffer(q->rect());
2207}
2208
2209void QWidgetPrivate::stackUnder_sys(QWidget* w)
2210{
2211 Q_Q(QWidget);
2212 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2213 if (q->internalWinId() && w->internalWinId()) {
2214 Window stack[2];
2215 stack[0] = w->internalWinId();;
2216 stack[1] = q->internalWinId();
2217 XRestackWindows(X11->display, stack, 2);
2218 }
2219 if(!q->isWindow() || !w->internalWinId())
2220 invalidateBuffer(q->rect());
2221}
2222
2223
2224static void do_size_hints(QWidget* widget, QWExtra *x)
2225{
2226 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
2227 XSizeHints s;
2228 s.flags = 0;
2229 if (x) {
2230 QRect g = widget->geometry();
2231 s.x = g.x();
2232 s.y = g.y();
2233 s.width = g.width();
2234 s.height = g.height();
2235 if (x->minw > 0 || x->minh > 0) {
2236 // add minimum size hints
2237 s.flags |= PMinSize;
2238 s.min_width = qMin(XCOORD_MAX, x->minw);
2239 s.min_height = qMin(XCOORD_MAX, x->minh);
2240 }
2241 if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
2242 // add maximum size hints
2243 s.flags |= PMaxSize;
2244 s.max_width = qMin(XCOORD_MAX, x->maxw);
2245 s.max_height = qMin(XCOORD_MAX, x->maxh);
2246 }
2247 if (x->topextra &&
2248 (x->topextra->incw > 0 || x->topextra->inch > 0)) {
2249 // add resize increment hints
2250 s.flags |= PResizeInc | PBaseSize;
2251 s.width_inc = x->topextra->incw;
2252 s.height_inc = x->topextra->inch;
2253 s.base_width = x->topextra->basew;
2254 s.base_height = x->topextra->baseh;
2255 }
2256 }
2257 if (widget->testAttribute(Qt::WA_Moved)) {
2258 // user (i.e. command-line) specified position
2259 s.flags |= USPosition;
2260 s.flags |= PPosition;
2261 }
2262 if (widget->testAttribute(Qt::WA_Resized)) {
2263 // user (i.e. command-line) specified size
2264 s.flags |= USSize;
2265 s.flags |= PSize;
2266 }
2267 s.flags |= PWinGravity;
2268 if (widget->testAttribute(Qt::WA_Moved) && x && x->topextra && !x->topextra->posFromMove) {
2269 // position came from setGeometry(), tell the WM that we don't
2270 // want our window gravity-shifted
2271 s.win_gravity = StaticGravity;
2272 } else {
2273 // position came from move()
2274 s.x = widget->x();
2275 s.y = widget->y();
2276 s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
2277 }
2278 if (widget->internalWinId())
2279 XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
2280}
2281
2282
2283/*
2284 Helper function for non-toplevel widgets. Helps to map Qt's 32bit
2285 coordinate system to X11's 16bit coordinate system.
2286
2287 Sets the geometry of the widget to data.crect, but clipped to sizes
2288 that X can handle. Unmaps widgets that are completely outside the
2289 valid range.
2290
2291 Maintains data.wrect, which is the geometry of the X widget,
2292 measured in this widget's coordinate system.
2293
2294 if the parent is not clipped, parentWRect is empty, otherwise
2295 parentWRect is the geometry of the parent's X rect, measured in
2296 parent's coord sys
2297 */
2298void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
2299{
2300 Q_Q(QWidget);
2301 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2302
2303 /*
2304 There are up to four different coordinate systems here:
2305 Qt coordinate system for this widget.
2306 X coordinate system for this widget (relative to wrect).
2307 Qt coordinate system for parent
2308 X coordinate system for parent (relative to parent's wrect).
2309 */
2310 Display *dpy = xinfo.display();
2311 QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
2312 QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
2313 QRect wrect;
2314 //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)
2315 QRect xrect = data.crect;
2316
2317 const QWidget *const parent = q->parentWidget();
2318 QRect parentWRect = parent->data->wrect;
2319
2320 if (parentWRect.isValid()) {
2321 // parent is clipped, and we have to clip to the same limit as parent
2322 if (!parentWRect.contains(xrect)) {
2323 xrect &= parentWRect;
2324 wrect = xrect;
2325 //translate from parent's to my Qt coord sys
2326 wrect.translate(-data.crect.topLeft());
2327 }
2328 //translate from parent's Qt coords to parent's X coords
2329 xrect.translate(-parentWRect.topLeft());
2330
2331 } else {
2332 // parent is not clipped, we may or may not have to clip
2333
2334 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
2335 // This is where the main optimization is: we are already
2336 // clipped, and if our clip is still valid, we can just
2337 // move our window, and do not need to move or clip
2338 // children
2339
2340 QRect vrect = xrect & parent->rect();
2341 vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
2342 if (data.wrect.contains(vrect)) {
2343 xrect = data.wrect;
2344 xrect.translate(data.crect.topLeft());
2345 if (data.winid)
2346 XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
2347 return;
2348 }
2349 }
2350
2351 if (!validRange.contains(xrect)) {
2352 // we are too big, and must clip
2353 xrect &=wrectRange;
2354 wrect = xrect;
2355 wrect.translate(-data.crect.topLeft());
2356 //parent's X coord system is equal to parent's Qt coord
2357 //sys, so we don't need to map xrect.
2358 }
2359
2360 }
2361
2362 // unmap if we are outside the valid window system coord system
2363 bool outsideRange = !xrect.isValid();
2364 bool mapWindow = false;
2365 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
2366 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
2367 if (outsideRange) {
2368 if (data.winid)
2369 XUnmapWindow(dpy, data.winid);
2370 q->setAttribute(Qt::WA_Mapped, false);
2371 } else if (!q->isHidden()) {
2372 mapWindow = true;
2373 }
2374 }
2375
2376 if (outsideRange)
2377 return;
2378
2379 bool jump = (data.wrect != wrect);
2380 data.wrect = wrect;
2381
2382
2383 // and now recursively for all children...
2384 // ### can be optimized
2385 for (int i = 0; i < children.size(); ++i) {
2386 QObject *object = children.at(i);
2387 if (object->isWidgetType()) {
2388 QWidget *w = static_cast<QWidget *>(object);
2389 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
2390 w->d_func()->setWSGeometry(jump);
2391 }
2392 }
2393
2394 if (data.winid) {
2395 // move ourselves to the new position and map (if necessary) after
2396 // the movement. Rationale: moving unmapped windows is much faster
2397 // than moving mapped windows
2398 if (jump) //avoid flicker when jumping
2399 XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
2400 if (!parent->internalWinId())
2401 xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
2402 XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
2403 }
2404
2405 //to avoid flicker, we have to show children after the helper widget has moved
2406 if (jump) {
2407 for (int i = 0; i < children.size(); ++i) {
2408 QObject *object = children.at(i);
2409 if (object->isWidgetType()) {
2410 QWidget *w = static_cast<QWidget *>(object);
2411 if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
2412 w->setAttribute(Qt::WA_Mapped);
2413 if (w->internalWinId())
2414 XMapWindow(dpy, w->data->winid);
2415 }
2416 }
2417 }
2418 }
2419
2420
2421 if (jump && data.winid)
2422 XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
2423
2424 if (mapWindow && !dontShow) {
2425 q->setAttribute(Qt::WA_Mapped);
2426 if (data.winid)
2427 XMapWindow(dpy, data.winid);
2428 }
2429}
2430
2431void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
2432{
2433 Q_Q(QWidget);
2434 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2435 Display *dpy = X11->display;
2436
2437 if ((q->windowType() == Qt::Desktop))
2438 return;
2439 if (q->isWindow()) {
2440 if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
2441 && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
2442 data.window_state &= ~Qt::WindowMaximized;
2443 if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
2444 data.window_state &= ~Qt::WindowFullScreen;
2445 if (QTLWExtra *topData = maybeTopData())
2446 topData->normalGeometry = QRect(0,0,-1,-1);
2447 } else {
2448 uint s = data.window_state;
2449 s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
2450 data.window_state = s;
2451 }
2452 if (extra) { // any size restrictions?
2453 w = qMin(w,extra->maxw);
2454 h = qMin(h,extra->maxh);
2455 w = qMax(w,extra->minw);
2456 h = qMax(h,extra->minh);
2457 }
2458 QPoint oldPos(q->pos());
2459 QSize oldSize(q->size());
2460 QRect oldGeom(data.crect);
2461 QRect r(x, y, w, h);
2462
2463 // We only care about stuff that changes the geometry, or may
2464 // cause the window manager to change its state
2465 if (!q->isWindow() && oldGeom == r)
2466 return;
2467
2468 data.crect = r;
2469 bool isResize = q->size() != oldSize;
2470
2471 if (q->isWindow()) {
2472 if (w == 0 || h == 0) {
2473 q->setAttribute(Qt::WA_OutsideWSRange, true);
2474 if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
2475 hide_sys();
2476 } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
2477 q->setAttribute(Qt::WA_OutsideWSRange, false);
2478
2479 // put the window in its place and show it
2480 if (data.winid)
2481 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2482 topData()->posFromMove = false; // force StaticGravity
2483 do_size_hints(q, extra);
2484 show_sys();
2485 } else {
2486 q->setAttribute(Qt::WA_OutsideWSRange, false);
2487 if (!q->isVisible())
2488 do_size_hints(q, extra);
2489 if (isMove) {
2490 if ((data.window_flags & Qt::X11BypassWindowManagerHint) == Qt::X11BypassWindowManagerHint
2491 // work around 4Dwm's incompliance with ICCCM 4.1.5
2492 || X11->desktopEnvironment == DE_4DWM) {
2493 if (data.winid)
2494 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2495 } else if (q->isVisible()
2496 && topData()->validWMState
2497 && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) {
2498 XEvent e;
2499 e.xclient.type = ClientMessage;
2500 e.xclient.message_type = ATOM(_NET_MOVERESIZE_WINDOW);
2501 e.xclient.display = X11->display;
2502 e.xclient.window = q->internalWinId();
2503 e.xclient.format = 32;
2504 e.xclient.data.l[0] = StaticGravity | 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12;
2505 e.xclient.data.l[1] = x;
2506 e.xclient.data.l[2] = y;
2507 e.xclient.data.l[3] = w;
2508 e.xclient.data.l[4] = h;
2509 XSendEvent(X11->display, RootWindow(X11->display, q->x11Info().screen()),
2510 false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
2511 } else if (data.winid) {
2512 // pos() is right according to ICCCM 4.1.5
2513 XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
2514 }
2515 } else if (isResize && data.winid) {
2516 if (!q->isVisible()
2517 && topData()->validWMState
2518 && !q->testAttribute(Qt::WA_PendingMoveEvent)) {
2519 /*
2520 even though we've not visible, we could be in a
2521 race w/ the window manager, and it may ignore
2522 our ConfigureRequest. setting posFromMove to
2523 false makes sure that doDeferredMap() in
2524 qapplication_x11.cpp keeps the window in the
2525 right place
2526 */
2527 topData()->posFromMove = false;
2528 }
2529 XResizeWindow(dpy, data.winid, w, h);
2530 }
2531 }
2532 if (isResize && !q->testAttribute(Qt::WA_DontShowOnScreen)) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
2533 q->setAttribute(Qt::WA_WState_ConfigPending);
2534
2535 } else {
2536 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
2537 const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
2538 const bool disableInTopLevelResize = inTopLevelResize && q->internalWinId();
2539 if (disableInTopLevelResize) {
2540 // Top-level resize optimization does not work for native child widgets;
2541 // disable it for this particular widget.
2542 tlwExtra->inTopLevelResize = false;
2543 }
2544
2545 if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) {
2546 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
2547 }
2548 if (q->testAttribute(Qt::WA_WState_Created))
2549 setWSGeometry();
2550
2551 if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible())
2552 invalidateBuffer_resizeHelper(oldPos, oldSize);
2553
2554 if (disableInTopLevelResize)
2555 tlwExtra->inTopLevelResize = true;
2556 }
2557
2558 if (q->isVisible()) {
2559 if (isMove && q->pos() != oldPos) {
2560 if (X11->desktopEnvironment != DE_4DWM) {
2561 // pos() is right according to ICCCM 4.1.5
2562 QMoveEvent e(q->pos(), oldPos);
2563 QApplication::sendEvent(q, &e);
2564 } else {
2565 // work around 4Dwm's incompliance with ICCCM 4.1.5
2566 QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
2567 QApplication::sendEvent(q, &e);
2568 }
2569 }
2570 if (isResize) {
2571 static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
2572 // If we have a backing store with static contents, we have to disable the top-level
2573 // resize optimization in order to get invalidated regions for resized widgets.
2574 // The optimization discards all invalidateBuffer() calls since we're going to
2575 // repaint everything anyways, but that's not the case with static contents.
2576 const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
2577 && !extra->topextra->inTopLevelResize
2578 && (!extra->topextra->backingStore
2579 || !extra->topextra->backingStore->hasStaticContents());
2580 if (setTopLevelResize)
2581 extra->topextra->inTopLevelResize = true;
2582 QResizeEvent e(q->size(), oldSize);
2583 QApplication::sendEvent(q, &e);
2584 if (setTopLevelResize)
2585 extra->topextra->inTopLevelResize = false;
2586 }
2587 } else {
2588 if (isMove && q->pos() != oldPos)
2589 q->setAttribute(Qt::WA_PendingMoveEvent, true);
2590 if (isResize)
2591 q->setAttribute(Qt::WA_PendingResizeEvent, true);
2592 }
2593}
2594
2595void QWidgetPrivate::setConstraints_sys()
2596{
2597 Q_Q(QWidget);
2598#ifdef ALIEN_DEBUG
2599 qDebug() << "QWidgetPrivate::setConstraints_sys START" << q;
2600#endif
2601 if (q->testAttribute(Qt::WA_WState_Created))
2602 do_size_hints(q, extra);
2603#ifdef ALIEN_DEBUG
2604 qDebug() << "QWidgetPrivate::setConstraints_sys END" << q;
2605#endif
2606}
2607
2608void QWidgetPrivate::scroll_sys(int dx, int dy)
2609{
2610 Q_Q(QWidget);
2611
2612 scrollChildren(dx, dy);
2613 if (!paintOnScreen()) {
2614 scrollRect(q->rect(), dx, dy);
2615 } else {
2616 scroll_sys(dx, dy, QRect());
2617 }
2618}
2619
2620void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
2621{
2622 Q_Q(QWidget);
2623
2624 if (!paintOnScreen()) {
2625 scrollRect(r, dx, dy);
2626 return;
2627 }
2628 bool valid_rect = r.isValid();
2629 bool just_update = qAbs(dx) > q->width() || qAbs(dy) > q->height();
2630 QRect sr = valid_rect ? r : clipRect();
2631 if (just_update)
2632 q->update();
2633 else if (!valid_rect)
2634 dirty.translate(dx, dy);
2635
2636 int x1, y1, x2, y2, w = sr.width(), h = sr.height();
2637 if (dx > 0) {
2638 x1 = sr.x();
2639 x2 = x1+dx;
2640 w -= dx;
2641 } else {
2642 x2 = sr.x();
2643 x1 = x2-dx;
2644 w += dx;
2645 }
2646 if (dy > 0) {
2647 y1 = sr.y();
2648 y2 = y1+dy;
2649 h -= dy;
2650 } else {
2651 y2 = sr.y();
2652 y1 = y2-dy;
2653 h += dy;
2654 }
2655
2656 if (dx == 0 && dy == 0)
2657 return;
2658
2659 Display *dpy = X11->display;
2660 // Want expose events
2661 if (w > 0 && h > 0 && !just_update && q->internalWinId()) {
2662 GC gc = XCreateGC(dpy, q->internalWinId(), 0, 0);
2663 XSetGraphicsExposures(dpy, gc, True);
2664 XCopyArea(dpy, q->internalWinId(), q->internalWinId(), gc, x1, y1, w, h, x2, y2);
2665 XFreeGC(dpy, gc);
2666 }
2667
2668 if (!valid_rect && !children.isEmpty()) { // scroll children
2669 QPoint pd(dx, dy);
2670 for (int i = 0; i < children.size(); ++i) { // move all children
2671 register QObject *object = children.at(i);
2672 if (object->isWidgetType()) {
2673 QWidget *w = static_cast<QWidget *>(object);
2674 if (!w->isWindow())
2675 w->move(w->pos() + pd);
2676 }
2677 }
2678 }
2679
2680 if (just_update)
2681 return;
2682
2683 // Don't let the server be bogged-down with repaint events
2684 bool repaint_immediately = (qt_sip_count(q) < 3 && !q->testAttribute(Qt::WA_WState_InPaintEvent));
2685
2686 if (dx) {
2687 int x = x2 == sr.x() ? sr.x()+w : sr.x();
2688 if (repaint_immediately)
2689 q->repaint(x, sr.y(), qAbs(dx), sr.height());
2690 else if (q->internalWinId())
2691 XClearArea(dpy, data.winid, x, sr.y(), qAbs(dx), sr.height(), True);
2692 }
2693 if (dy) {
2694 int y = y2 == sr.y() ? sr.y()+h : sr.y();
2695 if (repaint_immediately)
2696 q->repaint(sr.x(), y, sr.width(), qAbs(dy));
2697 else if (q->internalWinId())
2698 XClearArea(dpy, data.winid, sr.x(), y, sr.width(), qAbs(dy), True);
2699 }
2700
2701 qt_insert_sip(q, dx, dy); // #### ignores r
2702}
2703
2704int QWidget::metric(PaintDeviceMetric m) const
2705{
2706 Q_D(const QWidget);
2707 int val;
2708 if (m == PdmWidth) {
2709 val = data->crect.width();
2710 } else if (m == PdmHeight) {
2711 val = data->crect.height();
2712 } else {
2713 Display *dpy = X11->display;
2714 int scr = d->xinfo.screen();
2715 switch (m) {
2716 case PdmDpiX:
2717 case PdmPhysicalDpiX:
2718 if (d->extra && d->extra->customDpiX)
2719 val = d->extra->customDpiX;
2720 else if (d->parent)
2721 val = static_cast<QWidget *>(d->parent)->metric(m);
2722 else
2723 val = QX11Info::appDpiX(scr);
2724 break;
2725 case PdmDpiY:
2726 case PdmPhysicalDpiY:
2727 if (d->extra && d->extra->customDpiY)
2728 val = d->extra->customDpiY;
2729 else if (d->parent)
2730 val = static_cast<QWidget *>(d->parent)->metric(m);
2731 else
2732 val = QX11Info::appDpiY(scr);
2733 break;
2734 case PdmWidthMM:
2735 val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
2736 DisplayWidth(dpy,scr);
2737 break;
2738 case PdmHeightMM:
2739 val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
2740 DisplayHeight(dpy,scr);
2741 break;
2742 case PdmNumColors:
2743 val = d->xinfo.cells();
2744 break;
2745 case PdmDepth:
2746 val = d->xinfo.depth();
2747 break;
2748 default:
2749 val = 0;
2750 qWarning("QWidget::metric: Invalid metric command");
2751 }
2752 }
2753 return val;
2754}
2755
2756void QWidgetPrivate::createSysExtra()
2757{
2758 extra->compress_events = true;
2759 extra->xDndProxy = 0;
2760}
2761
2762void QWidgetPrivate::deleteSysExtra()
2763{
2764}
2765
2766void QWidgetPrivate::createTLSysExtra()
2767{
2768 extra->topextra->spont_unmapped = 0;
2769 extra->topextra->dnd = 0;
2770 extra->topextra->validWMState = 0;
2771 extra->topextra->waitingForMapNotify = 0;
2772 extra->topextra->parentWinId = 0;
2773 extra->topextra->userTimeWindow = 0;
2774#ifndef QT_NO_XSYNC
2775 extra->topextra->syncUpdateCounter = 0;
2776 extra->topextra->syncRequestTimestamp = 0;
2777 extra->topextra->newCounterValueHi = 0;
2778 extra->topextra->newCounterValueLo = 0;
2779#endif
2780}
2781
2782void QWidgetPrivate::deleteTLSysExtra()
2783{
2784 // don't destroy input context here. it will be destroyed in
2785 // QWidget::destroy() destroyInputContext();
2786}
2787
2788void QWidgetPrivate::registerDropSite(bool on)
2789{
2790 Q_UNUSED(on);
2791}
2792
2793void QWidgetPrivate::setMask_sys(const QRegion &region)
2794{
2795 Q_Q(QWidget);
2796 if (!q->internalWinId())
2797 return;
2798
2799 if (region.isEmpty()) {
2800 XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2801 XNone, ShapeSet);
2802 } else {
2803 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2804 region.handle(), ShapeSet);
2805 }
2806}
2807
2808/*!
2809 \internal
2810
2811 Computes the frame rectangle when needed. This is an internal function, you
2812 should never call this.
2813*/
2814
2815void QWidgetPrivate::updateFrameStrut()
2816{
2817 Q_Q(QWidget);
2818
2819 QTLWExtra *top = topData();
2820 if (!top->validWMState) {
2821 return;
2822 }
2823 if (!q->isWindow() && !q->internalWinId()) {
2824 data.fstrut_dirty = false;
2825 return;
2826 }
2827
2828 Atom type_ret;
2829 Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root
2830 Window *c;
2831 int i_unused;
2832 unsigned int nc;
2833 unsigned char *data_ret;
2834 unsigned long l_unused;
2835
2836 while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
2837 if (c && nc > 0)
2838 XFree(c);
2839
2840 if (! p) {
2841 qWarning("QWidget::updateFrameStrut: No parent");
2842 return;
2843 }
2844
2845 // if the parent window is the root window, an Enlightenment virtual root or
2846 // a NET WM virtual root window, stop here
2847 data_ret = 0;
2848 if (p == r ||
2849 (XGetWindowProperty(X11->display, p,
2850 ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
2851 &type_ret, &i_unused, &l_unused, &l_unused,
2852 &data_ret) == Success &&
2853 type_ret == XA_CARDINAL)) {
2854 if (data_ret)
2855 XFree(data_ret);
2856
2857 break;
2858 } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
2859 int i = 0;
2860 while (X11->net_virtual_root_list[i] != 0) {
2861 if (X11->net_virtual_root_list[i++] == p)
2862 break;
2863 }
2864 }
2865
2866 l = w;
2867 w = p;
2868 }
2869
2870 // we have our window
2871 int transx, transy;
2872 XWindowAttributes wattr;
2873 if (XTranslateCoordinates(X11->display, l, w,
2874 0, 0, &transx, &transy, &p) &&
2875 XGetWindowAttributes(X11->display, w, &wattr)) {
2876 top->frameStrut.setCoords(transx,
2877 transy,
2878 wattr.width - data.crect.width() - transx,
2879 wattr.height - data.crect.height() - transy);
2880
2881 // add the border_width for the window managers frame... some window managers
2882 // do not use a border_width of zero for their frames, and if we the left and
2883 // top strut, we ensure that pos() is absolutely correct. frameGeometry()
2884 // will still be incorrect though... perhaps i should have foffset as well, to
2885 // indicate the frame offset (equal to the border_width on X).
2886 // - Brad
2887 top->frameStrut.adjust(wattr.border_width,
2888 wattr.border_width,
2889 wattr.border_width,
2890 wattr.border_width);
2891 }
2892
2893 data.fstrut_dirty = false;
2894}
2895
2896void QWidgetPrivate::setWindowOpacity_sys(qreal opacity)
2897{
2898 Q_Q(QWidget);
2899 ulong value = ulong(opacity * 0xffffffff);
2900 XChangeProperty(QX11Info::display(), q->internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL,
2901 32, PropModeReplace, (uchar*)&value, 1);
2902}
2903
2904const QX11Info &QWidget::x11Info() const
2905{
2906 Q_D(const QWidget);
2907 return d->xinfo;
2908}
2909
2910void QWidgetPrivate::setWindowRole()
2911{
2912 Q_Q(QWidget);
2913 if (!q->internalWinId())
2914 return;
2915 QByteArray windowRole = topData()->role.toUtf8();
2916 XChangeProperty(X11->display, q->internalWinId(),
2917 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
2918 (unsigned char *)windowRole.constData(), windowRole.length());
2919}
2920
2921Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
2922QPaintEngine *QWidget::paintEngine() const
2923{
2924 Q_D(const QWidget);
2925 if (qt_widget_paintengine()->isActive()) {
2926 if (d->extraPaintEngine)
2927 return d->extraPaintEngine;
2928 QWidget *self = const_cast<QWidget *>(this);
2929 self->d_func()->extraPaintEngine = new QX11PaintEngine();
2930 return d->extraPaintEngine;
2931 }
2932 return qt_widget_paintengine();
2933}
2934
2935QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
2936{
2937 return new QX11WindowSurface(q_func());
2938}
2939
2940Qt::HANDLE QWidget::x11PictureHandle() const
2941{
2942#ifndef QT_NO_XRENDER
2943 Q_D(const QWidget);
2944 if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
2945 (void)winId(); // enforce native window
2946 return d->picture;
2947#else
2948 return 0;
2949#endif // QT_NO_XRENDER
2950}
2951
2952#ifndef QT_NO_XRENDER
2953XRenderColor QX11Data::preMultiply(const QColor &c)
2954{
2955 XRenderColor color;
2956 const uint A = c.alpha(),
2957 R = c.red(),
2958 G = c.green(),
2959 B = c.blue();
2960 color.alpha = (A | A << 8);
2961 color.red = (R | R << 8) * color.alpha / 0x10000;
2962 color.green = (G | G << 8) * color.alpha / 0x10000;
2963 color.blue = (B | B << 8) * color.alpha / 0x10000;
2964 return color;
2965}
2966Picture QX11Data::getSolidFill(int screen, const QColor &c)
2967{
2968 if (!X11->use_xrender)
2969 return XNone;
2970
2971 XRenderColor color = preMultiply(c);
2972 for (int i = 0; i < X11->solid_fill_count; ++i) {
2973 if (X11->solid_fills[i].screen == screen
2974 && X11->solid_fills[i].color.alpha == color.alpha
2975 && X11->solid_fills[i].color.red == color.red
2976 && X11->solid_fills[i].color.green == color.green
2977 && X11->solid_fills[i].color.blue == color.blue)
2978 return X11->solid_fills[i].picture;
2979 }
2980 // none found, replace one
2981 int i = rand() % 16;
2982
2983 if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
2984 XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
2985 X11->solid_fills[i].picture = 0;
2986 }
2987
2988 if (!X11->solid_fills[i].picture) {
2989 Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
2990 XRenderPictureAttributes attrs;
2991 attrs.repeat = True;
2992 X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
2993 XRenderFindStandardFormat(X11->display, PictStandardARGB32),
2994 CPRepeat, &attrs);
2995 XFreePixmap (X11->display, pixmap);
2996 }
2997
2998 X11->solid_fills[i].color = color;
2999 X11->solid_fills[i].screen = screen;
3000 XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
3001 return X11->solid_fills[i].picture;
3002}
3003#endif
3004
3005void QWidgetPrivate::setModal_sys()
3006{
3007}
3008
3009void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att)
3010{
3011 QX11InfoData* xd = xinfo->getX11Data(true);
3012 const XWindowAttributes &a = *(att.att);
3013 // find which screen the window is on...
3014 xd->screen = QX11Info::appScreen(); // by default, use the default :)
3015 int i;
3016 for (i = 0; i < ScreenCount(X11->display); i++) {
3017 if (RootWindow(X11->display, i) == a.root) {
3018 xd->screen = i;
3019 break;
3020 }
3021 }
3022
3023 xd->depth = a.depth;
3024 xd->cells = DisplayCells(X11->display, xd->screen);
3025 xd->visual = a.visual;
3026 xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
3027 XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo->screen())));
3028 xd->colormap = a.colormap;
3029 xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo->screen()));
3030 xinfo->setX11Data(xd);
3031}
3032
3033QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.