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

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

File size: 109.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** 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 qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qevent.h"
43#include "qwidget.h"
44#include "qdesktopwidget.h"
45#include "qapplication.h"
46#include "qapplication_p.h"
47#include "qnamespace.h"
48#include "qpainter.h"
49#include "qbitmap.h"
50#include "qlayout.h"
51#include "qtextcodec.h"
52#include "qelapsedtimer.h"
53#include "qcursor.h"
54#include "qstack.h"
55#include "qcolormap.h"
56#include "qdebug.h"
57#include "qmenu.h"
58#include "private/qmenu_p.h"
59#include "private/qbackingstore_p.h"
60#include "private/qwindowsurface_x11_p.h"
61
62//extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp
63
64#include <private/qpixmap_x11_p.h>
65#include <private/qpaintengine_x11_p.h>
66#include "qt_x11_p.h"
67#include "qx11info_x11.h"
68
69#include <stdlib.h>
70
71//#define ALIEN_DEBUG
72
73// defined in qapplication_x11.cpp
74//bool qt_wstate_iconified(WId);
75//void qt_updated_rootinfo();
76
77
78#if !defined(QT_NO_IM)
79#include "qinputcontext.h"
80#include "qinputcontextfactory.h"
81#endif
82
83#include "qwidget_p.h"
84
85#define XCOORD_MAX 16383
86#define WRECT_MAX 8191
87
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 QElapsedTimer t;
356 t.start();
357 static const int maximumWaitTime = 2000;
358 if (!w->testAttribute(Qt::WA_WState_Created))
359 return;
360
361 WId winid = w->internalWinId();
362
363 // first deliver events that are already in the local queue
364 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 = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : 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->internalWinId()) {
893 qt_x11_enforce_cursor(q);
894 if (QWidget *p = q->parentWidget()) // reset the cursor on the native parent
895 qt_x11_enforce_cursor(p);
896 }
897
898 if (extra && !extra->mask.isEmpty() && q->internalWinId())
899 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
900 extra->mask.handle(), ShapeSet);
901
902 if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
903 QInputContext *inputContext = q->inputContext();
904 if (inputContext)
905 inputContext->setFocusWidget(q);
906 }
907
908 if (destroyw)
909 qt_XDestroyWindow(q, dpy, destroyw);
910
911 // newly created windows are positioned at the window system's
912 // (0,0) position. If the parent uses wrect mapping to expand the
913 // coordinate system, we must also adjust this widget's window
914 // system position
915 if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
916 setWSGeometry();
917 else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0))
918 q->setAttribute(Qt::WA_OutsideWSRange, true);
919
920 if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) {
921 Q_ASSERT(q->internalWinId());
922 XMapWindow(X11->display, q->internalWinId());
923 // Ensure that mapped alien widgets are flushed immediately when re-created as native widgets.
924 if (QWindowSurface *surface = q->windowSurface())
925 surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint()));
926 }
927
928#ifdef ALIEN_DEBUG
929 qDebug() << "QWidgetPrivate::create_sys END:" << q;
930#endif
931}
932
933static void qt_x11_recreateWidget(QWidget *widget)
934{
935 if (widget->inherits("QGLWidget")) {
936 // We send QGLWidgets a ParentChange event which causes them to
937 // recreate their GL context, which in turn causes them to choose
938 // their visual again. Now that WA_TranslucentBackground is set,
939 // QGLContext::chooseVisual will select an ARGB visual.
940 QEvent e(QEvent::ParentChange);
941 QApplication::sendEvent(widget, &e);
942 } else {
943 // For regular widgets, reparent them with their parent which
944 // also triggers a recreation of the native window
945 QPoint pos = widget->pos();
946 bool visible = widget->isVisible();
947 if (visible)
948 widget->hide();
949
950 widget->setParent(widget->parentWidget(), widget->windowFlags());
951 widget->move(pos);
952 if (visible)
953 widget->show();
954 }
955}
956
957static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget)
958{
959 if (widget->internalWinId())
960 qt_x11_recreateWidget(widget);
961
962 const QObjectList &children = widget->children();
963 for (int i = 0; i < children.size(); ++i) {
964 QWidget *child = qobject_cast<QWidget*>(children.at(i));
965 if (child)
966 qt_x11_recreateNativeWidgetsRecursive(child);
967 }
968}
969
970void QWidgetPrivate::x11UpdateIsOpaque()
971{
972#ifndef QT_NO_XRENDER
973 Q_Q(QWidget);
974 if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
975 return;
976
977 bool topLevel = (data.window_flags & Qt::Window);
978 int screen = xinfo.screen();
979 if (topLevel && X11->use_xrender
980 && X11->argbVisuals[screen] && xinfo.depth() != 32)
981 {
982 qt_x11_recreateNativeWidgetsRecursive(q);
983 }
984#endif
985}
986
987/*
988 Returns true if the background is inherited; otherwise returns
989 false.
990
991 Mainly used in the paintOnScreen case.
992*/
993bool QWidgetPrivate::isBackgroundInherited() const
994{
995 Q_Q(const QWidget);
996
997 // windows do not inherit their background
998 if (q->isWindow() || q->windowType() == Qt::SubWindow)
999 return false;
1000
1001 if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
1002 return false;
1003
1004 const QPalette &pal = q->palette();
1005 QPalette::ColorRole bg = q->backgroundRole();
1006 QBrush brush = pal.brush(bg);
1007
1008 // non opaque brushes leaves us no choice, we must inherit
1009 if (!q->autoFillBackground() || !brush.isOpaque())
1010 return true;
1011
1012 if (brush.style() == Qt::SolidPattern) {
1013 // the background is just a solid color. If there is no
1014 // propagated contents, then we claim as performance
1015 // optimization that it was not inheritet. This is the normal
1016 // case in standard Windows or Motif style.
1017 const QWidget *w = q->parentWidget();
1018 if (!w->d_func()->isBackgroundInherited())
1019 return false;
1020 }
1021
1022 return true;
1023}
1024
1025void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
1026{
1027 Q_D(QWidget);
1028 d->aboutToDestroy();
1029 if (!isWindow() && parentWidget())
1030 parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
1031 d->deactivateWidgetCleanup();
1032 if (testAttribute(Qt::WA_WState_Created)) {
1033 setAttribute(Qt::WA_WState_Created, false);
1034 QObjectList childList = children();
1035 for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
1036 register QObject *obj = childList.at(i);
1037 if (obj->isWidgetType())
1038 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
1039 destroySubWindows);
1040 }
1041 if (QWidgetPrivate::mouseGrabber == this)
1042 releaseMouse();
1043 if (QWidgetPrivate::keyboardGrabber == this)
1044 releaseKeyboard();
1045 if (isWindow())
1046 X11->deferred_map.removeAll(this);
1047 if (isModal()) {
1048 // just be sure we leave modal
1049 QApplicationPrivate::leaveModal(this);
1050 }
1051 else if ((windowType() == Qt::Popup))
1052 qApp->d_func()->closePopup(this);
1053
1054#ifndef QT_NO_XRENDER
1055 if (d->picture) {
1056 if (destroyWindow)
1057 XRenderFreePicture(X11->display, d->picture);
1058 d->picture = 0;
1059 }
1060#endif // QT_NO_XRENDER
1061
1062 // delete the _NET_WM_USER_TIME_WINDOW
1063 qt_net_remove_user_time(this);
1064
1065 if ((windowType() == Qt::Desktop)) {
1066 if (acceptDrops())
1067 X11->dndEnable(this, false);
1068 } else {
1069 if (isWindow())
1070 X11->dndEnable(this, false);
1071 if (destroyWindow)
1072 qt_XDestroyWindow(this, X11->display, data->winid);
1073 }
1074 QT_TRY {
1075 d->setWinId(0);
1076 } QT_CATCH (const std::bad_alloc &) {
1077 // swallow - destructors must not throw
1078 }
1079
1080 extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
1081 if (testAttribute(Qt::WA_WState_Reparented))
1082 qPRCleanup(this);
1083
1084 if(d->ic) {
1085 delete d->ic;
1086 } else {
1087 // release previous focus information participating with
1088 // preedit preservation of qic
1089 QInputContext *qic = QApplicationPrivate::inputContext;
1090 if (qic)
1091 qic->widgetDestroyed(this);
1092 }
1093 }
1094}
1095
1096void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
1097{
1098 Q_Q(QWidget);
1099#ifdef ALIEN_DEBUG
1100 qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent;
1101#endif
1102 QX11Info old_xinfo = xinfo;
1103 if (parent && parent->windowType() == Qt::Desktop) {
1104 // make sure the widget is created on the same screen as the
1105 // programmer specified desktop widget
1106 xinfo = parent->d_func()->xinfo;
1107 parent = 0;
1108 }
1109
1110 QTLWExtra *topData = maybeTopData();
1111 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
1112 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
1113 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
1114 extern void qPRCreate(const QWidget *, Window);
1115#ifndef QT_NO_CURSOR
1116 QCursor oldcurs;
1117#endif
1118
1119 // dnd unregister (we will register again below)
1120 if (q->testAttribute(Qt::WA_DropSiteRegistered))
1121 q->setAttribute(Qt::WA_DropSiteRegistered, false);
1122
1123 // if we are a top then remove our dnd prop for now
1124 // it will get rest later
1125 if (q->isWindow() && wasCreated)
1126 X11->dndEnable(q, false);
1127
1128 if (topData)
1129 qt_net_remove_user_time(q);
1130
1131// QWidget *oldparent = q->parentWidget();
1132 WId old_winid = wasCreated ? data.winid : 0;
1133 if ((q->windowType() == Qt::Desktop))
1134 old_winid = 0;
1135 setWinId(0);
1136
1137#ifndef QT_NO_XRENDER
1138 if (picture) {
1139 XRenderFreePicture(X11->display, picture);
1140 picture = 0;
1141 }
1142#endif
1143
1144 // hide and reparent our own window away. Otherwise we might get
1145 // destroyed when emitting the child remove event below. See QWorkspace.
1146 if (wasCreated && old_winid) {
1147 XUnmapWindow(X11->display, old_winid);
1148 if (!old_xinfo.screen() != xinfo.screen())
1149 XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
1150 }
1151 if (topData) {
1152 topData->parentWinId = 0;
1153 // zero the frame strut and mark it dirty
1154 topData->frameStrut.setCoords(0, 0, 0, 0);
1155
1156 // reparenting from top-level, make sure show() works again
1157 topData->waitingForMapNotify = 0;
1158 topData->validWMState = 0;
1159 }
1160 data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
1161
1162 QObjectPrivate::setParent_helper(parent);
1163 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
1164
1165 data.window_flags = f;
1166 q->setAttribute(Qt::WA_WState_Created, false);
1167 q->setAttribute(Qt::WA_WState_Visible, false);
1168 q->setAttribute(Qt::WA_WState_Hidden, false);
1169 adjustFlags(data.window_flags, q);
1170 // keep compatibility with previous versions, we need to preserve the created state
1171 // (but we recreate the winId for the widget being reparented, again for compatibility)
1172 if (wasCreated)
1173 createWinId();
1174 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
1175 q->setAttribute(Qt::WA_WState_Hidden);
1176 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
1177
1178 if (wasCreated) {
1179 QObjectList chlist = q->children();
1180 for (int i = 0; i < chlist.size(); ++i) { // reparent children
1181 QObject *obj = chlist.at(i);
1182 if (obj->isWidgetType()) {
1183 QWidget *w = (QWidget *)obj;
1184 if (!w->testAttribute(Qt::WA_WState_Created))
1185 continue;
1186 if (xinfo.screen() != w->d_func()->xinfo.screen()) {
1187 // ### force setParent() to not shortcut out (because
1188 // ### we're setting the parent to the current parent)
1189 // ### setParent will add child back to the list
1190 // ### of children so we need to make sure the
1191 // ### widget won't be added twice.
1192 w->d_func()->parent = 0;
1193 this->children.removeOne(w);
1194 w->setParent(q);
1195 } else if (!w->isWindow()) {
1196 w->d_func()->invalidateBuffer(w->rect());
1197 if (w->internalWinId()) {
1198 if (w->testAttribute(Qt::WA_NativeWindow)) {
1199 QWidget *nativeParentWidget = w->nativeParentWidget();
1200 // Qt::WA_NativeWindow ensures that we always have a nativeParentWidget
1201 Q_ASSERT(nativeParentWidget != 0);
1202 QPoint p = w->mapTo(nativeParentWidget, QPoint());
1203 XReparentWindow(X11->display,
1204 w->internalWinId(),
1205 nativeParentWidget->internalWinId(),
1206 p.x(), p.y());
1207 } else {
1208 w->d_func()->setParent_sys(q, w->data->window_flags);
1209 }
1210 }
1211 } else if (isTransient(w)) {
1212 /*
1213 when reparenting toplevel windows with toplevel-transient children,
1214 we need to make sure that the window manager gets the updated
1215 WM_TRANSIENT_FOR information... unfortunately, some window managers
1216 don't handle changing WM_TRANSIENT_FOR before the toplevel window is
1217 visible, so we unmap and remap all toplevel-transient children *after*
1218 the toplevel parent has been mapped. thankfully, this is easy in Qt :)
1219
1220 note that the WM_TRANSIENT_FOR hint is actually updated in
1221 QWidgetPrivate::show_sys()
1222 */
1223 if (w->internalWinId())
1224 XUnmapWindow(X11->display, w->internalWinId());
1225 QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
1226 }
1227 }
1228 }
1229 qPRCreate(q, old_winid);
1230 updateSystemBackground();
1231
1232 if (old_winid) {
1233 Window *cmwret;
1234 int count;
1235 if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) {
1236 Window *cmw;
1237 int cmw_size = sizeof(Window)*count;
1238 cmw = new Window[count];
1239 memcpy((char *)cmw, (char *)cmwret, cmw_size);
1240 XFree((char *)cmwret);
1241 int i;
1242 for (i=0; i<count; i++) {
1243 if (cmw[i] == old_winid) {
1244 cmw[i] = q->internalWinId();
1245 break;
1246 }
1247 }
1248 int top_count;
1249 if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(),
1250 &cmwret, &top_count))
1251 {
1252 Window *merged_cmw = new Window[count + top_count];
1253 memcpy((char *)merged_cmw, (char *)cmw, cmw_size);
1254 memcpy((char *)merged_cmw + cmw_size, (char *)cmwret, sizeof(Window)*top_count);
1255 delete [] cmw;
1256 XFree((char *)cmwret);
1257 cmw = merged_cmw;
1258 count += top_count;
1259 }
1260
1261 XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count);
1262 delete [] cmw;
1263 }
1264
1265 qt_XDestroyWindow(q, X11->display, old_winid);
1266 }
1267 }
1268
1269 // check if we need to register our dropsite
1270 if (q->testAttribute(Qt::WA_AcceptDrops)
1271 || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) {
1272 q->setAttribute(Qt::WA_DropSiteRegistered, true);
1273 }
1274#if !defined(QT_NO_IM)
1275 ic = 0;
1276#endif
1277 invalidateBuffer(q->rect());
1278#ifdef ALIEN_DEBUG
1279 qDebug() << "QWidgetPrivate::setParent_sys END" << q;
1280#endif
1281}
1282
1283
1284QPoint QWidget::mapToGlobal(const QPoint &pos) const
1285{
1286 Q_D(const QWidget);
1287 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
1288 QPoint p = pos + data->crect.topLeft();
1289 //cannot trust that !isWindow() implies parentWidget() before create
1290 return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
1291 }
1292 int x, y;
1293 Window child;
1294 QPoint p = d->mapToWS(pos);
1295 XTranslateCoordinates(X11->display, internalWinId(),
1296 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
1297 p.x(), p.y(), &x, &y, &child);
1298 return QPoint(x, y);
1299}
1300
1301
1302QPoint QWidget::mapFromGlobal(const QPoint &pos) const
1303{
1304 Q_D(const QWidget);
1305 if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
1306 //cannot trust that !isWindow() implies parentWidget() before create
1307 QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
1308 return p - data->crect.topLeft();
1309 }
1310 int x, y;
1311 Window child;
1312 XTranslateCoordinates(X11->display,
1313 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
1314 internalWinId(), pos.x(), pos.y(), &x, &y, &child);
1315 return d->mapFromWS(QPoint(x, y));
1316}
1317
1318void QWidgetPrivate::updateSystemBackground()
1319{
1320 Q_Q(QWidget);
1321 if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId())
1322 return;
1323 QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole());
1324 Qt::WindowType type = q->windowType();
1325 if (brush.style() == Qt::NoBrush
1326 || q->testAttribute(Qt::WA_NoSystemBackground)
1327 || q->testAttribute(Qt::WA_UpdatesDisabled)
1328 || type == Qt::Popup || type == Qt::ToolTip
1329 )
1330 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
1331 else if (brush.style() == Qt::SolidPattern && brush.isOpaque())
1332 XSetWindowBackground(X11->display, q->internalWinId(),
1333 QColormap::instance(xinfo.screen()).pixel(brush.color()));
1334 else if (isBackgroundInherited())
1335 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative);
1336 else if (brush.style() == Qt::TexturePattern) {
1337 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp
1338 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
1339 static_cast<QX11PixmapData*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth());
1340 } else
1341 XSetWindowBackground(X11->display, q->internalWinId(),
1342 QColormap::instance(xinfo.screen()).pixel(brush.color()));
1343}
1344
1345#ifndef QT_NO_CURSOR
1346void QWidgetPrivate::setCursor_sys(const QCursor &)
1347{
1348 Q_Q(QWidget);
1349 qt_x11_enforce_cursor(q);
1350 XFlush(X11->display);
1351}
1352
1353void QWidgetPrivate::unsetCursor_sys()
1354{
1355 Q_Q(QWidget);
1356 qt_x11_enforce_cursor(q);
1357 XFlush(X11->display);
1358}
1359#endif
1360
1361static XTextProperty*
1362qstring_to_xtp(const QString& s)
1363{
1364 static XTextProperty tp = { 0, 0, 0, 0 };
1365 static bool free_prop = true; // we can't free tp.value in case it references
1366 // the data of the static QCString below.
1367 if (tp.value) {
1368 if (free_prop)
1369 XFree(tp.value);
1370 tp.value = 0;
1371 free_prop = true;
1372 }
1373
1374 static const QTextCodec* mapper = QTextCodec::codecForLocale();
1375 int errCode = 0;
1376 if (mapper) {
1377 QByteArray mapped = mapper->fromUnicode(s);
1378 char* tl[2];
1379 tl[0] = mapped.data();
1380 tl[1] = 0;
1381 errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
1382#if defined(QT_DEBUG)
1383 if (errCode < 0)
1384 qDebug("qstring_to_xtp result code %d", errCode);
1385#endif
1386 }
1387 if (!mapper || errCode < 0) {
1388 static QByteArray qcs;
1389 qcs = s.toAscii();
1390 tp.value = (uchar*)qcs.data();
1391 tp.encoding = XA_STRING;
1392 tp.format = 8;
1393 tp.nitems = qcs.length();
1394 free_prop = false;
1395 }
1396
1397 // ### If we knew WM could understand unicode, we could use
1398 // ### a much simpler, cheaper encoding...
1399 /*
1400 tp.value = (XChar2b*)s.unicode();
1401 tp.encoding = XA_UNICODE; // wish
1402 tp.format = 16;
1403 tp.nitems = s.length();
1404 */
1405
1406 return &tp;
1407}
1408
1409void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
1410{
1411 Q_Q(QWidget);
1412 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1413 if (!q->internalWinId())
1414 return;
1415 XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
1416
1417 QByteArray net_wm_name = caption.toUtf8();
1418 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
1419 PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
1420}
1421
1422void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
1423{
1424 Q_Q(QWidget);
1425 if (!q->testAttribute(Qt::WA_WState_Created))
1426 return;
1427 QTLWExtra *topData = this->topData();
1428 if (topData->iconPixmap && !forceReset)
1429 // already been set
1430 return;
1431
1432 // preparing images to set the _NET_WM_ICON property
1433 QIcon icon = q->windowIcon();
1434 QVector<long> icon_data;
1435 Qt::HANDLE pixmap_handle = 0;
1436 if (!icon.isNull()) {
1437 QList<QSize> availableSizes = icon.availableSizes();
1438 if(availableSizes.isEmpty()) {
1439 // try to use default sizes since the icon can be a scalable image like svg.
1440 availableSizes.push_back(QSize(16,16));
1441 availableSizes.push_back(QSize(32,32));
1442 availableSizes.push_back(QSize(64,64));
1443 availableSizes.push_back(QSize(128,128));
1444 }
1445 for(int i = 0; i < availableSizes.size(); ++i) {
1446 QSize size = availableSizes.at(i);
1447 QPixmap pixmap = icon.pixmap(size);
1448 if (!pixmap.isNull()) {
1449 QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
1450 int pos = icon_data.size();
1451 icon_data.resize(pos + 2 + image.width()*image.height());
1452 icon_data[pos++] = image.width();
1453 icon_data[pos++] = image.height();
1454 if (sizeof(long) == sizeof(quint32)) {
1455 memcpy(icon_data.data() + pos, image.scanLine(0), image.byteCount());
1456 } else {
1457 for (int y = 0; y < image.height(); ++y) {
1458 uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y));
1459 for (int x = 0; x < image.width(); ++x)
1460 icon_data[pos + y*image.width() + x] = scanLine[x];
1461 }
1462 }
1463 }
1464 }
1465 if (!icon_data.isEmpty()) {
1466 extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
1467 /*
1468 if the app is running on an unknown desktop, or it is not
1469 using the default visual, convert the icon to 1bpp as stated
1470 in the ICCCM section 4.1.2.4; otherwise, create the icon pixmap
1471 in the default depth (even though this violates the ICCCM)
1472 */
1473 if (X11->desktopEnvironment == DE_UNKNOWN
1474 || !QX11Info::appDefaultVisual(xinfo.screen())
1475 || !QX11Info::appDefaultColormap(xinfo.screen())) {
1476 // unknown DE or non-default visual/colormap, use 1bpp bitmap
1477 if (!forceReset || !topData->iconPixmap)
1478 topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
1479 pixmap_handle = topData->iconPixmap->handle();
1480 } else {
1481 // default depth, use a normal pixmap (even though this
1482 // violates the ICCCM), since this works on all DEs known to Qt
1483 if (!forceReset || !topData->iconPixmap)
1484 topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
1485 pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth();
1486 }
1487 }
1488 }
1489
1490 if (!q->internalWinId())
1491 return;
1492
1493 if (!icon_data.isEmpty()) {
1494 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
1495 PropModeReplace, (unsigned char *) icon_data.data(),
1496 icon_data.size());
1497 } else {
1498 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
1499 }
1500
1501 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1502 XWMHints wm_hints;
1503 if (!h) {
1504 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1505 h = &wm_hints;
1506 }
1507
1508 if (pixmap_handle) {
1509 h->icon_pixmap = pixmap_handle;
1510 h->flags |= IconPixmapHint;
1511 } else {
1512 h->icon_pixmap = 0;
1513 h->flags &= ~(IconPixmapHint | IconMaskHint);
1514 }
1515
1516 XSetWMHints(X11->display, q->internalWinId(), h);
1517 if (h != &wm_hints)
1518 XFree((char *)h);
1519}
1520
1521void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
1522{
1523 Q_Q(QWidget);
1524 if (!q->internalWinId())
1525 return;
1526 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1527 XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
1528
1529 QByteArray icon_name = iconText.toUtf8();
1530 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
1531 PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
1532}
1533
1534
1535void QWidget::grabMouse()
1536{
1537 if (isVisible() && !qt_nograb()) {
1538 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1539 QWidgetPrivate::mouseGrabber->releaseMouse();
1540 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1541#ifndef QT_NO_DEBUG
1542 int status =
1543#endif
1544 XGrabPointer(X11->display, effectiveWinId(), False,
1545 (uint)(ButtonPressMask | ButtonReleaseMask |
1546 PointerMotionMask | EnterWindowMask |
1547 LeaveWindowMask),
1548 GrabModeAsync, GrabModeAsync,
1549 XNone, XNone, X11->time);
1550#ifndef QT_NO_DEBUG
1551 if (status) {
1552 const char *s =
1553 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1554 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1555 status == GrabFrozen ? "\"GrabFrozen\"" :
1556 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1557 "<?>";
1558 qWarning("QWidget::grabMouse: Failed with %s", s);
1559 }
1560#endif
1561 QWidgetPrivate::mouseGrabber = this;
1562 }
1563}
1564
1565
1566#ifndef QT_NO_CURSOR
1567void QWidget::grabMouse(const QCursor &cursor)
1568{
1569 if (!qt_nograb()) {
1570 if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
1571 QWidgetPrivate::mouseGrabber->releaseMouse();
1572 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1573#ifndef QT_NO_DEBUG
1574 int status =
1575#endif
1576 XGrabPointer(X11->display, effectiveWinId(), False,
1577 (uint)(ButtonPressMask | ButtonReleaseMask |
1578 PointerMotionMask | EnterWindowMask | LeaveWindowMask),
1579 GrabModeAsync, GrabModeAsync,
1580 XNone, cursor.handle(), X11->time);
1581#ifndef QT_NO_DEBUG
1582 if (status) {
1583 const char *s =
1584 status == GrabNotViewable ? "\"GrabNotViewable\"" :
1585 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1586 status == GrabFrozen ? "\"GrabFrozen\"" :
1587 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1588 "<?>";
1589 qWarning("QWidget::grabMouse: Failed with %s", s);
1590 }
1591#endif
1592 QWidgetPrivate::mouseGrabber = this;
1593 }
1594}
1595#endif
1596
1597
1598void QWidget::releaseMouse()
1599{
1600 if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
1601 XUngrabPointer(X11->display, X11->time);
1602 XFlush(X11->display);
1603 QWidgetPrivate::mouseGrabber = 0;
1604 }
1605}
1606
1607
1608void QWidget::grabKeyboard()
1609{
1610 if (!qt_nograb()) {
1611 if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
1612 QWidgetPrivate::keyboardGrabber->releaseKeyboard();
1613 XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync,
1614 X11->time);
1615 QWidgetPrivate::keyboardGrabber = this;
1616 }
1617}
1618
1619
1620void QWidget::releaseKeyboard()
1621{
1622 if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
1623 XUngrabKeyboard(X11->display, X11->time);
1624 QWidgetPrivate::keyboardGrabber = 0;
1625 }
1626}
1627
1628
1629QWidget *QWidget::mouseGrabber()
1630{
1631 return QWidgetPrivate::mouseGrabber;
1632}
1633
1634
1635QWidget *QWidget::keyboardGrabber()
1636{
1637 return QWidgetPrivate::keyboardGrabber;
1638}
1639
1640void QWidget::activateWindow()
1641{
1642 QWidget *tlw = window();
1643 if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
1644 if (X11->userTime == 0)
1645 X11->userTime = X11->time;
1646 qt_net_update_user_time(tlw, X11->userTime);
1647
1648 if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW))
1649 && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) {
1650 XEvent e;
1651 e.xclient.type = ClientMessage;
1652 e.xclient.message_type = ATOM(_NET_ACTIVE_WINDOW);
1653 e.xclient.display = X11->display;
1654 e.xclient.window = tlw->internalWinId();
1655 e.xclient.format = 32;
1656 e.xclient.data.l[0] = 1; // 1 == application
1657 e.xclient.data.l[1] = X11->userTime;
1658 if (QWidget *aw = QApplication::activeWindow())
1659 e.xclient.data.l[2] = aw->internalWinId();
1660 else
1661 e.xclient.data.l[2] = XNone;
1662 e.xclient.data.l[3] = 0;
1663 e.xclient.data.l[4] = 0;
1664 XSendEvent(X11->display, RootWindow(X11->display, tlw->x11Info().screen()),
1665 false, SubstructureNotifyMask | SubstructureRedirectMask, &e);
1666 } else {
1667 if (!qt_widget_private(tlw)->topData()->waitingForMapNotify)
1668 XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
1669 }
1670 }
1671}
1672
1673void QWidget::setWindowState(Qt::WindowStates newstate)
1674{
1675 Q_D(QWidget);
1676 bool needShow = false;
1677 Qt::WindowStates oldstate = windowState();
1678 if (oldstate == newstate)
1679 return;
1680 if (isWindow()) {
1681 // Ensure the initial size is valid, since we store it as normalGeometry below.
1682 if (!testAttribute(Qt::WA_Resized) && !isVisible())
1683 adjustSize();
1684
1685 QTLWExtra *top = d->topData();
1686
1687 if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
1688 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
1689 && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
1690 if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
1691 top->normalGeometry = geometry();
1692 qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
1693 ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
1694 ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
1695 } else if (! (newstate & Qt::WindowFullScreen)) {
1696 if (newstate & Qt::WindowMaximized) {
1697 // save original geometry
1698 const QRect normalGeometry = geometry();
1699
1700 if (isVisible()) {
1701 data->fstrut_dirty = true;
1702 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
1703 const QRect r = top->normalGeometry;
1704 const QRect fs = d->frameStrut();
1705 setGeometry(maxRect.x() + fs.left(),
1706 maxRect.y() + fs.top(),
1707 maxRect.width() - fs.left() - fs.right(),
1708 maxRect.height() - fs.top() - fs.bottom());
1709 top->normalGeometry = r;
1710 }
1711
1712 if (top->normalGeometry.width() < 0)
1713 top->normalGeometry = normalGeometry;
1714 } else {
1715 // restore original geometry
1716 setGeometry(top->normalGeometry);
1717 }
1718 }
1719 }
1720
1721 if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
1722 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
1723 if (newstate & Qt::WindowFullScreen) {
1724 top->normalGeometry = geometry();
1725 top->fullScreenOffset = d->frameStrut().topLeft();
1726 }
1727 qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
1728 ATOM(_NET_WM_STATE_FULLSCREEN));
1729 } else {
1730 needShow = isVisible();
1731
1732 if (newstate & Qt::WindowFullScreen) {
1733 data->fstrut_dirty = true;
1734 const QRect normalGeometry = geometry();
1735 const QPoint fullScreenOffset = d->frameStrut().topLeft();
1736
1737 top->savedFlags = windowFlags();
1738 setParent(0, Qt::Window | Qt::FramelessWindowHint);
1739 const QRect r = top->normalGeometry;
1740 setGeometry(qApp->desktop()->screenGeometry(this));
1741 top->normalGeometry = r;
1742
1743 if (top->normalGeometry.width() < 0) {
1744 top->normalGeometry = normalGeometry;
1745 top->fullScreenOffset = fullScreenOffset;
1746 }
1747 } else {
1748 setParent(0, top->savedFlags);
1749
1750 if (newstate & Qt::WindowMaximized) {
1751 // from fullscreen to maximized
1752 data->fstrut_dirty = true;
1753 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
1754 const QRect r = top->normalGeometry;
1755 const QRect fs = d->frameStrut();
1756 setGeometry(maxRect.x() + fs.left(),
1757 maxRect.y() + fs.top(),
1758 maxRect.width() - fs.left() - fs.right(),
1759 maxRect.height() - fs.top() - fs.bottom());
1760 top->normalGeometry = r;
1761 } else {
1762 // restore original geometry
1763 setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
1764 -top->fullScreenOffset.y(),
1765 -top->fullScreenOffset.x(),
1766 -top->fullScreenOffset.y()));
1767 }
1768 }
1769 }
1770 }
1771
1772 createWinId();
1773 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
1774 if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
1775 if (isVisible()) {
1776 if (newstate & Qt::WindowMinimized) {
1777 XEvent e;
1778 e.xclient.type = ClientMessage;
1779 e.xclient.message_type = ATOM(WM_CHANGE_STATE);
1780 e.xclient.display = X11->display;
1781 e.xclient.window = data->winid;
1782 e.xclient.format = 32;
1783 e.xclient.data.l[0] = IconicState;
1784 e.xclient.data.l[1] = 0;
1785 e.xclient.data.l[2] = 0;
1786 e.xclient.data.l[3] = 0;
1787 e.xclient.data.l[4] = 0;
1788 XSendEvent(X11->display,
1789 RootWindow(X11->display,d->xinfo.screen()),
1790 False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
1791 } else {
1792 setAttribute(Qt::WA_Mapped);
1793 XMapWindow(X11->display, effectiveWinId());
1794 }
1795 }
1796
1797 needShow = false;
1798 }
1799 }
1800
1801 data->window_state = newstate;
1802
1803 if (needShow)
1804 show();
1805
1806 if (newstate & Qt::WindowActive)
1807 activateWindow();
1808
1809 QWindowStateChangeEvent e(oldstate);
1810 QApplication::sendEvent(this, &e);
1811}
1812
1813/*!
1814 \internal
1815 Platform-specific part of QWidget::show().
1816*/
1817
1818void QWidgetPrivate::show_sys()
1819{
1820 Q_Q(QWidget);
1821 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
1822
1823 if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
1824 invalidateBuffer(q->rect());
1825 q->setAttribute(Qt::WA_Mapped);
1826 if (QTLWExtra *tlwExtra = maybeTopData())
1827 tlwExtra->waitingForMapNotify = 0;
1828 return;
1829 }
1830
1831 if (q->isWindow()) {
1832 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
1833 XWMHints wm_hints;
1834 bool got_hints = h != 0;
1835 if (!got_hints) {
1836 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
1837 h = &wm_hints;
1838 }
1839 h->initial_state = q->isMinimized() ? IconicState : NormalState;
1840 h->flags |= StateHint;
1841 XSetWMHints(X11->display, q->internalWinId(), h);
1842 if (got_hints)
1843 XFree((char *)h);
1844
1845 // update WM_NORMAL_HINTS
1846 do_size_hints(q, extra);
1847
1848 // udpate WM_TRANSIENT_FOR
1849 if (isTransient(q)) {
1850 QWidget *p = q->parentWidget();
1851
1852#ifndef QT_NO_MENU
1853 // hackish ... try to find the main window related to this QMenu
1854 if (qobject_cast<QMenu *>(q)) {
1855 p = static_cast<QMenuPrivate*>(this)->causedPopup.widget;
1856 if (!p)
1857 p = q->parentWidget();
1858 if (!p)
1859 p = QApplication::widgetAt(q->pos());
1860 if (!p)
1861 p = qApp->activeWindow();
1862 }
1863#endif
1864 if (p)
1865 p = p->window();
1866 if (p) {
1867 // transient for window
1868 XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
1869 } else {
1870 // transient for group
1871 XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
1872 }
1873 }
1874
1875 // update _MOTIF_WM_HINTS
1876 QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
1877
1878 if (data.window_modality != Qt::NonModal) {
1879 switch (data.window_modality) {
1880 case Qt::WindowModal:
1881 mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
1882 break;
1883 case Qt::ApplicationModal:
1884 default:
1885 mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
1886 break;
1887 }
1888 mwmhints.flags |= MWM_HINTS_INPUT_MODE;
1889 } else {
1890 mwmhints.input_mode = MWM_INPUT_MODELESS;
1891 mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
1892 }
1893
1894 if (q->minimumSize() == q->maximumSize()) {
1895 // fixed size, remove the resize handle (since mwm/dtwm
1896 // isn't smart enough to do it itself)
1897 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
1898 if (mwmhints.functions == MWM_FUNC_ALL) {
1899 mwmhints.functions = MWM_FUNC_MOVE;
1900 } else {
1901 mwmhints.functions &= ~MWM_FUNC_RESIZE;
1902 }
1903
1904 if (mwmhints.decorations == MWM_DECOR_ALL) {
1905 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1906 mwmhints.decorations = (MWM_DECOR_BORDER
1907 | MWM_DECOR_TITLE
1908 | MWM_DECOR_MENU);
1909 } else {
1910 mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
1911 }
1912
1913 if (q->windowFlags() & Qt::WindowMinimizeButtonHint) {
1914 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1915 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
1916 mwmhints.functions |= MWM_FUNC_MINIMIZE;
1917 }
1918 if (q->windowFlags() & Qt::WindowMaximizeButtonHint) {
1919 mwmhints.flags |= MWM_HINTS_DECORATIONS;
1920 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
1921 mwmhints.functions |= MWM_FUNC_MAXIMIZE;
1922 }
1923 if (q->windowFlags() & Qt::WindowCloseButtonHint)
1924 mwmhints.functions |= MWM_FUNC_CLOSE;
1925 }
1926
1927 SetMWMHints(X11->display, q->internalWinId(), mwmhints);
1928
1929 // update _NET_WM_STATE
1930 QVector<Atom> netWmState = getNetWmState(q);
1931
1932 Qt::WindowFlags flags = q->windowFlags();
1933 if (flags & Qt::WindowStaysOnTopHint) {
1934 if (flags & Qt::WindowStaysOnBottomHint)
1935 qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time";
1936 if (!netWmState.contains(ATOM(_NET_WM_STATE_ABOVE)))
1937 netWmState.append(ATOM(_NET_WM_STATE_ABOVE));
1938 if (!netWmState.contains(ATOM(_NET_WM_STATE_STAYS_ON_TOP)))
1939 netWmState.append(ATOM(_NET_WM_STATE_STAYS_ON_TOP));
1940 } else if (flags & Qt::WindowStaysOnBottomHint) {
1941 if (!netWmState.contains(ATOM(_NET_WM_STATE_BELOW)))
1942 netWmState.append(ATOM(_NET_WM_STATE_BELOW));
1943 }
1944 if (q->isFullScreen()) {
1945 if (!netWmState.contains(ATOM(_NET_WM_STATE_FULLSCREEN)))
1946 netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN));
1947 }
1948 if (q->isMaximized()) {
1949 if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
1950 netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ));
1951 if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))
1952 netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
1953 }
1954 if (data.window_modality != Qt::NonModal) {
1955 if (!netWmState.contains(ATOM(_NET_WM_STATE_MODAL)))
1956 netWmState.append(ATOM(_NET_WM_STATE_MODAL));
1957 }
1958
1959 if (!netWmState.isEmpty()) {
1960 XChangeProperty(X11->display, q->internalWinId(),
1961 ATOM(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace,
1962 (unsigned char *) netWmState.data(), netWmState.size());
1963 } else {
1964 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
1965 }
1966
1967 // set _NET_WM_USER_TIME
1968 Time userTime = X11->userTime;
1969 bool setUserTime = false;
1970 if (q->testAttribute(Qt::WA_ShowWithoutActivating)) {
1971 userTime = 0;
1972 setUserTime = true;
1973 } else if (userTime != CurrentTime) {
1974 setUserTime = true;
1975 }
1976 if (setUserTime)
1977 qt_net_update_user_time(q, userTime);
1978
1979#ifndef QT_NO_XSYNC
1980 if (!topData()->syncUpdateCounter) {
1981 XSyncValue value;
1982 XSyncIntToValue(&value, 0);
1983 topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
1984
1985 XChangeProperty(X11->display, q->internalWinId(),
1986 ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
1987 XA_CARDINAL,
1988 32, PropModeReplace,
1989 (uchar *) &topData()->syncUpdateCounter, 1);
1990
1991 topData()->newCounterValueHi = 0;
1992 topData()->newCounterValueLo = 0;
1993 }
1994#endif
1995
1996 if (!topData()->embedded
1997 && (topData()->validWMState || topData()->waitingForMapNotify)
1998 && !q->isMinimized()) {
1999 X11->deferred_map.append(q);
2000 return;
2001 }
2002
2003 if (q->isMaximized() && !q->isFullScreen()
2004 && !(X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
2005 && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
2006 XMapWindow(X11->display, q->internalWinId());
2007 data.fstrut_dirty = true;
2008 qt_x11_wait_for_window_manager(q);
2009
2010 // if the wm was not smart enough to adjust our size, do that manually
2011 QRect maxRect = QApplication::desktop()->availableGeometry(q);
2012
2013 QTLWExtra *top = topData();
2014 QRect normalRect = top->normalGeometry;
2015 const QRect fs = frameStrut();
2016
2017 q->setGeometry(maxRect.x() + fs.left(),
2018 maxRect.y() + fs.top(),
2019 maxRect.width() - fs.left() - fs.right(),
2020 maxRect.height() - fs.top() - fs.bottom());
2021
2022 // restore the original normalGeometry
2023 top->normalGeometry = normalRect;
2024 // internalSetGeometry() clears the maximized flag... make sure we set it back
2025 data.window_state = data.window_state | Qt::WindowMaximized;
2026 q->setAttribute(Qt::WA_Mapped);
2027 return;
2028 }
2029
2030 if (q->isFullScreen() && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
2031 XMapWindow(X11->display, q->internalWinId());
2032 qt_x11_wait_for_window_manager(q);
2033 q->setAttribute(Qt::WA_Mapped);
2034 return;
2035 }
2036 }
2037
2038 invalidateBuffer(q->rect());
2039
2040 if (q->testAttribute(Qt::WA_OutsideWSRange))
2041 return;
2042 q->setAttribute(Qt::WA_Mapped);
2043 if (q->isWindow())
2044 topData()->waitingForMapNotify = 1;
2045
2046 if (!q->isWindow()
2047 && (!q->autoFillBackground()
2048 || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
2049 if (q->internalWinId()) {
2050 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
2051 XMapWindow(X11->display, q->internalWinId());
2052 updateSystemBackground();
2053 }
2054 return;
2055 }
2056
2057 if (q->internalWinId())
2058 XMapWindow(X11->display, q->internalWinId());
2059
2060 // Freedesktop.org Startup Notification
2061 if (X11->startupId && q->isWindow()) {
2062 QByteArray message("remove: ID=");
2063 message.append(X11->startupId);
2064 sendStartupMessage(message.constData());
2065 X11->startupId = 0;
2066 }
2067}
2068
2069/*!
2070 \internal
2071 Platform-specific part of QWidget::show().
2072*/
2073
2074void QWidgetPrivate::sendStartupMessage(const char *message) const
2075{
2076 Q_Q(const QWidget);
2077
2078 if (!message)
2079 return;
2080
2081 XEvent xevent;
2082 xevent.xclient.type = ClientMessage;
2083 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN);
2084 xevent.xclient.display = X11->display;
2085 xevent.xclient.window = q->internalWinId();
2086 xevent.xclient.format = 8;
2087
2088 Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
2089 uint sent = 0;
2090 uint length = strlen(message) + 1;
2091 do {
2092 if (sent == 20)
2093 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
2094
2095 for (uint i = 0; i < 20 && i + sent <= length; i++)
2096 xevent.xclient.data.b[i] = message[i + sent++];
2097
2098 XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
2099 } while (sent <= length);
2100}
2101
2102void QWidgetPrivate::setNetWmWindowTypes()
2103{
2104 Q_Q(QWidget);
2105 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2106
2107 if (!q->isWindow()) {
2108 if (q->internalWinId())
2109 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE));
2110 return;
2111 }
2112
2113 QVector<long> windowTypes;
2114
2115 // manual selection 1 (these are never set by Qt and take precedence)
2116 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop))
2117 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DESKTOP));
2118 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock))
2119 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DOCK));
2120 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification))
2121 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NOTIFICATION));
2122
2123 // manual selection 2 (Qt uses these during auto selection);
2124 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility))
2125 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2126 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash))
2127 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2128 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog))
2129 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2130 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip))
2131 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2132
2133 // manual selection 3 (these can be set by Qt, but don't have a
2134 // corresponding Qt::WindowType). note that order of the *MENU
2135 // atoms is important
2136 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu))
2137 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_MENU));
2138 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu))
2139 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
2140 if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu))
2141 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU));
2142 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar))
2143 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR));
2144 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo))
2145 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_COMBO));
2146 if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND))
2147 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DND));
2148
2149 // automatic selection
2150 switch (q->windowType()) {
2151 case Qt::Dialog:
2152 case Qt::Sheet:
2153 // dialog netwm type
2154 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG));
2155 break;
2156
2157 case Qt::Tool:
2158 case Qt::Drawer:
2159 // utility netwm type
2160 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY));
2161 break;
2162
2163 case Qt::ToolTip:
2164 // tooltip netwm type
2165 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP));
2166 break;
2167
2168 case Qt::SplashScreen:
2169 // splash netwm type
2170 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH));
2171 break;
2172
2173 default:
2174 break;
2175 }
2176
2177 if (q->windowFlags() & Qt::FramelessWindowHint) {
2178 // override netwm type - quick and easy for KDE noborder
2179 windowTypes.append(ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
2180 }
2181
2182 // normal netwm type - default
2183 windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL));
2184
2185 if (!windowTypes.isEmpty()) {
2186 XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32,
2187 PropModeReplace, (unsigned char *) windowTypes.constData(),
2188 windowTypes.count());
2189 } else {
2190 XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE));
2191 }
2192}
2193
2194/*!
2195 \internal
2196 Platform-specific part of QWidget::hide().
2197*/
2198
2199void QWidgetPrivate::hide_sys()
2200{
2201 Q_Q(QWidget);
2202 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2203 deactivateWidgetCleanup();
2204 if (q->isWindow()) {
2205 X11->deferred_map.removeAll(q);
2206 if (q->internalWinId()) // in nsplugin, may be 0
2207 XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen());
2208 XFlush(X11->display);
2209 } else {
2210 invalidateBuffer(q->rect());
2211 if (q->internalWinId()) // in nsplugin, may be 0
2212 XUnmapWindow(X11->display, q->internalWinId());
2213 }
2214 q->setAttribute(Qt::WA_Mapped, false);
2215}
2216
2217void QWidgetPrivate::setFocus_sys()
2218{
2219
2220}
2221
2222
2223void QWidgetPrivate::raise_sys()
2224{
2225 Q_Q(QWidget);
2226 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2227 if (q->internalWinId())
2228 XRaiseWindow(X11->display, q->internalWinId());
2229}
2230
2231void QWidgetPrivate::lower_sys()
2232{
2233 Q_Q(QWidget);
2234 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2235 if (q->internalWinId())
2236 XLowerWindow(X11->display, q->internalWinId());
2237 if(!q->isWindow())
2238 invalidateBuffer(q->rect());
2239}
2240
2241void QWidgetPrivate::stackUnder_sys(QWidget* w)
2242{
2243 Q_Q(QWidget);
2244 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2245 if (q->internalWinId() && w->internalWinId()) {
2246 Window stack[2];
2247 stack[0] = w->internalWinId();;
2248 stack[1] = q->internalWinId();
2249 XRestackWindows(X11->display, stack, 2);
2250 }
2251 if(!q->isWindow() || !w->internalWinId())
2252 invalidateBuffer(q->rect());
2253}
2254
2255
2256static void do_size_hints(QWidget* widget, QWExtra *x)
2257{
2258 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
2259 XSizeHints s;
2260 s.flags = 0;
2261 if (x) {
2262 QRect g = widget->geometry();
2263 s.x = g.x();
2264 s.y = g.y();
2265 s.width = g.width();
2266 s.height = g.height();
2267 if (x->minw > 0 || x->minh > 0) {
2268 // add minimum size hints
2269 s.flags |= PMinSize;
2270 s.min_width = qMin(XCOORD_MAX, x->minw);
2271 s.min_height = qMin(XCOORD_MAX, x->minh);
2272 }
2273 if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
2274 // add maximum size hints
2275 s.flags |= PMaxSize;
2276 s.max_width = qMin(XCOORD_MAX, x->maxw);
2277 s.max_height = qMin(XCOORD_MAX, x->maxh);
2278 }
2279 if (x->topextra &&
2280 (x->topextra->incw > 0 || x->topextra->inch > 0)) {
2281 // add resize increment hints
2282 s.flags |= PResizeInc | PBaseSize;
2283 s.width_inc = x->topextra->incw;
2284 s.height_inc = x->topextra->inch;
2285 s.base_width = x->topextra->basew;
2286 s.base_height = x->topextra->baseh;
2287 }
2288 }
2289 if (widget->testAttribute(Qt::WA_Moved)) {
2290 // user (i.e. command-line) specified position
2291 s.flags |= USPosition;
2292 s.flags |= PPosition;
2293 }
2294 if (widget->testAttribute(Qt::WA_Resized)) {
2295 // user (i.e. command-line) specified size
2296 s.flags |= USSize;
2297 s.flags |= PSize;
2298 }
2299 s.flags |= PWinGravity;
2300 if (widget->testAttribute(Qt::WA_Moved) && x && x->topextra && !x->topextra->posFromMove) {
2301 // position came from setGeometry(), tell the WM that we don't
2302 // want our window gravity-shifted
2303 s.win_gravity = StaticGravity;
2304 } else {
2305 // position came from move()
2306 s.x = widget->x();
2307 s.y = widget->y();
2308 s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
2309 }
2310 if (widget->internalWinId())
2311 XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
2312}
2313
2314
2315/*
2316 Helper function for non-toplevel widgets. Helps to map Qt's 32bit
2317 coordinate system to X11's 16bit coordinate system.
2318
2319 Sets the geometry of the widget to data.crect, but clipped to sizes
2320 that X can handle. Unmaps widgets that are completely outside the
2321 valid range.
2322
2323 Maintains data.wrect, which is the geometry of the X widget,
2324 measured in this widget's coordinate system.
2325
2326 if the parent is not clipped, parentWRect is empty, otherwise
2327 parentWRect is the geometry of the parent's X rect, measured in
2328 parent's coord sys
2329 */
2330void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
2331{
2332 Q_Q(QWidget);
2333 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2334
2335 /*
2336 There are up to four different coordinate systems here:
2337 Qt coordinate system for this widget.
2338 X coordinate system for this widget (relative to wrect).
2339 Qt coordinate system for parent
2340 X coordinate system for parent (relative to parent's wrect).
2341 */
2342 Display *dpy = xinfo.display();
2343 QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
2344 QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
2345 QRect wrect;
2346 //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)
2347 QRect xrect = data.crect;
2348
2349 const QWidget *const parent = q->parentWidget();
2350 QRect parentWRect = parent->data->wrect;
2351
2352 if (parentWRect.isValid()) {
2353 // parent is clipped, and we have to clip to the same limit as parent
2354 if (!parentWRect.contains(xrect)) {
2355 xrect &= parentWRect;
2356 wrect = xrect;
2357 //translate from parent's to my Qt coord sys
2358 wrect.translate(-data.crect.topLeft());
2359 }
2360 //translate from parent's Qt coords to parent's X coords
2361 xrect.translate(-parentWRect.topLeft());
2362
2363 } else {
2364 // parent is not clipped, we may or may not have to clip
2365
2366 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
2367 // This is where the main optimization is: we are already
2368 // clipped, and if our clip is still valid, we can just
2369 // move our window, and do not need to move or clip
2370 // children
2371
2372 QRect vrect = xrect & parent->rect();
2373 vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
2374 if (data.wrect.contains(vrect)) {
2375 xrect = data.wrect;
2376 xrect.translate(data.crect.topLeft());
2377 if (data.winid)
2378 XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
2379 return;
2380 }
2381 }
2382
2383 if (!validRange.contains(xrect)) {
2384 // we are too big, and must clip
2385 xrect &=wrectRange;
2386 wrect = xrect;
2387 wrect.translate(-data.crect.topLeft());
2388 //parent's X coord system is equal to parent's Qt coord
2389 //sys, so we don't need to map xrect.
2390 }
2391
2392 }
2393
2394 // unmap if we are outside the valid window system coord system
2395 bool outsideRange = !xrect.isValid();
2396 bool mapWindow = false;
2397 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
2398 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
2399 if (outsideRange) {
2400 if (data.winid)
2401 XUnmapWindow(dpy, data.winid);
2402 q->setAttribute(Qt::WA_Mapped, false);
2403 } else if (!q->isHidden()) {
2404 mapWindow = true;
2405 }
2406 }
2407
2408 if (outsideRange)
2409 return;
2410
2411 bool jump = (data.wrect != wrect);
2412 data.wrect = wrect;
2413
2414
2415 // and now recursively for all children...
2416 // ### can be optimized
2417 for (int i = 0; i < children.size(); ++i) {
2418 QObject *object = children.at(i);
2419 if (object->isWidgetType()) {
2420 QWidget *w = static_cast<QWidget *>(object);
2421 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
2422 w->d_func()->setWSGeometry(jump);
2423 }
2424 }
2425
2426 if (data.winid) {
2427 // move ourselves to the new position and map (if necessary) after
2428 // the movement. Rationale: moving unmapped windows is much faster
2429 // than moving mapped windows
2430 if (jump) //avoid flicker when jumping
2431 XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
2432 if (!parent->internalWinId())
2433 xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
2434 XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
2435 }
2436
2437 //to avoid flicker, we have to show children after the helper widget has moved
2438 if (jump) {
2439 for (int i = 0; i < children.size(); ++i) {
2440 QObject *object = children.at(i);
2441 if (object->isWidgetType()) {
2442 QWidget *w = static_cast<QWidget *>(object);
2443 if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
2444 w->setAttribute(Qt::WA_Mapped);
2445 if (w->internalWinId())
2446 XMapWindow(dpy, w->data->winid);
2447 }
2448 }
2449 }
2450 }
2451
2452
2453 if (jump && data.winid)
2454 XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
2455
2456 if (mapWindow && !dontShow) {
2457 q->setAttribute(Qt::WA_Mapped);
2458 if (data.winid)
2459 XMapWindow(dpy, data.winid);
2460 }
2461}
2462
2463void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
2464{
2465 Q_Q(QWidget);
2466 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
2467 Display *dpy = X11->display;
2468
2469 if ((q->windowType() == Qt::Desktop))
2470 return;
2471 if (q->isWindow()) {
2472 if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
2473 && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
2474 data.window_state &= ~Qt::WindowMaximized;
2475 if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
2476 data.window_state &= ~Qt::WindowFullScreen;
2477 if (QTLWExtra *topData = maybeTopData())
2478 topData->normalGeometry = QRect(0,0,-1,-1);
2479 } else {
2480 uint s = data.window_state;
2481 s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
2482 data.window_state = s;
2483 }
2484 if (extra) { // any size restrictions?
2485 w = qMin(w,extra->maxw);
2486 h = qMin(h,extra->maxh);
2487 w = qMax(w,extra->minw);
2488 h = qMax(h,extra->minh);
2489 }
2490 QPoint oldPos(q->pos());
2491 QSize oldSize(q->size());
2492 QRect oldGeom(data.crect);
2493 QRect r(x, y, w, h);
2494
2495 // We only care about stuff that changes the geometry, or may
2496 // cause the window manager to change its state
2497 if (!q->isWindow() && oldGeom == r)
2498 return;
2499
2500 data.crect = r;
2501 bool isResize = q->size() != oldSize;
2502
2503 if (q->isWindow()) {
2504 if (w == 0 || h == 0) {
2505 q->setAttribute(Qt::WA_OutsideWSRange, true);
2506 if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
2507 hide_sys();
2508 } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
2509 q->setAttribute(Qt::WA_OutsideWSRange, false);
2510
2511 // put the window in its place and show it
2512 if (data.winid)
2513 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2514 topData()->posFromMove = false; // force StaticGravity
2515 do_size_hints(q, extra);
2516 show_sys();
2517 } else {
2518 q->setAttribute(Qt::WA_OutsideWSRange, false);
2519 if (!q->isVisible())
2520 do_size_hints(q, extra);
2521 if (isMove) {
2522 if ((data.window_flags & Qt::X11BypassWindowManagerHint) == Qt::X11BypassWindowManagerHint
2523 // work around 4Dwm's incompliance with ICCCM 4.1.5
2524 || X11->desktopEnvironment == DE_4DWM) {
2525 if (data.winid)
2526 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
2527 } else if (q->isVisible()
2528 && topData()->validWMState
2529 && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) {
2530 XEvent e;
2531 e.xclient.type = ClientMessage;
2532 e.xclient.message_type = ATOM(_NET_MOVERESIZE_WINDOW);
2533 e.xclient.display = X11->display;
2534 e.xclient.window = q->internalWinId();
2535 e.xclient.format = 32;
2536 e.xclient.data.l[0] = StaticGravity | 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12;
2537 e.xclient.data.l[1] = x;
2538 e.xclient.data.l[2] = y;
2539 e.xclient.data.l[3] = w;
2540 e.xclient.data.l[4] = h;
2541 XSendEvent(X11->display, RootWindow(X11->display, q->x11Info().screen()),
2542 false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
2543 } else if (data.winid) {
2544 // pos() is right according to ICCCM 4.1.5
2545 XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
2546 }
2547 } else if (isResize && data.winid) {
2548 if (!q->isVisible()
2549 && topData()->validWMState
2550 && !q->testAttribute(Qt::WA_PendingMoveEvent)) {
2551 /*
2552 even though we've not visible, we could be in a
2553 race w/ the window manager, and it may ignore
2554 our ConfigureRequest. setting posFromMove to
2555 false makes sure that doDeferredMap() in
2556 qapplication_x11.cpp keeps the window in the
2557 right place
2558 */
2559 topData()->posFromMove = false;
2560 }
2561 XResizeWindow(dpy, data.winid, w, h);
2562 }
2563 }
2564 if (isResize && !q->testAttribute(Qt::WA_DontShowOnScreen)) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
2565 q->setAttribute(Qt::WA_WState_ConfigPending);
2566
2567 } else {
2568 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
2569 const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
2570 const bool disableInTopLevelResize = inTopLevelResize && q->internalWinId();
2571 if (disableInTopLevelResize) {
2572 // Top-level resize optimization does not work for native child widgets;
2573 // disable it for this particular widget.
2574 tlwExtra->inTopLevelResize = false;
2575 }
2576
2577 if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) {
2578 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
2579 }
2580 if (q->testAttribute(Qt::WA_WState_Created))
2581 setWSGeometry();
2582
2583 if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible())
2584 invalidateBuffer_resizeHelper(oldPos, oldSize);
2585
2586 if (disableInTopLevelResize)
2587 tlwExtra->inTopLevelResize = true;
2588 }
2589
2590 if (q->isVisible()) {
2591 if (isMove && q->pos() != oldPos) {
2592 if (X11->desktopEnvironment != DE_4DWM) {
2593 // pos() is right according to ICCCM 4.1.5
2594 QMoveEvent e(q->pos(), oldPos);
2595 QApplication::sendEvent(q, &e);
2596 } else {
2597 // work around 4Dwm's incompliance with ICCCM 4.1.5
2598 QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
2599 QApplication::sendEvent(q, &e);
2600 }
2601 }
2602 if (isResize) {
2603 static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
2604 // If we have a backing store with static contents, we have to disable the top-level
2605 // resize optimization in order to get invalidated regions for resized widgets.
2606 // The optimization discards all invalidateBuffer() calls since we're going to
2607 // repaint everything anyways, but that's not the case with static contents.
2608 const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
2609 && !extra->topextra->inTopLevelResize
2610 && (!extra->topextra->backingStore
2611 || !extra->topextra->backingStore->hasStaticContents());
2612 if (setTopLevelResize)
2613 extra->topextra->inTopLevelResize = true;
2614 QResizeEvent e(q->size(), oldSize);
2615 QApplication::sendEvent(q, &e);
2616 if (setTopLevelResize)
2617 extra->topextra->inTopLevelResize = false;
2618 }
2619 } else {
2620 if (isMove && q->pos() != oldPos)
2621 q->setAttribute(Qt::WA_PendingMoveEvent, true);
2622 if (isResize)
2623 q->setAttribute(Qt::WA_PendingResizeEvent, true);
2624 }
2625}
2626
2627void QWidgetPrivate::setConstraints_sys()
2628{
2629 Q_Q(QWidget);
2630#ifdef ALIEN_DEBUG
2631 qDebug() << "QWidgetPrivate::setConstraints_sys START" << q;
2632#endif
2633 if (q->testAttribute(Qt::WA_WState_Created))
2634 do_size_hints(q, extra);
2635#ifdef ALIEN_DEBUG
2636 qDebug() << "QWidgetPrivate::setConstraints_sys END" << q;
2637#endif
2638}
2639
2640void QWidgetPrivate::scroll_sys(int dx, int dy)
2641{
2642 Q_Q(QWidget);
2643
2644 scrollChildren(dx, dy);
2645 if (!paintOnScreen()) {
2646 scrollRect(q->rect(), dx, dy);
2647 } else {
2648 scroll_sys(dx, dy, QRect());
2649 }
2650}
2651
2652void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
2653{
2654 Q_Q(QWidget);
2655
2656 if (!paintOnScreen()) {
2657 scrollRect(r, dx, dy);
2658 return;
2659 }
2660 bool valid_rect = r.isValid();
2661 bool just_update = qAbs(dx) > q->width() || qAbs(dy) > q->height();
2662 QRect sr = valid_rect ? r : clipRect();
2663 if (just_update)
2664 q->update();
2665 else if (!valid_rect)
2666 dirty.translate(dx, dy);
2667
2668 int x1, y1, x2, y2, w = sr.width(), h = sr.height();
2669 if (dx > 0) {
2670 x1 = sr.x();
2671 x2 = x1+dx;
2672 w -= dx;
2673 } else {
2674 x2 = sr.x();
2675 x1 = x2-dx;
2676 w += dx;
2677 }
2678 if (dy > 0) {
2679 y1 = sr.y();
2680 y2 = y1+dy;
2681 h -= dy;
2682 } else {
2683 y2 = sr.y();
2684 y1 = y2-dy;
2685 h += dy;
2686 }
2687
2688 if (dx == 0 && dy == 0)
2689 return;
2690
2691 Display *dpy = X11->display;
2692 // Want expose events
2693 if (w > 0 && h > 0 && !just_update && q->internalWinId()) {
2694 GC gc = XCreateGC(dpy, q->internalWinId(), 0, 0);
2695 XSetGraphicsExposures(dpy, gc, True);
2696 XCopyArea(dpy, q->internalWinId(), q->internalWinId(), gc, x1, y1, w, h, x2, y2);
2697 XFreeGC(dpy, gc);
2698 }
2699
2700 if (!valid_rect && !children.isEmpty()) { // scroll children
2701 QPoint pd(dx, dy);
2702 for (int i = 0; i < children.size(); ++i) { // move all children
2703 register QObject *object = children.at(i);
2704 if (object->isWidgetType()) {
2705 QWidget *w = static_cast<QWidget *>(object);
2706 if (!w->isWindow())
2707 w->move(w->pos() + pd);
2708 }
2709 }
2710 }
2711
2712 if (just_update)
2713 return;
2714
2715 // Don't let the server be bogged-down with repaint events
2716 bool repaint_immediately = (qt_sip_count(q) < 3 && !q->testAttribute(Qt::WA_WState_InPaintEvent));
2717
2718 if (dx) {
2719 int x = x2 == sr.x() ? sr.x()+w : sr.x();
2720 if (repaint_immediately)
2721 q->repaint(x, sr.y(), qAbs(dx), sr.height());
2722 else if (q->internalWinId())
2723 XClearArea(dpy, data.winid, x, sr.y(), qAbs(dx), sr.height(), True);
2724 }
2725 if (dy) {
2726 int y = y2 == sr.y() ? sr.y()+h : sr.y();
2727 if (repaint_immediately)
2728 q->repaint(sr.x(), y, sr.width(), qAbs(dy));
2729 else if (q->internalWinId())
2730 XClearArea(dpy, data.winid, sr.x(), y, sr.width(), qAbs(dy), True);
2731 }
2732
2733 qt_insert_sip(q, dx, dy); // #### ignores r
2734}
2735
2736int QWidget::metric(PaintDeviceMetric m) const
2737{
2738 Q_D(const QWidget);
2739 int val;
2740 if (m == PdmWidth) {
2741 val = data->crect.width();
2742 } else if (m == PdmHeight) {
2743 val = data->crect.height();
2744 } else {
2745 Display *dpy = X11->display;
2746 int scr = d->xinfo.screen();
2747 switch (m) {
2748 case PdmDpiX:
2749 case PdmPhysicalDpiX:
2750 if (d->extra && d->extra->customDpiX)
2751 val = d->extra->customDpiX;
2752 else if (d->parent)
2753 val = static_cast<QWidget *>(d->parent)->metric(m);
2754 else
2755 val = QX11Info::appDpiX(scr);
2756 break;
2757 case PdmDpiY:
2758 case PdmPhysicalDpiY:
2759 if (d->extra && d->extra->customDpiY)
2760 val = d->extra->customDpiY;
2761 else if (d->parent)
2762 val = static_cast<QWidget *>(d->parent)->metric(m);
2763 else
2764 val = QX11Info::appDpiY(scr);
2765 break;
2766 case PdmWidthMM:
2767 val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
2768 DisplayWidth(dpy,scr);
2769 break;
2770 case PdmHeightMM:
2771 val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
2772 DisplayHeight(dpy,scr);
2773 break;
2774 case PdmNumColors:
2775 val = d->xinfo.cells();
2776 break;
2777 case PdmDepth:
2778 val = d->xinfo.depth();
2779 break;
2780 default:
2781 val = 0;
2782 qWarning("QWidget::metric: Invalid metric command");
2783 }
2784 }
2785 return val;
2786}
2787
2788void QWidgetPrivate::createSysExtra()
2789{
2790 extra->compress_events = true;
2791 extra->xDndProxy = 0;
2792}
2793
2794void QWidgetPrivate::deleteSysExtra()
2795{
2796}
2797
2798void QWidgetPrivate::createTLSysExtra()
2799{
2800 extra->topextra->spont_unmapped = 0;
2801 extra->topextra->dnd = 0;
2802 extra->topextra->validWMState = 0;
2803 extra->topextra->waitingForMapNotify = 0;
2804 extra->topextra->parentWinId = 0;
2805 extra->topextra->userTimeWindow = 0;
2806#ifndef QT_NO_XSYNC
2807 extra->topextra->syncUpdateCounter = 0;
2808 extra->topextra->syncRequestTimestamp = 0;
2809 extra->topextra->newCounterValueHi = 0;
2810 extra->topextra->newCounterValueLo = 0;
2811#endif
2812}
2813
2814void QWidgetPrivate::deleteTLSysExtra()
2815{
2816 // don't destroy input context here. it will be destroyed in
2817 // QWidget::destroy() destroyInputContext();
2818}
2819
2820void QWidgetPrivate::registerDropSite(bool on)
2821{
2822 Q_UNUSED(on);
2823}
2824
2825void QWidgetPrivate::setMask_sys(const QRegion &region)
2826{
2827 Q_Q(QWidget);
2828 if (!q->internalWinId())
2829 return;
2830
2831 if (region.isEmpty()) {
2832 XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2833 XNone, ShapeSet);
2834 } else {
2835 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
2836 region.handle(), ShapeSet);
2837 }
2838}
2839
2840/*!
2841 \internal
2842
2843 Computes the frame rectangle when needed. This is an internal function, you
2844 should never call this.
2845*/
2846
2847void QWidgetPrivate::updateFrameStrut()
2848{
2849 Q_Q(QWidget);
2850
2851 QTLWExtra *top = topData();
2852 if (!top->validWMState) {
2853 return;
2854 }
2855 if (!q->isWindow() && !q->internalWinId()) {
2856 data.fstrut_dirty = false;
2857 return;
2858 }
2859
2860 Atom type_ret;
2861 Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root
2862 Window *c;
2863 int i_unused;
2864 unsigned int nc;
2865 unsigned char *data_ret;
2866 unsigned long l_unused;
2867
2868 while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
2869 if (c && nc > 0)
2870 XFree(c);
2871
2872 if (! p) {
2873 qWarning("QWidget::updateFrameStrut: No parent");
2874 return;
2875 }
2876
2877 // if the parent window is the root window, an Enlightenment virtual root or
2878 // a NET WM virtual root window, stop here
2879 data_ret = 0;
2880 if (p == r ||
2881 (XGetWindowProperty(X11->display, p,
2882 ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
2883 &type_ret, &i_unused, &l_unused, &l_unused,
2884 &data_ret) == Success &&
2885 type_ret == XA_CARDINAL)) {
2886 if (data_ret)
2887 XFree(data_ret);
2888
2889 break;
2890 } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
2891 int i = 0;
2892 while (X11->net_virtual_root_list[i] != 0) {
2893 if (X11->net_virtual_root_list[i++] == p)
2894 break;
2895 }
2896 }
2897
2898 l = w;
2899 w = p;
2900 }
2901
2902 // we have our window
2903 int transx, transy;
2904 XWindowAttributes wattr;
2905 if (XTranslateCoordinates(X11->display, l, w,
2906 0, 0, &transx, &transy, &p) &&
2907 XGetWindowAttributes(X11->display, w, &wattr)) {
2908 top->frameStrut.setCoords(transx,
2909 transy,
2910 wattr.width - data.crect.width() - transx,
2911 wattr.height - data.crect.height() - transy);
2912
2913 // add the border_width for the window managers frame... some window managers
2914 // do not use a border_width of zero for their frames, and if we the left and
2915 // top strut, we ensure that pos() is absolutely correct. frameGeometry()
2916 // will still be incorrect though... perhaps i should have foffset as well, to
2917 // indicate the frame offset (equal to the border_width on X).
2918 // - Brad
2919 top->frameStrut.adjust(wattr.border_width,
2920 wattr.border_width,
2921 wattr.border_width,
2922 wattr.border_width);
2923 }
2924
2925 data.fstrut_dirty = false;
2926}
2927
2928void QWidgetPrivate::setWindowOpacity_sys(qreal opacity)
2929{
2930 Q_Q(QWidget);
2931 ulong value = ulong(opacity * 0xffffffff);
2932 XChangeProperty(QX11Info::display(), q->internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL,
2933 32, PropModeReplace, (uchar*)&value, 1);
2934}
2935
2936const QX11Info &QWidget::x11Info() const
2937{
2938 Q_D(const QWidget);
2939 return d->xinfo;
2940}
2941
2942void QWidgetPrivate::setWindowRole()
2943{
2944 Q_Q(QWidget);
2945 if (!q->internalWinId())
2946 return;
2947 QByteArray windowRole = topData()->role.toUtf8();
2948 XChangeProperty(X11->display, q->internalWinId(),
2949 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
2950 (unsigned char *)windowRole.constData(), windowRole.length());
2951}
2952
2953Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
2954QPaintEngine *QWidget::paintEngine() const
2955{
2956 Q_D(const QWidget);
2957 if (qt_widget_paintengine()->isActive()) {
2958 if (d->extraPaintEngine)
2959 return d->extraPaintEngine;
2960 QWidget *self = const_cast<QWidget *>(this);
2961 self->d_func()->extraPaintEngine = new QX11PaintEngine();
2962 return d->extraPaintEngine;
2963 }
2964 return qt_widget_paintengine();
2965}
2966
2967QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
2968{
2969 return new QX11WindowSurface(q_func());
2970}
2971
2972Qt::HANDLE QWidget::x11PictureHandle() const
2973{
2974#ifndef QT_NO_XRENDER
2975 Q_D(const QWidget);
2976 if (!internalWinId() && testAttribute(Qt::WA_WState_Created))
2977 (void)winId(); // enforce native window
2978 return d->picture;
2979#else
2980 return 0;
2981#endif // QT_NO_XRENDER
2982}
2983
2984#ifndef QT_NO_XRENDER
2985XRenderColor QX11Data::preMultiply(const QColor &c)
2986{
2987 XRenderColor color;
2988 const uint A = c.alpha(),
2989 R = c.red(),
2990 G = c.green(),
2991 B = c.blue();
2992 color.alpha = (A | A << 8);
2993 color.red = (R | R << 8) * color.alpha / 0x10000;
2994 color.green = (G | G << 8) * color.alpha / 0x10000;
2995 color.blue = (B | B << 8) * color.alpha / 0x10000;
2996 return color;
2997}
2998Picture QX11Data::getSolidFill(int screen, const QColor &c)
2999{
3000 if (!X11->use_xrender)
3001 return XNone;
3002
3003 XRenderColor color = preMultiply(c);
3004 for (int i = 0; i < X11->solid_fill_count; ++i) {
3005 if (X11->solid_fills[i].screen == screen
3006 && X11->solid_fills[i].color.alpha == color.alpha
3007 && X11->solid_fills[i].color.red == color.red
3008 && X11->solid_fills[i].color.green == color.green
3009 && X11->solid_fills[i].color.blue == color.blue)
3010 return X11->solid_fills[i].picture;
3011 }
3012 // none found, replace one
3013 int i = qrand() % 16;
3014
3015 if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
3016 XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
3017 X11->solid_fills[i].picture = 0;
3018 }
3019
3020 if (!X11->solid_fills[i].picture) {
3021 Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
3022 XRenderPictureAttributes attrs;
3023 attrs.repeat = True;
3024 X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
3025 XRenderFindStandardFormat(X11->display, PictStandardARGB32),
3026 CPRepeat, &attrs);
3027 XFreePixmap (X11->display, pixmap);
3028 }
3029
3030 X11->solid_fills[i].color = color;
3031 X11->solid_fills[i].screen = screen;
3032 XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
3033 return X11->solid_fills[i].picture;
3034}
3035#endif
3036
3037void QWidgetPrivate::setModal_sys()
3038{
3039}
3040
3041void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att)
3042{
3043 QX11InfoData* xd = xinfo->getX11Data(true);
3044 const XWindowAttributes &a = *(att.att);
3045 // find which screen the window is on...
3046 xd->screen = QX11Info::appScreen(); // by default, use the default :)
3047 int i;
3048 for (i = 0; i < ScreenCount(X11->display); i++) {
3049 if (RootWindow(X11->display, i) == a.root) {
3050 xd->screen = i;
3051 break;
3052 }
3053 }
3054
3055 xd->depth = a.depth;
3056 xd->cells = DisplayCells(X11->display, xd->screen);
3057 xd->visual = a.visual;
3058 xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
3059 XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo->screen())));
3060 xd->colormap = a.colormap;
3061 xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo->screen()));
3062 xinfo->setX11Data(xd);
3063}
3064
3065void QWidgetPrivate::updateX11AcceptFocus()
3066{
3067 Q_Q(QWidget);
3068 if (!q->isWindow() || !q->internalWinId())
3069 return;
3070
3071 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
3072 XWMHints wm_hints;
3073 if (!h) {
3074 memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
3075 h = &wm_hints;
3076 }
3077 h->flags |= InputHint;
3078 h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True;
3079
3080 XSetWMHints(X11->display, q->internalWinId(), h);
3081 if (h != &wm_hints)
3082 XFree((char *)h);
3083}
3084
3085QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.