1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the gui module of the Qt Toolkit.
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.
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.
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.
21
** Contact info@trolltech.com if any conditions of this licensing are
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.
27
****************************************************************************/
31
#include "qdesktopwidget.h"
32
#include "qapplication.h"
33
#include "qapplication_p.h"
34
#include "qnamespace.h"
38
#include "qtextcodec.h"
39
#include "qdatetime.h"
42
#include "qcolormap.h"
45
extern bool qt_reuse_double_buffer; // declared in qapplication_x11.cpp
47
#include <private/qpixmap_p.h>
48
#include <private/qpaintengine_x11_p.h>
50
#include "qx11info_x11.h"
54
// defined in qapplication_x11.cpp
55
bool qt_wstate_iconified(WId);
56
void qt_updated_rootinfo();
59
#if !defined(QT_NO_IM)
60
#include "qinputcontext.h"
61
#include "qinputcontextfactory.h"
64
#include "qwidget_p.h"
66
#define XCOORD_MAX 32767
67
#define WRECT_MAX 8191
69
extern bool qt_nograb();
71
static QWidget *mouseGrb = 0;
72
static QWidget *keyboardGrb = 0;
75
int qt_x11_create_desktop_on_screen = -1;
80
ulong flags, functions, decorations;
86
MWM_HINTS_FUNCTIONS = (1L << 0),
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),
95
MWM_HINTS_DECORATIONS = (1L << 1),
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),
105
MWM_HINTS_INPUT_MODE = (1L << 2),
107
MWM_INPUT_FULL_APPLICATION_MODAL = 3L
111
static QtMWMHints GetMWMHints(Display *display, Window window)
117
ulong nitems, bytesLeft;
119
if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
120
ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
122
&& (type == ATOM(_MOTIF_WM_HINTS)
125
mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
128
mwmhints.functions = MWM_FUNC_ALL;
129
mwmhints.decorations = MWM_DECOR_ALL;
130
mwmhints.input_mode = 0L;
131
mwmhints.status = 0L;
141
/*****************************************************************************
142
QWidget member functions
143
*****************************************************************************/
145
extern bool qt_broken_wm;
147
// defined in qapplication_x11.cpp
148
extern bool qt_net_supports(Atom);
150
const uint stdWidgetEventMask = // X event mask
152
KeyPressMask | KeyReleaseMask |
153
ButtonPressMask | ButtonReleaseMask |
155
ButtonMotionMask | PointerMotionMask |
156
EnterWindowMask | LeaveWindowMask |
163
const uint stdDesktopEventMask = // X event mask
166
EnterWindowMask | LeaveWindowMask |
172
The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
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);
189
static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
191
QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
192
X11->sip_list.append(sip);
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;
201
XSendEvent(X11->display, scrolled_widget->winId(), False, NoEventMask,
202
(XEvent*)&client_message);
205
static int qt_sip_count(QWidget* scrolled_widget)
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)
219
static void create_wm_client_leader()
221
if (X11->wm_client_leader) return;
223
X11->wm_client_leader =
224
XCreateSimpleWindow(X11->display,
225
QX11Info::appRootWindow(),
226
0, 0, 1, 1, 0, 0, 0);
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);
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());
245
Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
247
if (w->testAttribute(Qt::WA_SetCursor)) {
248
QCursor *oc = QApplication::overrideCursor();
250
XDefineCursor(X11->display, w->winId(), oc->handle());
251
} else if (w->isEnabled()) {
252
XDefineCursor(X11->display, w->winId(), w->cursor().handle());
254
// enforce the windows behavior of clearing the cursor on
256
XDefineCursor(X11->display, w->winId(), XNone);
259
XDefineCursor(X11->display, w->winId(), XNone);
263
Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
265
QApplication::flush();
269
while (!XCheckTypedWindowEvent(X11->display, w->winId(), ReparentNotify, &ev)) {
270
if (XCheckTypedWindowEvent(X11->display, w->winId(), MapNotify, &ev))
272
if (t.elapsed() > 500)
273
return; // give up, no event available
274
qApp->syncX(); // non-busy wait
276
qApp->x11ProcessEvent(&ev);
277
if (XCheckTypedWindowEvent(X11->display, w->winId(), ConfigureNotify, &ev))
278
qApp->x11ProcessEvent(&ev);
281
static void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
283
if (!w->isVisible()) // not managed by the window manager
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);
301
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
304
Qt::WindowType type = q->windowType();
305
Qt::WindowFlags &flags = data.window_flags;
306
QWidget *parentWidget = q->parentWidget();
308
if (type == Qt::ToolTip)
309
flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
311
bool topLevel = (flags & Qt::Window);
312
bool popup = (type == Qt::Popup);
313
bool dialog = (type == Qt::Dialog
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);
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
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;
337
Window parentw, destroyw = 0;
342
initializeWindow = true;
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;
354
//get display, screen number, root window and desktop geometry for
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);
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);
371
parentw = topLevel ? root_win : parentWidget->winId();
373
XSetWindowAttributes wsa;
375
if (window) { // override the old window
376
if (destroyOldWindow)
377
destroyw = data.winid;
381
XGetWindowAttributes(dpy, window, &a);
382
q->data->crect.setRect(a.x, a.y, a.width, a.height);
384
if (a.map_state == IsUnmapped)
385
q->setAttribute(Qt::WA_WState_Visible, false);
387
q->setAttribute(Qt::WA_WState_Visible);
389
QX11InfoData* xd = xinfo.getX11Data(true);
391
// find which screen the window is on...
392
xd->screen = QX11Info::appScreen(); // by default, use the default :)
394
for (i = 0; i < ScreenCount(dpy); i++) {
395
if (RootWindow(dpy, i) == a.root) {
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
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(),
425
BlackPixel(dpy, xinfo.screen()),
426
WhitePixel(dpy, xinfo.screen()));
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,
440
setWinId(id); // set widget id/handle + hd
443
#ifndef QT_NO_XRENDER
445
XRenderFreePicture(X11->display, picture);
449
if (X11->use_xrender) {
450
picture = XRenderCreatePicture(dpy, id, XRenderFindVisualFormat (dpy, (Visual *) xinfo.visual()), 0, 0);
452
#endif // QT_NO_XRENDER
455
long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
456
int curr_wintype = 0;
460
mwmhints.functions = MWM_FUNC_ALL;
461
mwmhints.decorations = MWM_DECOR_ALL;
462
mwmhints.input_mode = 0L;
463
mwmhints.status = 0L;
469
mwmhints.decorations = 0L;
470
mwmhints.flags |= MWM_HINTS_DECORATIONS;
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);
481
mwmhints.decorations |= MWM_DECOR_BORDER;
482
mwmhints.decorations |= MWM_DECOR_RESIZEH;
484
if (flags & Qt::WindowTitleHint)
485
mwmhints.decorations |= MWM_DECOR_TITLE;
487
if (flags & Qt::WindowSystemMenuHint)
488
mwmhints.decorations |= MWM_DECOR_MENU;
490
if (flags & Qt::WindowMinimizeButtonHint)
491
mwmhints.decorations |= MWM_DECOR_MINIMIZE;
493
if (flags & Qt::WindowMaximizeButtonHint)
494
mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
496
} else if (desktop || popup) {
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);
504
flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
506
} else if (type == Qt::Tool || type == Qt::Drawer) {
507
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
509
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
513
wsa.save_under = True;
514
wsa_mask |= CWSaveUnder;
516
// ### need a better way to do this
517
if (q->inherits("QMenu")) {
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);
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);
533
if (flags & Qt::X11BypassWindowManagerHint) {
534
wsa.override_redirect = True;
535
wsa_mask |= CWOverrideRedirect;
538
if (wsa_mask && initializeWindow)
539
XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
540
} else if (!customize) {
541
flags |= Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint;
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,
552
} else if (topLevel && !desktop) { // top-level widget
553
if (!X11->wm_client_leader)
554
create_wm_client_leader();
557
QWidget *p = parentWidget;
561
if (dialog || tool) {
563
// transient for window
564
XSetTransientForHint(dpy, id, p->winId());
566
// transient for group
567
XSetTransientForHint(dpy, id, X11->wm_client_leader);
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;
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;
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
591
XSetWMProperties(dpy, id, 0, 0, 0, 0, &size_hints, &wm_hints, &class_hint);
593
XResizeWindow(dpy, id, data.crect.width(), data.crect.height());
594
XStoreName(dpy, id, appName.data());
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);
605
if (mwmhints.flags != 0l) {
606
XChangeProperty(dpy, id, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
607
PropModeReplace, (unsigned char *) &mwmhints, 5);
609
XDeleteProperty(dpy, id, ATOM(_MOTIF_WM_HINTS));
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);
617
XDeleteProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE));
620
long curr_pid = getpid();
621
XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
622
(unsigned char *) &curr_pid, 1);
624
// when we create a toplevel widget, the frame strut should be dirty
625
data.fstrut_dirty = 1;
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());
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);
638
// non-toplevel widgets don't have a frame, so no need to
640
data.fstrut_dirty = 0;
643
if (initializeWindow) {
644
// don't erase when resizing
645
wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
646
XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
649
// set X11 event mask
651
// QWidget* main_desktop = find(id);
652
// if (main_desktop->testWFlags(Qt::WPaintDesktop))
653
// XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
655
XSelectInput(dpy, id, stdDesktopEventMask);
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),
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);
677
qt_XDestroyWindow(q, dpy, destroyw);
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
683
if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
686
#if !defined(QT_NO_IM)
693
Frees up window system resources. Destroys the widget window if \a
694
destroyWindow is true.
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.
701
This function is usually called from the QWidget destructor.
704
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
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,
717
if (mouseGrb == this)
719
if (keyboardGrb == this)
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);
728
#ifndef QT_NO_XRENDER
731
XRenderFreePicture(X11->display, d->picture);
734
#endif // QT_NO_XRENDER
736
if ((windowType() == Qt::Desktop)) {
738
X11->dndEnable(this, false);
741
qt_XDestroyWindow(this, X11->display, data->winid);
745
extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp
746
if (testAttribute(Qt::WA_WState_Reparented))
752
// release previous focus information participating with
753
// preedit preservation of qic
754
QInputContext *qic = inputContext();
756
qic->widgetDestroyed(this);
761
void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WFlags f)
764
extern void qPRCreate(const QWidget *, Window);
767
bool setcurs = q->testAttribute(Qt::WA_SetCursor);
769
oldcurs = q->cursor();
773
// dnd unregister (we will register again below)
774
bool accept_drops = q->acceptDrops();
775
q->setAcceptDrops(false);
777
QWidget *oldparent = q->parentWidget();
778
WId old_winid = data.winid;
779
if ((q->windowType() == Qt::Desktop))
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);
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;
796
QObjectPrivate::setParent_helper(parent);
797
bool enable = q->isEnabled(); // remember status
798
Qt::FocusPolicy fp = q->focusPolicy();
800
bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
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);
807
if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
808
q->setAttribute(Qt::WA_WState_Hidden);
809
q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
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)) {
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 :)
835
XUnmapWindow(X11->display, w->winId());
836
XSetTransientForHint(X11->display, w->winId(), q->winId());
837
QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
841
qPRCreate(q, old_winid);
842
updateSystemBackground();
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);
853
q->setGeometry(0, 0, s.width(), s.height());
856
setEnabled_helper(enable); //preserving WA_ForceDisabled
858
q->setFocusPolicy(fp);
859
if (extra && !extra->mask.isEmpty())
860
q->setMask(extra->mask);
862
qt_XDestroyWindow(q, X11->display, old_winid);
864
q->setCursor(oldcurs);
868
oldparent->d_func()->checkChildrenDnd();
871
q->setAcceptDrops(true);
875
X11->dndEnable(q, (extra && extra->children_use_dnd));
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.
885
\sa mapFromGlobal() mapTo() mapToParent()
888
QPoint QWidget::mapToGlobal(const QPoint &pos) const
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);
901
Translates the global screen coordinate \a pos to widget
904
\sa mapToGlobal() mapFrom() mapFromParent()
907
QPoint QWidget::mapFromGlobal(const QPoint &pos) const
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));
918
void QWidgetPrivate::updateSystemBackground()
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
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());
935
XSetWindowBackground(X11->display, q->winId(),
936
QColormap::instance(xinfo.screen()).pixel(brush.color()));
939
void QWidget::setCursor(const QCursor &cursor)
942
if (cursor.shape() != Qt::ArrowCursor
943
|| (d->extra && d->extra->curs)) {
945
delete d->extra->curs;
946
d->extra->curs = new QCursor(cursor);
948
setAttribute(Qt::WA_SetCursor);
949
qt_x11_enforce_cursor(this);
950
XFlush(X11->display);
953
void QWidget::unsetCursor()
957
delete d->extra->curs;
961
setAttribute(Qt::WA_SetCursor, false);
962
qt_x11_enforce_cursor(this);
963
XFlush(X11->display);
966
static XTextProperty*
967
qstring_to_xtp(const QString& s)
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.
979
static const QTextCodec* mapper = QTextCodec::codecForLocale();
982
QByteArray mapped = mapper->fromUnicode(s);
984
tl[0] = mapped.data();
986
errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
987
#if defined(QT_DEBUG)
989
qDebug("qstring_to_xtp result code %d", errCode);
992
if (!mapper || errCode < 0) {
993
static QByteArray qcs;
995
tp.value = (uchar*)qcs.data();
996
tp.encoding = XA_STRING;
998
tp.nitems = qcs.length();
1002
// ### If we knew WM could understand unicode, we could use
1003
// ### a much simpler, cheaper encoding...
1005
tp.value = (XChar2b*)s.unicode();
1006
tp.encoding = XA_UNICODE; // wish
1008
tp.nitems = s.length();
1014
void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
1017
XSetWMName(X11->display, q->winId(), qstring_to_xtp(caption));
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());
1024
void QWidgetPrivate::setWindowIcon_sys()
1027
QTLWExtra *topData = extra->topextra;
1028
if (topData->iconPixmap)
1032
XWMHints *h = XGetWMHints(X11->display, q->winId());
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;
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;
1055
h->flags &= ~(IconPixmapHint | IconMaskHint);
1058
XSetWMHints(X11->display, q->winId(), h);
1063
void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
1066
XSetWMIconName(X11->display, q->winId(), qstring_to_xtp(iconText));
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());
1075
Grabs the mouse input.
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
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.
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
1091
Note that only visible widgets can grab mouse input. If
1092
isVisible() returns false for a widget, that widget cannot call
1095
\sa releaseMouse() grabKeyboard() releaseKeyboard() grabKeyboard()
1099
void QWidget::grabMouse()
1101
if (isVisible() && !qt_nograb()) {
1103
mouseGrb->releaseMouse();
1107
XGrabPointer(X11->display, winId(), False,
1108
(uint)(ButtonPressMask | ButtonReleaseMask |
1109
PointerMotionMask | EnterWindowMask |
1111
GrabModeAsync, GrabModeAsync,
1112
XNone, XNone, X11->time);
1116
status == GrabNotViewable ? "\"GrabNotViewable\"" :
1117
status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1118
status == GrabFrozen ? "\"GrabFrozen\"" :
1119
status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1121
qWarning("Grabbing the mouse failed with %s", s);
1131
Grabs the mouse input and changes the cursor shape.
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().
1137
\warning Grabbing the mouse might lock the terminal.
1139
\sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor()
1142
void QWidget::grabMouse(const QCursor &cursor)
1146
mouseGrb->releaseMouse();
1150
XGrabPointer(X11->display, winId(), False,
1151
(uint)(ButtonPressMask | ButtonReleaseMask |
1152
PointerMotionMask | EnterWindowMask | LeaveWindowMask),
1153
GrabModeAsync, GrabModeAsync,
1154
XNone, cursor.handle(), X11->time);
1158
status == GrabNotViewable ? "\"GrabNotViewable\"" :
1159
status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
1160
status == GrabFrozen ? "\"GrabFrozen\"" :
1161
status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
1163
qWarning("Grabbing the mouse failed with %s", s);
1171
Releases the mouse grab.
1173
\sa grabMouse(), grabKeyboard(), releaseKeyboard()
1176
void QWidget::releaseMouse()
1178
if (!qt_nograb() && mouseGrb == this) {
1179
XUngrabPointer(X11->display, X11->time);
1180
XFlush(X11->display);
1186
Grabs the keyboard input.
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.
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.
1197
If a different widget is currently grabbing keyboard input, that
1198
widget's grab is released first.
1200
\sa releaseKeyboard() grabMouse() releaseMouse() focusWidget()
1203
void QWidget::grabKeyboard()
1207
keyboardGrb->releaseKeyboard();
1208
XGrabKeyboard(X11->display, data->winid, False, GrabModeAsync, GrabModeAsync,
1215
Releases the keyboard grab.
1217
\sa grabKeyboard(), grabMouse(), releaseMouse()
1220
void QWidget::releaseKeyboard()
1222
if (!qt_nograb() && keyboardGrb == this) {
1223
XUngrabKeyboard(X11->display, X11->time);
1230
Returns the widget that is currently grabbing the mouse input.
1232
If no widget in this application is currently grabbing the mouse,
1235
\sa grabMouse(), keyboardGrabber()
1238
QWidget *QWidget::mouseGrabber()
1244
Returns the widget that is currently grabbing the keyboard input.
1246
If no widget in this application is currently grabbing the
1247
keyboard, 0 is returned.
1249
\sa grabMouse(), mouseGrabber()
1252
QWidget *QWidget::keyboardGrabber()
1258
Sets the top-level widget containing this widget to be the active
1261
An active window is a visible top-level window that has the
1262
keyboard input focus.
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.
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.
1277
\sa isActiveWindow(), window(), show()
1280
void QWidget::activateWindow()
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();
1291
void QWidget::update()
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));
1301
void QWidget::update(const QRegion &rgn)
1304
if (isVisible() && updatesEnabled()) {
1305
d->invalidated_region |= (rgn & d->clipRect());
1306
QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
1310
void QWidget::update(const QRect &r)
1313
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
1314
if (w && h && isVisible() && updatesEnabled()) {
1316
w = data->crect.width() - x;
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));
1326
struct QX11DoubleBuffer
1329
MaxWidth = SHRT_MAX,
1330
MaxHeight = SHRT_MAX
1333
Qt::HANDLE hd, picture;
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;
1343
This function can be used to enable/disable the global double
1344
buffering under X11.
1347
Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable)
1349
qt_x11_enable_global_db = enable;
1352
static void qt_discard_double_buffer(QX11DoubleBuffer **db)
1356
XFreePixmap(X11->display, (*db)->hd);
1357
#ifndef QT_NO_XRENDER
1358
if (X11->use_xrender)
1359
XRenderFreePicture(X11->display, (*db)->picture);
1365
void qt_discard_double_buffer()
1367
qt_discard_double_buffer(&qt_x11_global_double_buffer);
1370
static void qt_x11_release_double_buffer(QX11DoubleBuffer **db)
1372
if (*db != qt_x11_global_double_buffer) {
1373
// qDebug("--> discarding temporary double buffer");
1374
qt_discard_double_buffer(db);
1376
// qDebug("--> global double buffer unused");
1377
qt_x11_global_double_buffer_active = false;
1381
static QX11DoubleBuffer *qt_x11_create_double_buffer(Qt::HANDLE hd, int screen, int depth, int width, int height)
1383
QX11DoubleBuffer *db = new QX11DoubleBuffer;
1384
db->hd = XCreatePixmap(X11->display, hd, width, height, depth);
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);
1391
db->screen = screen;
1394
db->height = height;
1399
void qt_x11_get_double_buffer(QX11DoubleBuffer **db, Qt::HANDLE hd, int screen, int depth, int width, int height)
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);
1407
// qDebug("<-- using global double buffer");
1408
qt_x11_global_double_buffer_active = true;
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);
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;
1423
width = qMax(qt_x11_global_double_buffer->width, width);
1424
height = qMax(qt_x11_global_double_buffer->height, height);
1426
qt_discard_double_buffer();
1429
qt_x11_global_double_buffer = *db = qt_x11_create_double_buffer(hd, screen, depth, width, height);
1432
void QWidget::repaint(const QRegion& rgn)
1435
if (!isVisible() || !updatesEnabled() || !testAttribute(Qt::WA_Mapped) || rgn.isEmpty())
1438
if (testAttribute(Qt::WA_WState_InPaintEvent))
1439
qWarning("QWidget::repaint: recursive repaint detected.");
1442
if (!d->invalidated_region.isEmpty())
1443
d->invalidated_region -= rgn;
1445
setAttribute(Qt::WA_WState_InPaintEvent);
1447
QRect br = rgn.boundingRect();
1448
QVector<QRect> rects = rgn.rects();
1449
QRect brWS = d->mapToWS(br);
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);
1458
bool do_system_clip = !double_buffer && (rects.size() > 1 || (br != QRect(0,0,data->crect.width(),data->crect.height())));
1460
Qt::HANDLE old_hd = d->hd;
1461
Qt::HANDLE old_picture = d->picture;
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());
1469
d->hd = qDoubleBuffer->hd;
1470
d->picture = qDoubleBuffer->picture;
1471
redirectionOffset = br.topLeft();
1473
redirectionOffset = data->wrect.topLeft();
1476
if (!redirectionOffset.isNull())
1477
QPainter::setRedirected(this, this, redirectionOffset);
1479
QPaintEngine *engine = paintEngine();
1481
if (engine && do_system_clip) {
1482
if (redirectionOffset.isNull()) {
1483
engine->setSystemClip(rgn);
1485
QRegion redirectedRegion(rgn);
1486
redirectedRegion.translate(-redirectionOffset);
1487
engine->setSystemClip(redirectedRegion);
1493
&& !testAttribute(Qt::WA_NoBackground)
1494
&& !testAttribute(Qt::WA_NoSystemBackground)) {
1495
d->composeBackground(br);
1500
QApplication::sendSpontaneousEvent(this, &e);
1502
if (engine && do_system_clip)
1503
engine->setSystemClip(QRegion());
1505
if (!redirectionOffset.isNull())
1506
QPainter::restoreRedirected(this);
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(),
1519
XFreeGC(d->xinfo.display(), gc);
1522
d->picture = old_picture;
1524
qt_x11_release_double_buffer(&qDoubleBuffer);
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);
1534
// Clean out the temporary engine if used...
1535
if (d->extraPaintEngine) {
1536
delete d->extraPaintEngine;
1537
d->extraPaintEngine = 0;
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");
1544
if (testAttribute(Qt::WA_ContentsPropagated))
1545
d->updatePropagatedBackground(&rgn);
1548
void QWidget::setWindowState(Qt::WindowStates newstate)
1551
bool needShow = false;
1552
Qt::WindowStates oldstate = windowState();
1553
if (oldstate == newstate)
1556
// Ensure the initial size is valid, since we store it as normalGeometry below.
1557
if (!testAttribute(Qt::WA_Resized) && !isVisible())
1560
QTLWExtra *top = d->topData();
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();
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;
1586
if (top->normalGeometry.width() < 0)
1587
top->normalGeometry = normalGeometry;
1589
// restore original geometry
1590
setGeometry(top->normalGeometry);
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));
1602
needShow = isVisible();
1604
if (newstate & Qt::WindowFullScreen) {
1605
d->updateFrameStrut();
1606
const QRect normalGeometry = geometry();
1607
const QPoint fullScreenOffset = QPoint(top->fleft, top->ftop);
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;
1615
if (top->normalGeometry.width() < 0) {
1616
top->normalGeometry = normalGeometry;
1617
top->fullScreenOffset = fullScreenOffset;
1620
setParent(0, top->savedFlags);
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;
1633
// restore original geometry
1634
setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
1635
-top->fullScreenOffset.y(),
1636
-top->fullScreenOffset.x(),
1637
-top->fullScreenOffset.y()));
1643
if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
1645
if (newstate & Qt::WindowMinimized) {
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);
1661
setAttribute(Qt::WA_Mapped);
1662
XMapWindow(X11->display, winId());
1670
data->window_state = newstate;
1675
if (newstate & Qt::WindowActive)
1678
QWindowStateChangeEvent e(oldstate);
1679
QApplication::sendEvent(this, &e);
1684
Platform-specific part of QWidget::show().
1687
void QWidgetPrivate::show_sys()
1690
if (q->isWindow()) {
1691
XWMHints *h = XGetWMHints(X11->display, q->winId());
1693
bool got_hints = h != 0;
1698
h->initial_state = q->isMinimized() ? IconicState : NormalState;
1699
h->flags |= StateHint;
1700
XSetWMHints(X11->display, q->winId(), h);
1704
// update _MOTIF_WM_HINTS
1705
QtMWMHints mwmhints = GetMWMHints(X11->display, q->winId());
1707
if (q->testAttribute(Qt::WA_ShowModal)) {
1708
mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
1709
mwmhints.flags |= MWM_HINTS_INPUT_MODE;
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
1722
mwmhints.functions &= ~MWM_FUNC_RESIZE;
1725
mwmhints.flags |= MWM_HINTS_DECORATIONS;
1726
if (mwmhints.decorations == MWM_DECOR_ALL) {
1727
mwmhints.decorations = (MWM_DECOR_BORDER
1731
| MWM_DECOR_MINIMIZE
1732
| MWM_DECOR_MAXIMIZE);
1734
mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
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);
1743
XDeleteProperty(X11->display, q->winId(), ATOM(_MOTIF_WM_HINTS));
1746
// set _NET_WM_STATE
1747
Atom net_winstates[6] = { 0, 0, 0, 0, 0, 0 };
1748
int curr_winstate = 0;
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);
1755
if (q->isFullScreen()) {
1756
net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_FULLSCREEN);
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);
1762
if (q->testAttribute(Qt::WA_ShowModal)) {
1763
net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MODAL);
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);
1770
XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_STATE));
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);
1779
if (!topData()->embedded
1780
&& topData()->parentWinId
1781
&& topData()->parentWinId != QX11Info::appRootWindow(xinfo.screen())
1782
&& !q->isMinimized()) {
1783
X11->deferred_map.append(q);
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);
1793
// if the wm was not smart enough to adjust our size, do that manually
1795
QRect maxRect = QApplication::desktop()->availableGeometry(q);
1797
QTLWExtra *top = topData();
1798
QRect normalRect = top->normalGeometry;
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);
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;
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);
1820
if (q->testAttribute(Qt::WA_OutsideWSRange))
1822
q->setAttribute(Qt::WA_Mapped);
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());
1831
XMapWindow(X11->display, q->winId());
1837
Platform-specific part of QWidget::hide().
1840
void QWidgetPrivate::hide_sys()
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());
1849
QTLWExtra *top = topData();
1850
data.crect.moveTopLeft(QPoint(data.crect.x() - top->fleft,
1851
data.crect.y() - top->ftop));
1853
// zero the frame strut and mark it dirty
1854
top->fleft = top->fright = top->ftop = top->fbottom = 0;
1855
data.fstrut_dirty = true;
1857
XFlush(X11->display);
1859
q->setAttribute(Qt::WA_Mapped, false);
1860
if (q->winId()) // in nsplugin, may be 0
1861
XUnmapWindow(X11->display, q->winId());
1865
void QWidgetPrivate::raise_sys()
1868
XRaiseWindow(X11->display, q->winId());
1871
void QWidgetPrivate::lower_sys()
1874
XLowerWindow(X11->display, q->winId());
1877
void QWidgetPrivate::stackUnder_sys(QWidget* w)
1881
stack[0] = w->winId();;
1882
stack[1] = q->winId();
1883
XRestackWindows(X11->display, stack, 2);
1887
static void do_size_hints(QWidget* widget, QWExtra *x)
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);
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);
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;
1917
if (x->topextra && x->topextra->uspos) {
1918
// user (i.e. command-line) specified position
1919
s.flags |= USPosition;
1920
s.flags |= PPosition;
1922
if (x->topextra && x->topextra->ussize) {
1923
// user (i.e. command-line) specified size
1928
s.flags |= PWinGravity;
1929
s.win_gravity = NorthWestGravity;
1930
XSetWMNormalHints(X11->display, widget->winId(), &s);
1935
Helper function for non-toplevel widgets. Helps to map Qt's 32bit
1936
coordinate system to X11's 16bit coordinate system.
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
1942
Maintains data.wrect, which is the geometry of the X widget,
1943
measured in this widget's coordinate system.
1945
if the parent is not clipped, parentWRect is empty, otherwise
1946
parentWRect is the geometry of the parent's X rect, measured in
1949
void QWidgetPrivate::setWSGeometry(bool dontShow)
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).
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);
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;
1967
QRect parentWRect = q->parentWidget()->data->wrect;
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;
1974
//translate from parent's to my Qt coord sys
1975
wrect.translate(-data.crect.topLeft());
1977
//translate from parent's Qt coords to parent's X coords
1978
xrect.translate(-parentWRect.topLeft());
1981
// parent is not clipped, we may or may not have to clip
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
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)) {
1993
xrect.translate(data.crect.topLeft());
1994
XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
1999
if (!validRange.contains(xrect)) {
2000
// we are too big, and must clip
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.
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);
2016
XUnmapWindow(dpy, data.winid);
2017
q->setAttribute(Qt::WA_Mapped, false);
2018
} else if (!q->isHidden()) {
2026
bool jump = (data.wrect != wrect);
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);
2037
w->d_func()->setWSGeometry(jump);
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());
2048
//to avoid flicker, we have to show children after the helper widget has moved
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);
2064
XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
2066
if (mapWindow && !dontShow) {
2067
q->setAttribute(Qt::WA_Mapped);
2068
XMapWindow(dpy, data.winid);
2072
void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
2075
Display *dpy = X11->display;
2077
if ((q->windowType() == Qt::Desktop))
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);
2089
uint s = data.window_state;
2090
s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
2091
data.window_state = s;
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);
2099
QPoint oldPos(q->pos());
2100
QSize oldSize(q->size());
2101
QRect oldGeom(data.crect);
2102
QRect r(x, y, w, h);
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)
2110
bool isResize = q->size() != oldSize;
2112
if (q->isWindow()) {
2114
topData()->uspos = 1;
2116
topData()->ussize = 1;
2117
do_size_hints(q, extra);
2120
// pos() is right according to ICCCM 4.1.5
2121
XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
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);
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);
2138
// work around 4Dwm's incompliance with ICCCM 4.1.5
2139
QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
2140
QApplication::sendEvent(q, &e);
2144
// set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
2145
q->setAttribute(Qt::WA_WState_ConfigPending);
2147
QResizeEvent e(q->size(), oldSize);
2148
QApplication::sendEvent(q, &e);
2151
if (isMove && q->pos() != oldPos)
2152
q->setAttribute(Qt::WA_PendingMoveEvent, true);
2154
q->setAttribute(Qt::WA_PendingResizeEvent, true);
2158
void QWidgetPrivate::setConstraints_sys()
2161
do_size_hints(q, extra);
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.
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).
2177
\sa QScrollView bitBlt()
2180
void QWidget::scroll(int dx, int dy)
2182
scroll(dx, dy, QRect());
2188
This version only scrolls \a r and does not move the children of
2191
If \a r is empty or invalid, the result is undefined.
2193
\sa QScrollView bitBlt()
2195
void QWidget::scroll(int dx, int dy, const QRect& r)
2198
if (!updatesEnabled() && children().size() == 0)
2200
bool valid_rect = r.isValid();
2201
bool just_update = qAbs(dx) > width() || qAbs(dy) > height();
2202
QRect sr = valid_rect ? r : d->clipRect();
2205
} else if (!valid_rect){
2206
d->invalidated_region.translate(dx, dy);
2209
int x1, y1, x2, y2, w = sr.width(), h = sr.height();
2229
if (dx == 0 && dy == 0)
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);
2241
if (!valid_rect && !d->children.isEmpty()) { // scroll children
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);
2248
w->move(w->pos() + pd);
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));
2260
int x = x2 == sr.x() ? sr.x()+w : sr.x();
2261
if (repaint_immediately)
2262
repaint(x, sr.y(), qAbs(dx), sr.height());
2264
XClearArea(dpy, data->winid, x, sr.y(), qAbs(dx), sr.height(), True);
2267
int y = y2 == sr.y() ? sr.y()+h : sr.y();
2268
if (repaint_immediately)
2269
repaint(sr.x(), y, sr.width(), qAbs(dy));
2271
XClearArea(dpy, data->winid, sr.x(), y, sr.width(), qAbs(dy), True);
2274
qt_insert_sip(this, dx, dy); // #### ignores r
2278
Internal implementation of the virtual QPaintDevice::metric()
2281
\a m is the metric to get.
2284
int QWidget::metric(PaintDeviceMetric m) const
2288
if (m == PdmWidth) {
2289
val = data->crect.width();
2290
} else if (m == PdmHeight) {
2291
val = data->crect.height();
2293
Display *dpy = X11->display;
2294
int scr = d->xinfo.screen();
2297
case PdmPhysicalDpiX:
2298
val = QX11Info::appDpiX(scr);
2301
case PdmPhysicalDpiY:
2302
val = QX11Info::appDpiY(scr);
2305
val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
2306
DisplayWidth(dpy,scr);
2309
val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
2310
DisplayHeight(dpy,scr);
2313
val = d->xinfo.cells();
2316
val = d->xinfo.depth();
2320
qWarning("QWidget::metric: Invalid metric command");
2326
void QWidgetPrivate::createSysExtra()
2328
extra->xDndProxy = 0;
2329
extra->children_use_dnd = false;
2330
extra->compress_events = true;
2333
void QWidgetPrivate::deleteSysExtra()
2337
void QWidgetPrivate::createTLSysExtra()
2339
extra->topextra->iconMask = 0;
2342
void QWidgetPrivate::deleteTLSysExtra()
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;
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...
2356
void QWidgetPrivate::checkChildrenDnd()
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));
2374
widget->d_func()->createExtra();
2375
widget->d_func()->extra->children_use_dnd = children_use_dnd;
2377
widget = widget->parentWidget();
2381
bool QWidgetPrivate::setAcceptDrops_sys(bool on)
2383
bool ok = X11->dndEnable(q_func(), on);
2384
checkChildrenDnd(); // ## ???
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.
2396
Note that this effect can be slow if the region is particularly
2399
\sa setMask(), clearMask()
2402
void QWidget::setMask(const QRegion& region)
2406
if(QWExtra *extra = d->extraData())
2407
extra->mask = region;
2409
XShapeCombineRegion(X11->display, winId(), ShapeBounding, 0, 0,
2410
region.handle(), ShapeSet);
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.
2419
Note that this effect can be slow if the region is particularly
2423
See \c examples/tux for an example of masking for transparency.
2426
The following code shows how an image with an alpha channel can be
2427
used to generate a mask for a widget:
2429
\quotefromfile snippets/widget-mask/main.cpp
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.
2440
void QWidget::setMask(const QBitmap &bitmap)
2444
if(QWExtra *extra = d->extraData())
2445
extra->mask = QRegion(bitmap);
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);
2455
Removes any mask set by setMask().
2460
void QWidget::clearMask()
2462
XShapeCombineMask(X11->display, winId(), ShapeBounding, 0, 0,
2469
Computes the frame rectangle when needed. This is an internal function, you
2470
should never call this.
2473
void QWidgetPrivate::updateFrameStrut() const
2476
if (! q->isVisible() || (q->windowType() == Qt::Desktop)) {
2477
data.fstrut_dirty = (!q->isVisible());
2482
Window l = q->winId(), w = l, p, r; // target window, it's parent, root
2486
unsigned char *data_ret;
2487
unsigned long l_unused;
2489
while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
2494
qWarning("QWidget::updateFrameStrut(): ERROR - no parent");
2498
// if the parent window is the root window, an Enlightenment virtual root or
2499
// a NET WM virtual root window, stop here
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)) {
2511
} else if (qt_net_supports(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
2513
while (X11->net_virtual_root_list[i] != 0) {
2514
if (X11->net_virtual_root_list[i++] == p)
2523
// we have our window
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;
2532
top->fright = wattr.width - data.crect.width() - top->fleft;
2533
top->fbottom = wattr.height - data.crect.height() - top->ftop;
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).
2541
top->fleft += wattr.border_width;
2542
top->fright += wattr.border_width;
2543
top->ftop += wattr.border_width;
2544
top->fbottom += wattr.border_width;
2547
data.fstrut_dirty = 0;
2550
void QWidget::setWindowOpacity(qreal)
2554
qreal QWidget::windowOpacity() const
2562
const QX11Info &QWidget::x11Info() const
2568
void QWidgetPrivate::setWindowRole(const char *role)
2571
XChangeProperty(X11->display, q->winId(),
2572
ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
2573
(unsigned char *)role, qstrlen(role));
2576
Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
2577
QPaintEngine *QWidget::paintEngine() const
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;
2587
return qt_widget_paintengine();
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.
2597
Qt::HANDLE QWidget::x11PictureHandle() const
2599
#ifndef QT_NO_XRENDER
2604
#endif // QT_NO_XRENDER