~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/kernel/qwidget_x11.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the gui module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qevent.h"
 
30
#include "qwidget.h"
 
31
#include "qdesktopwidget.h"
 
32
#include "qapplication.h"
 
33
#include "qapplication_p.h"
 
34
#include "qnamespace.h"
 
35
#include "qpainter.h"
 
36
#include "qbitmap.h"
 
37
#include "qlayout.h"
 
38
#include "qtextcodec.h"
 
39
#include "qdatetime.h"
 
40
#include "qcursor.h"
 
41
#include "qstack.h"
 
42
#include "qcolormap.h"
 
43
#include "qdebug.h"
 
44
 
 
45
extern bool qt_reuse_double_buffer; // declared in qapplication_x11.cpp
 
46
 
 
47
#include <private/qpixmap_p.h>
 
48
#include <private/qpaintengine_x11_p.h>
 
49
#include "qt_x11_p.h"
 
50
#include "qx11info_x11.h"
 
51
 
 
52
#include <stdlib.h>
 
53
 
 
54
// defined in qapplication_x11.cpp
 
55
bool qt_wstate_iconified(WId);
 
56
void qt_updated_rootinfo();
 
57
 
 
58
 
 
59
#if !defined(QT_NO_IM)
 
60
#include "qinputcontext.h"
 
61
#include "qinputcontextfactory.h"
 
62
#endif
 
63
 
 
64
#include "qwidget_p.h"
 
65
 
 
66
#define XCOORD_MAX 32767
 
67
#define WRECT_MAX 8191
 
68
 
 
69
extern bool qt_nograb();
 
70
 
 
71
static QWidget *mouseGrb    = 0;
 
72
static QWidget *keyboardGrb = 0;
 
73
 
 
74
 
 
75
int qt_x11_create_desktop_on_screen = -1;
 
76
 
 
77
 
 
78
// MWM support
 
79
struct QtMWMHints {
 
80
    ulong flags, functions, decorations;
 
81
    long input_mode;
 
82
    ulong status;
 
83
};
 
84
 
 
85
enum {
 
86
    MWM_HINTS_FUNCTIONS   = (1L << 0),
 
87
 
 
88
    MWM_FUNC_ALL      = (1L << 0),
 
89
    MWM_FUNC_RESIZE   = (1L << 1),
 
90
    MWM_FUNC_MOVE     = (1L << 2),
 
91
    MWM_FUNC_MINIMIZE = (1L << 3),
 
92
    MWM_FUNC_MAXIMIZE = (1L << 4),
 
93
    MWM_FUNC_CLOSE    = (1L << 5),
 
94
 
 
95
    MWM_HINTS_DECORATIONS = (1L << 1),
 
96
 
 
97
    MWM_DECOR_ALL      = (1L << 0),
 
98
    MWM_DECOR_BORDER   = (1L << 1),
 
99
    MWM_DECOR_RESIZEH  = (1L << 2),
 
100
    MWM_DECOR_TITLE    = (1L << 3),
 
101
    MWM_DECOR_MENU     = (1L << 4),
 
102
    MWM_DECOR_MINIMIZE = (1L << 5),
 
103
    MWM_DECOR_MAXIMIZE = (1L << 6),
 
104
 
 
105
    MWM_HINTS_INPUT_MODE = (1L << 2),
 
106
 
 
107
    MWM_INPUT_FULL_APPLICATION_MODAL    = 3L
 
108
};
 
109
 
 
110
 
 
111
static QtMWMHints GetMWMHints(Display *display, Window window)
 
112
{
 
113
    QtMWMHints mwmhints;
 
114
 
 
115
    Atom type;
 
116
    int format;
 
117
    ulong nitems, bytesLeft;
 
118
    uchar *data = 0;
 
119
    if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
 
120
                            ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
 
121
                            &data) == Success)
 
122
        && (type == ATOM(_MOTIF_WM_HINTS)
 
123
            && format == 32
 
124
            && nitems >= 5)) {
 
125
        mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
 
126
    } else {
 
127
        mwmhints.flags = 0L;
 
128
        mwmhints.functions = MWM_FUNC_ALL;
 
129
        mwmhints.decorations = MWM_DECOR_ALL;
 
130
        mwmhints.input_mode = 0L;
 
131
        mwmhints.status = 0L;
 
132
    }
 
133
 
 
134
    if (data)
 
135
        XFree(data);
 
136
 
 
137
    return mwmhints;
 
138
}
 
139
 
 
140
 
 
141
/*****************************************************************************
 
142
  QWidget member functions
 
143
 *****************************************************************************/
 
144
 
 
145
extern bool qt_broken_wm;
 
146
 
 
147
// defined in qapplication_x11.cpp
 
148
extern bool qt_net_supports(Atom);
 
149
 
 
150
const uint stdWidgetEventMask =                        // X event mask
 
151
        (uint)(
 
152
            KeyPressMask | KeyReleaseMask |
 
153
            ButtonPressMask | ButtonReleaseMask |
 
154
            KeymapStateMask |
 
155
            ButtonMotionMask | PointerMotionMask |
 
156
            EnterWindowMask | LeaveWindowMask |
 
157
            FocusChangeMask |
 
158
            ExposureMask |
 
159
            PropertyChangeMask |
 
160
            StructureNotifyMask
 
161
       );
 
162
 
 
163
const uint stdDesktopEventMask =                        // X event mask
 
164
       (uint)(
 
165
           KeymapStateMask |
 
166
           EnterWindowMask | LeaveWindowMask |
 
167
           PropertyChangeMask
 
168
      );
 
169
 
 
170
 
 
171
/*
 
172
  The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
 
173
*/
 
174
 
 
175
Window qt_XCreateWindow(const QWidget *creator,
 
176
                         Display *display, Window parent,
 
177
                         int x, int y, uint w, uint h,
 
178
                         int borderwidth, int depth,
 
179
                         uint windowclass, Visual *visual,
 
180
                         ulong valuemask, XSetWindowAttributes *attributes);
 
181
Window qt_XCreateSimpleWindow(const QWidget *creator,
 
182
                               Display *display, Window parent,
 
183
                               int x, int y, uint w, uint h, int borderwidth,
 
184
                               ulong border, ulong background);
 
185
void qt_XDestroyWindow(const QWidget *destroyer,
 
186
                        Display *display, Window window);
 
187
 
 
188
 
 
189
static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
 
190
{
 
191
    QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
 
192
    X11->sip_list.append(sip);
 
193
 
 
194
    XClientMessageEvent client_message;
 
195
    client_message.type = ClientMessage;
 
196
    client_message.window = scrolled_widget->winId();
 
197
    client_message.format = 32;
 
198
    client_message.message_type = ATOM(_QT_SCROLL_DONE);
 
199
    client_message.data.l[0] = sip.id;
 
200
 
 
201
    XSendEvent(X11->display, scrolled_widget->winId(), False, NoEventMask,
 
202
        (XEvent*)&client_message);
 
203
}
 
204
 
 
205
static int qt_sip_count(QWidget* scrolled_widget)
 
206
{
 
207
    int sips=0;
 
208
 
 
209
    for (int i = 0; i < X11->sip_list.size(); ++i) {
 
210
        const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
 
211
        if (sip.scrolled_widget == scrolled_widget)
 
212
            sips++;
 
213
    }
 
214
 
 
215
    return sips;
 
216
}
 
217
 
 
218
 
 
219
static void create_wm_client_leader()
 
220
{
 
221
    if (X11->wm_client_leader) return;
 
222
 
 
223
    X11->wm_client_leader =
 
224
        XCreateSimpleWindow(X11->display,
 
225
                             QX11Info::appRootWindow(),
 
226
                             0, 0, 1, 1, 0, 0, 0);
 
227
 
 
228
    // set client leader property to itself
 
229
    XChangeProperty(X11->display,
 
230
                     X11->wm_client_leader, ATOM(WM_CLIENT_LEADER),
 
231
                     XA_WINDOW, 32, PropModeReplace,
 
232
                     (unsigned char *)&X11->wm_client_leader, 1);
 
233
 
 
234
    // If we are session managed, inform the window manager about it
 
235
    QByteArray session = qApp->sessionId().toLatin1();
 
236
    if (!session.isEmpty()) {
 
237
        XChangeProperty(X11->display,
 
238
                         X11->wm_client_leader, ATOM(SM_CLIENT_ID),
 
239
                         XA_STRING, 8, PropModeReplace,
 
240
                         (unsigned char *)session.data(), session.size());
 
241
    }
 
242
}
 
243
 
 
244
 
 
245
Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
 
246
{
 
247
    if (w->testAttribute(Qt::WA_SetCursor)) {
 
248
        QCursor *oc = QApplication::overrideCursor();
 
249
        if (oc) {
 
250
            XDefineCursor(X11->display, w->winId(), oc->handle());
 
251
        } else if (w->isEnabled()) {
 
252
            XDefineCursor(X11->display, w->winId(), w->cursor().handle());
 
253
        } else {
 
254
            // enforce the windows behavior of clearing the cursor on
 
255
            // disabled widgets
 
256
            XDefineCursor(X11->display, w->winId(), XNone);
 
257
        }
 
258
    } else {
 
259
        XDefineCursor(X11->display, w->winId(), XNone);
 
260
    }
 
261
}
 
262
 
 
263
Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
 
264
{
 
265
    QApplication::flush();
 
266
    XEvent ev;
 
267
    QTime t;
 
268
    t.start();
 
269
    while (!XCheckTypedWindowEvent(X11->display, w->winId(), ReparentNotify, &ev)) {
 
270
        if (XCheckTypedWindowEvent(X11->display, w->winId(), MapNotify, &ev))
 
271
            break;
 
272
        if (t.elapsed() > 500)
 
273
            return; // give up, no event available
 
274
        qApp->syncX(); // non-busy wait
 
275
    }
 
276
    qApp->x11ProcessEvent(&ev);
 
277
    if (XCheckTypedWindowEvent(X11->display, w->winId(), ConfigureNotify, &ev))
 
278
        qApp->x11ProcessEvent(&ev);
 
279
}
 
280
 
 
281
static void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
 
282
{
 
283
    if (!w->isVisible()) // not managed by the window manager
 
284
        return;
 
285
 
 
286
    XEvent e;
 
287
    e.xclient.type = ClientMessage;
 
288
    e.xclient.message_type = ATOM(_NET_WM_STATE);
 
289
    e.xclient.display = X11->display;
 
290
    e.xclient.window = w->winId();
 
291
    e.xclient.format = 32;
 
292
    e.xclient.data.l[0] = set ? 1 : 0;
 
293
    e.xclient.data.l[1] = one;
 
294
    e.xclient.data.l[2] = two;
 
295
    e.xclient.data.l[3] = 0;
 
296
    e.xclient.data.l[4] = 0;
 
297
    XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()),
 
298
               false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
 
299
}
 
300
 
 
301
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
 
302
{
 
303
    Q_Q(QWidget);
 
304
    Qt::WindowType type = q->windowType();
 
305
    Qt::WindowFlags &flags = data.window_flags;
 
306
    QWidget *parentWidget = q->parentWidget();
 
307
 
 
308
    if (type == Qt::ToolTip)
 
309
        flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
 
310
 
 
311
    bool topLevel = (flags & Qt::Window);
 
312
    bool popup = (type == Qt::Popup);
 
313
    bool dialog = (type == Qt::Dialog
 
314
                   || type == Qt::Sheet
 
315
                   || (flags & Qt::MSWindowsFixedSizeDialogHint));
 
316
    bool desktop = (type == Qt::Desktop);
 
317
    bool tool = (type == Qt::Tool || type == Qt::SplashScreen
 
318
                || type == Qt::ToolTip || type == Qt::Drawer);
 
319
 
 
320
    bool customize =  (flags & (
 
321
                                Qt::X11BypassWindowManagerHint
 
322
                                | Qt::FramelessWindowHint
 
323
                                | Qt::WindowTitleHint
 
324
                                | Qt::WindowSystemMenuHint
 
325
                                | Qt::WindowMinimizeButtonHint
 
326
                                | Qt::WindowMaximizeButtonHint
 
327
                                | Qt::WindowContextHelpButtonHint
 
328
                                ));
 
329
 
 
330
 
 
331
    if(topLevel && parentWidget) { // if our parent stays on top, so must we
 
332
        QWidget *ptl = parentWidget->window();
 
333
        if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
 
334
            flags |= Qt::WindowStaysOnTopHint;
 
335
    }
 
336
 
 
337
    Window parentw, destroyw = 0;
 
338
    WId id;
 
339
 
 
340
    // always initialize
 
341
    if (!window)
 
342
        initializeWindow = true;
 
343
 
 
344
    if (desktop &&
 
345
        qt_x11_create_desktop_on_screen >= 0 &&
 
346
        qt_x11_create_desktop_on_screen != xinfo.screen()) {
 
347
        // desktop on a certain screen other than the default requested
 
348
        QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen];
 
349
        xinfo.setX11Data(xd);
 
350
    } else if (parentWidget &&  parentWidget->d_func()->xinfo.screen() != xinfo.screen()) {
 
351
        xinfo = parentWidget->d_func()->xinfo;
 
352
    }
 
353
 
 
354
    //get display, screen number, root window and desktop geometry for
 
355
    //the current screen
 
356
    Display *dpy = X11->display;
 
357
    int scr = xinfo.screen();
 
358
    Window root_win = RootWindow(dpy, scr);
 
359
    int sw = DisplayWidth(dpy,scr);
 
360
    int sh = DisplayHeight(dpy,scr);
 
361
 
 
362
    if (desktop) {                                // desktop widget
 
363
        dialog = popup = false;                        // force these flags off
 
364
        q->data->crect.setRect(0, 0, sw, sh);
 
365
    } else if (topLevel) {                        // calc pos/size from screen
 
366
        q->data->crect.setRect(sw/4, 3*sh/10, sw/2, 4*sh/10);
 
367
    } else {                                        // child widget
 
368
        q->data->crect.setRect(0, 0, 100, 30);
 
369
    }
 
370
 
 
371
    parentw = topLevel ? root_win : parentWidget->winId();
 
372
 
 
373
    XSetWindowAttributes wsa;
 
374
 
 
375
    if (window) {                                // override the old window
 
376
        if (destroyOldWindow)
 
377
            destroyw = data.winid;
 
378
        id = window;
 
379
        setWinId(window);
 
380
        XWindowAttributes a;
 
381
        XGetWindowAttributes(dpy, window, &a);
 
382
        q->data->crect.setRect(a.x, a.y, a.width, a.height);
 
383
 
 
384
        if (a.map_state == IsUnmapped)
 
385
            q->setAttribute(Qt::WA_WState_Visible, false);
 
386
        else
 
387
            q->setAttribute(Qt::WA_WState_Visible);
 
388
 
 
389
        QX11InfoData* xd = xinfo.getX11Data(true);
 
390
 
 
391
        // find which screen the window is on...
 
392
        xd->screen = QX11Info::appScreen(); // by default, use the default :)
 
393
        int i;
 
394
        for (i = 0; i < ScreenCount(dpy); i++) {
 
395
            if (RootWindow(dpy, i) == a.root) {
 
396
                xd->screen = i;
 
397
                break;
 
398
            }
 
399
        }
 
400
 
 
401
        xd->depth = a.depth;
 
402
        xd->cells = DisplayCells(dpy, xd->screen);
 
403
        xd->visual = a.visual;
 
404
        xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
 
405
                             XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo.screen())));
 
406
        xd->colormap = a.colormap;
 
407
        xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo.screen()));
 
408
        xinfo.setX11Data(xd);
 
409
    } else if (desktop) {                        // desktop widget
 
410
        id = (WId)parentw;                        // id = root window
 
411
//         QWidget *otherDesktop = find(id);        // is there another desktop?
 
412
//         if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
 
413
//             otherDesktop->d->setWinId(0);        // remove id from widget mapper
 
414
//             d->setWinId(id);                     // make sure otherDesktop is
 
415
//             otherDesktop->d->setWinId(id);       // found first
 
416
//         } else {
 
417
            setWinId(id);
 
418
//         }
 
419
    } else {
 
420
        if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
 
421
            id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
 
422
                                             q->data->crect.left(), q->data->crect.top(),
 
423
                                             q->data->crect.width(), q->data->crect.height(),
 
424
                                             0,
 
425
                                             BlackPixel(dpy, xinfo.screen()),
 
426
                                             WhitePixel(dpy, xinfo.screen()));
 
427
        } else {
 
428
            wsa.background_pixel = WhitePixel(dpy, xinfo.screen());
 
429
            wsa.border_pixel = BlackPixel(dpy, xinfo.screen());
 
430
            wsa.colormap = xinfo.colormap();
 
431
            id = (WId)qt_XCreateWindow(q, dpy, parentw,
 
432
                                       data.crect.left(), data.crect.top(),
 
433
                                       data.crect.width(), data.crect.height(),
 
434
                                       0, xinfo.depth(), InputOutput,
 
435
                                       (Visual *) xinfo.visual(),
 
436
                                       CWBackPixel|CWBorderPixel|CWColormap,
 
437
                                       &wsa);
 
438
        }
 
439
 
 
440
        setWinId(id);                                // set widget id/handle + hd
 
441
    }
 
442
 
 
443
#ifndef QT_NO_XRENDER
 
444
    if (picture) {
 
445
        XRenderFreePicture(X11->display, picture);
 
446
        picture = 0;
 
447
    }
 
448
 
 
449
    if (X11->use_xrender) {
 
450
        picture = XRenderCreatePicture(dpy, id, XRenderFindVisualFormat (dpy, (Visual *) xinfo.visual()), 0, 0);
 
451
    }
 
452
#endif // QT_NO_XRENDER
 
453
 
 
454
    // NET window types
 
455
    long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
 
456
    int curr_wintype = 0;
 
457
 
 
458
    QtMWMHints mwmhints;
 
459
    mwmhints.flags = 0L;
 
460
    mwmhints.functions = MWM_FUNC_ALL;
 
461
    mwmhints.decorations = MWM_DECOR_ALL;
 
462
    mwmhints.input_mode = 0L;
 
463
    mwmhints.status = 0L;
 
464
 
 
465
    if (topLevel) {
 
466
        ulong wsa_mask = 0;
 
467
 
 
468
        if (customize) {
 
469
            mwmhints.decorations = 0L;
 
470
            mwmhints.flags |= MWM_HINTS_DECORATIONS;
 
471
 
 
472
            // All these buttons depend on the system menu, so we enable it
 
473
            if (flags & (Qt::WindowMinimizeButtonHint
 
474
                         | Qt::WindowMaximizeButtonHint
 
475
                         | Qt::WindowContextHelpButtonHint))
 
476
                flags |= Qt::WindowSystemMenuHint;
 
477
            if (flags & Qt::FramelessWindowHint) {
 
478
                // override netwm type - quick and easy for KDE noborder
 
479
                net_wintypes[curr_wintype++] = ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
 
480
            } else {
 
481
                mwmhints.decorations |= MWM_DECOR_BORDER;
 
482
                mwmhints.decorations |= MWM_DECOR_RESIZEH;
 
483
 
 
484
                if (flags & Qt::WindowTitleHint)
 
485
                    mwmhints.decorations |= MWM_DECOR_TITLE;
 
486
 
 
487
                if (flags & Qt::WindowSystemMenuHint)
 
488
                    mwmhints.decorations |= MWM_DECOR_MENU;
 
489
 
 
490
                if (flags & Qt::WindowMinimizeButtonHint)
 
491
                    mwmhints.decorations |= MWM_DECOR_MINIMIZE;
 
492
 
 
493
                if (flags & Qt::WindowMaximizeButtonHint)
 
494
                    mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
 
495
            }
 
496
        } else if (desktop || popup) {
 
497
        } else if (dialog) {
 
498
            flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint;
 
499
        } else if (type == Qt::SplashScreen) {
 
500
            if (qt_net_supports(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
 
501
                flags &= ~Qt::X11BypassWindowManagerHint;
 
502
                net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
 
503
            } else {
 
504
                flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
 
505
            }
 
506
        } else if (type == Qt::Tool || type == Qt::Drawer) {
 
507
            flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
 
508
        } else {
 
509
            flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
 
510
        }
 
511
 
 
512
        if (tool) {
 
513
            wsa.save_under = True;
 
514
            wsa_mask |= CWSaveUnder;
 
515
        }
 
516
        // ### need a better way to do this
 
517
        if (q->inherits("QMenu")) {
 
518
            // menu netwm type
 
519
            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_MENU);
 
520
        } else if (q->inherits("QToolBar")) {
 
521
            // toolbar netwm type
 
522
            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
 
523
        } else if (type == Qt::Tool || type == Qt::Drawer) {
 
524
            // utility netwm type
 
525
            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
 
526
        }
 
527
 
 
528
        if (dialog) // dialog netwm type
 
529
            net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
 
530
        // normal netwm type - default
 
531
        net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
 
532
 
 
533
        if (flags & Qt::X11BypassWindowManagerHint) {
 
534
            wsa.override_redirect = True;
 
535
            wsa_mask |= CWOverrideRedirect;
 
536
        }
 
537
 
 
538
        if (wsa_mask && initializeWindow)
 
539
            XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
 
540
    } else if (!customize) {
 
541
        flags |= Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint;
 
542
    }
 
543
 
 
544
 
 
545
    if (!initializeWindow) {
 
546
        // do no initialization
 
547
    } else if (popup) {                        // popup widget
 
548
        wsa.override_redirect = True;
 
549
        wsa.save_under = True;
 
550
        XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
 
551
                                &wsa);
 
552
    } else if (topLevel && !desktop) {        // top-level widget
 
553
        if (!X11->wm_client_leader)
 
554
            create_wm_client_leader();
 
555
 
 
556
        // real parent
 
557
        QWidget *p = parentWidget;
 
558
        if (p)
 
559
            p = p->window();
 
560
 
 
561
        if (dialog || tool) {
 
562
            if (p) {
 
563
                // transient for window
 
564
                XSetTransientForHint(dpy, id, p->winId());
 
565
            } else {
 
566
                // transient for group
 
567
                XSetTransientForHint(dpy, id, X11->wm_client_leader);
 
568
            }
 
569
        }
 
570
 
 
571
        XSizeHints size_hints;
 
572
        size_hints.flags = USSize | PSize | PWinGravity;
 
573
        size_hints.x = data.crect.left();
 
574
        size_hints.y = data.crect.top();
 
575
        size_hints.width = data.crect.width();
 
576
        size_hints.height = data.crect.height();
 
577
        size_hints.win_gravity =
 
578
            QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
 
579
 
 
580
        XWMHints wm_hints;                        // window manager hints
 
581
        wm_hints.flags = InputHint | StateHint | WindowGroupHint;
 
582
        wm_hints.input = True;
 
583
        wm_hints.initial_state = NormalState;
 
584
        wm_hints.window_group = X11->wm_client_leader;
 
585
 
 
586
        XClassHint class_hint;
 
587
        QByteArray appName = qAppName().toLatin1();
 
588
        class_hint.res_name = appName.data(); // application name
 
589
        class_hint.res_class = const_cast<char *>(QX11Info::appClass());   // application class
 
590
 
 
591
        XSetWMProperties(dpy, id, 0, 0, 0, 0, &size_hints, &wm_hints, &class_hint);
 
592
 
 
593
        XResizeWindow(dpy, id, data.crect.width(), data.crect.height());
 
594
        XStoreName(dpy, id, appName.data());
 
595
        Atom protocols[4];
 
596
        int n = 0;
 
597
        protocols[n++] = ATOM(WM_DELETE_WINDOW);        // support del window protocol
 
598
        protocols[n++] = ATOM(WM_TAKE_FOCUS);                // support take focus window protocol
 
599
        protocols[n++] = ATOM(_NET_WM_PING);                // support _NET_WM_PING protocol
 
600
        if (flags & Qt::WindowContextHelpButtonHint)
 
601
            protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
 
602
        XSetWMProtocols(dpy, id, protocols, n);
 
603
 
 
604
        // set mwm hints
 
605
        if (mwmhints.flags != 0l) {
 
606
            XChangeProperty(dpy, id, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
 
607
                            PropModeReplace, (unsigned char *) &mwmhints, 5);
 
608
        } else {
 
609
            XDeleteProperty(dpy, id, ATOM(_MOTIF_WM_HINTS));
 
610
        }
 
611
 
 
612
        // set _NET_WM_WINDOW_TYPE
 
613
        if (curr_wintype > 0)
 
614
            XChangeProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, PropModeReplace,
 
615
                            (unsigned char *) net_wintypes, curr_wintype);
 
616
        else
 
617
            XDeleteProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE));
 
618
 
 
619
        // set _NET_WM_PID
 
620
        long curr_pid = getpid();
 
621
        XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
 
622
                        (unsigned char *) &curr_pid, 1);
 
623
 
 
624
        // when we create a toplevel widget, the frame strut should be dirty
 
625
        data.fstrut_dirty = 1;
 
626
 
 
627
        // declare the widget's object name as window role
 
628
        QByteArray objName = q->objectName().toLocal8Bit();
 
629
        XChangeProperty(dpy, id,
 
630
                        ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
 
631
                        (unsigned char *)objName.constData(), objName.length());
 
632
 
 
633
        // set client leader property
 
634
        XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
 
635
                        XA_WINDOW, 32, PropModeReplace,
 
636
                        (unsigned char *)&X11->wm_client_leader, 1);
 
637
    } else {
 
638
        // non-toplevel widgets don't have a frame, so no need to
 
639
        // update the strut
 
640
        data.fstrut_dirty = 0;
 
641
    }
 
642
 
 
643
    if (initializeWindow) {
 
644
        // don't erase when resizing
 
645
        wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
 
646
        XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
 
647
    }
 
648
 
 
649
    // set X11 event mask
 
650
    if (desktop) {
 
651
//         QWidget* main_desktop = find(id);
 
652
//         if (main_desktop->testWFlags(Qt::WPaintDesktop))
 
653
//             XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
 
654
//         else
 
655
            XSelectInput(dpy, id, stdDesktopEventMask);
 
656
    } else {
 
657
        XSelectInput(dpy, id, stdWidgetEventMask);
 
658
#if !defined (QT_NO_TABLET_SUPPORT)
 
659
        TabletDeviceDataList *tablet_list = qt_tablet_devices();
 
660
        for (int i = 0; i < tablet_list->size(); ++i) {
 
661
            TabletDeviceData tablet = tablet_list->at(i);
 
662
            XSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList),
 
663
                                  tablet.eventCount);
 
664
        }
 
665
#endif
 
666
    }
 
667
 
 
668
    if (desktop) {
 
669
        q->setAttribute(Qt::WA_WState_Visible);
 
670
    } else if (topLevel) {                        // set X cursor
 
671
        q->setAttribute(Qt::WA_SetCursor);
 
672
        if (initializeWindow)
 
673
            qt_x11_enforce_cursor(q);
 
674
    }
 
675
 
 
676
    if (destroyw)
 
677
        qt_XDestroyWindow(q, dpy, destroyw);
 
678
 
 
679
    // newly created windows are positioned at the window system's
 
680
    // (0,0) position. If the parent uses wrect mapping to expand the
 
681
    // coordinate system, we must also adjust this widget's window
 
682
    // system position
 
683
    if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
 
684
        setWSGeometry();
 
685
 
 
686
#if !defined(QT_NO_IM)
 
687
    ic = 0;
 
688
#endif
 
689
}
 
690
 
 
691
 
 
692
/*!
 
693
    Frees up window system resources. Destroys the widget window if \a
 
694
    destroyWindow is true.
 
695
 
 
696
    destroy() calls itself recursively for all the child widgets,
 
697
    passing \a destroySubWindows for the \a destroyWindow parameter.
 
698
    To have more control over destruction of subwidgets, destroy
 
699
    subwidgets selectively first.
 
700
 
 
701
    This function is usually called from the QWidget destructor.
 
702
*/
 
703
 
 
704
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
 
705
{
 
706
    Q_D(QWidget);
 
707
    d->deactivateWidgetCleanup();
 
708
    if (testAttribute(Qt::WA_WState_Created)) {
 
709
        setAttribute(Qt::WA_WState_Created, false);
 
710
        QObjectList childs = children();
 
711
        for (int i = 0; i < childs.size(); ++i) { // destroy all widget children
 
712
            register QObject *obj = childs.at(i);
 
713
            if (obj->isWidgetType())
 
714
                static_cast<QWidget*>(obj)->destroy(destroySubWindows,
 
715
                                                    destroySubWindows);
 
716
        }
 
717
        if (mouseGrb == this)
 
718
            releaseMouse();
 
719
        if (keyboardGrb == this)
 
720
            releaseKeyboard();
 
721
        if (isWindow())
 
722
            X11->deferred_map.removeAll(this);
 
723
        if (testAttribute(Qt::WA_ShowModal))                // just be sure we leave modal
 
724
            QApplicationPrivate::leaveModal(this);
 
725
        else if ((windowType() == Qt::Popup))
 
726
            qApp->d_func()->closePopup(this);
 
727
 
 
728
#ifndef QT_NO_XRENDER
 
729
        if (d->picture) {
 
730
            if (destroyWindow)
 
731
                XRenderFreePicture(X11->display, d->picture);
 
732
            d->picture = 0;
 
733
        }
 
734
#endif // QT_NO_XRENDER
 
735
 
 
736
        if ((windowType() == Qt::Desktop)) {
 
737
            if (acceptDrops())
 
738
                X11->dndEnable(this, false);
 
739
        } else {
 
740
            if (destroyWindow)
 
741
                qt_XDestroyWindow(this, X11->display, data->winid);
 
742
        }
 
743
        d->setWinId(0);
 
744
 
 
745
        extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
 
746
        if (testAttribute(Qt::WA_WState_Reparented))
 
747
            qPRCleanup(this);
 
748
 
 
749
        if(d->ic) {
 
750
            delete d->ic;
 
751
        } else {
 
752
            // release previous focus information participating with
 
753
            // preedit preservation of qic
 
754
            QInputContext *qic = inputContext();
 
755
            if (qic)
 
756
                qic->widgetDestroyed(this);
 
757
        }
 
758
    }
 
759
}
 
760
 
 
761
void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WFlags f)
 
762
{
 
763
    Q_Q(QWidget);
 
764
    extern void qPRCreate(const QWidget *, Window);
 
765
 
 
766
    QCursor oldcurs;
 
767
    bool setcurs = q->testAttribute(Qt::WA_SetCursor);
 
768
    if (setcurs) {
 
769
        oldcurs = q->cursor();
 
770
        q->unsetCursor();
 
771
    }
 
772
 
 
773
    // dnd unregister (we will register again below)
 
774
    bool accept_drops = q->acceptDrops();
 
775
    q->setAcceptDrops(false);
 
776
 
 
777
    QWidget *oldparent = q->parentWidget();
 
778
    WId old_winid = data.winid;
 
779
    if ((q->windowType() == Qt::Desktop))
 
780
        old_winid = 0;
 
781
    setWinId(0);
 
782
 
 
783
    // hide and reparent our own window away. Otherwise we might get
 
784
    // destroyed when emitting the child remove event below. See QWorkspace.
 
785
    XUnmapWindow(X11->display, old_winid);
 
786
    XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
 
787
 
 
788
    if (q->isWindow() || !parent) { // we are toplevel, or reparenting to toplevel
 
789
        QTLWExtra *top = topData();
 
790
        top->parentWinId = 0;
 
791
        // zero the frame strut and mark it dirty
 
792
        top->fleft = top->fright = top->ftop = top->fbottom = 0;
 
793
        data.fstrut_dirty = true;
 
794
    }
 
795
 
 
796
    QObjectPrivate::setParent_helper(parent);
 
797
    bool     enable = q->isEnabled();                // remember status
 
798
    Qt::FocusPolicy fp = q->focusPolicy();
 
799
    QSize    s            = q->size();
 
800
    bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
 
801
 
 
802
    data.window_flags = f;
 
803
    q->setAttribute(Qt::WA_WState_Created, false);
 
804
    q->setAttribute(Qt::WA_WState_Visible, false);
 
805
    q->setAttribute(Qt::WA_WState_Hidden, false);
 
806
    q->create();
 
807
    if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
 
808
        q->setAttribute(Qt::WA_WState_Hidden);
 
809
    q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
 
810
 
 
811
    QObjectList chlist = q->children();
 
812
    for (int i = 0; i < chlist.size(); ++i) { // reparent children
 
813
        QObject *obj = chlist.at(i);
 
814
        if (obj->isWidgetType()) {
 
815
            QWidget *w = (QWidget *)obj;
 
816
            if (!w->isWindow()) {
 
817
                XReparentWindow(X11->display, w->winId(), q->winId(),
 
818
                                w->geometry().x(), w->geometry().y());
 
819
            } else if ((w->windowType() == Qt::Popup)
 
820
                       || (w->windowFlags() & Qt::MSWindowsFixedSizeDialogHint)
 
821
                       || (w->windowType() == Qt::Dialog)
 
822
                       || (w->windowType() == Qt::SplashScreen)
 
823
                       || (w->windowType() == Qt::ToolTip)
 
824
                       || (w->windowType() == Qt::Tool)
 
825
                       || (w->windowType() == Qt::Drawer)
 
826
                       || (w->windowType() == Qt::Sheet)) {
 
827
                /*
 
828
                  when reparenting toplevel windows with toplevel-transient children,
 
829
                  we need to make sure that the window manager gets the updated
 
830
                  WM_TRANSIENT_FOR information... unfortunately, some window managers
 
831
                  don't handle changing WM_TRANSIENT_FOR before the toplevel window is
 
832
                  visible, so we unmap and remap all toplevel-transient children *after*
 
833
                  the toplevel parent has been mapped.  thankfully, this is easy in Qt :)
 
834
                */
 
835
                XUnmapWindow(X11->display, w->winId());
 
836
                XSetTransientForHint(X11->display, w->winId(), q->winId());
 
837
                QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
 
838
            }
 
839
        }
 
840
    }
 
841
    qPRCreate(q, old_winid);
 
842
    updateSystemBackground();
 
843
 
 
844
    if (q->isWindow()) {
 
845
        uint window_state = data.window_state;
 
846
        const QRect r = topData()->normalGeometry;
 
847
        q->setGeometry(0, 0, s.width(), s.height());
 
848
        data.window_state = window_state;
 
849
        topData()->normalGeometry = r;
 
850
        if (!extra->topextra->caption.isEmpty())
 
851
            setWindowTitle_helper(extra->topextra->caption);
 
852
    } else {
 
853
        q->setGeometry(0, 0, s.width(), s.height());
 
854
    }
 
855
 
 
856
    setEnabled_helper(enable); //preserving WA_ForceDisabled
 
857
 
 
858
    q->setFocusPolicy(fp);
 
859
    if (extra && !extra->mask.isEmpty())
 
860
        q->setMask(extra->mask);
 
861
    if (old_winid)
 
862
        qt_XDestroyWindow(q, X11->display, old_winid);
 
863
    if (setcurs)
 
864
        q->setCursor(oldcurs);
 
865
 
 
866
    // re-register dnd
 
867
    if (oldparent)
 
868
        oldparent->d_func()->checkChildrenDnd();
 
869
 
 
870
    if (accept_drops)
 
871
        q->setAcceptDrops(true);
 
872
    else {
 
873
        checkChildrenDnd();
 
874
        topData()->dnd = 0;
 
875
        X11->dndEnable(q, (extra && extra->children_use_dnd));
 
876
    }
 
877
}
 
878
 
 
879
 
 
880
/*!
 
881
    Translates the widget coordinate \a pos to global screen
 
882
    coordinates. For example, \c{mapToGlobal(QPoint(0,0))} would give
 
883
    the global coordinates of the top-left pixel of the widget.
 
884
 
 
885
    \sa mapFromGlobal() mapTo() mapToParent()
 
886
*/
 
887
 
 
888
QPoint QWidget::mapToGlobal(const QPoint &pos) const
 
889
{
 
890
    Q_D(const QWidget);
 
891
    int           x, y;
 
892
    Window child;
 
893
    QPoint p = d->mapToWS(pos);
 
894
    XTranslateCoordinates(X11->display, winId(),
 
895
                          QApplication::desktop()->screen(d->xinfo.screen())->winId(),
 
896
                          p.x(), p.y(), &x, &y, &child);
 
897
    return QPoint(x, y);
 
898
}
 
899
 
 
900
/*!
 
901
    Translates the global screen coordinate \a pos to widget
 
902
    coordinates.
 
903
 
 
904
    \sa mapToGlobal() mapFrom() mapFromParent()
 
905
*/
 
906
 
 
907
QPoint QWidget::mapFromGlobal(const QPoint &pos) const
 
908
{
 
909
    Q_D(const QWidget);
 
910
    int           x, y;
 
911
    Window child;
 
912
    XTranslateCoordinates(X11->display,
 
913
                          QApplication::desktop()->screen(d->xinfo.screen())->winId(),
 
914
                          winId(), pos.x(), pos.y(), &x, &y, &child);
 
915
    return d->mapFromWS(QPoint(x, y));
 
916
}
 
917
 
 
918
void QWidgetPrivate::updateSystemBackground()
 
919
{
 
920
    Q_Q(QWidget);
 
921
    QBrush brush = q->palette().brush(q->backgroundRole());
 
922
    Qt::WindowType type = q->windowType();
 
923
    if (brush.style() == Qt::NoBrush
 
924
        || q->testAttribute(Qt::WA_NoSystemBackground)
 
925
        || q->testAttribute(Qt::WA_UpdatesDisabled)
 
926
        || type == Qt::Popup || type == Qt::ToolTip
 
927
        )
 
928
        XSetWindowBackgroundPixmap(X11->display, q->winId(), XNone);
 
929
    else if (isBackgroundInherited())
 
930
        XSetWindowBackgroundPixmap(X11->display, q->winId(), ParentRelative);
 
931
    else if (brush.style() == Qt::TexturePattern)
 
932
        XSetWindowBackgroundPixmap(X11->display, q->winId(),
 
933
                                   brush.texture().data->x11ConvertToDefaultDepth());
 
934
    else
 
935
        XSetWindowBackground(X11->display, q->winId(),
 
936
                             QColormap::instance(xinfo.screen()).pixel(brush.color()));
 
937
}
 
938
 
 
939
void QWidget::setCursor(const QCursor &cursor)
 
940
{
 
941
    Q_D(QWidget);
 
942
    if (cursor.shape() != Qt::ArrowCursor
 
943
        || (d->extra && d->extra->curs)) {
 
944
        d->createExtra();
 
945
        delete d->extra->curs;
 
946
        d->extra->curs = new QCursor(cursor);
 
947
    }
 
948
    setAttribute(Qt::WA_SetCursor);
 
949
    qt_x11_enforce_cursor(this);
 
950
    XFlush(X11->display);
 
951
}
 
952
 
 
953
void QWidget::unsetCursor()
 
954
{
 
955
    Q_D(QWidget);
 
956
    if (d->extra) {
 
957
        delete d->extra->curs;
 
958
        d->extra->curs = 0;
 
959
    }
 
960
    if (!isWindow())
 
961
        setAttribute(Qt::WA_SetCursor, false);
 
962
    qt_x11_enforce_cursor(this);
 
963
    XFlush(X11->display);
 
964
}
 
965
 
 
966
static XTextProperty*
 
967
qstring_to_xtp(const QString& s)
 
968
{
 
969
    static XTextProperty tp = { 0, 0, 0, 0 };
 
970
    static bool free_prop = true; // we can't free tp.value in case it references
 
971
    // the data of the static QCString below.
 
972
    if (tp.value) {
 
973
        if (free_prop)
 
974
            XFree(tp.value);
 
975
        tp.value = 0;
 
976
        free_prop = true;
 
977
    }
 
978
 
 
979
    static const QTextCodec* mapper = QTextCodec::codecForLocale();
 
980
    int errCode = 0;
 
981
    if (mapper) {
 
982
        QByteArray mapped = mapper->fromUnicode(s);
 
983
        char* tl[2];
 
984
        tl[0] = mapped.data();
 
985
        tl[1] = 0;
 
986
        errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
 
987
#if defined(QT_DEBUG)
 
988
        if (errCode < 0)
 
989
            qDebug("qstring_to_xtp result code %d", errCode);
 
990
#endif
 
991
    }
 
992
    if (!mapper || errCode < 0) {
 
993
        static QByteArray qcs;
 
994
        qcs = s.toAscii();
 
995
        tp.value = (uchar*)qcs.data();
 
996
        tp.encoding = XA_STRING;
 
997
        tp.format = 8;
 
998
        tp.nitems = qcs.length();
 
999
        free_prop = false;
 
1000
    }
 
1001
 
 
1002
    // ### If we knew WM could understand unicode, we could use
 
1003
    // ### a much simpler, cheaper encoding...
 
1004
    /*
 
1005
        tp.value = (XChar2b*)s.unicode();
 
1006
        tp.encoding = XA_UNICODE; // wish
 
1007
        tp.format = 16;
 
1008
        tp.nitems = s.length();
 
1009
    */
 
1010
 
 
1011
    return &tp;
 
1012
}
 
1013
 
 
1014
void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
 
1015
{
 
1016
    Q_Q(QWidget);
 
1017
    XSetWMName(X11->display, q->winId(), qstring_to_xtp(caption));
 
1018
 
 
1019
    QByteArray net_wm_name = caption.toUtf8();
 
1020
    XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
 
1021
                    PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
 
1022
}
 
1023
 
 
1024
void QWidgetPrivate::setWindowIcon_sys()
 
1025
{
 
1026
    Q_Q(QWidget);
 
1027
    QTLWExtra *topData = extra->topextra;
 
1028
    if (topData->iconPixmap)
 
1029
        // already been set
 
1030
        return;
 
1031
 
 
1032
    XWMHints *h = XGetWMHints(X11->display, q->winId());
 
1033
    XWMHints wm_hints;
 
1034
    if (!h) {
 
1035
        h = &wm_hints;
 
1036
        h->flags = 0;
 
1037
    }
 
1038
 
 
1039
    QIcon icon = q->windowIcon();
 
1040
    if (!icon.isNull()) {
 
1041
        QSize size = icon.actualSize(QSize(64, 64));
 
1042
        topData->iconPixmap = new QPixmap(icon.pixmap(size));
 
1043
        h->icon_pixmap = topData->iconPixmap->data->x11ConvertToDefaultDepth();
 
1044
        h->flags |= IconPixmapHint;
 
1045
 
 
1046
        QBitmap mask = topData->iconPixmap->mask();
 
1047
        if (!mask.isNull()) {
 
1048
            if (!extra->topextra->iconMask)
 
1049
                extra->topextra->iconMask = new QBitmap;
 
1050
            *extra->topextra->iconMask = mask;
 
1051
            h->icon_mask = extra->topextra->iconMask->handle();
 
1052
            h->flags |= IconMaskHint;
 
1053
        }
 
1054
    } else {
 
1055
        h->flags &= ~(IconPixmapHint | IconMaskHint);
 
1056
    }
 
1057
 
 
1058
    XSetWMHints(X11->display, q->winId(), h);
 
1059
    if (h != &wm_hints)
 
1060
        XFree((char *)h);
 
1061
}
 
1062
 
 
1063
void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
 
1064
{
 
1065
    Q_Q(QWidget);
 
1066
    XSetWMIconName(X11->display, q->winId(), qstring_to_xtp(iconText));
 
1067
 
 
1068
    QByteArray icon_name = iconText.toUtf8();
 
1069
    XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
 
1070
                    PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
 
1071
}
 
1072
 
 
1073
 
 
1074
/*!
 
1075
    Grabs the mouse input.
 
1076
 
 
1077
    This widget receives all mouse events until releaseMouse() is
 
1078
    called; other widgets get no mouse events at all. Keyboard
 
1079
    events are not affected. Use grabKeyboard() if you want to grab
 
1080
    that.
 
1081
 
 
1082
    \warning Bugs in mouse-grabbing applications very often lock the
 
1083
    terminal. Use this function with extreme caution, and consider
 
1084
    using the \c -nograb command line option while debugging.
 
1085
 
 
1086
    It is almost never necessary to grab the mouse when using Qt, as
 
1087
    Qt grabs and releases it sensibly. In particular, Qt grabs the
 
1088
    mouse when a mouse button is pressed and keeps it until the last
 
1089
    button is released.
 
1090
 
 
1091
    Note that only visible widgets can grab mouse input. If
 
1092
    isVisible() returns false for a widget, that widget cannot call
 
1093
    grabMouse().
 
1094
 
 
1095
    \sa releaseMouse() grabKeyboard() releaseKeyboard() grabKeyboard()
 
1096
    focusWidget()
 
1097
*/
 
1098
 
 
1099
void QWidget::grabMouse()
 
1100
{
 
1101
    if (isVisible() && !qt_nograb()) {
 
1102
        if (mouseGrb)
 
1103
            mouseGrb->releaseMouse();
 
1104
#ifndef QT_NO_DEBUG
 
1105
        int status =
 
1106
#endif
 
1107
            XGrabPointer(X11->display, winId(), False,
 
1108
                          (uint)(ButtonPressMask | ButtonReleaseMask |
 
1109
                                  PointerMotionMask | EnterWindowMask |
 
1110
                                  LeaveWindowMask),
 
1111
                          GrabModeAsync, GrabModeAsync,
 
1112
                          XNone, XNone, X11->time);
 
1113
#ifndef QT_NO_DEBUG
 
1114
        if (status) {
 
1115
            const char *s =
 
1116
                status == GrabNotViewable ? "\"GrabNotViewable\"" :
 
1117
                status == AlreadyGrabbed  ? "\"AlreadyGrabbed\"" :
 
1118
                status == GrabFrozen      ? "\"GrabFrozen\"" :
 
1119
                status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
 
1120
                "<?>";
 
1121
            qWarning("Grabbing the mouse failed with %s", s);
 
1122
        }
 
1123
#endif
 
1124
        mouseGrb = this;
 
1125
    }
 
1126
}
 
1127
 
 
1128
/*!
 
1129
    \overload
 
1130
 
 
1131
    Grabs the mouse input and changes the cursor shape.
 
1132
 
 
1133
    The cursor will assume shape \a cursor (for as long as the mouse
 
1134
    focus is grabbed) and this widget will be the only one to receive
 
1135
    mouse events until releaseMouse() is called().
 
1136
 
 
1137
    \warning Grabbing the mouse might lock the terminal.
 
1138
 
 
1139
    \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
 
1140
*/
 
1141
 
 
1142
void QWidget::grabMouse(const QCursor &cursor)
 
1143
{
 
1144
    if (!qt_nograb()) {
 
1145
        if (mouseGrb)
 
1146
            mouseGrb->releaseMouse();
 
1147
#ifndef QT_NO_DEBUG
 
1148
        int status =
 
1149
#endif
 
1150
        XGrabPointer(X11->display, winId(), False,
 
1151
                      (uint)(ButtonPressMask | ButtonReleaseMask |
 
1152
                             PointerMotionMask | EnterWindowMask | LeaveWindowMask),
 
1153
                      GrabModeAsync, GrabModeAsync,
 
1154
                      XNone, cursor.handle(), X11->time);
 
1155
#ifndef QT_NO_DEBUG
 
1156
        if (status) {
 
1157
            const char *s =
 
1158
                status == GrabNotViewable ? "\"GrabNotViewable\"" :
 
1159
                status == AlreadyGrabbed  ? "\"AlreadyGrabbed\"" :
 
1160
                status == GrabFrozen      ? "\"GrabFrozen\"" :
 
1161
                status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
 
1162
                                            "<?>";
 
1163
            qWarning("Grabbing the mouse failed with %s", s);
 
1164
        }
 
1165
#endif
 
1166
        mouseGrb = this;
 
1167
    }
 
1168
}
 
1169
 
 
1170
/*!
 
1171
    Releases the mouse grab.
 
1172
 
 
1173
    \sa grabMouse(), grabKeyboard(), releaseKeyboard()
 
1174
*/
 
1175
 
 
1176
void QWidget::releaseMouse()
 
1177
{
 
1178
    if (!qt_nograb() && mouseGrb == this) {
 
1179
        XUngrabPointer(X11->display, X11->time);
 
1180
        XFlush(X11->display);
 
1181
        mouseGrb = 0;
 
1182
    }
 
1183
}
 
1184
 
 
1185
/*!
 
1186
    Grabs the keyboard input.
 
1187
 
 
1188
    This widget reveives all keyboard events until releaseKeyboard()
 
1189
    is called; other widgets get no keyboard events at all. Mouse
 
1190
    events are not affected. Use grabMouse() if you want to grab that.
 
1191
 
 
1192
    The focus widget is not affected, except that it doesn't receive
 
1193
    any keyboard events. setFocus() moves the focus as usual, but the
 
1194
    new focus widget receives keyboard events only after
 
1195
    releaseKeyboard() is called.
 
1196
 
 
1197
    If a different widget is currently grabbing keyboard input, that
 
1198
    widget's grab is released first.
 
1199
 
 
1200
    \sa releaseKeyboard() grabMouse() releaseMouse() focusWidget()
 
1201
*/
 
1202
 
 
1203
void QWidget::grabKeyboard()
 
1204
{
 
1205
    if (!qt_nograb()) {
 
1206
        if (keyboardGrb)
 
1207
            keyboardGrb->releaseKeyboard();
 
1208
        XGrabKeyboard(X11->display, data->winid, False, GrabModeAsync, GrabModeAsync,
 
1209
                      X11->time);
 
1210
        keyboardGrb = this;
 
1211
    }
 
1212
}
 
1213
 
 
1214
/*!
 
1215
    Releases the keyboard grab.
 
1216
 
 
1217
    \sa grabKeyboard(), grabMouse(), releaseMouse()
 
1218
*/
 
1219
 
 
1220
void QWidget::releaseKeyboard()
 
1221
{
 
1222
    if (!qt_nograb() && keyboardGrb == this) {
 
1223
        XUngrabKeyboard(X11->display, X11->time);
 
1224
        keyboardGrb = 0;
 
1225
    }
 
1226
}
 
1227
 
 
1228
 
 
1229
/*!
 
1230
    Returns the widget that is currently grabbing the mouse input.
 
1231
 
 
1232
    If no widget in this application is currently grabbing the mouse,
 
1233
    0 is returned.
 
1234
 
 
1235
    \sa grabMouse(), keyboardGrabber()
 
1236
*/
 
1237
 
 
1238
QWidget *QWidget::mouseGrabber()
 
1239
{
 
1240
    return mouseGrb;
 
1241
}
 
1242
 
 
1243
/*!
 
1244
    Returns the widget that is currently grabbing the keyboard input.
 
1245
 
 
1246
    If no widget in this application is currently grabbing the
 
1247
    keyboard, 0 is returned.
 
1248
 
 
1249
    \sa grabMouse(), mouseGrabber()
 
1250
*/
 
1251
 
 
1252
QWidget *QWidget::keyboardGrabber()
 
1253
{
 
1254
    return keyboardGrb;
 
1255
}
 
1256
 
 
1257
/*!
 
1258
    Sets the top-level widget containing this widget to be the active
 
1259
    window.
 
1260
 
 
1261
    An active window is a visible top-level window that has the
 
1262
    keyboard input focus.
 
1263
 
 
1264
    This function performs the same operation as clicking the mouse on
 
1265
    the title bar of a top-level window. On X11, the result depends on
 
1266
    the Window Manager. If you want to ensure that the window is
 
1267
    stacked on top as well you should also call raise(). Note that the
 
1268
    window must be visible, otherwise activateWindow() has no effect.
 
1269
 
 
1270
    On Windows, if you are calling this when the application is not
 
1271
    currently the active one then it will not make it the active
 
1272
    window.  It will flash the task bar entry blue to indicate that
 
1273
    the window has done something. This is because Microsoft do not
 
1274
    allow an application to interrupt what the user is currently doing
 
1275
    in another application.
 
1276
 
 
1277
    \sa isActiveWindow(), window(), show()
 
1278
*/
 
1279
 
 
1280
void QWidget::activateWindow()
 
1281
{
 
1282
    Q_D(QWidget);
 
1283
    QWidget *tlw = window();
 
1284
    if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
 
1285
        XSetInputFocus(X11->display, tlw->winId(), XRevertToParent, X11->time);
 
1286
        d->focusInputContext();
 
1287
    }
 
1288
}
 
1289
 
 
1290
 
 
1291
void QWidget::update()
 
1292
{
 
1293
    Q_D(QWidget);
 
1294
    if (isVisible() && updatesEnabled()) {
 
1295
//         d->removePendingPaintEvents(); // ### this is far too slow to go in
 
1296
        d->invalidated_region = d->clipRect();
 
1297
        QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
 
1298
    }
 
1299
}
 
1300
 
 
1301
void QWidget::update(const QRegion &rgn)
 
1302
{
 
1303
    Q_D(QWidget);
 
1304
    if (isVisible() && updatesEnabled()) {
 
1305
        d->invalidated_region |= (rgn & d->clipRect());
 
1306
        QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
 
1307
    }
 
1308
}
 
1309
 
 
1310
void QWidget::update(const QRect &r)
 
1311
{
 
1312
    Q_D(QWidget);
 
1313
    int x = r.x(), y = r.y(), w = r.width(), h = r.height();
 
1314
    if (w && h && isVisible() && updatesEnabled()) {
 
1315
        if (w < 0)
 
1316
            w = data->crect.width()  - x;
 
1317
        if (h < 0)
 
1318
            h = data->crect.height() - y;
 
1319
        if (w != 0 && h != 0) {
 
1320
            d->invalidated_region |= (d->clipRect() & QRect(x, y, w, h));
 
1321
            QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
 
1322
        }
 
1323
    }
 
1324
}
 
1325
 
 
1326
struct QX11DoubleBuffer
 
1327
{
 
1328
    enum {
 
1329
        MaxWidth  = SHRT_MAX,
 
1330
        MaxHeight = SHRT_MAX
 
1331
    };
 
1332
 
 
1333
    Qt::HANDLE hd, picture;
 
1334
    int screen, depth;
 
1335
    int width, height;
 
1336
};
 
1337
 
 
1338
static QX11DoubleBuffer *qt_x11_global_double_buffer = 0;
 
1339
static bool qt_x11_global_double_buffer_active = false;
 
1340
static bool qt_x11_enable_global_db = true;
 
1341
 
 
1342
/*!
 
1343
    This function can be used to enable/disable the global double
 
1344
    buffering under X11.
 
1345
*/
 
1346
 
 
1347
Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable)
 
1348
{
 
1349
    qt_x11_enable_global_db = enable;
 
1350
}
 
1351
 
 
1352
static void qt_discard_double_buffer(QX11DoubleBuffer **db)
 
1353
{
 
1354
    if (!*db) return;
 
1355
 
 
1356
    XFreePixmap(X11->display, (*db)->hd);
 
1357
#ifndef QT_NO_XRENDER
 
1358
    if (X11->use_xrender)
 
1359
        XRenderFreePicture(X11->display, (*db)->picture);
 
1360
#endif
 
1361
    delete *db;
 
1362
    *db = 0;
 
1363
}
 
1364
 
 
1365
void qt_discard_double_buffer()
 
1366
{
 
1367
    qt_discard_double_buffer(&qt_x11_global_double_buffer);
 
1368
}
 
1369
 
 
1370
static void qt_x11_release_double_buffer(QX11DoubleBuffer **db)
 
1371
{
 
1372
    if (*db != qt_x11_global_double_buffer) {
 
1373
        // qDebug("--> discarding temporary double buffer");
 
1374
        qt_discard_double_buffer(db);
 
1375
    } else {
 
1376
        // qDebug("--> global double buffer unused");
 
1377
        qt_x11_global_double_buffer_active = false;
 
1378
    }
 
1379
}
 
1380
 
 
1381
static QX11DoubleBuffer *qt_x11_create_double_buffer(Qt::HANDLE hd, int screen, int depth, int width, int height)
 
1382
{
 
1383
    QX11DoubleBuffer *db = new QX11DoubleBuffer;
 
1384
    db->hd = XCreatePixmap(X11->display, hd, width, height, depth);
 
1385
    db->picture = 0;
 
1386
#ifndef QT_NO_XRENDER
 
1387
    if (X11->use_xrender)
 
1388
        db->picture = XRenderCreatePicture(X11->display, db->hd,
 
1389
                                           XRenderFindVisualFormat(X11->display, (Visual *) QX11Info::appVisual()), 0, 0);
 
1390
#endif
 
1391
    db->screen = screen;
 
1392
    db->depth = depth;
 
1393
    db->width = width;
 
1394
    db->height = height;
 
1395
    return db;
 
1396
}
 
1397
 
 
1398
static
 
1399
void qt_x11_get_double_buffer(QX11DoubleBuffer **db, Qt::HANDLE hd, int screen, int depth, int width, int height)
 
1400
{
 
1401
    if (!qt_reuse_double_buffer || qt_x11_global_double_buffer_active) {
 
1402
        // qDebug("<-- creating temporary double buffer");
 
1403
        *db = qt_x11_create_double_buffer(hd, screen, depth, width, height);
 
1404
        return;
 
1405
    }
 
1406
 
 
1407
    // qDebug("<-- using global double buffer");
 
1408
    qt_x11_global_double_buffer_active = true;
 
1409
 
 
1410
    // the db should consist of 128x128 chunks
 
1411
    width  = qMin(((width / 128) + 1) * 128, (int)QX11DoubleBuffer::MaxWidth);
 
1412
    height = qMin(((height / 128) + 1) * 128, (int)QX11DoubleBuffer::MaxHeight);
 
1413
 
 
1414
    if (qt_x11_global_double_buffer) {
 
1415
        if (qt_x11_global_double_buffer->screen == screen
 
1416
            && qt_x11_global_double_buffer->depth == depth
 
1417
            && qt_x11_global_double_buffer->width >= width
 
1418
            && qt_x11_global_double_buffer->height >= height) {
 
1419
            *db = qt_x11_global_double_buffer;
 
1420
            return;
 
1421
        }
 
1422
 
 
1423
        width  = qMax(qt_x11_global_double_buffer->width, width);
 
1424
        height = qMax(qt_x11_global_double_buffer->height, height);
 
1425
 
 
1426
        qt_discard_double_buffer();
 
1427
    }
 
1428
 
 
1429
    qt_x11_global_double_buffer = *db = qt_x11_create_double_buffer(hd, screen, depth, width, height);
 
1430
}
 
1431
 
 
1432
void QWidget::repaint(const QRegion& rgn)
 
1433
{
 
1434
    Q_D(QWidget);
 
1435
    if (!isVisible() || !updatesEnabled() || !testAttribute(Qt::WA_Mapped) || rgn.isEmpty())
 
1436
        return;
 
1437
 
 
1438
    if (testAttribute(Qt::WA_WState_InPaintEvent))
 
1439
        qWarning("QWidget::repaint: recursive repaint detected.");
 
1440
 
 
1441
 
 
1442
    if (!d->invalidated_region.isEmpty())
 
1443
        d->invalidated_region -= rgn;
 
1444
 
 
1445
    setAttribute(Qt::WA_WState_InPaintEvent);
 
1446
 
 
1447
    QRect br = rgn.boundingRect();
 
1448
    QVector<QRect> rects = rgn.rects();
 
1449
    QRect brWS = d->mapToWS(br);
 
1450
 
 
1451
    bool double_buffer = (!testAttribute(Qt::WA_PaintOnScreen)
 
1452
                          && !testAttribute(Qt::WA_NoSystemBackground)
 
1453
                          && br.width()  <= QX11DoubleBuffer::MaxWidth
 
1454
                          && br.height() <= QX11DoubleBuffer::MaxHeight
 
1455
                          && !QPainter::redirected(this)
 
1456
                          && qt_x11_enable_global_db);
 
1457
 
 
1458
    bool do_system_clip = !double_buffer && (rects.size() > 1 || (br != QRect(0,0,data->crect.width(),data->crect.height())));
 
1459
 
 
1460
    Qt::HANDLE old_hd = d->hd;
 
1461
    Qt::HANDLE old_picture = d->picture;
 
1462
 
 
1463
    QPoint redirectionOffset;
 
1464
    QX11DoubleBuffer *qDoubleBuffer = 0;
 
1465
    if (double_buffer) {
 
1466
        qt_x11_get_double_buffer(&qDoubleBuffer, d->hd, d->xinfo.screen(), d->xinfo.depth(),
 
1467
                                 br.width(), br.height());
 
1468
 
 
1469
        d->hd = qDoubleBuffer->hd;
 
1470
        d->picture = qDoubleBuffer->picture;
 
1471
        redirectionOffset = br.topLeft();
 
1472
    } else {
 
1473
        redirectionOffset = data->wrect.topLeft();
 
1474
    }
 
1475
 
 
1476
    if (!redirectionOffset.isNull())
 
1477
        QPainter::setRedirected(this, this, redirectionOffset);
 
1478
 
 
1479
    QPaintEngine *engine = paintEngine();
 
1480
 
 
1481
    if (engine && do_system_clip) {
 
1482
        if (redirectionOffset.isNull()) {
 
1483
            engine->setSystemClip(rgn);
 
1484
        } else {
 
1485
            QRegion redirectedRegion(rgn);
 
1486
            redirectedRegion.translate(-redirectionOffset);
 
1487
            engine->setSystemClip(redirectedRegion);
 
1488
        }
 
1489
    }
 
1490
 
 
1491
    QPaintEvent e(rgn);
 
1492
    if (engine
 
1493
        && !testAttribute(Qt::WA_NoBackground)
 
1494
        && !testAttribute(Qt::WA_NoSystemBackground)) {
 
1495
        d->composeBackground(br);
 
1496
#ifdef QT3_SUPPORT
 
1497
        e.setErased(true);
 
1498
#endif
 
1499
    }
 
1500
    QApplication::sendSpontaneousEvent(this, &e);
 
1501
 
 
1502
    if (engine && do_system_clip)
 
1503
        engine->setSystemClip(QRegion());
 
1504
 
 
1505
    if (!redirectionOffset.isNull())
 
1506
        QPainter::restoreRedirected(this);
 
1507
 
 
1508
    if (double_buffer) {
 
1509
        GC gc = XCreateGC(d->xinfo.display(), d->hd, 0, 0);
 
1510
        if (testAttribute(Qt::WA_PaintUnclipped))
 
1511
            XSetSubwindowMode(X11->display, gc, IncludeInferiors);
 
1512
        for (int i = 0; i < rects.size(); ++i) {
 
1513
            QRect rr = d->mapToWS(rects.at(i));
 
1514
            XCopyArea(X11->display, d->hd, winId(), gc,
 
1515
                      rr.x() - brWS.x(), rr.y() - brWS.y(),
 
1516
                      rr.width(), rr.height(),
 
1517
                      rr.x(), rr.y());
 
1518
        }
 
1519
        XFreeGC(d->xinfo.display(), gc);
 
1520
 
 
1521
        d->hd = old_hd;
 
1522
        d->picture = old_picture;
 
1523
 
 
1524
        qt_x11_release_double_buffer(&qDoubleBuffer);
 
1525
 
 
1526
        if (!QApplicationPrivate::active_window) {
 
1527
            extern int qt_double_buffer_timer;
 
1528
            if (qt_double_buffer_timer)
 
1529
                qApp->killTimer(qt_double_buffer_timer);
 
1530
            qt_double_buffer_timer = qApp->startTimer(500);
 
1531
        }
 
1532
    }
 
1533
 
 
1534
    // Clean out the temporary engine if used...
 
1535
    if (d->extraPaintEngine) {
 
1536
        delete d->extraPaintEngine;
 
1537
        d->extraPaintEngine = 0;
 
1538
    }
 
1539
 
 
1540
    setAttribute(Qt::WA_WState_InPaintEvent, false);
 
1541
    if(!testAttribute(Qt::WA_PaintOutsidePaintEvent) && paintingActive())
 
1542
        qWarning("It is dangerous to leave painters active on a widget outside of the PaintEvent");
 
1543
 
 
1544
    if (testAttribute(Qt::WA_ContentsPropagated))
 
1545
        d->updatePropagatedBackground(&rgn);
 
1546
}
 
1547
 
 
1548
void QWidget::setWindowState(Qt::WindowStates newstate)
 
1549
{
 
1550
    Q_D(QWidget);
 
1551
    bool needShow = false;
 
1552
    Qt::WindowStates oldstate = windowState();
 
1553
    if (oldstate == newstate)
 
1554
        return;
 
1555
    if (isWindow()) {
 
1556
        // Ensure the initial size is valid, since we store it as normalGeometry below.
 
1557
        if (!testAttribute(Qt::WA_Resized) && !isVisible())
 
1558
            adjustSize();
 
1559
 
 
1560
        QTLWExtra *top = d->topData();
 
1561
 
 
1562
        if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
 
1563
            if (qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
 
1564
                && qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
 
1565
                if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
 
1566
                    top->normalGeometry = geometry();
 
1567
                qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
 
1568
                                       ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
 
1569
                                       ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
 
1570
            } else if (! (newstate & Qt::WindowFullScreen)) {
 
1571
                if (newstate & Qt::WindowMaximized) {
 
1572
                    // save original geometry
 
1573
                    const QRect normalGeometry = geometry();
 
1574
 
 
1575
                    if (isVisible()) {
 
1576
                        d->updateFrameStrut();
 
1577
                        const QRect maxRect = QApplication::desktop()->availableGeometry(this);
 
1578
                        const QRect r = top->normalGeometry;
 
1579
                        setGeometry(maxRect.x() + top->fleft,
 
1580
                                    maxRect.y() + top->ftop,
 
1581
                                    maxRect.width() - top->fleft - top->fright,
 
1582
                                    maxRect.height() - top->ftop - top->fbottom);
 
1583
                        top->normalGeometry = r;
 
1584
                    }
 
1585
 
 
1586
                    if (top->normalGeometry.width() < 0)
 
1587
                        top->normalGeometry = normalGeometry;
 
1588
                } else {
 
1589
                    // restore original geometry
 
1590
                    setGeometry(top->normalGeometry);
 
1591
                }
 
1592
            }
 
1593
        }
 
1594
 
 
1595
        if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
 
1596
            if (qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN))) {
 
1597
                if (newstate & Qt::WindowFullScreen)
 
1598
                    top->normalGeometry = geometry();
 
1599
                qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
 
1600
                                       ATOM(_NET_WM_STATE_FULLSCREEN));
 
1601
            } else {
 
1602
                needShow = isVisible();
 
1603
 
 
1604
                if (newstate & Qt::WindowFullScreen) {
 
1605
                    d->updateFrameStrut();
 
1606
                    const QRect normalGeometry = geometry();
 
1607
                    const QPoint fullScreenOffset = QPoint(top->fleft, top->ftop);
 
1608
 
 
1609
                    top->savedFlags = windowFlags();
 
1610
                    setParent(0, Qt::Window | Qt::FramelessWindowHint);
 
1611
                    const QRect r = top->normalGeometry;
 
1612
                    setGeometry(qApp->desktop()->screenGeometry(this));
 
1613
                    top->normalGeometry = r;
 
1614
 
 
1615
                    if (top->normalGeometry.width() < 0) {
 
1616
                        top->normalGeometry = normalGeometry;
 
1617
                        top->fullScreenOffset = fullScreenOffset;
 
1618
                    }
 
1619
                } else {
 
1620
                    setParent(0, top->savedFlags);
 
1621
 
 
1622
                    if (newstate & Qt::WindowMaximized) {
 
1623
                        // from fullscreen to maximized
 
1624
                        d->updateFrameStrut();
 
1625
                        const QRect maxRect = QApplication::desktop()->availableGeometry(this);
 
1626
                        const QRect r = top->normalGeometry;
 
1627
                        setGeometry(maxRect.x() + top->fleft,
 
1628
                                    maxRect.y() + top->ftop,
 
1629
                                    maxRect.width() - top->fleft - top->fright,
 
1630
                                    maxRect.height() - top->ftop - top->fbottom);
 
1631
                        top->normalGeometry = r;
 
1632
                    } else {
 
1633
                        // restore original geometry
 
1634
                        setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
 
1635
                                                                 -top->fullScreenOffset.y(),
 
1636
                                                                 -top->fullScreenOffset.x(),
 
1637
                                                                 -top->fullScreenOffset.y()));
 
1638
                    }
 
1639
                }
 
1640
            }
 
1641
        }
 
1642
 
 
1643
        if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
 
1644
            if (isVisible()) {
 
1645
                if (newstate & Qt::WindowMinimized) {
 
1646
                    XEvent e;
 
1647
                    e.xclient.type = ClientMessage;
 
1648
                    e.xclient.message_type = ATOM(WM_CHANGE_STATE);
 
1649
                    e.xclient.display = X11->display;
 
1650
                    e.xclient.window = data->winid;
 
1651
                    e.xclient.format = 32;
 
1652
                    e.xclient.data.l[0] = IconicState;
 
1653
                    e.xclient.data.l[1] = 0;
 
1654
                    e.xclient.data.l[2] = 0;
 
1655
                    e.xclient.data.l[3] = 0;
 
1656
                    e.xclient.data.l[4] = 0;
 
1657
                    XSendEvent(X11->display,
 
1658
                               RootWindow(X11->display,d->xinfo.screen()),
 
1659
                               False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
 
1660
                } else {
 
1661
                    setAttribute(Qt::WA_Mapped);
 
1662
                    XMapWindow(X11->display, winId());
 
1663
                }
 
1664
            }
 
1665
 
 
1666
            needShow = false;
 
1667
        }
 
1668
    }
 
1669
 
 
1670
    data->window_state = newstate;
 
1671
 
 
1672
    if (needShow)
 
1673
        show();
 
1674
 
 
1675
    if (newstate & Qt::WindowActive)
 
1676
        activateWindow();
 
1677
 
 
1678
    QWindowStateChangeEvent e(oldstate);
 
1679
    QApplication::sendEvent(this, &e);
 
1680
}
 
1681
 
 
1682
/*!
 
1683
  \internal
 
1684
  Platform-specific part of QWidget::show().
 
1685
*/
 
1686
 
 
1687
void QWidgetPrivate::show_sys()
 
1688
{
 
1689
    Q_Q(QWidget);
 
1690
    if (q->isWindow()) {
 
1691
        XWMHints *h = XGetWMHints(X11->display, q->winId());
 
1692
        XWMHints  wm_hints;
 
1693
        bool got_hints = h != 0;
 
1694
        if (!got_hints) {
 
1695
            h = &wm_hints;
 
1696
            h->flags = 0;
 
1697
        }
 
1698
        h->initial_state = q->isMinimized() ? IconicState : NormalState;
 
1699
        h->flags |= StateHint;
 
1700
        XSetWMHints(X11->display, q->winId(), h);
 
1701
        if (got_hints)
 
1702
            XFree((char *)h);
 
1703
 
 
1704
        // update _MOTIF_WM_HINTS
 
1705
        QtMWMHints mwmhints = GetMWMHints(X11->display, q->winId());
 
1706
 
 
1707
        if (q->testAttribute(Qt::WA_ShowModal)) {
 
1708
            mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
 
1709
            mwmhints.flags |= MWM_HINTS_INPUT_MODE;
 
1710
        }
 
1711
 
 
1712
        if (q->minimumSize() == q->maximumSize()) {
 
1713
            // fixed size, remove the resize handle (since mwm/dtwm
 
1714
            // isn't smart enough to do it itself)
 
1715
            mwmhints.flags |= MWM_HINTS_FUNCTIONS;
 
1716
            if (mwmhints.functions == MWM_FUNC_ALL) {
 
1717
                mwmhints.functions = (MWM_FUNC_MOVE
 
1718
                                      | MWM_FUNC_MINIMIZE
 
1719
                                      | MWM_FUNC_MAXIMIZE
 
1720
                                      | MWM_FUNC_CLOSE);
 
1721
            } else {
 
1722
                mwmhints.functions &= ~MWM_FUNC_RESIZE;
 
1723
            }
 
1724
 
 
1725
            mwmhints.flags |= MWM_HINTS_DECORATIONS;
 
1726
            if (mwmhints.decorations == MWM_DECOR_ALL) {
 
1727
                mwmhints.decorations = (MWM_DECOR_BORDER
 
1728
                                        | MWM_DECOR_RESIZEH
 
1729
                                        | MWM_DECOR_TITLE
 
1730
                                        | MWM_DECOR_MENU
 
1731
                                        | MWM_DECOR_MINIMIZE
 
1732
                                        | MWM_DECOR_MAXIMIZE);
 
1733
            } else {
 
1734
                mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
 
1735
            }
 
1736
        }
 
1737
 
 
1738
        if (mwmhints.flags != 0l) {
 
1739
            XChangeProperty(X11->display, q->winId(), ATOM(_MOTIF_WM_HINTS),
 
1740
                            ATOM(_MOTIF_WM_HINTS), 32, PropModeReplace,
 
1741
                            (unsigned char *) &mwmhints, 5);
 
1742
        } else {
 
1743
            XDeleteProperty(X11->display, q->winId(), ATOM(_MOTIF_WM_HINTS));
 
1744
        }
 
1745
 
 
1746
        // set _NET_WM_STATE
 
1747
        Atom net_winstates[6] = { 0, 0, 0, 0, 0, 0 };
 
1748
        int curr_winstate = 0;
 
1749
 
 
1750
        Qt::WindowFlags flags = q->windowFlags();
 
1751
        if (flags & Qt::WindowStaysOnTopHint) {
 
1752
            net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_ABOVE);
 
1753
            net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_STAYS_ON_TOP);
 
1754
        }
 
1755
        if (q->isFullScreen()) {
 
1756
            net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_FULLSCREEN);
 
1757
        }
 
1758
        if (q->isMaximized()) {
 
1759
            net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
 
1760
            net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
 
1761
        }
 
1762
        if (q->testAttribute(Qt::WA_ShowModal)) {
 
1763
            net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MODAL);
 
1764
        }
 
1765
 
 
1766
        if (curr_winstate > 0) {
 
1767
            XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_STATE), XA_ATOM,
 
1768
                            32, PropModeReplace, (unsigned char *) net_winstates, curr_winstate);
 
1769
        } else {
 
1770
            XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_STATE));
 
1771
        }
 
1772
 
 
1773
        // set _NET_WM_USER_TIME
 
1774
        if (X11->userTime != CurrentTime) {
 
1775
            XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_USER_TIME), XA_CARDINAL,
 
1776
                            32, PropModeReplace, (unsigned char *) &X11->userTime, 1);
 
1777
        }
 
1778
 
 
1779
        if (!topData()->embedded
 
1780
            && topData()->parentWinId
 
1781
            && topData()->parentWinId != QX11Info::appRootWindow(xinfo.screen())
 
1782
            && !q->isMinimized()) {
 
1783
            X11->deferred_map.append(q);
 
1784
            return;
 
1785
        }
 
1786
 
 
1787
        if (q->isMaximized() && !q->isFullScreen()
 
1788
            && !(qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
 
1789
                 && qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
 
1790
            XMapWindow(X11->display, q->winId());
 
1791
            qt_x11_wait_for_window_manager(q);
 
1792
 
 
1793
            // if the wm was not smart enough to adjust our size, do that manually
 
1794
            updateFrameStrut();
 
1795
            QRect maxRect = QApplication::desktop()->availableGeometry(q);
 
1796
 
 
1797
            QTLWExtra *top = topData();
 
1798
            QRect normalRect = top->normalGeometry;
 
1799
 
 
1800
            q->setGeometry(maxRect.x() + top->fleft,
 
1801
                        maxRect.y() + top->ftop,
 
1802
                        maxRect.width() - top->fleft - top->fright,
 
1803
                        maxRect.height() - top->ftop - top->fbottom);
 
1804
 
 
1805
            // restore the original normalGeometry
 
1806
            top->normalGeometry = normalRect;
 
1807
            // internalSetGeometry() clears the maximized flag... make sure we set it back
 
1808
            data.window_state = data.window_state | Qt::WindowMaximized;
 
1809
 
 
1810
            return;
 
1811
        }
 
1812
 
 
1813
        if (q->isFullScreen() && !qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN))) {
 
1814
            XMapWindow(X11->display, q->winId());
 
1815
            qt_x11_wait_for_window_manager(q);
 
1816
            return;
 
1817
        }
 
1818
    }
 
1819
 
 
1820
    if (q->testAttribute(Qt::WA_OutsideWSRange))
 
1821
        return;
 
1822
    q->setAttribute(Qt::WA_Mapped);
 
1823
 
 
1824
    if (!q->isWindow()
 
1825
        && (q->testAttribute(Qt::WA_NoBackground)
 
1826
            || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
 
1827
        XSetWindowBackgroundPixmap(X11->display, q->winId(), XNone);
 
1828
        XMapWindow(X11->display, q->winId());
 
1829
        return;
 
1830
    }
 
1831
    XMapWindow(X11->display, q->winId());
 
1832
}
 
1833
 
 
1834
 
 
1835
/*!
 
1836
  \internal
 
1837
  Platform-specific part of QWidget::hide().
 
1838
*/
 
1839
 
 
1840
void QWidgetPrivate::hide_sys()
 
1841
{
 
1842
    Q_Q(QWidget);
 
1843
    deactivateWidgetCleanup();
 
1844
    if (q->isWindow()) {
 
1845
        X11->deferred_map.removeAll(q);
 
1846
        if (q->winId()) // in nsplugin, may be 0
 
1847
            XWithdrawWindow(X11->display, q->winId(), xinfo.screen());
 
1848
 
 
1849
        QTLWExtra *top = topData();
 
1850
        data.crect.moveTopLeft(QPoint(data.crect.x() - top->fleft,
 
1851
                                          data.crect.y() - top->ftop));
 
1852
 
 
1853
        // zero the frame strut and mark it dirty
 
1854
        top->fleft = top->fright = top->ftop = top->fbottom = 0;
 
1855
        data.fstrut_dirty = true;
 
1856
 
 
1857
        XFlush(X11->display);
 
1858
    } else {
 
1859
        q->setAttribute(Qt::WA_Mapped, false);
 
1860
        if (q->winId()) // in nsplugin, may be 0
 
1861
            XUnmapWindow(X11->display, q->winId());
 
1862
    }
 
1863
}
 
1864
 
 
1865
void QWidgetPrivate::raise_sys()
 
1866
{
 
1867
    Q_Q(QWidget);
 
1868
    XRaiseWindow(X11->display, q->winId());
 
1869
}
 
1870
 
 
1871
void QWidgetPrivate::lower_sys()
 
1872
{
 
1873
    Q_Q(QWidget);
 
1874
    XLowerWindow(X11->display, q->winId());
 
1875
}
 
1876
 
 
1877
void QWidgetPrivate::stackUnder_sys(QWidget* w)
 
1878
{
 
1879
    Q_Q(QWidget);
 
1880
    Window stack[2];
 
1881
    stack[0] = w->winId();;
 
1882
    stack[1] = q->winId();
 
1883
    XRestackWindows(X11->display, stack, 2);
 
1884
}
 
1885
 
 
1886
 
 
1887
static void do_size_hints(QWidget* widget, QWExtra *x)
 
1888
{
 
1889
    XSizeHints s;
 
1890
    s.flags = 0;
 
1891
    if (x) {
 
1892
        s.x = widget->x();
 
1893
        s.y = widget->y();
 
1894
        s.width = widget->width();
 
1895
        s.height = widget->height();
 
1896
        if (x->minw > 0 || x->minh > 0) {
 
1897
            // add minimum size hints
 
1898
            s.flags |= PMinSize;
 
1899
            s.min_width  = qMin(XCOORD_MAX, x->minw);
 
1900
            s.min_height = qMin(XCOORD_MAX, x->minh);
 
1901
        }
 
1902
        if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
 
1903
            // add maximum size hints
 
1904
            s.flags |= PMaxSize;
 
1905
            s.max_width  = qMin(XCOORD_MAX, x->maxw);
 
1906
            s.max_height = qMin(XCOORD_MAX, x->maxh);
 
1907
        }
 
1908
        if (x->topextra &&
 
1909
            (x->topextra->incw > 0 || x->topextra->inch > 0)) {
 
1910
            // add resize increment hints
 
1911
            s.flags |= PResizeInc | PBaseSize;
 
1912
            s.width_inc = x->topextra->incw;
 
1913
            s.height_inc = x->topextra->inch;
 
1914
            s.base_width = x->topextra->basew;
 
1915
            s.base_height = x->topextra->baseh;
 
1916
        }
 
1917
        if (x->topextra && x->topextra->uspos) {
 
1918
            // user (i.e. command-line) specified position
 
1919
            s.flags |= USPosition;
 
1920
            s.flags |= PPosition;
 
1921
        }
 
1922
        if (x->topextra && x->topextra->ussize) {
 
1923
            // user (i.e. command-line) specified size
 
1924
            s.flags |= USSize;
 
1925
            s.flags |= PSize;
 
1926
        }
 
1927
    }
 
1928
    s.flags |= PWinGravity;
 
1929
    s.win_gravity = NorthWestGravity;
 
1930
    XSetWMNormalHints(X11->display, widget->winId(), &s);
 
1931
}
 
1932
 
 
1933
 
 
1934
/*
 
1935
  Helper function for non-toplevel widgets. Helps to map Qt's 32bit
 
1936
  coordinate system to X11's 16bit coordinate system.
 
1937
 
 
1938
  Sets the geometry of the widget to data.crect, but clipped to sizes
 
1939
  that X can handle. Unmaps widgets that are completely outside the
 
1940
  valid range.
 
1941
 
 
1942
  Maintains data.wrect, which is the geometry of the X widget,
 
1943
  measured in this widget's coordinate system.
 
1944
 
 
1945
  if the parent is not clipped, parentWRect is empty, otherwise
 
1946
  parentWRect is the geometry of the parent's X rect, measured in
 
1947
  parent's coord sys
 
1948
 */
 
1949
void QWidgetPrivate::setWSGeometry(bool dontShow)
 
1950
{
 
1951
    Q_Q(QWidget);
 
1952
 
 
1953
    /*
 
1954
      There are up to four different coordinate systems here:
 
1955
      Qt coordinate system for this widget.
 
1956
      X coordinate system for this widget (relative to wrect).
 
1957
      Qt coordinate system for parent
 
1958
      X coordinate system for parent (relative to parent's wrect).
 
1959
     */
 
1960
    Display *dpy = xinfo.display();
 
1961
    QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
 
1962
    QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
 
1963
    QRect wrect;
 
1964
    //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)
 
1965
    QRect xrect = data.crect;
 
1966
 
 
1967
    QRect parentWRect = q->parentWidget()->data->wrect;
 
1968
 
 
1969
    if (parentWRect.isValid()) {
 
1970
        // parent is clipped, and we have to clip to the same limit as parent
 
1971
        if (!parentWRect.contains(xrect)) {
 
1972
            xrect &= parentWRect;
 
1973
            wrect = xrect;
 
1974
            //translate from parent's to my Qt coord sys
 
1975
            wrect.translate(-data.crect.topLeft());
 
1976
        }
 
1977
        //translate from parent's Qt coords to parent's X coords
 
1978
        xrect.translate(-parentWRect.topLeft());
 
1979
 
 
1980
    } else {
 
1981
        // parent is not clipped, we may or may not have to clip
 
1982
 
 
1983
        if (data.wrect.isValid()) {
 
1984
            // This is where the main optimization is: we are already
 
1985
            // clipped, and if our clip is still valid, we can just
 
1986
            // move our window, and do not need to move or clip
 
1987
            // children
 
1988
 
 
1989
            QRect vrect = xrect & q->parentWidget()->rect();
 
1990
            vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
 
1991
            if (data.wrect.contains(vrect)) {
 
1992
                xrect = data.wrect;
 
1993
                xrect.translate(data.crect.topLeft());
 
1994
                XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
 
1995
                return;
 
1996
            }
 
1997
        }
 
1998
 
 
1999
        if (!validRange.contains(xrect)) {
 
2000
            // we are too big, and must clip
 
2001
            xrect &=wrectRange;
 
2002
            wrect = xrect;
 
2003
            wrect.translate(-data.crect.topLeft());
 
2004
            //parent's X coord system is equal to parent's Qt coord
 
2005
            //sys, so we don't need to map xrect.
 
2006
        }
 
2007
 
 
2008
    }
 
2009
 
 
2010
    // unmap if we are outside the valid window system coord system
 
2011
    bool outsideRange = !xrect.isValid();
 
2012
    bool mapWindow = false;
 
2013
    if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
 
2014
        q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
 
2015
        if (outsideRange) {
 
2016
            XUnmapWindow(dpy, data.winid);
 
2017
            q->setAttribute(Qt::WA_Mapped, false);
 
2018
        } else if (!q->isHidden()) {
 
2019
            mapWindow = true;
 
2020
        }
 
2021
    }
 
2022
 
 
2023
    if (outsideRange)
 
2024
        return;
 
2025
 
 
2026
    bool jump = (data.wrect != wrect);
 
2027
    data.wrect = wrect;
 
2028
 
 
2029
 
 
2030
    // and now recursively for all children...
 
2031
    // ### can be optimized
 
2032
    for (int i = 0; i < children.size(); ++i) {
 
2033
        QObject *object = children.at(i);
 
2034
        if (object->isWidgetType()) {
 
2035
            QWidget *w = static_cast<QWidget *>(object);
 
2036
            if (!w->isWindow())
 
2037
                w->d_func()->setWSGeometry(jump);
 
2038
        }
 
2039
    }
 
2040
 
 
2041
    // move ourselves to the new position and map (if necessary) after
 
2042
    // the movement. Rationale: moving unmapped windows is much faster
 
2043
    // than moving mapped windows
 
2044
    if (jump) //avoid flicker when jumping
 
2045
        XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
 
2046
    XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
 
2047
 
 
2048
    //to avoid flicker, we have to show children after the helper widget has moved
 
2049
    if (jump) {
 
2050
        for (int i = 0; i < children.size(); ++i) {
 
2051
            QObject *object = children.at(i);
 
2052
            if (object->isWidgetType()) {
 
2053
                QWidget *w = static_cast<QWidget *>(object);
 
2054
                if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
 
2055
                    w->setAttribute(Qt::WA_Mapped);
 
2056
                    XMapWindow(dpy, w->data->winid);
 
2057
                }
 
2058
            }
 
2059
        }
 
2060
    }
 
2061
 
 
2062
 
 
2063
    if  (jump)
 
2064
        XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
 
2065
 
 
2066
    if (mapWindow && !dontShow) {
 
2067
            q->setAttribute(Qt::WA_Mapped);
 
2068
            XMapWindow(dpy, data.winid);
 
2069
    }
 
2070
}
 
2071
 
 
2072
void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
 
2073
{
 
2074
    Q_Q(QWidget);
 
2075
    Display *dpy = X11->display;
 
2076
 
 
2077
    if ((q->windowType() == Qt::Desktop))
 
2078
        return;
 
2079
    if (q->isWindow()) {
 
2080
        if (!qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
 
2081
            && !qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
 
2082
            data.window_state &= ~Qt::WindowMaximized;
 
2083
        if (!qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN)))
 
2084
            data.window_state &= ~Qt::WindowFullScreen;
 
2085
        topData()->normalGeometry = QRect(0,0,-1,-1);
 
2086
        w = qMax(1, w);
 
2087
        h = qMax(1, h);
 
2088
    } else {
 
2089
        uint s = data.window_state;
 
2090
        s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
 
2091
        data.window_state = s;
 
2092
    }
 
2093
    if (extra) {                                // any size restrictions?
 
2094
        w = qMin(w,extra->maxw);
 
2095
        h = qMin(h,extra->maxh);
 
2096
        w = qMax(w,extra->minw);
 
2097
        h = qMax(h,extra->minh);
 
2098
    }
 
2099
    QPoint oldPos(q->pos());
 
2100
    QSize oldSize(q->size());
 
2101
    QRect oldGeom(data.crect);
 
2102
    QRect  r(x, y, w, h);
 
2103
 
 
2104
    // We only care about stuff that changes the geometry, or may
 
2105
    // cause the window manager to change its state
 
2106
    if (!q->isWindow() && oldGeom == r)
 
2107
        return;
 
2108
 
 
2109
    data.crect = r;
 
2110
    bool isResize = q->size() != oldSize;
 
2111
 
 
2112
    if (q->isWindow()) {
 
2113
        if (isMove)
 
2114
            topData()->uspos = 1;
 
2115
        if (isResize)
 
2116
            topData()->ussize = 1;
 
2117
        do_size_hints(q, extra);
 
2118
        if (isMove) {
 
2119
            if (! qt_broken_wm)
 
2120
                // pos() is right according to ICCCM 4.1.5
 
2121
                XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
 
2122
            else
 
2123
                // work around 4Dwm's incompliance with ICCCM 4.1.5
 
2124
                XMoveResizeWindow(dpy, data.winid, x, y, w, h);
 
2125
        } else if (isResize)
 
2126
            XResizeWindow(dpy, data.winid, w, h);
 
2127
    } else {
 
2128
        setWSGeometry();
 
2129
    }
 
2130
 
 
2131
    if (q->isVisible()) {
 
2132
        if (isMove && q->pos() != oldPos) {
 
2133
            if (! qt_broken_wm) {
 
2134
                // pos() is right according to ICCCM 4.1.5
 
2135
                QMoveEvent e(q->pos(), oldPos);
 
2136
                QApplication::sendEvent(q, &e);
 
2137
            } else {
 
2138
                // work around 4Dwm's incompliance with ICCCM 4.1.5
 
2139
                QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
 
2140
                QApplication::sendEvent(q, &e);
 
2141
            }
 
2142
        }
 
2143
        if (isResize) {
 
2144
            // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
 
2145
            q->setAttribute(Qt::WA_WState_ConfigPending);
 
2146
 
 
2147
            QResizeEvent e(q->size(), oldSize);
 
2148
            QApplication::sendEvent(q, &e);
 
2149
        }
 
2150
    } else {
 
2151
        if (isMove && q->pos() != oldPos)
 
2152
            q->setAttribute(Qt::WA_PendingMoveEvent, true);
 
2153
        if (isResize)
 
2154
            q->setAttribute(Qt::WA_PendingResizeEvent, true);
 
2155
    }
 
2156
}
 
2157
 
 
2158
void QWidgetPrivate::setConstraints_sys()
 
2159
{
 
2160
    Q_Q(QWidget);
 
2161
    do_size_hints(q, extra);
 
2162
}
 
2163
 
 
2164
 
 
2165
/*!
 
2166
    Scrolls the widget including its children \a dx pixels to the
 
2167
    right and \a dy downwards. Both \a dx and \a dy may be negative.
 
2168
 
 
2169
    After scrolling, scroll() sends a paint event for the the part
 
2170
    that is read but not written. For example, when scrolling 10
 
2171
    pixels rightwards, the leftmost ten pixels of the widget need
 
2172
    repainting. The paint event may be delivered immediately or later,
 
2173
    depending on some heuristics (note that you might have to force
 
2174
    processing of paint events using QApplication::sendPostedEvents()
 
2175
    when using scroll() and move() in combination).
 
2176
 
 
2177
    \sa QScrollView bitBlt()
 
2178
*/
 
2179
 
 
2180
void QWidget::scroll(int dx, int dy)
 
2181
{
 
2182
    scroll(dx, dy, QRect());
 
2183
}
 
2184
 
 
2185
/*!
 
2186
    \overload
 
2187
 
 
2188
    This version only scrolls \a r and does not move the children of
 
2189
    the widget.
 
2190
 
 
2191
    If \a r is empty or invalid, the result is undefined.
 
2192
 
 
2193
    \sa QScrollView bitBlt()
 
2194
*/
 
2195
void QWidget::scroll(int dx, int dy, const QRect& r)
 
2196
{
 
2197
    Q_D(QWidget);
 
2198
    if (!updatesEnabled() && children().size() == 0)
 
2199
        return;
 
2200
    bool valid_rect = r.isValid();
 
2201
    bool just_update = qAbs(dx) > width() || qAbs(dy) > height();
 
2202
    QRect sr = valid_rect ? r : d->clipRect();
 
2203
    if (just_update) {
 
2204
        update();
 
2205
    } else if (!valid_rect){
 
2206
        d->invalidated_region.translate(dx, dy);
 
2207
    }
 
2208
 
 
2209
    int x1, y1, x2, y2, w = sr.width(), h = sr.height();
 
2210
    if (dx > 0) {
 
2211
        x1 = sr.x();
 
2212
        x2 = x1+dx;
 
2213
        w -= dx;
 
2214
    } else {
 
2215
        x2 = sr.x();
 
2216
        x1 = x2-dx;
 
2217
        w += dx;
 
2218
    }
 
2219
    if (dy > 0) {
 
2220
        y1 = sr.y();
 
2221
        y2 = y1+dy;
 
2222
        h -= dy;
 
2223
    } else {
 
2224
        y2 = sr.y();
 
2225
        y1 = y2-dy;
 
2226
        h += dy;
 
2227
    }
 
2228
 
 
2229
    if (dx == 0 && dy == 0)
 
2230
        return;
 
2231
 
 
2232
    Display *dpy = X11->display;
 
2233
    // Want expose events
 
2234
    if (w > 0 && h > 0 && !just_update) {
 
2235
        GC gc = XCreateGC(dpy, winId(), 0, 0);
 
2236
        XSetGraphicsExposures(dpy, gc, True);
 
2237
        XCopyArea(dpy, winId(), winId(), gc, x1, y1, w, h, x2, y2);
 
2238
        XFreeGC(dpy, gc);
 
2239
    }
 
2240
 
 
2241
    if (!valid_rect && !d->children.isEmpty()) {        // scroll children
 
2242
        QPoint pd(dx, dy);
 
2243
        for (int i = 0; i < d->children.size(); ++i) { // move all children
 
2244
            register QObject *object = d->children.at(i);
 
2245
            if (object->isWidgetType()) {
 
2246
                QWidget *w = static_cast<QWidget *>(object);
 
2247
                if (!w->isWindow())
 
2248
                    w->move(w->pos() + pd);
 
2249
            }
 
2250
        }
 
2251
    }
 
2252
 
 
2253
    if (just_update)
 
2254
        return;
 
2255
 
 
2256
    // Don't let the server be bogged-down with repaint events
 
2257
    bool repaint_immediately = (qt_sip_count(this) < 3 && !testAttribute(Qt::WA_WState_InPaintEvent));
 
2258
 
 
2259
    if (dx) {
 
2260
        int x = x2 == sr.x() ? sr.x()+w : sr.x();
 
2261
        if (repaint_immediately)
 
2262
            repaint(x, sr.y(), qAbs(dx), sr.height());
 
2263
        else
 
2264
            XClearArea(dpy, data->winid, x, sr.y(), qAbs(dx), sr.height(), True);
 
2265
    }
 
2266
    if (dy) {
 
2267
        int y = y2 == sr.y() ? sr.y()+h : sr.y();
 
2268
        if (repaint_immediately)
 
2269
            repaint(sr.x(), y, sr.width(), qAbs(dy));
 
2270
        else
 
2271
            XClearArea(dpy, data->winid, sr.x(), y, sr.width(), qAbs(dy), True);
 
2272
    }
 
2273
 
 
2274
    qt_insert_sip(this, dx, dy); // #### ignores r
 
2275
}
 
2276
 
 
2277
/*!
 
2278
    Internal implementation of the virtual QPaintDevice::metric()
 
2279
    function.
 
2280
 
 
2281
    \a m is the metric to get.
 
2282
*/
 
2283
 
 
2284
int QWidget::metric(PaintDeviceMetric m) const
 
2285
{
 
2286
    Q_D(const QWidget);
 
2287
    int val;
 
2288
    if (m == PdmWidth) {
 
2289
        val = data->crect.width();
 
2290
    } else if (m == PdmHeight) {
 
2291
        val = data->crect.height();
 
2292
    } else {
 
2293
        Display *dpy = X11->display;
 
2294
        int scr = d->xinfo.screen();
 
2295
        switch (m) {
 
2296
            case PdmDpiX:
 
2297
            case PdmPhysicalDpiX:
 
2298
                val = QX11Info::appDpiX(scr);
 
2299
                break;
 
2300
            case PdmDpiY:
 
2301
            case PdmPhysicalDpiY:
 
2302
                val = QX11Info::appDpiY(scr);
 
2303
                break;
 
2304
            case PdmWidthMM:
 
2305
                val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
 
2306
                      DisplayWidth(dpy,scr);
 
2307
                break;
 
2308
            case PdmHeightMM:
 
2309
                val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
 
2310
                      DisplayHeight(dpy,scr);
 
2311
                break;
 
2312
            case PdmNumColors:
 
2313
                val = d->xinfo.cells();
 
2314
                break;
 
2315
            case PdmDepth:
 
2316
                val = d->xinfo.depth();
 
2317
                break;
 
2318
            default:
 
2319
                val = 0;
 
2320
                qWarning("QWidget::metric: Invalid metric command");
 
2321
        }
 
2322
    }
 
2323
    return val;
 
2324
}
 
2325
 
 
2326
void QWidgetPrivate::createSysExtra()
 
2327
{
 
2328
    extra->xDndProxy = 0;
 
2329
    extra->children_use_dnd = false;
 
2330
    extra->compress_events = true;
 
2331
}
 
2332
 
 
2333
void QWidgetPrivate::deleteSysExtra()
 
2334
{
 
2335
}
 
2336
 
 
2337
void QWidgetPrivate::createTLSysExtra()
 
2338
{
 
2339
    extra->topextra->iconMask = 0;
 
2340
}
 
2341
 
 
2342
void QWidgetPrivate::deleteTLSysExtra()
 
2343
{
 
2344
    // don't destroy input context here. it will be destroyed in
 
2345
    // QWidget::destroy() destroyInputContext();
 
2346
    delete extra->topextra->iconMask;
 
2347
    extra->topextra->iconMask = 0;
 
2348
}
 
2349
 
 
2350
/*
 
2351
   examine the children of our parent up the tree and set the
 
2352
   children_use_dnd extra data appropriately... this is used to keep DND enabled
 
2353
   for widgets that are reparented and don't have DND enabled, BUT *DO* have
 
2354
   children (or children of children ...) with DND enabled...
 
2355
*/
 
2356
void QWidgetPrivate::checkChildrenDnd()
 
2357
{
 
2358
    Q_Q(QWidget);
 
2359
    QWidget *widget = q;
 
2360
    while (widget && !(widget->windowType() == Qt::Desktop)) {
 
2361
        // note: this isn't done for the desktop widget
 
2362
        bool children_use_dnd = false;
 
2363
        for (int i = 0; i < widget->d_func()->children.size(); ++i) {
 
2364
            const QObject *object = widget->d_func()->children.at(i);
 
2365
            if (object->isWidgetType()) {
 
2366
                const QWidget *child = static_cast<const QWidget *>(object);
 
2367
                children_use_dnd = (children_use_dnd ||
 
2368
                                    child->acceptDrops() ||
 
2369
                                    (child->d_func()->extra &&
 
2370
                                     child->d_func()->extra->children_use_dnd));
 
2371
            }
 
2372
        }
 
2373
 
 
2374
        widget->d_func()->createExtra();
 
2375
        widget->d_func()->extra->children_use_dnd = children_use_dnd;
 
2376
 
 
2377
        widget = widget->parentWidget();
 
2378
    }
 
2379
}
 
2380
 
 
2381
bool QWidgetPrivate::setAcceptDrops_sys(bool on)
 
2382
{
 
2383
    bool ok = X11->dndEnable(q_func(), on);
 
2384
    checkChildrenDnd(); // ## ???
 
2385
    return ok;
 
2386
}
 
2387
 
 
2388
/*!
 
2389
    \overload
 
2390
 
 
2391
    Causes only the parts of the widget which overlap \a region to be
 
2392
    visible. If the region includes pixels outside the rect() of the
 
2393
    widget, window system controls in that area may or may not be
 
2394
    visible, depending on the platform.
 
2395
 
 
2396
    Note that this effect can be slow if the region is particularly
 
2397
    complex.
 
2398
 
 
2399
    \sa setMask(), clearMask()
 
2400
*/
 
2401
 
 
2402
void QWidget::setMask(const QRegion& region)
 
2403
{
 
2404
    Q_D(QWidget);
 
2405
    d->createExtra();
 
2406
    if(QWExtra *extra = d->extraData())
 
2407
        extra->mask = region;
 
2408
 
 
2409
    XShapeCombineRegion(X11->display, winId(), ShapeBounding, 0, 0,
 
2410
                         region.handle(), ShapeSet);
 
2411
}
 
2412
 
 
2413
/*!
 
2414
    Causes only the pixels of the widget for which \a bitmap has a
 
2415
    corresponding 1 bit to be visible. If the region includes pixels
 
2416
    outside the rect() of the widget, window system controls in that
 
2417
    area may or may not be visible, depending on the platform.
 
2418
 
 
2419
    Note that this effect can be slow if the region is particularly
 
2420
    complex.
 
2421
 
 
2422
    \omit
 
2423
    See \c examples/tux for an example of masking for transparency.
 
2424
    \endomit
 
2425
 
 
2426
    The following code shows how an image with an alpha channel can be
 
2427
    used to generate a mask for a widget:
 
2428
 
 
2429
    \quotefromfile snippets/widget-mask/main.cpp
 
2430
    \skipto QLabel
 
2431
    \printuntil setMask
 
2432
 
 
2433
    The label shown by this code is masked using the image it contains,
 
2434
    giving the appearance that an irregularly-shaped image is being drawn
 
2435
    directly onto the screen.
 
2436
 
 
2437
    \sa clearMask()
 
2438
*/
 
2439
 
 
2440
void QWidget::setMask(const QBitmap &bitmap)
 
2441
{
 
2442
    Q_D(QWidget);
 
2443
    d->createExtra();
 
2444
    if(QWExtra *extra = d->extraData())
 
2445
        extra->mask = QRegion(bitmap);
 
2446
 
 
2447
    QBitmap bm = bitmap;
 
2448
    if (bm.x11Info().screen() != d->xinfo.screen())
 
2449
        bm.x11SetScreen(d->xinfo.screen());
 
2450
    XShapeCombineMask(X11->display, winId(), ShapeBounding, 0, 0,
 
2451
                       bm.handle(), ShapeSet);
 
2452
}
 
2453
 
 
2454
/*!
 
2455
    Removes any mask set by setMask().
 
2456
 
 
2457
    \sa setMask()
 
2458
*/
 
2459
 
 
2460
void QWidget::clearMask()
 
2461
{
 
2462
    XShapeCombineMask(X11->display, winId(), ShapeBounding, 0, 0,
 
2463
                       XNone, ShapeSet);
 
2464
}
 
2465
 
 
2466
/*!
 
2467
  \internal
 
2468
 
 
2469
  Computes the frame rectangle when needed.  This is an internal function, you
 
2470
  should never call this.
 
2471
*/
 
2472
 
 
2473
void QWidgetPrivate::updateFrameStrut() const
 
2474
{
 
2475
    Q_Q(const QWidget);
 
2476
    if (! q->isVisible() || (q->windowType() == Qt::Desktop)) {
 
2477
        data.fstrut_dirty = (!q->isVisible());
 
2478
        return;
 
2479
    }
 
2480
 
 
2481
    Atom type_ret;
 
2482
    Window l = q->winId(), w = l, p, r; // target window, it's parent, root
 
2483
    Window *c;
 
2484
    int i_unused;
 
2485
    unsigned int nc;
 
2486
    unsigned char *data_ret;
 
2487
    unsigned long l_unused;
 
2488
 
 
2489
    while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
 
2490
        if (c && nc > 0)
 
2491
            XFree(c);
 
2492
 
 
2493
        if (! p) {
 
2494
            qWarning("QWidget::updateFrameStrut(): ERROR - no parent");
 
2495
            return;
 
2496
        }
 
2497
 
 
2498
        // if the parent window is the root window, an Enlightenment virtual root or
 
2499
        // a NET WM virtual root window, stop here
 
2500
        data_ret = 0;
 
2501
        if (p == r ||
 
2502
            (XGetWindowProperty(X11->display, p,
 
2503
                                ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
 
2504
                                &type_ret, &i_unused, &l_unused, &l_unused,
 
2505
                                &data_ret) == Success &&
 
2506
             type_ret == XA_CARDINAL)) {
 
2507
            if (data_ret)
 
2508
                XFree(data_ret);
 
2509
 
 
2510
            break;
 
2511
        } else if (qt_net_supports(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
 
2512
            int i = 0;
 
2513
            while (X11->net_virtual_root_list[i] != 0) {
 
2514
                if (X11->net_virtual_root_list[i++] == p)
 
2515
                    break;
 
2516
            }
 
2517
        }
 
2518
 
 
2519
        l = w;
 
2520
        w = p;
 
2521
    }
 
2522
 
 
2523
    // we have our window
 
2524
    int transx, transy;
 
2525
    XWindowAttributes wattr;
 
2526
    if (XTranslateCoordinates(X11->display, l, w,
 
2527
                              0, 0, &transx, &transy, &p) &&
 
2528
        XGetWindowAttributes(X11->display, w, &wattr)) {
 
2529
        QTLWExtra *top = topData();
 
2530
        top->fleft = transx;
 
2531
        top->ftop = transy;
 
2532
        top->fright = wattr.width - data.crect.width() - top->fleft;
 
2533
        top->fbottom = wattr.height - data.crect.height() - top->ftop;
 
2534
 
 
2535
        // add the border_width for the window managers frame... some window managers
 
2536
        // do not use a border_width of zero for their frames, and if we the left and
 
2537
        // top strut, we ensure that pos() is absolutely correct.  frameGeometry()
 
2538
        // will still be incorrect though... perhaps i should have foffset as well, to
 
2539
        // indicate the frame offset (equal to the border_width on X).
 
2540
        // - Brad
 
2541
        top->fleft += wattr.border_width;
 
2542
        top->fright += wattr.border_width;
 
2543
        top->ftop += wattr.border_width;
 
2544
        top->fbottom += wattr.border_width;
 
2545
    }
 
2546
 
 
2547
   data.fstrut_dirty = 0;
 
2548
}
 
2549
 
 
2550
void QWidget::setWindowOpacity(qreal)
 
2551
{
 
2552
}
 
2553
 
 
2554
qreal QWidget::windowOpacity() const
 
2555
{
 
2556
    return 1.0;
 
2557
}
 
2558
 
 
2559
/*!
 
2560
    \internal
 
2561
*/
 
2562
const QX11Info &QWidget::x11Info() const
 
2563
{
 
2564
    Q_D(const QWidget);
 
2565
    return d->xinfo;
 
2566
}
 
2567
 
 
2568
void QWidgetPrivate::setWindowRole(const char *role)
 
2569
{
 
2570
    Q_Q(QWidget);
 
2571
    XChangeProperty(X11->display, q->winId(),
 
2572
                    ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
 
2573
                    (unsigned char *)role, qstrlen(role));
 
2574
}
 
2575
 
 
2576
Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
 
2577
QPaintEngine *QWidget::paintEngine() const
 
2578
{
 
2579
    Q_D(const QWidget);
 
2580
    if (qt_widget_paintengine()->isActive()) {
 
2581
        if (d->extraPaintEngine)
 
2582
            return d->extraPaintEngine;
 
2583
        QWidget *self = const_cast<QWidget *>(this);
 
2584
        self->d_func()->extraPaintEngine = new QX11PaintEngine();
 
2585
        return d->extraPaintEngine;
 
2586
    }
 
2587
    return qt_widget_paintengine();
 
2588
}
 
2589
 
 
2590
/*!
 
2591
    Returns the X11 Picture handle of the widget for XRender
 
2592
    support. Use of this function is not portable. This function will
 
2593
    return 0 if XRender support is not compiled into Qt, if the
 
2594
    XRender extension is not supported on the X11 display, or if the
 
2595
    handle could not be created.
 
2596
*/
 
2597
Qt::HANDLE QWidget::x11PictureHandle() const
 
2598
{
 
2599
#ifndef QT_NO_XRENDER
 
2600
    Q_D(const QWidget);
 
2601
    return d->picture;
 
2602
#else
 
2603
    return 0;
 
2604
#endif // QT_NO_XRENDER
 
2605
}