00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qevent.h"
00025 #include "qwidget.h"
00026 #include "qdesktopwidget.h"
00027 #include "qapplication.h"
00028 #include "qapplication_p.h"
00029 #include "qnamespace.h"
00030 #include "qpainter.h"
00031 #include "qbitmap.h"
00032 #include "qlayout.h"
00033 #include "qtextcodec.h"
00034 #include "qdatetime.h"
00035 #include "qcursor.h"
00036 #include "qstack.h"
00037 #include "qcolormap.h"
00038 #include "qdebug.h"
00039 #include "private/qbackingstore_p.h"
00040
00041 extern bool qt_reuse_double_buffer;
00042 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
00043
00044 #include <private/qpixmap_p.h>
00045 #include <private/qpaintengine_x11_p.h>
00046 #include "qt_x11_p.h"
00047 #include "qx11info_x11.h"
00048
00049 #include <stdlib.h>
00050
00051
00052 bool qt_wstate_iconified(WId);
00053 void qt_updated_rootinfo();
00054
00055
00056 #if !defined(QT_NO_IM)
00057 #include "qinputcontext.h"
00058 #include "qinputcontextfactory.h"
00059 #endif
00060
00061 #include "qwidget_p.h"
00062
00063 #define XCOORD_MAX 16383
00064 #define WRECT_MAX 8191
00065
00066 extern bool qt_nograb();
00067
00068 static QWidget *mouseGrb = 0;
00069 static QWidget *keyboardGrb = 0;
00070
00071
00072 int qt_x11_create_desktop_on_screen = -1;
00073
00074
00075
00076 struct QtMWMHints {
00077 ulong flags, functions, decorations;
00078 long input_mode;
00079 ulong status;
00080 };
00081
00082 enum {
00083 MWM_HINTS_FUNCTIONS = (1L << 0),
00084
00085 MWM_FUNC_ALL = (1L << 0),
00086 MWM_FUNC_RESIZE = (1L << 1),
00087 MWM_FUNC_MOVE = (1L << 2),
00088 MWM_FUNC_MINIMIZE = (1L << 3),
00089 MWM_FUNC_MAXIMIZE = (1L << 4),
00090 MWM_FUNC_CLOSE = (1L << 5),
00091
00092 MWM_HINTS_DECORATIONS = (1L << 1),
00093
00094 MWM_DECOR_ALL = (1L << 0),
00095 MWM_DECOR_BORDER = (1L << 1),
00096 MWM_DECOR_RESIZEH = (1L << 2),
00097 MWM_DECOR_TITLE = (1L << 3),
00098 MWM_DECOR_MENU = (1L << 4),
00099 MWM_DECOR_MINIMIZE = (1L << 5),
00100 MWM_DECOR_MAXIMIZE = (1L << 6),
00101
00102 MWM_HINTS_INPUT_MODE = (1L << 2),
00103
00104 MWM_INPUT_MODELESS = 0L,
00105 MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
00106 MWM_INPUT_FULL_APPLICATION_MODAL = 3L
00107 };
00108
00109
00110 static QtMWMHints GetMWMHints(Display *display, Window window)
00111 {
00112 QtMWMHints mwmhints;
00113
00114 Atom type;
00115 int format;
00116 ulong nitems, bytesLeft;
00117 uchar *data = 0;
00118 if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false,
00119 ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft,
00120 &data) == Success)
00121 && (type == ATOM(_MOTIF_WM_HINTS)
00122 && format == 32
00123 && nitems >= 5)) {
00124 mwmhints = *(reinterpret_cast<QtMWMHints *>(data));
00125 } else {
00126 mwmhints.flags = 0L;
00127 mwmhints.functions = MWM_FUNC_ALL;
00128 mwmhints.decorations = MWM_DECOR_ALL;
00129 mwmhints.input_mode = 0L;
00130 mwmhints.status = 0L;
00131 }
00132
00133 if (data)
00134 XFree(data);
00135
00136 return mwmhints;
00137 }
00138
00139 static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints)
00140 {
00141 if (mwmhints.flags != 0l) {
00142 XChangeProperty(display, window, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32,
00143 PropModeReplace, (unsigned char *) &mwmhints, 5);
00144 } else {
00145 XDeleteProperty(display, window, ATOM(_MOTIF_WM_HINTS));
00146 }
00147 }
00148
00149
00150 static inline bool isTransient(const QWidget *w)
00151 {
00152 return ((w->windowType() == Qt::Dialog)
00153 || (w->windowType() == Qt::Sheet)
00154 || (w->windowFlags() & Qt::MSWindowsFixedSizeDialogHint)
00155 || (w->windowType() == Qt::Tool)
00156 || (w->windowType() == Qt::SplashScreen)
00157 || (w->windowType() == Qt::ToolTip)
00158 || (w->windowType() == Qt::Drawer));
00159 }
00160
00161 static void do_size_hints(QWidget* widget, QWExtra *x);
00162
00163
00164
00165
00166
00167 extern bool qt_broken_wm;
00168
00169
00170 extern bool qt_net_supports(Atom);
00171
00172 const uint stdWidgetEventMask =
00173 (uint)(
00174 KeyPressMask | KeyReleaseMask |
00175 ButtonPressMask | ButtonReleaseMask |
00176 KeymapStateMask |
00177 ButtonMotionMask | PointerMotionMask |
00178 EnterWindowMask | LeaveWindowMask |
00179 FocusChangeMask |
00180 ExposureMask |
00181 PropertyChangeMask |
00182 StructureNotifyMask
00183 );
00184
00185 const uint stdDesktopEventMask =
00186 (uint)(
00187 KeymapStateMask |
00188 EnterWindowMask | LeaveWindowMask |
00189 PropertyChangeMask
00190 );
00191
00192
00193
00194
00195
00196
00197 Window qt_XCreateWindow(const QWidget *creator,
00198 Display *display, Window parent,
00199 int x, int y, uint w, uint h,
00200 int borderwidth, int depth,
00201 uint windowclass, Visual *visual,
00202 ulong valuemask, XSetWindowAttributes *attributes);
00203 Window qt_XCreateSimpleWindow(const QWidget *creator,
00204 Display *display, Window parent,
00205 int x, int y, uint w, uint h, int borderwidth,
00206 ulong border, ulong background);
00207 void qt_XDestroyWindow(const QWidget *destroyer,
00208 Display *display, Window window);
00209
00210
00211 static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy)
00212 {
00213 QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy };
00214 X11->sip_list.append(sip);
00215
00216 XClientMessageEvent client_message;
00217 client_message.type = ClientMessage;
00218 client_message.window = scrolled_widget->internalWinId();
00219 client_message.format = 32;
00220 client_message.message_type = ATOM(_QT_SCROLL_DONE);
00221 client_message.data.l[0] = sip.id;
00222
00223 XSendEvent(X11->display, scrolled_widget->internalWinId(), False, NoEventMask,
00224 (XEvent*)&client_message);
00225 }
00226
00227 static int qt_sip_count(QWidget* scrolled_widget)
00228 {
00229 int sips=0;
00230
00231 for (int i = 0; i < X11->sip_list.size(); ++i) {
00232 const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
00233 if (sip.scrolled_widget == scrolled_widget)
00234 sips++;
00235 }
00236
00237 return sips;
00238 }
00239
00240 static void create_wm_client_leader()
00241 {
00242 if (X11->wm_client_leader) return;
00243
00244 X11->wm_client_leader =
00245 XCreateSimpleWindow(X11->display,
00246 QX11Info::appRootWindow(),
00247 0, 0, 1, 1, 0, 0, 0);
00248
00249
00250 XChangeProperty(X11->display,
00251 X11->wm_client_leader, ATOM(WM_CLIENT_LEADER),
00252 XA_WINDOW, 32, PropModeReplace,
00253 (unsigned char *)&X11->wm_client_leader, 1);
00254
00255 #ifndef QT_NO_SESSIONMANAGER
00256
00257 QByteArray session = qApp->sessionId().toLatin1();
00258 if (!session.isEmpty()) {
00259 XChangeProperty(X11->display,
00260 X11->wm_client_leader, ATOM(SM_CLIENT_ID),
00261 XA_STRING, 8, PropModeReplace,
00262 (unsigned char *)session.data(), session.size());
00263 }
00264 #endif
00265 }
00266
00267
00268 Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
00269 {
00270 if (!w->testAttribute(Qt::WA_WState_Created))
00271 return;
00272 if (w->testAttribute(Qt::WA_SetCursor)) {
00273 QCursor *oc = QApplication::overrideCursor();
00274 if (oc) {
00275 XDefineCursor(X11->display, w->internalWinId(), oc->handle());
00276 } else if (w->isEnabled()) {
00277 XDefineCursor(X11->display, w->internalWinId(), w->cursor().handle());
00278 } else {
00279
00280
00281 XDefineCursor(X11->display, w->internalWinId(), XNone);
00282 }
00283 } else {
00284 XDefineCursor(X11->display, w->internalWinId(), XNone);
00285 }
00286 }
00287
00288 Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
00289 {
00290 QApplication::flush();
00291 XEvent ev;
00292 QTime t;
00293 t.start();
00294 Q_ASSERT(w->testAttribute(Qt::WA_WState_Created));
00295 while (!XCheckTypedWindowEvent(X11->display, w->internalWinId(), ReparentNotify, &ev)) {
00296 if (XCheckTypedWindowEvent(X11->display, w->internalWinId(), MapNotify, &ev))
00297 break;
00298 if (t.elapsed() > 500)
00299 return;
00300 qApp->syncX();
00301 }
00302 qApp->x11ProcessEvent(&ev);
00303 if (XCheckTypedWindowEvent(X11->display, w->internalWinId(), ConfigureNotify, &ev))
00304 qApp->x11ProcessEvent(&ev);
00305 }
00306
00307 static void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
00308 {
00309 if (!w->isVisible())
00310 return;
00311
00312 XEvent e;
00313 e.xclient.type = ClientMessage;
00314 e.xclient.message_type = ATOM(_NET_WM_STATE);
00315 e.xclient.display = X11->display;
00316 e.xclient.window = w->internalWinId();
00317 e.xclient.format = 32;
00318 e.xclient.data.l[0] = set ? 1 : 0;
00319 e.xclient.data.l[1] = one;
00320 e.xclient.data.l[2] = two;
00321 e.xclient.data.l[3] = 0;
00322 e.xclient.data.l[4] = 0;
00323 XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()),
00324 false, (SubstructureNotifyMask | SubstructureRedirectMask), &e);
00325 }
00326
00327 void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
00328 {
00329 Q_Q(QWidget);
00330 Qt::WindowType type = q->windowType();
00331 Qt::WindowFlags flags = data.window_flags;
00332 QWidget *parentWidget = q->parentWidget();
00333
00334 if (type == Qt::ToolTip)
00335 flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint;
00336
00337 bool topLevel = (flags & Qt::Window);
00338 bool popup = (type == Qt::Popup);
00339 bool dialog = (type == Qt::Dialog
00340 || type == Qt::Sheet
00341 || (flags & Qt::MSWindowsFixedSizeDialogHint));
00342 bool desktop = (type == Qt::Desktop);
00343 bool tool = (type == Qt::Tool || type == Qt::SplashScreen
00344 || type == Qt::ToolTip || type == Qt::Drawer);
00345
00346 if (topLevel) {
00347 if (parentWidget) {
00348 QWidget *ptl = parentWidget->window();
00349 if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint))
00350 flags |= Qt::WindowStaysOnTopHint;
00351 }
00352
00353 if (type == Qt::SplashScreen) {
00354 if (qt_net_supports(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) {
00355 flags &= ~Qt::X11BypassWindowManagerHint;
00356 } else {
00357 flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint;
00358 }
00359 }
00360
00361 if (flags & (Qt::WindowMinimizeButtonHint
00362 | Qt::WindowMaximizeButtonHint
00363 | Qt::WindowContextHelpButtonHint))
00364 flags |= Qt::WindowSystemMenuHint;
00365 }
00366
00367
00368 Window parentw, destroyw = 0;
00369 WId id;
00370
00371
00372 if (!window)
00373 initializeWindow = true;
00374
00375 if (desktop &&
00376 qt_x11_create_desktop_on_screen >= 0 &&
00377 qt_x11_create_desktop_on_screen != xinfo.screen()) {
00378
00379 QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen];
00380 xinfo.setX11Data(xd);
00381 } else if (parentWidget && parentWidget->d_func()->xinfo.screen() != xinfo.screen()) {
00382 xinfo = parentWidget->d_func()->xinfo;
00383 }
00384
00385
00386
00387 Display *dpy = X11->display;
00388 int scr = xinfo.screen();
00389 Window root_win = RootWindow(dpy, scr);
00390 int sw = DisplayWidth(dpy,scr);
00391 int sh = DisplayHeight(dpy,scr);
00392
00393 if (desktop) {
00394 dialog = popup = false;
00395 data.crect.setRect(0, 0, sw, sh);
00396 } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) {
00397 data.crect.setSize(QSize(sw/2, 4*sh/10));
00398 }
00399
00400 parentw = topLevel ? root_win : parentWidget->internalWinId();
00401
00402 XSetWindowAttributes wsa;
00403
00404 if (window) {
00405 if (destroyOldWindow)
00406 destroyw = data.winid;
00407 id = window;
00408 setWinId(window);
00409 XWindowAttributes a;
00410 XGetWindowAttributes(dpy, window, &a);
00411 data.crect.setRect(a.x, a.y, a.width, a.height);
00412
00413 if (a.map_state == IsUnmapped)
00414 q->setAttribute(Qt::WA_WState_Visible, false);
00415 else
00416 q->setAttribute(Qt::WA_WState_Visible);
00417
00418 QX11InfoData* xd = xinfo.getX11Data(true);
00419
00420
00421 xd->screen = QX11Info::appScreen();
00422 int i;
00423 for (i = 0; i < ScreenCount(dpy); i++) {
00424 if (RootWindow(dpy, i) == a.root) {
00425 xd->screen = i;
00426 break;
00427 }
00428 }
00429
00430 xd->depth = a.depth;
00431 xd->cells = DisplayCells(dpy, xd->screen);
00432 xd->visual = a.visual;
00433 xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) ==
00434 XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo.screen())));
00435 xd->colormap = a.colormap;
00436 xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo.screen()));
00437 xinfo.setX11Data(xd);
00438 } else if (desktop) {
00439 #ifdef QWIDGET_EXTRA_DEBUG
00440 qDebug() << "create desktop";
00441 #endif
00442 id = (WId)parentw;
00443
00444
00445
00446
00447
00448
00449 setWinId(id);
00450
00451 } else {
00452 #ifdef QWIDGET_EXTRA_DEBUG
00453 static int topLevels = 0;
00454 static int children = 0;
00455 if (parentw == root_win)
00456 qDebug() << "create toplevel" << ++topLevels;
00457 else
00458 qDebug() << "create child" << ++children;
00459 #endif
00460 QRect safeRect = data.crect;
00461 if (safeRect.width() < 1|| safeRect.height() < 1)
00462 safeRect = QRect(-1000,-1000,1,1);
00463 if (xinfo.defaultVisual() && xinfo.defaultColormap()) {
00464 id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw,
00465 safeRect.left(), safeRect.top(),
00466 safeRect.width(), safeRect.height(),
00467 0,
00468 BlackPixel(dpy, xinfo.screen()),
00469 WhitePixel(dpy, xinfo.screen()));
00470 } else {
00471 wsa.background_pixel = WhitePixel(dpy, xinfo.screen());
00472 wsa.border_pixel = BlackPixel(dpy, xinfo.screen());
00473 wsa.colormap = xinfo.colormap();
00474 id = (WId)qt_XCreateWindow(q, dpy, parentw,
00475 safeRect.left(), safeRect.top(),
00476 safeRect.width(), safeRect.height(),
00477 0, xinfo.depth(), InputOutput,
00478 (Visual *) xinfo.visual(),
00479 CWBackPixel|CWBorderPixel|CWColormap,
00480 &wsa);
00481 }
00482
00483 setWinId(id);
00484 }
00485
00486 #ifndef QT_NO_XRENDER
00487 if (picture) {
00488 XRenderFreePicture(X11->display, picture);
00489 picture = 0;
00490 }
00491
00492 if (X11->use_xrender) {
00493 XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual());
00494 if (format)
00495 picture = XRenderCreatePicture(dpy, id, format, 0, 0);
00496 }
00497 #endif // QT_NO_XRENDER
00498
00499
00500 long net_wintypes[7] = { 0, 0, 0, 0, 0, 0, 0 };
00501 int curr_wintype = 0;
00502
00503 QtMWMHints mwmhints;
00504 mwmhints.flags = 0L;
00505 mwmhints.functions = MWM_FUNC_ALL;
00506 mwmhints.decorations = MWM_DECOR_ALL;
00507 mwmhints.input_mode = 0L;
00508 mwmhints.status = 0L;
00509
00510 if (topLevel) {
00511 ulong wsa_mask = 0;
00512 if (type == Qt::SplashScreen) {
00513 net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_SPLASH);
00514 } else {
00515 mwmhints.decorations = 0L;
00516 mwmhints.flags |= MWM_HINTS_DECORATIONS;
00517
00518 if (flags & Qt::FramelessWindowHint) {
00519
00520 net_wintypes[curr_wintype++] = ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE);
00521 } else {
00522 mwmhints.decorations |= MWM_DECOR_BORDER;
00523 mwmhints.decorations |= MWM_DECOR_RESIZEH;
00524
00525 if (flags & Qt::WindowTitleHint)
00526 mwmhints.decorations |= MWM_DECOR_TITLE;
00527
00528 if (flags & Qt::WindowSystemMenuHint)
00529 mwmhints.decorations |= MWM_DECOR_MENU;
00530
00531 if (flags & Qt::WindowMinimizeButtonHint)
00532 mwmhints.decorations |= MWM_DECOR_MINIMIZE;
00533
00534 if (flags & Qt::WindowMaximizeButtonHint)
00535 mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
00536 }
00537 }
00538
00539 if (tool) {
00540 wsa.save_under = True;
00541 wsa_mask |= CWSaveUnder;
00542 }
00543
00544 if (q->inherits("QMenu")) {
00545
00546 net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_MENU);
00547 } else if (q->inherits("QToolBar")) {
00548
00549 net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
00550 } else if (type == Qt::Tool || type == Qt::Drawer) {
00551
00552 net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
00553 }
00554
00555 if (dialog)
00556 net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
00557
00558 net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_NORMAL);
00559
00560 if (flags & Qt::X11BypassWindowManagerHint) {
00561 wsa.override_redirect = True;
00562 wsa_mask |= CWOverrideRedirect;
00563 }
00564
00565 if (wsa_mask && initializeWindow)
00566 XChangeWindowAttributes(dpy, id, wsa_mask, &wsa);
00567 }
00568
00569
00570 if (!initializeWindow) {
00571
00572 } else if (popup) {
00573 wsa.override_redirect = True;
00574 wsa.save_under = True;
00575 XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
00576 &wsa);
00577 } else if (topLevel && !desktop) {
00578 if (!X11->wm_client_leader)
00579 create_wm_client_leader();
00580
00581
00582
00583 XSizeHints size_hints;
00584 size_hints.flags = USSize | PSize | PWinGravity;
00585 size_hints.x = data.crect.left();
00586 size_hints.y = data.crect.top();
00587 size_hints.width = data.crect.width();
00588 size_hints.height = data.crect.height();
00589 size_hints.win_gravity =
00590 QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
00591
00592 XWMHints wm_hints;
00593 wm_hints.flags = InputHint | StateHint | WindowGroupHint;
00594 wm_hints.input = True;
00595 wm_hints.initial_state = NormalState;
00596 wm_hints.window_group = X11->wm_client_leader;
00597
00598 XClassHint class_hint;
00599 QByteArray appName = qAppName().toLatin1();
00600 class_hint.res_name = appName.data();
00601 class_hint.res_class = const_cast<char *>(QX11Info::appClass());
00602
00603 XSetWMProperties(dpy, id, 0, 0, 0, 0, &size_hints, &wm_hints, &class_hint);
00604
00605 XResizeWindow(dpy, id,
00606 qBound(1, data.crect.width(), XCOORD_MAX),
00607 qBound(1, data.crect.height(), XCOORD_MAX));
00608 XStoreName(dpy, id, appName.data());
00609 Atom protocols[4];
00610 int n = 0;
00611 protocols[n++] = ATOM(WM_DELETE_WINDOW);
00612 protocols[n++] = ATOM(WM_TAKE_FOCUS);
00613 protocols[n++] = ATOM(_NET_WM_PING);
00614 if (flags & Qt::WindowContextHelpButtonHint)
00615 protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
00616 XSetWMProtocols(dpy, id, protocols, n);
00617
00618
00619 SetMWMHints(dpy, id, mwmhints);
00620
00621
00622 if (curr_wintype > 0)
00623 XChangeProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, PropModeReplace,
00624 (unsigned char *) net_wintypes, curr_wintype);
00625 else
00626 XDeleteProperty(dpy, id, ATOM(_NET_WM_WINDOW_TYPE));
00627
00628
00629 long curr_pid = getpid();
00630 XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace,
00631 (unsigned char *) &curr_pid, 1);
00632
00633
00634 data.fstrut_dirty = 1;
00635
00636
00637 QByteArray objName = q->objectName().toLocal8Bit();
00638 XChangeProperty(dpy, id,
00639 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
00640 (unsigned char *)objName.constData(), objName.length());
00641
00642
00643 XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
00644 XA_WINDOW, 32, PropModeReplace,
00645 (unsigned char *)&X11->wm_client_leader, 1);
00646 } else {
00647
00648
00649 data.fstrut_dirty = 0;
00650 }
00651
00652 if (initializeWindow) {
00653
00654 wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
00655 XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
00656 }
00657
00658
00659 if (desktop) {
00660
00661
00662
00663
00664 XSelectInput(dpy, id, stdDesktopEventMask);
00665 } else {
00666 XSelectInput(dpy, id, stdWidgetEventMask);
00667 #if !defined (QT_NO_TABLET)
00668 QTabletDeviceDataList *tablet_list = qt_tablet_devices();
00669 for (int i = 0; i < tablet_list->size(); ++i) {
00670 QTabletDeviceData tablet = tablet_list->at(i);
00671 XSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList),
00672 tablet.eventCount);
00673 }
00674 #endif
00675 }
00676
00677 if (desktop) {
00678 q->setAttribute(Qt::WA_WState_Visible);
00679 } else if (topLevel) {
00680 q->setAttribute(Qt::WA_SetCursor);
00681 if (initializeWindow) {
00682 qt_x11_enforce_cursor(q);
00683
00684 if (QTLWExtra *topData = maybeTopData())
00685 setWindowTitle_helper(topData->caption);
00686
00687 X11->dndEnable(q, true);
00688
00689 if (maybeTopData() && maybeTopData()->opacity != 255)
00690 q->setWindowOpacity(maybeTopData()->opacity/255.);
00691
00692 }
00693 } else {
00694 if (q->testAttribute(Qt::WA_SetCursor))
00695 qt_x11_enforce_cursor(q);
00696 }
00697
00698 if (extra && !extra->mask.isEmpty())
00699 XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0,
00700 extra->mask.handle(), ShapeSet);
00701
00702 if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) {
00703 QInputContext *inputContext = q->inputContext();
00704 if (inputContext)
00705 inputContext->setFocusWidget(q);
00706 }
00707
00708 if (destroyw)
00709 qt_XDestroyWindow(q, dpy, destroyw);
00710
00711
00712
00713
00714
00715 if (!topLevel && !parentWidget->data->wrect.topLeft().isNull())
00716 setWSGeometry();
00717 }
00718
00731 void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
00732 {
00733 Q_D(QWidget);
00734 if (!isWindow() && parentWidget())
00735 parentWidget()->d_func()->invalidateBuffer(geometry());
00736 d->deactivateWidgetCleanup();
00737 if (testAttribute(Qt::WA_WState_Created)) {
00738 setAttribute(Qt::WA_WState_Created, false);
00739 QObjectList childList = children();
00740 for (int i = 0; i < childList.size(); ++i) {
00741 register QObject *obj = childList.at(i);
00742 if (obj->isWidgetType())
00743 static_cast<QWidget*>(obj)->destroy(destroySubWindows,
00744 destroySubWindows);
00745 }
00746 if (mouseGrb == this)
00747 releaseMouse();
00748 if (keyboardGrb == this)
00749 releaseKeyboard();
00750 if (isWindow())
00751 X11->deferred_map.removeAll(this);
00752 if (isModal()) {
00753
00754 QApplicationPrivate::leaveModal(this);
00755 }
00756 else if ((windowType() == Qt::Popup))
00757 qApp->d_func()->closePopup(this);
00758
00759 #ifndef QT_NO_XRENDER
00760 if (d->picture) {
00761 if (destroyWindow)
00762 XRenderFreePicture(X11->display, d->picture);
00763 d->picture = 0;
00764 }
00765 #endif // QT_NO_XRENDER
00766
00767 if ((windowType() == Qt::Desktop)) {
00768 if (acceptDrops())
00769 X11->dndEnable(this, false);
00770 } else {
00771 if (destroyWindow)
00772 qt_XDestroyWindow(this, X11->display, data->winid);
00773 }
00774 d->setWinId(0);
00775
00776 extern void qPRCleanup(QWidget *widget);
00777 if (testAttribute(Qt::WA_WState_Reparented))
00778 qPRCleanup(this);
00779
00780 if(d->ic) {
00781 delete d->ic;
00782 } else {
00783
00784
00785 QInputContext *qic = inputContext();
00786 if (qic)
00787 qic->widgetDestroyed(this);
00788 }
00789 }
00790 }
00791
00792 void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
00793 {
00794 Q_Q(QWidget);
00795 QTLWExtra *topData = maybeTopData();
00796 bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
00797 if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
00798 q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
00799 extern void qPRCreate(const QWidget *, Window);
00800 QCursor oldcurs;
00801
00802
00803 if (q->testAttribute(Qt::WA_DropSiteRegistered))
00804 q->setAttribute(Qt::WA_DropSiteRegistered, false);
00805
00806
00807
00808 if (q->isWindow() && wasCreated)
00809 X11->dndEnable(q, false);
00810
00811
00812 WId old_winid = wasCreated ? data.winid : 0;
00813 if ((q->windowType() == Qt::Desktop))
00814 old_winid = 0;
00815 setWinId(0);
00816
00817 #ifndef QT_NO_XRENDER
00818 if (picture) {
00819 XRenderFreePicture(X11->display, picture);
00820 picture = 0;
00821 }
00822 #endif
00823
00824
00825 if (wasCreated) {
00826 XUnmapWindow(X11->display, old_winid);
00827 XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0);
00828 }
00829 if (topData) {
00830 topData->parentWinId = 0;
00831
00832 topData->frameStrut.setCoords(0, 0, 0, 0);
00833
00834
00835 topData->waitingForMapNotify = 0;
00836 topData->validWMState = 0;
00837 }
00838 data.fstrut_dirty = (!parent || (f & Qt::Window));
00839
00840 QObjectPrivate::setParent_helper(parent);
00841 bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
00842
00843 data.window_flags = f;
00844 q->setAttribute(Qt::WA_WState_Created, false);
00845 q->setAttribute(Qt::WA_WState_Visible, false);
00846 q->setAttribute(Qt::WA_WState_Hidden, false);
00847 adjustFlags(data.window_flags, q);
00848
00849
00850 if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
00851 createWinId();
00852 if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
00853 q->setAttribute(Qt::WA_WState_Hidden);
00854 q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
00855
00856 if (wasCreated) {
00857 QObjectList chlist = q->children();
00858 for (int i = 0; i < chlist.size(); ++i) {
00859 QObject *obj = chlist.at(i);
00860 if (obj->isWidgetType()) {
00861 QWidget *w = (QWidget *)obj;
00862 if (!w->testAttribute(Qt::WA_WState_Created))
00863 continue;
00864 if (xinfo.screen() != w->d_func()->xinfo.screen()) {
00865
00866
00867 w->d_func()->parent = 0;
00868 w->setParent(q);
00869 } else if (!w->isWindow()) {
00870 w->d_func()->invalidateBuffer(w->rect());
00871 XReparentWindow(X11->display, w->internalWinId(), q->internalWinId(),
00872 w->geometry().x(), w->geometry().y());
00873 } else if (isTransient(w)) {
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 XUnmapWindow(X11->display, w->internalWinId());
00886 QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest));
00887 }
00888 }
00889
00890 }
00891 qPRCreate(q, old_winid);
00892 updateSystemBackground();
00893
00894
00895 if (old_winid)
00896 qt_XDestroyWindow(q, X11->display, old_winid);
00897
00898 }
00899
00900
00901
00902 if (q->testAttribute(Qt::WA_AcceptDrops)
00903 || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) {
00904 q->setAttribute(Qt::WA_DropSiteRegistered, true);
00905 }
00906 #if !defined(QT_NO_IM)
00907 ic = 0;
00908 #endif
00909 invalidateBuffer(q->rect());
00910 }
00911
00920 QPoint QWidget::mapToGlobal(const QPoint &pos) const
00921 {
00922 Q_D(const QWidget);
00923 if (!testAttribute(Qt::WA_WState_Created)) {
00924 QPoint p = pos + data->crect.topLeft();
00925
00926 return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
00927 }
00928 int x, y;
00929 Window child;
00930 QPoint p = d->mapToWS(pos);
00931 XTranslateCoordinates(X11->display, internalWinId(),
00932 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
00933 p.x(), p.y(), &x, &y, &child);
00934 return QPoint(x, y);
00935 }
00936
00944 QPoint QWidget::mapFromGlobal(const QPoint &pos) const
00945 {
00946 Q_D(const QWidget);
00947 if (!testAttribute(Qt::WA_WState_Created)) {
00948
00949 QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
00950 return p - data->crect.topLeft();
00951 }
00952 int x, y;
00953 Window child;
00954 XTranslateCoordinates(X11->display,
00955 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
00956 internalWinId(), pos.x(), pos.y(), &x, &y, &child);
00957 return d->mapFromWS(QPoint(x, y));
00958 }
00959
00960 void QWidgetPrivate::updateSystemBackground()
00961 {
00962 Q_Q(QWidget);
00963 if (!q->testAttribute(Qt::WA_WState_Created))
00964 return;
00965 QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole());
00966 Qt::WindowType type = q->windowType();
00967 if (brush.style() == Qt::NoBrush
00968 || q->testAttribute(Qt::WA_NoSystemBackground)
00969 || q->testAttribute(Qt::WA_UpdatesDisabled)
00970 || type == Qt::Popup || type == Qt::ToolTip
00971 )
00972 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
00973 else if (brush.style() == Qt::SolidPattern && brush.isOpaque())
00974 XSetWindowBackground(X11->display, q->internalWinId(),
00975 QColormap::instance(xinfo.screen()).pixel(brush.color()));
00976 else if (isBackgroundInherited())
00977 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative);
00978 else if (brush.style() == Qt::TexturePattern)
00979 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(),
00980 brush.texture().data->x11ConvertToDefaultDepth());
00981 else
00982 XSetWindowBackground(X11->display, q->internalWinId(),
00983 QColormap::instance(xinfo.screen()).pixel(brush.color()));
00984 }
00985
00986 void QWidgetPrivate::setCursor_sys(const QCursor &)
00987 {
00988 Q_Q(QWidget);
00989 qt_x11_enforce_cursor(q);
00990 XFlush(X11->display);
00991 }
00992
00993 void QWidgetPrivate::unsetCursor_sys()
00994 {
00995 Q_Q(QWidget);
00996 qt_x11_enforce_cursor(q);
00997 XFlush(X11->display);
00998 }
00999
01000 static XTextProperty*
01001 qstring_to_xtp(const QString& s)
01002 {
01003 static XTextProperty tp = { 0, 0, 0, 0 };
01004 static bool free_prop = true;
01005
01006 if (tp.value) {
01007 if (free_prop)
01008 XFree(tp.value);
01009 tp.value = 0;
01010 free_prop = true;
01011 }
01012
01013 static const QTextCodec* mapper = QTextCodec::codecForLocale();
01014 int errCode = 0;
01015 if (mapper) {
01016 QByteArray mapped = mapper->fromUnicode(s);
01017 char* tl[2];
01018 tl[0] = mapped.data();
01019 tl[1] = 0;
01020 errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp);
01021 #if defined(QT_DEBUG)
01022 if (errCode < 0)
01023 qDebug("qstring_to_xtp result code %d", errCode);
01024 #endif
01025 }
01026 if (!mapper || errCode < 0) {
01027 static QByteArray qcs;
01028 qcs = s.toAscii();
01029 tp.value = (uchar*)qcs.data();
01030 tp.encoding = XA_STRING;
01031 tp.format = 8;
01032 tp.nitems = qcs.length();
01033 free_prop = false;
01034 }
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045 return &tp;
01046 }
01047
01048 void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
01049 {
01050 Q_Q(QWidget);
01051 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01052 XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption));
01053
01054 QByteArray net_wm_name = caption.toUtf8();
01055 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
01056 PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
01057 }
01058
01059 void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
01060 {
01061 Q_Q(QWidget);
01062 if (!q->testAttribute(Qt::WA_WState_Created))
01063 return;
01064 QTLWExtra *topData = this->topData();
01065 if (topData->iconPixmap && !forceReset)
01066
01067 return;
01068
01069 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
01070 XWMHints wm_hints;
01071 if (!h) {
01072 h = &wm_hints;
01073 h->flags = 0;
01074 }
01075
01076 QIcon icon = q->windowIcon();
01077 QSize size = icon.actualSize(QSize(64, 64));
01078 if (!icon.isNull() && !size.isEmpty()) {
01079 QPixmap pixmap = icon.pixmap(size);
01080
01081
01082 QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
01083 QVector<long> icon_data(2 + image.width()*image.height());
01084
01085 icon_data[0] = image.width();
01086 icon_data[1] = image.height();
01087
01088 if (sizeof(long) == sizeof(quint32)) {
01089 memcpy(icon_data.data() + 2, image.scanLine(0), image.numBytes());
01090 } else {
01091 for (int y = 0; y < image.height(); ++y) {
01092 uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y));
01093 for (int x = 0; x < image.width(); ++x)
01094 icon_data[2 + y*image.width() + x] = scanLine[x];
01095 }
01096 }
01097
01098 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
01099 PropModeReplace, (unsigned char *) icon_data.data(),
01100 icon_data.size());
01101
01102
01103
01104
01105
01106
01107 if (!QX11Info::appDefaultVisual(xinfo.screen())
01108 || !QX11Info::appDefaultColormap(xinfo.screen())) {
01109
01110 if (!forceReset || !topData->iconPixmap)
01111 topData->iconPixmap = new QBitmap(pixmap);
01112 h->icon_pixmap = topData->iconPixmap->handle();
01113 } else {
01114
01115
01116 if (!forceReset || !topData->iconPixmap)
01117 topData->iconPixmap = new QPixmap(pixmap);
01118 h->icon_pixmap = topData->iconPixmap->data->x11ConvertToDefaultDepth();
01119 }
01120 h->flags |= IconPixmapHint;
01121
01122 QBitmap mask = topData->iconPixmap->mask();
01123 if (!mask.isNull()) {
01124 if (!topData->iconMask)
01125 topData->iconMask = new QBitmap;
01126 *topData->iconMask = mask;
01127 h->icon_mask = topData->iconMask->handle();
01128 h->flags |= IconMaskHint;
01129 }
01130 } else {
01131 h->flags &= ~(IconPixmapHint | IconMaskHint);
01132 }
01133
01134 XSetWMHints(X11->display, q->internalWinId(), h);
01135 if (h != &wm_hints)
01136 XFree((char *)h);
01137 }
01138
01139 void QWidgetPrivate::setWindowIconText_sys(const QString &iconText)
01140 {
01141 Q_Q(QWidget);
01142 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01143 XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText));
01144
01145 QByteArray icon_name = iconText.toUtf8();
01146 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8,
01147 PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size());
01148 }
01149
01150
01176 void QWidget::grabMouse()
01177 {
01178 if (isVisible() && !qt_nograb()) {
01179 if (mouseGrb)
01180 mouseGrb->releaseMouse();
01181 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
01182 #ifndef QT_NO_DEBUG
01183 int status =
01184 #endif
01185 XGrabPointer(X11->display, internalWinId(), False,
01186 (uint)(ButtonPressMask | ButtonReleaseMask |
01187 PointerMotionMask | EnterWindowMask |
01188 LeaveWindowMask),
01189 GrabModeAsync, GrabModeAsync,
01190 XNone, XNone, X11->time);
01191 #ifndef QT_NO_DEBUG
01192 if (status) {
01193 const char *s =
01194 status == GrabNotViewable ? "\"GrabNotViewable\"" :
01195 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
01196 status == GrabFrozen ? "\"GrabFrozen\"" :
01197 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
01198 "<?>";
01199 qWarning("QWidget::grabMouse: Failed with %s", s);
01200 }
01201 #endif
01202 mouseGrb = this;
01203 }
01204 }
01205
01220 void QWidget::grabMouse(const QCursor &cursor)
01221 {
01222 if (!qt_nograb()) {
01223 if (mouseGrb)
01224 mouseGrb->releaseMouse();
01225 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
01226 #ifndef QT_NO_DEBUG
01227 int status =
01228 #endif
01229 XGrabPointer(X11->display, internalWinId(), False,
01230 (uint)(ButtonPressMask | ButtonReleaseMask |
01231 PointerMotionMask | EnterWindowMask | LeaveWindowMask),
01232 GrabModeAsync, GrabModeAsync,
01233 XNone, cursor.handle(), X11->time);
01234 #ifndef QT_NO_DEBUG
01235 if (status) {
01236 const char *s =
01237 status == GrabNotViewable ? "\"GrabNotViewable\"" :
01238 status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" :
01239 status == GrabFrozen ? "\"GrabFrozen\"" :
01240 status == GrabInvalidTime ? "\"GrabInvalidTime\"" :
01241 "<?>";
01242 qWarning("QWidget::grabMouse: Failed with %s", s);
01243 }
01244 #endif
01245 mouseGrb = this;
01246 }
01247 }
01248
01255 void QWidget::releaseMouse()
01256 {
01257 if (!qt_nograb() && mouseGrb == this) {
01258 XUngrabPointer(X11->display, X11->time);
01259 XFlush(X11->display);
01260 mouseGrb = 0;
01261 }
01262 }
01263
01282 void QWidget::grabKeyboard()
01283 {
01284 if (!qt_nograb()) {
01285 if (keyboardGrb)
01286 keyboardGrb->releaseKeyboard();
01287 XGrabKeyboard(X11->display, data->winid, False, GrabModeAsync, GrabModeAsync,
01288 X11->time);
01289 keyboardGrb = this;
01290 }
01291 }
01292
01299 void QWidget::releaseKeyboard()
01300 {
01301 if (!qt_nograb() && keyboardGrb == this) {
01302 XUngrabKeyboard(X11->display, X11->time);
01303 keyboardGrb = 0;
01304 }
01305 }
01306
01307
01317 QWidget *QWidget::mouseGrabber()
01318 {
01319 return mouseGrb;
01320 }
01321
01331 QWidget *QWidget::keyboardGrabber()
01332 {
01333 return keyboardGrb;
01334 }
01335
01359 void QWidget::activateWindow()
01360 {
01361 Q_D(QWidget);
01362 QWidget *tlw = window();
01363 if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) {
01364 XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time);
01365 d->focusInputContext();
01366 }
01367 }
01368
01369 void QWidgetPrivate::dirtyWidget_sys(const QRegion &rgn)
01370 {
01371 Q_Q(QWidget);
01372 if (!rgn.isEmpty()) {
01373 dirtyOnScreen += rgn;
01374 QApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
01375 }
01376 }
01377
01378 void QWidgetPrivate::cleanWidget_sys(const QRegion& rgn)
01379 {
01380 dirtyOnScreen -= rgn;
01381 }
01382
01383 void QWidget::setWindowState(Qt::WindowStates newstate)
01384 {
01385 Q_D(QWidget);
01386 bool needShow = false;
01387 Qt::WindowStates oldstate = windowState();
01388 if (oldstate == newstate)
01389 return;
01390 if (isWindow()) {
01391
01392 if (!testAttribute(Qt::WA_Resized) && !isVisible())
01393 adjustSize();
01394
01395 QTLWExtra *top = d->topData();
01396
01397 if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
01398 if (qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
01399 && qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) {
01400 if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen))
01401 top->normalGeometry = geometry();
01402 qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized),
01403 ATOM(_NET_WM_STATE_MAXIMIZED_HORZ),
01404 ATOM(_NET_WM_STATE_MAXIMIZED_VERT));
01405 } else if (! (newstate & Qt::WindowFullScreen)) {
01406 if (newstate & Qt::WindowMaximized) {
01407
01408 const QRect normalGeometry = geometry();
01409
01410 if (isVisible()) {
01411 data->fstrut_dirty = true;
01412 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
01413 const QRect r = top->normalGeometry;
01414 const QRect fs = d->frameStrut();
01415 setGeometry(maxRect.x() + fs.left(),
01416 maxRect.y() + fs.top(),
01417 maxRect.width() - fs.left() - fs.right(),
01418 maxRect.height() - fs.top() - fs.bottom());
01419 top->normalGeometry = r;
01420 }
01421
01422 if (top->normalGeometry.width() < 0)
01423 top->normalGeometry = normalGeometry;
01424 } else {
01425
01426 setGeometry(top->normalGeometry);
01427 }
01428 }
01429 }
01430
01431 if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
01432 if (qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN))) {
01433 if (newstate & Qt::WindowFullScreen)
01434 top->normalGeometry = geometry();
01435 qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen),
01436 ATOM(_NET_WM_STATE_FULLSCREEN));
01437 } else {
01438 needShow = isVisible();
01439
01440 if (newstate & Qt::WindowFullScreen) {
01441 data->fstrut_dirty = true;
01442 const QRect normalGeometry = geometry();
01443 const QPoint fullScreenOffset = d->frameStrut().topLeft();
01444
01445 top->savedFlags = windowFlags();
01446 setParent(0, Qt::Window | Qt::FramelessWindowHint);
01447 const QRect r = top->normalGeometry;
01448 setGeometry(qApp->desktop()->screenGeometry(this));
01449 top->normalGeometry = r;
01450
01451 if (top->normalGeometry.width() < 0) {
01452 top->normalGeometry = normalGeometry;
01453 top->fullScreenOffset = fullScreenOffset;
01454 }
01455 } else {
01456 setParent(0, top->savedFlags);
01457
01458 if (newstate & Qt::WindowMaximized) {
01459
01460 data->fstrut_dirty = true;
01461 const QRect maxRect = QApplication::desktop()->availableGeometry(this);
01462 const QRect r = top->normalGeometry;
01463 const QRect fs = d->frameStrut();
01464 setGeometry(maxRect.x() + fs.left(),
01465 maxRect.y() + fs.top(),
01466 maxRect.width() - fs.left() - fs.right(),
01467 maxRect.height() - fs.top() - fs.bottom());
01468 top->normalGeometry = r;
01469 } else {
01470
01471 setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(),
01472 -top->fullScreenOffset.y(),
01473 -top->fullScreenOffset.x(),
01474 -top->fullScreenOffset.y()));
01475 }
01476 }
01477 }
01478 }
01479
01480 createWinId();
01481 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
01482 if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
01483 if (isVisible()) {
01484 if (newstate & Qt::WindowMinimized) {
01485 XEvent e;
01486 e.xclient.type = ClientMessage;
01487 e.xclient.message_type = ATOM(WM_CHANGE_STATE);
01488 e.xclient.display = X11->display;
01489 e.xclient.window = data->winid;
01490 e.xclient.format = 32;
01491 e.xclient.data.l[0] = IconicState;
01492 e.xclient.data.l[1] = 0;
01493 e.xclient.data.l[2] = 0;
01494 e.xclient.data.l[3] = 0;
01495 e.xclient.data.l[4] = 0;
01496 XSendEvent(X11->display,
01497 RootWindow(X11->display,d->xinfo.screen()),
01498 False, (SubstructureNotifyMask|SubstructureRedirectMask), &e);
01499 } else {
01500 setAttribute(Qt::WA_Mapped);
01501 XMapWindow(X11->display, internalWinId());
01502 }
01503 }
01504
01505 needShow = false;
01506 }
01507 }
01508
01509 data->window_state = newstate;
01510
01511 if (needShow)
01512 show();
01513
01514 if (newstate & Qt::WindowActive)
01515 activateWindow();
01516
01517 QWindowStateChangeEvent e(oldstate);
01518 QApplication::sendEvent(this, &e);
01519 }
01520
01526 void QWidgetPrivate::show_sys()
01527 {
01528 Q_Q(QWidget);
01529 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01530 if (q->isWindow()) {
01531 XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
01532 XWMHints wm_hints;
01533 bool got_hints = h != 0;
01534 if (!got_hints) {
01535 h = &wm_hints;
01536 h->flags = 0;
01537 }
01538 h->initial_state = q->isMinimized() ? IconicState : NormalState;
01539 h->flags |= StateHint;
01540 XSetWMHints(X11->display, q->internalWinId(), h);
01541 if (got_hints)
01542 XFree((char *)h);
01543
01544
01545 do_size_hints(q, extra);
01546
01547
01548 if (isTransient(q)) {
01549 QWidget *p = q->parentWidget();
01550 if (p)
01551 p = p->window();
01552 if (p) {
01553
01554 XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
01555 } else {
01556
01557 XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
01558 }
01559 }
01560
01561
01562 QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId());
01563
01564 if (data.window_modality != Qt::NonModal) {
01565 switch (data.window_modality) {
01566 case Qt::WindowModal:
01567 mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
01568 break;
01569 case Qt::ApplicationModal:
01570 default:
01571 mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
01572 break;
01573 }
01574 mwmhints.flags |= MWM_HINTS_INPUT_MODE;
01575 } else {
01576 mwmhints.input_mode = MWM_INPUT_MODELESS;
01577 mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
01578 }
01579
01580 if (q->minimumSize() == q->maximumSize()) {
01581
01582
01583 mwmhints.flags |= MWM_HINTS_FUNCTIONS;
01584 if (mwmhints.functions == MWM_FUNC_ALL) {
01585 mwmhints.functions = (MWM_FUNC_MOVE
01586 | MWM_FUNC_MINIMIZE
01587 | MWM_FUNC_MAXIMIZE
01588 | MWM_FUNC_CLOSE);
01589 } else {
01590 mwmhints.functions &= ~MWM_FUNC_RESIZE;
01591 }
01592
01593 mwmhints.flags |= MWM_HINTS_DECORATIONS;
01594 if (mwmhints.decorations == MWM_DECOR_ALL) {
01595 mwmhints.decorations = (MWM_DECOR_BORDER
01596 | MWM_DECOR_TITLE
01597 | MWM_DECOR_MENU
01598 | MWM_DECOR_MINIMIZE
01599 | MWM_DECOR_MAXIMIZE);
01600 } else {
01601 mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
01602 }
01603 }
01604
01605 SetMWMHints(X11->display, q->internalWinId(), mwmhints);
01606
01607
01608 Atom net_winstates[6] = { 0, 0, 0, 0, 0, 0 };
01609 int curr_winstate = 0;
01610
01611 Qt::WindowFlags flags = q->windowFlags();
01612 if (flags & Qt::WindowStaysOnTopHint) {
01613 net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_ABOVE);
01614 net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_STAYS_ON_TOP);
01615 }
01616 if (q->isFullScreen()) {
01617 net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_FULLSCREEN);
01618 }
01619 if (q->isMaximized()) {
01620 net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
01621 net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
01622 }
01623 if (data.window_modality != Qt::NonModal) {
01624 net_winstates[curr_winstate++] = ATOM(_NET_WM_STATE_MODAL);
01625 }
01626
01627 if (curr_winstate > 0) {
01628 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE), XA_ATOM,
01629 32, PropModeReplace, (unsigned char *) net_winstates, curr_winstate);
01630 } else {
01631 XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE));
01632 }
01633
01634
01635 if (X11->userTime != CurrentTime) {
01636 XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_USER_TIME), XA_CARDINAL,
01637 32, PropModeReplace, (unsigned char *) &X11->userTime, 1);
01638 }
01639
01640 if (!topData()->embedded
01641 && (topData()->validWMState || topData()->waitingForMapNotify)
01642 && !q->isMinimized()) {
01643 X11->deferred_map.append(q);
01644 return;
01645 }
01646
01647 if (q->isMaximized() && !q->isFullScreen()
01648 && !(qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
01649 && qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) {
01650 XMapWindow(X11->display, q->internalWinId());
01651 data.fstrut_dirty = true;
01652 qt_x11_wait_for_window_manager(q);
01653
01654
01655 QRect maxRect = QApplication::desktop()->availableGeometry(q);
01656
01657 QTLWExtra *top = topData();
01658 QRect normalRect = top->normalGeometry;
01659 const QRect fs = frameStrut();
01660
01661 q->setGeometry(maxRect.x() + fs.left(),
01662 maxRect.y() + fs.top(),
01663 maxRect.width() - fs.left() - fs.right(),
01664 maxRect.height() - fs.top() - fs.bottom());
01665
01666
01667 top->normalGeometry = normalRect;
01668
01669 data.window_state = data.window_state | Qt::WindowMaximized;
01670 q->setAttribute(Qt::WA_Mapped);
01671 return;
01672 }
01673
01674 if (q->isFullScreen() && !qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN))) {
01675 XMapWindow(X11->display, q->internalWinId());
01676 qt_x11_wait_for_window_manager(q);
01677 q->setAttribute(Qt::WA_Mapped);
01678 return;
01679 }
01680 }
01681
01682 invalidateBuffer(q->rect());
01683
01684 if (q->testAttribute(Qt::WA_OutsideWSRange))
01685 return;
01686 q->setAttribute(Qt::WA_Mapped);
01687 if (q->isWindow())
01688 topData()->waitingForMapNotify = 1;
01689
01690 if (!q->isWindow()
01691 && (!q->autoFillBackground()
01692 || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) {
01693 XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone);
01694 XMapWindow(X11->display, q->internalWinId());
01695 updateSystemBackground();
01696 return;
01697 }
01698 XMapWindow(X11->display, q->internalWinId());
01699
01700
01701 if (X11->startupId && q->isWindow()) {
01702 QByteArray message("remove: ID=");
01703 message.append(X11->startupId);
01704 sendStartupMessage(message.constData());
01705 X11->startupId = 0;
01706 }
01707 }
01708
01714 void QWidgetPrivate::sendStartupMessage(const char *message) const
01715 {
01716 Q_Q(const QWidget);
01717
01718 if (!message)
01719 return;
01720
01721 XEvent xevent;
01722 xevent.xclient.type = ClientMessage;
01723 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN);
01724 xevent.xclient.display = X11->display;
01725 xevent.xclient.window = q->internalWinId();
01726 xevent.xclient.format = 8;
01727
01728 Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display));
01729 uint sent = 0;
01730 uint length = strlen(message) + 1;
01731 do {
01732 if (sent == 20)
01733 xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO);
01734
01735 for (uint i = 0; i < 20 && i + sent <= length; i++)
01736 xevent.xclient.data.b[i] = message[i + sent++];
01737
01738 XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent);
01739 } while (sent <= length);
01740 }
01741
01742
01748 void QWidgetPrivate::hide_sys()
01749 {
01750 Q_Q(QWidget);
01751 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01752 deactivateWidgetCleanup();
01753 if (q->isWindow()) {
01754 X11->deferred_map.removeAll(q);
01755 if (q->internalWinId())
01756 XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen());
01757
01758 if (QTLWExtra *x = maybeTopData()) {
01759 const QRect fs = x->frameStrut;
01760 data.crect.moveTopLeft(QPoint(data.crect.x() - fs.left(),
01761 data.crect.y() - fs.top()));
01762
01763 x->frameStrut.setCoords(0, 0, 0, 0);
01764 data.fstrut_dirty = true;
01765 }
01766
01767 XFlush(X11->display);
01768 } else {
01769 invalidateBuffer(q->rect());
01770 q->setAttribute(Qt::WA_Mapped, false);
01771 if (q->internalWinId())
01772 XUnmapWindow(X11->display, q->internalWinId());
01773 }
01774 }
01775
01776 void QWidgetPrivate::raise_sys()
01777 {
01778 Q_Q(QWidget);
01779 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01780 XRaiseWindow(X11->display, q->internalWinId());
01781 if(!q->isWindow())
01782 invalidateBuffer(q->rect());
01783 }
01784
01785 void QWidgetPrivate::lower_sys()
01786 {
01787 Q_Q(QWidget);
01788 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01789 XLowerWindow(X11->display, q->internalWinId());
01790 if(!q->isWindow())
01791 invalidateBuffer(q->rect());
01792 }
01793
01794 void QWidgetPrivate::stackUnder_sys(QWidget* w)
01795 {
01796 Q_Q(QWidget);
01797 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01798 Window stack[2];
01799 stack[0] = w->internalWinId();;
01800 stack[1] = q->internalWinId();
01801 XRestackWindows(X11->display, stack, 2);
01802 if(!q->isWindow())
01803 invalidateBuffer(q->rect());
01804 }
01805
01806
01807 static void do_size_hints(QWidget* widget, QWExtra *x)
01808 {
01809 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
01810 XSizeHints s;
01811 s.flags = 0;
01812 if (x) {
01813 QRect g = widget->geometry();
01814 s.x = g.x();
01815 s.y = g.y();
01816 s.width = g.width();
01817 s.height = g.height();
01818 if (x->minw > 0 || x->minh > 0) {
01819
01820 s.flags |= PMinSize;
01821 s.min_width = qMin(XCOORD_MAX, x->minw);
01822 s.min_height = qMin(XCOORD_MAX, x->minh);
01823 }
01824 if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) {
01825
01826 s.flags |= PMaxSize;
01827 s.max_width = qMin(XCOORD_MAX, x->maxw);
01828 s.max_height = qMin(XCOORD_MAX, x->maxh);
01829 }
01830 if (x->topextra &&
01831 (x->topextra->incw > 0 || x->topextra->inch > 0)) {
01832
01833 s.flags |= PResizeInc | PBaseSize;
01834 s.width_inc = x->topextra->incw;
01835 s.height_inc = x->topextra->inch;
01836 s.base_width = x->topextra->basew;
01837 s.base_height = x->topextra->baseh;
01838 }
01839 }
01840 if (widget->testAttribute(Qt::WA_Moved)) {
01841
01842 s.flags |= USPosition;
01843 s.flags |= PPosition;
01844 }
01845 if (widget->testAttribute(Qt::WA_Resized)) {
01846
01847 s.flags |= USSize;
01848 s.flags |= PSize;
01849 }
01850 s.flags |= PWinGravity;
01851 s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
01852 XSetWMNormalHints(X11->display, widget->internalWinId(), &s);
01853 }
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871 void QWidgetPrivate::setWSGeometry(bool dontShow)
01872 {
01873 Q_Q(QWidget);
01874
01875
01876
01877
01878
01879
01880
01881
01882 Display *dpy = xinfo.display();
01883 QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
01884 QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
01885 QRect wrect;
01886
01887 QRect xrect = data.crect;
01888
01889 QRect parentWRect = q->parentWidget()->data->wrect;
01890
01891 if (parentWRect.isValid()) {
01892
01893 if (!parentWRect.contains(xrect)) {
01894 xrect &= parentWRect;
01895 wrect = xrect;
01896
01897 wrect.translate(-data.crect.topLeft());
01898 }
01899
01900 xrect.translate(-parentWRect.topLeft());
01901
01902 } else {
01903
01904
01905 if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
01906
01907
01908
01909
01910
01911 QRect vrect = xrect & q->parentWidget()->rect();
01912 vrect.translate(-data.crect.topLeft());
01913 if (data.wrect.contains(vrect)) {
01914 xrect = data.wrect;
01915 xrect.translate(data.crect.topLeft());
01916 XMoveWindow(dpy, data.winid, xrect.x(), xrect.y());
01917 return;
01918 }
01919 }
01920
01921 if (!validRange.contains(xrect)) {
01922
01923 xrect &=wrectRange;
01924 wrect = xrect;
01925 wrect.translate(-data.crect.topLeft());
01926
01927
01928 }
01929
01930 }
01931
01932
01933 bool outsideRange = !xrect.isValid();
01934 bool mapWindow = false;
01935 if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
01936 q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
01937 if (outsideRange) {
01938 XUnmapWindow(dpy, data.winid);
01939 q->setAttribute(Qt::WA_Mapped, false);
01940 } else if (!q->isHidden()) {
01941 mapWindow = true;
01942 }
01943 }
01944
01945 if (outsideRange)
01946 return;
01947
01948 bool jump = (data.wrect != wrect);
01949 data.wrect = wrect;
01950
01951
01952
01953
01954 for (int i = 0; i < children.size(); ++i) {
01955 QObject *object = children.at(i);
01956 if (object->isWidgetType()) {
01957 QWidget *w = static_cast<QWidget *>(object);
01958 if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
01959 w->d_func()->setWSGeometry(jump);
01960 }
01961 }
01962
01963
01964
01965
01966 if (jump)
01967 XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
01968 XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
01969
01970
01971 if (jump) {
01972 for (int i = 0; i < children.size(); ++i) {
01973 QObject *object = children.at(i);
01974 if (object->isWidgetType()) {
01975 QWidget *w = static_cast<QWidget *>(object);
01976 if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
01977 w->setAttribute(Qt::WA_Mapped);
01978 XMapWindow(dpy, w->data->winid);
01979 }
01980 }
01981 }
01982 }
01983
01984
01985 if (jump)
01986 XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True);
01987
01988 if (mapWindow && !dontShow) {
01989 q->setAttribute(Qt::WA_Mapped);
01990 XMapWindow(dpy, data.winid);
01991 }
01992 }
01993
01994 void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
01995 {
01996 Q_Q(QWidget);
01997 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
01998 Display *dpy = X11->display;
01999
02000 if ((q->windowType() == Qt::Desktop))
02001 return;
02002 if (q->isWindow()) {
02003 if (!qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
02004 && !qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
02005 data.window_state &= ~Qt::WindowMaximized;
02006 if (!qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN)))
02007 data.window_state &= ~Qt::WindowFullScreen;
02008 if (QTLWExtra *topData = maybeTopData())
02009 topData->normalGeometry = QRect(0,0,-1,-1);
02010 w = qMax(1, w);
02011 h = qMax(1, h);
02012 } else {
02013 uint s = data.window_state;
02014 s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
02015 data.window_state = s;
02016 }
02017 if (extra) {
02018 w = qMin(w,extra->maxw);
02019 h = qMin(h,extra->maxh);
02020 w = qMax(w,extra->minw);
02021 h = qMax(h,extra->minh);
02022 }
02023 QPoint oldPos(q->pos());
02024 QSize oldSize(q->size());
02025 QRect oldGeom(data.crect);
02026 QRect r(x, y, w, h);
02027
02028
02029
02030 if (!q->isWindow() && oldGeom == r)
02031 return;
02032
02033 data.crect = r;
02034 bool isResize = q->size() != oldSize;
02035
02036 if (q->isWindow()) {
02037 if (!q->isVisible())
02038 do_size_hints(q, extra);
02039 if (isMove) {
02040 if (! qt_broken_wm)
02041
02042 XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
02043 else
02044
02045 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
02046 } else if (isResize)
02047 XResizeWindow(dpy, data.winid, w, h);
02048 if (isResize)
02049 q->setAttribute(Qt::WA_WState_ConfigPending);
02050
02051 } else {
02052 if(!isResize && q->isVisible()) {
02053 moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
02054 }
02055 if (q->testAttribute(Qt::WA_WState_Created))
02056 setWSGeometry();
02057 if (isResize && q->isVisible()) {
02058 invalidateBuffer(q->rect());
02059 QRegion oldRegion(QRect(oldPos, oldSize));
02060 if (!q->mask().isEmpty())
02061 oldRegion &= q->mask().translated(oldPos);
02062 q->parentWidget()->d_func()->invalidateBuffer(oldRegion);
02063 }
02064 }
02065
02066 if (q->isVisible()) {
02067 if (isMove && q->pos() != oldPos) {
02068 if (! qt_broken_wm) {
02069
02070 QMoveEvent e(q->pos(), oldPos);
02071 QApplication::sendEvent(q, &e);
02072 } else {
02073
02074 QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft());
02075 QApplication::sendEvent(q, &e);
02076 }
02077 }
02078 if (isResize) {
02079 QResizeEvent e(q->size(), oldSize);
02080 QApplication::sendEvent(q, &e);
02081 }
02082 } else {
02083 if (isMove && q->pos() != oldPos)
02084 q->setAttribute(Qt::WA_PendingMoveEvent, true);
02085 if (isResize)
02086 q->setAttribute(Qt::WA_PendingResizeEvent, true);
02087 }
02088 }
02089
02090 void QWidgetPrivate::setConstraints_sys()
02091 {
02092 Q_Q(QWidget);
02093 if (q->testAttribute(Qt::WA_WState_Created))
02094 do_size_hints(q, extra);
02095 }
02096
02097
02119 void QWidget::scroll(int dx, int dy)
02120 {
02121 Q_D(QWidget);
02122 if (!updatesEnabled() && children().size() == 0 || !isVisible())
02123 return;
02124 if (dx == 0 && dy == 0)
02125 return;
02126 d->scrollChildren(dx, dy);
02127 if (!QWidgetBackingStore::paintOnScreen(this)) {
02128 d->scrollRect(rect(), dx, dy);
02129 } else {
02130 scroll(dx, dy, QRect());
02131 }
02132 }
02133
02144 void QWidget::scroll(int dx, int dy, const QRect& r)
02145 {
02146
02147 Q_D(QWidget);
02148 if (!updatesEnabled() && children().size() == 0 || !isVisible())
02149 return;
02150 if (dx == 0 && dy == 0)
02151 return;
02152 if (!QWidgetBackingStore::paintOnScreen(this)) {
02153 d->scrollRect(r, dx, dy);
02154 d->dirtyWidget_sys(r);
02155 return;
02156 }
02157 bool valid_rect = r.isValid();
02158 bool just_update = qAbs(dx) > width() || qAbs(dy) > height();
02159 QRect sr = valid_rect ? r : d->clipRect();
02160 if (just_update) {
02161 update();
02162 } else if (!valid_rect){
02163 d->dirtyOnScreen.translate(dx,dy);
02164 }
02165
02166 int x1, y1, x2, y2, w = sr.width(), h = sr.height();
02167 if (dx > 0) {
02168 x1 = sr.x();
02169 x2 = x1+dx;
02170 w -= dx;
02171 } else {
02172 x2 = sr.x();
02173 x1 = x2-dx;
02174 w += dx;
02175 }
02176 if (dy > 0) {
02177 y1 = sr.y();
02178 y2 = y1+dy;
02179 h -= dy;
02180 } else {
02181 y2 = sr.y();
02182 y1 = y2-dy;
02183 h += dy;
02184 }
02185
02186 if (dx == 0 && dy == 0)
02187 return;
02188
02189 Display *dpy = X11->display;
02190
02191 if (w > 0 && h > 0 && !just_update) {
02192 GC gc = XCreateGC(dpy, internalWinId(), 0, 0);
02193 XSetGraphicsExposures(dpy, gc, True);
02194 XCopyArea(dpy, internalWinId(), internalWinId(), gc, x1, y1, w, h, x2, y2);
02195 XFreeGC(dpy, gc);
02196 }
02197
02198 if (!valid_rect && !d->children.isEmpty()) {
02199 QPoint pd(dx, dy);
02200 for (int i = 0; i < d->children.size(); ++i) {
02201 register QObject *object = d->children.at(i);
02202 if (object->isWidgetType()) {
02203 QWidget *w = static_cast<QWidget *>(object);
02204 if (!w->isWindow())
02205 w->move(w->pos() + pd);
02206 }
02207 }
02208 }
02209
02210 if (just_update)
02211 return;
02212
02213
02214 bool repaint_immediately = (qt_sip_count(this) < 3 && !testAttribute(Qt::WA_WState_InPaintEvent));
02215
02216 if (dx) {
02217 int x = x2 == sr.x() ? sr.x()+w : sr.x();
02218 if (repaint_immediately)
02219 repaint(x, sr.y(), qAbs(dx), sr.height());
02220 else
02221 XClearArea(dpy, data->winid, x, sr.y(), qAbs(dx), sr.height(), True);
02222 }
02223 if (dy) {
02224 int y = y2 == sr.y() ? sr.y()+h : sr.y();
02225 if (repaint_immediately)
02226 repaint(sr.x(), y, sr.width(), qAbs(dy));
02227 else
02228 XClearArea(dpy, data->winid, sr.x(), y, sr.width(), qAbs(dy), True);
02229 }
02230
02231 qt_insert_sip(this, dx, dy);
02232 }
02233
02241 int QWidget::metric(PaintDeviceMetric m) const
02242 {
02243 Q_D(const QWidget);
02244 int val;
02245 if (m == PdmWidth) {
02246 val = data->crect.width();
02247 } else if (m == PdmHeight) {
02248 val = data->crect.height();
02249 } else {
02250 Display *dpy = X11->display;
02251 int scr = d->xinfo.screen();
02252 switch (m) {
02253 case PdmDpiX:
02254 case PdmPhysicalDpiX:
02255 val = QX11Info::appDpiX(scr);
02256 break;
02257 case PdmDpiY:
02258 case PdmPhysicalDpiY:
02259 val = QX11Info::appDpiY(scr);
02260 break;
02261 case PdmWidthMM:
02262 val = (DisplayWidthMM(dpy,scr)*data->crect.width())/
02263 DisplayWidth(dpy,scr);
02264 break;
02265 case PdmHeightMM:
02266 val = (DisplayHeightMM(dpy,scr)*data->crect.height())/
02267 DisplayHeight(dpy,scr);
02268 break;
02269 case PdmNumColors:
02270 val = d->xinfo.cells();
02271 break;
02272 case PdmDepth:
02273 val = d->xinfo.depth();
02274 break;
02275 default:
02276 val = 0;
02277 qWarning("QWidget::metric: Invalid metric command");
02278 }
02279 }
02280 return val;
02281 }
02282
02283 void QWidgetPrivate::createSysExtra()
02284 {
02285 extra->xDndProxy = 0;
02286 extra->compress_events = true;
02287 }
02288
02289 void QWidgetPrivate::deleteSysExtra()
02290 {
02291 }
02292
02293 void QWidgetPrivate::createTLSysExtra()
02294 {
02295 extra->topextra->iconMask = 0;
02296 extra->topextra->backingStore = 0;
02297 extra->topextra->validWMState = 0;
02298 extra->topextra->waitingForMapNotify = 0;
02299 }
02300
02301 void QWidgetPrivate::deleteTLSysExtra()
02302 {
02303
02304
02305 delete extra->topextra->iconMask;
02306 extra->topextra->iconMask = 0;
02307 delete extra->topextra->backingStore;
02308 extra->topextra->backingStore = 0;
02309 }
02310
02311 void QWidgetPrivate::registerDropSite(bool on)
02312 {
02313 Q_UNUSED(on);
02314 }
02315
02330 void QWidget::setMask(const QRegion& region)
02331 {
02332 Q_D(QWidget);
02333 d->createExtra();
02334 if (region == d->extra->mask)
02335 return;
02336 #ifndef QT_NO_BACKINGSTORE
02337 QRegion parentR;
02338 if (!isWindow())
02339 parentR = d->extra->mask.isEmpty() ? QRegion(rect()) : d->extra->mask ;
02340 #endif
02341
02342 d->extra->mask = region;
02343
02344 if (!testAttribute(Qt::WA_WState_Created))
02345 return;
02346
02347 XShapeCombineRegion(X11->display, internalWinId(), ShapeBounding, 0, 0,
02348 region.handle(), ShapeSet);
02349 #ifndef QT_NO_BACKINGSTORE
02350 if (isVisible()) {
02351 if (!isWindow()) {
02352 parentR += d->extra->mask;
02353 parentWidget()->update(parentR.translated(geometry().topLeft()));
02354 }
02355 if (!testAttribute(Qt::WA_PaintOnScreen))
02356 update();
02357 }
02358 #endif
02359 }
02360
02387 void QWidget::setMask(const QBitmap &bitmap)
02388 {
02389 Q_D(QWidget);
02390 d->createExtra();
02391
02392 #ifndef QT_NO_BACKINGSTORE
02393 QRegion parentR;
02394 if (!isWindow())
02395 parentR = d->extra->mask.isEmpty() ? QRegion(rect()) : d->extra->mask ;
02396 #endif
02397
02398 d->extra->mask = QRegion(bitmap);
02399
02400 if (!testAttribute(Qt::WA_WState_Created))
02401 return;
02402
02403 QBitmap bm = bitmap;
02404 if (bm.x11Info().screen() != d->xinfo.screen())
02405 bm.x11SetScreen(d->xinfo.screen());
02406
02407 XShapeCombineMask(X11->display, internalWinId(), ShapeBounding, 0, 0,
02408 bm.handle(), ShapeSet);
02409
02410 #ifndef QT_NO_BACKINGSTORE
02411 if (isVisible()) {
02412 if (!isWindow()) {
02413 parentR += d->extra->mask;
02414 parentWidget()->update(parentR.translated(geometry().topLeft()));
02415 }
02416 if (!testAttribute(Qt::WA_PaintOnScreen))
02417 update();
02418 }
02419 #endif
02420 }
02421
02428 void QWidget::clearMask()
02429 {
02430 Q_D(QWidget);
02431 if (QWExtra *extra = d->extraData())
02432 extra->mask = QRegion();
02433 if (!testAttribute(Qt::WA_WState_Created))
02434 return;
02435 XShapeCombineMask(X11->display, internalWinId(), ShapeBounding, 0, 0,
02436 XNone, ShapeSet);
02437 }
02438
02446 void QWidgetPrivate::updateFrameStrut()
02447 {
02448 Q_Q(QWidget);
02449
02450 QTLWExtra *top = topData();
02451 if (!top->validWMState) {
02452 return;
02453 }
02454
02455 Atom type_ret;
02456 Window l = q->internalWinId(), w = l, p, r;
02457 Window *c;
02458 int i_unused;
02459 unsigned int nc;
02460 unsigned char *data_ret;
02461 unsigned long l_unused;
02462
02463 while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) {
02464 if (c && nc > 0)
02465 XFree(c);
02466
02467 if (! p) {
02468 qWarning("QWidget::updateFrameStrut: No parent");
02469 return;
02470 }
02471
02472
02473
02474 data_ret = 0;
02475 if (p == r ||
02476 (XGetWindowProperty(X11->display, p,
02477 ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL,
02478 &type_ret, &i_unused, &l_unused, &l_unused,
02479 &data_ret) == Success &&
02480 type_ret == XA_CARDINAL)) {
02481 if (data_ret)
02482 XFree(data_ret);
02483
02484 break;
02485 } else if (qt_net_supports(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) {
02486 int i = 0;
02487 while (X11->net_virtual_root_list[i] != 0) {
02488 if (X11->net_virtual_root_list[i++] == p)
02489 break;
02490 }
02491 }
02492
02493 l = w;
02494 w = p;
02495 }
02496
02497
02498 int transx, transy;
02499 XWindowAttributes wattr;
02500 if (XTranslateCoordinates(X11->display, l, w,
02501 0, 0, &transx, &transy, &p) &&
02502 XGetWindowAttributes(X11->display, w, &wattr)) {
02503 top->frameStrut.setCoords(transx,
02504 transy,
02505 wattr.width - data.crect.width() - transx,
02506 wattr.height - data.crect.height() - transy);
02507
02508
02509
02510
02511
02512
02513
02514 top->frameStrut.adjust(wattr.border_width,
02515 wattr.border_width,
02516 wattr.border_width,
02517 wattr.border_width);
02518 }
02519
02520 data.fstrut_dirty = false;
02521 }
02522
02523 void QWidget::setWindowOpacity(qreal opacity)
02524 {
02525 if (!isWindow())
02526 return;
02527
02528 Q_D(QWidget);
02529 opacity = qBound(0.0, opacity, 1.0);
02530 d->topData()->opacity = uint(opacity * 255);
02531 if (!testAttribute(Qt::WA_WState_Created))
02532 return;
02533 ulong value = ulong(opacity * 0xffffffff);
02534 XChangeProperty(QX11Info::display(), internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL,
02535 32, PropModeReplace, (uchar*)&value, 1);
02536 }
02537
02538 qreal QWidget::windowOpacity() const
02539 {
02540 Q_D(const QWidget);
02541 return (isWindow() && d->maybeTopData()) ? d->maybeTopData()->opacity / 255. : 1.0;
02542 }
02543
02550 const QX11Info &QWidget::x11Info() const
02551 {
02552 Q_D(const QWidget);
02553 return d->xinfo;
02554 }
02555
02556 void QWidgetPrivate::setWindowRole(const char *role)
02557 {
02558 Q_Q(QWidget);
02559 Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
02560 XChangeProperty(X11->display, q->internalWinId(),
02561 ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace,
02562 (unsigned char *)role, qstrlen(role));
02563 }
02564
02565 Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine)
02566 QPaintEngine *QWidget::paintEngine() const
02567 {
02568 Q_D(const QWidget);
02569 if (qt_widget_paintengine()->isActive()) {
02570 if (d->extraPaintEngine)
02571 return d->extraPaintEngine;
02572 QWidget *self = const_cast<QWidget *>(this);
02573 self->d_func()->extraPaintEngine = new QX11PaintEngine();
02574 return d->extraPaintEngine;
02575 }
02576 return qt_widget_paintengine();
02577 }
02578
02586 Qt::HANDLE QWidget::x11PictureHandle() const
02587 {
02588 #ifndef QT_NO_XRENDER
02589 Q_D(const QWidget);
02590 return d->picture;
02591 #else
02592 return 0;
02593 #endif // QT_NO_XRENDER
02594 }
02595
02596 #ifndef QT_NO_XRENDER
02597 XRenderColor QX11Data::preMultiply(const QColor &c)
02598 {
02599 XRenderColor color;
02600 const uint A = c.alpha(),
02601 R = c.red(),
02602 G = c.green(),
02603 B = c.blue();
02604 color.alpha = (A | A << 8);
02605 color.red = (R | R << 8) * color.alpha / 0x10000;
02606 color.green = (G | G << 8) * color.alpha / 0x10000;
02607 color.blue = (B | B << 8) * color.alpha / 0x10000;
02608 return color;
02609 }
02610 Picture QX11Data::getSolidFill(int screen, const QColor &c)
02611 {
02612 if (!X11->use_xrender)
02613 return XNone;
02614
02615 XRenderColor color = preMultiply(c);
02616 for (int i = 0; i < X11->solid_fill_count; ++i) {
02617 if (X11->solid_fills[i].screen == screen
02618 && X11->solid_fills[i].color.alpha == color.alpha
02619 && X11->solid_fills[i].color.red == color.red
02620 && X11->solid_fills[i].color.green == color.green
02621 && X11->solid_fills[i].color.blue == color.blue)
02622 return X11->solid_fills[i].picture;
02623 }
02624
02625 int i = rand() % 16;
02626
02627 if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
02628 XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
02629 X11->solid_fills[i].picture = 0;
02630 }
02631
02632 if (!X11->solid_fills[i].picture) {
02633 Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
02634 XRenderPictureAttributes attrs;
02635 attrs.repeat = True;
02636 X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
02637 XRenderFindStandardFormat(X11->display, PictStandardARGB32),
02638 CPRepeat, &attrs);
02639 XFreePixmap (X11->display, pixmap);
02640 }
02641
02642 X11->solid_fills[i].color = color;
02643 X11->solid_fills[i].screen = screen;
02644 XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
02645 return X11->solid_fills[i].picture;
02646 }
02647 #endif
02648
02649 void QWidgetPrivate::setModal_sys()
02650 {
02651 }