src/gui/kernel/qwidget_x11.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
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; // declared in qapplication_x11.cpp
00042 extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp
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 // defined in qapplication_x11.cpp
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 // MWM support
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 // Returns true if we should set WM_TRANSIENT_FOR on \a w
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   QWidget member functions
00165  *****************************************************************************/
00166 
00167 extern bool qt_broken_wm;
00168 
00169 // defined in qapplication_x11.cpp
00170 extern bool qt_net_supports(Atom);
00171 
00172 const uint stdWidgetEventMask =                        // X event mask
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 =                        // X event mask
00186        (uint)(
00187            KeymapStateMask |
00188            EnterWindowMask | LeaveWindowMask |
00189            PropertyChangeMask
00190       );
00191 
00192 
00193 /*
00194   The qt_ functions below are implemented in qwidgetcreate_x11.cpp.
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     // set client leader property to itself
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     // If we are session managed, inform the window manager about it
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             // enforce the windows behavior of clearing the cursor on
00280             // disabled widgets
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; // give up, no event available
00300         qApp->syncX(); // non-busy wait
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()) // not managed by the window manager
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) { // if our parent stays on top, so must we
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         // All these buttons depend on the system menu, so we enable it
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     // always initialize
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         // desktop on a certain screen other than the default requested
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     //get display, screen number, root window and desktop geometry for
00386     //the current screen
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) {                                // desktop widget
00394         dialog = popup = false;                        // force these flags off
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) {                                // override the old 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         // find which screen the window is on...
00421         xd->screen = QX11Info::appScreen(); // by default, use the default :)
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) {                        // desktop widget
00439 #ifdef QWIDGET_EXTRA_DEBUG
00440         qDebug() << "create desktop";
00441 #endif
00442         id = (WId)parentw;                        // id = root window
00443 //         QWidget *otherDesktop = find(id);        // is there another desktop?
00444 //         if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) {
00445 //             otherDesktop->d->setWinId(0);        // remove id from widget mapper
00446 //             d->setWinId(id);                     // make sure otherDesktop is
00447 //             otherDesktop->d->setWinId(id);       // found first
00448 //         } else {
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; //##### must handle huge sizes as well.... i.e. wrect
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);                                // set widget id/handle + hd
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     // NET window types
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 { //       if (customize) {
00515             mwmhints.decorations = 0L;
00516             mwmhints.flags |= MWM_HINTS_DECORATIONS;
00517 
00518             if (flags & Qt::FramelessWindowHint) {
00519                 // override netwm type - quick and easy for KDE noborder
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         // ### need a better way to do this
00544         if (q->inherits("QMenu")) {
00545             // menu netwm type
00546             net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_MENU);
00547         } else if (q->inherits("QToolBar")) {
00548             // toolbar netwm type
00549             net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR);
00550         } else if (type == Qt::Tool || type == Qt::Drawer) {
00551             // utility netwm type
00552             net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_UTILITY);
00553         }
00554 
00555         if (dialog) // dialog netwm type
00556             net_wintypes[curr_wintype++] = ATOM(_NET_WM_WINDOW_TYPE_DIALOG);
00557         // normal netwm type - default
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         // do no initialization
00572     } else if (popup) {                        // popup widget
00573         wsa.override_redirect = True;
00574         wsa.save_under = True;
00575         XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder,
00576                                 &wsa);
00577     } else if (topLevel && !desktop) {        // top-level widget
00578         if (!X11->wm_client_leader)
00579             create_wm_client_leader();
00580 
00581         // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys()
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;                        // window manager 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(); // application name
00601         class_hint.res_class = const_cast<char *>(QX11Info::appClass());   // application class
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);        // support del window protocol
00612         protocols[n++] = ATOM(WM_TAKE_FOCUS);                // support take focus window protocol
00613         protocols[n++] = ATOM(_NET_WM_PING);                // support _NET_WM_PING protocol
00614         if (flags & Qt::WindowContextHelpButtonHint)
00615             protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
00616         XSetWMProtocols(dpy, id, protocols, n);
00617 
00618         // set mwm hints
00619         SetMWMHints(dpy, id, mwmhints);
00620 
00621         // set _NET_WM_WINDOW_TYPE
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         // set _NET_WM_PID
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         // when we create a toplevel widget, the frame strut should be dirty
00634         data.fstrut_dirty = 1;
00635 
00636         // declare the widget's object name as window role
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         // set client leader property
00643         XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER),
00644                         XA_WINDOW, 32, PropModeReplace,
00645                         (unsigned char *)&X11->wm_client_leader, 1);
00646     } else {
00647         // non-toplevel widgets don't have a frame, so no need to
00648         // update the strut
00649         data.fstrut_dirty = 0;
00650     }
00651 
00652     if (initializeWindow) {
00653         // don't erase when resizing
00654         wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity;
00655         XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa);
00656     }
00657 
00658     // set X11 event mask
00659     if (desktop) {
00660 //         QWidget* main_desktop = find(id);
00661 //         if (main_desktop->testWFlags(Qt::WPaintDesktop))
00662 //             XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask);
00663 //         else
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) {                        // set X cursor
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); //always enable dnd: it's not worth the effort to maintain the state
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     // newly created windows are positioned at the window system's
00712     // (0,0) position. If the parent uses wrect mapping to expand the
00713     // coordinate system, we must also adjust this widget's window
00714     // system position
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) { // destroy all widget children
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             // just be sure we leave modal
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); // from qapplication_x11.cpp
00777         if (testAttribute(Qt::WA_WState_Reparented))
00778             qPRCleanup(this);
00779 
00780         if(d->ic) {
00781             delete d->ic;
00782         } else {
00783             // release previous focus information participating with
00784             // preedit preservation of qic
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     // dnd unregister (we will register again below)
00803     if (q->testAttribute(Qt::WA_DropSiteRegistered))
00804         q->setAttribute(Qt::WA_DropSiteRegistered, false);
00805 
00806     // if we are a top then remove our dnd prop for now
00807     // it will get rest later
00808     if (q->isWindow() && wasCreated)
00809         X11->dndEnable(q, false);
00810 
00811 //     QWidget *oldparent = q->parentWidget();
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     // hide and reparent our own window away. Otherwise we might get
00824     // destroyed when emitting the child remove event below. See QWorkspace.
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         // zero the frame strut and mark it dirty
00832         topData->frameStrut.setCoords(0, 0, 0, 0);
00833 
00834         // reparenting from top-level, make sure show() works again
00835         topData->waitingForMapNotify = 0;
00836         topData->validWMState = 0;
00837     }
00838     data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut
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     // keep compatibility with previous versions, we need to preserve the created state
00849     // (but we recreate the winId for the widget being reparented, again for compability)
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) { // reparent children
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                     // ### force setParent() to not shortcut out (because
00866                     // ### we're setting the parent to the current parent)
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                       when reparenting toplevel windows with toplevel-transient children,
00876                       we need to make sure that the window manager gets the updated
00877                       WM_TRANSIENT_FOR information... unfortunately, some window managers
00878                       don't handle changing WM_TRANSIENT_FOR before the toplevel window is
00879                       visible, so we unmap and remap all toplevel-transient children *after*
00880                       the toplevel parent has been mapped.  thankfully, this is easy in Qt :)
00881 
00882                       note that the WM_TRANSIENT_FOR hint is actually updated in
00883                       QWidgetPrivate::show_sys()
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     // check if we need to register our dropsite
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         //cannot trust that !isWindow() implies parentWidget() before create
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         //cannot trust that !isWindow() implies parentWidget() before create
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; // we can't free tp.value in case it references
01005     // the data of the static QCString below.
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     // ### If we knew WM could understand unicode, we could use
01037     // ### a much simpler, cheaper encoding...
01038     /*
01039         tp.value = (XChar2b*)s.unicode();
01040         tp.encoding = XA_UNICODE; // wish
01041         tp.format = 16;
01042         tp.nitems = s.length();
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         // already been set
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         // set the _NET_WM_ICON property
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           if the app is not using the default visual, convert the icon
01103           to 1bpp as stated in the ICCCM section 4.1.2.4; otherwise,
01104           create the icon pixmap in the default depth (even though
01105           this violates the ICCCM)
01106         */
01107         if (!QX11Info::appDefaultVisual(xinfo.screen())
01108             || !QX11Info::appDefaultColormap(xinfo.screen())) {
01109             // non-default visual/colormap, use 1bpp bitmap
01110             if (!forceReset || !topData->iconPixmap)
01111                 topData->iconPixmap = new QBitmap(pixmap);
01112             h->icon_pixmap = topData->iconPixmap->handle();
01113         } else {
01114             // default depth, use a normal pixmap (even though this
01115             // violates the ICCCM)
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         // Ensure the initial size is valid, since we store it as normalGeometry below.
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                     // save original geometry
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                     // restore original geometry
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                         // from fullscreen to maximized
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                         // restore original geometry
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         // update WM_NORMAL_HINTS
01545         do_size_hints(q, extra);
01546 
01547         // udpate WM_TRANSIENT_FOR
01548         if (isTransient(q)) {
01549             QWidget *p = q->parentWidget();
01550             if (p)
01551                 p = p->window();
01552             if (p) {
01553                 // transient for window
01554                 XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId());
01555             } else {
01556                 // transient for group
01557                 XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader);
01558             }
01559         }
01560 
01561         // update _MOTIF_WM_HINTS
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             // fixed size, remove the resize handle (since mwm/dtwm
01582             // isn't smart enough to do it itself)
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         // set _NET_WM_STATE
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         // set _NET_WM_USER_TIME
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             // if the wm was not smart enough to adjust our size, do that manually
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             // restore the original normalGeometry
01667             top->normalGeometry = normalRect;
01668             // internalSetGeometry() clears the maximized flag... make sure we set it back
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     // Freedesktop.org Startup Notification
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()) // in nsplugin, may be 0
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             // zero the frame strut and mark it dirty
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()) // in nsplugin, may be 0
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             // add minimum size hints
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             // add maximum size hints
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             // add resize increment hints
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         // user (i.e. command-line) specified position
01842         s.flags |= USPosition;
01843         s.flags |= PPosition;
01844     }
01845     if (widget->testAttribute(Qt::WA_Resized)) {
01846         // user (i.e. command-line) specified size
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   Helper function for non-toplevel widgets. Helps to map Qt's 32bit
01858   coordinate system to X11's 16bit coordinate system.
01859 
01860   Sets the geometry of the widget to data.crect, but clipped to sizes
01861   that X can handle. Unmaps widgets that are completely outside the
01862   valid range.
01863 
01864   Maintains data.wrect, which is the geometry of the X widget,
01865   measured in this widget's coordinate system.
01866 
01867   if the parent is not clipped, parentWRect is empty, otherwise
01868   parentWRect is the geometry of the parent's X rect, measured in
01869   parent's coord sys
01870  */
01871 void QWidgetPrivate::setWSGeometry(bool dontShow)
01872 {
01873     Q_Q(QWidget);
01874 
01875     /*
01876       There are up to four different coordinate systems here:
01877       Qt coordinate system for this widget.
01878       X coordinate system for this widget (relative to wrect).
01879       Qt coordinate system for parent
01880       X coordinate system for parent (relative to parent's wrect).
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     //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)
01887     QRect xrect = data.crect;
01888 
01889     QRect parentWRect = q->parentWidget()->data->wrect;
01890 
01891     if (parentWRect.isValid()) {
01892         // parent is clipped, and we have to clip to the same limit as parent
01893         if (!parentWRect.contains(xrect)) {
01894             xrect &= parentWRect;
01895             wrect = xrect;
01896             //translate from parent's to my Qt coord sys
01897             wrect.translate(-data.crect.topLeft());
01898         }
01899         //translate from parent's Qt coords to parent's X coords
01900         xrect.translate(-parentWRect.topLeft());
01901 
01902     } else {
01903         // parent is not clipped, we may or may not have to clip
01904 
01905         if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
01906             // This is where the main optimization is: we are already
01907             // clipped, and if our clip is still valid, we can just
01908             // move our window, and do not need to move or clip
01909             // children
01910 
01911             QRect vrect = xrect & q->parentWidget()->rect();
01912             vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
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             // we are too big, and must clip
01923             xrect &=wrectRange;
01924             wrect = xrect;
01925             wrect.translate(-data.crect.topLeft());
01926             //parent's X coord system is equal to parent's Qt coord
01927             //sys, so we don't need to map xrect.
01928         }
01929 
01930     }
01931 
01932     // unmap if we are outside the valid window system coord system
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     // and now recursively for all children...
01953     // ### can be optimized
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     // move ourselves to the new position and map (if necessary) after
01964     // the movement. Rationale: moving unmapped windows is much faster
01965     // than moving mapped windows
01966     if (jump) //avoid flicker when jumping
01967         XSetWindowBackgroundPixmap(dpy, data.winid, XNone);
01968     XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height());
01969 
01970     //to avoid flicker, we have to show children after the helper widget has moved
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) {                                // any size restrictions?
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     // We only care about stuff that changes the geometry, or may
02029     // cause the window manager to change its state
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                 // pos() is right according to ICCCM 4.1.5
02042                 XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h);
02043             else
02044                 // work around 4Dwm's incompliance with ICCCM 4.1.5
02045                 XMoveResizeWindow(dpy, data.winid, x, y, w, h);
02046         } else if (isResize)
02047             XResizeWindow(dpy, data.winid, w, h);
02048         if (isResize) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent()
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()); //after the resize
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                 // pos() is right according to ICCCM 4.1.5
02070                 QMoveEvent e(q->pos(), oldPos);
02071                 QApplication::sendEvent(q, &e);
02072             } else {
02073                 // work around 4Dwm's incompliance with ICCCM 4.1.5
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     // Want expose events
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()) {        // scroll children
02199         QPoint pd(dx, dy);
02200         for (int i = 0; i < d->children.size(); ++i) { // move all children
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     // Don't let the server be bogged-down with repaint events
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); // #### ignores r
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     // don't destroy input context here. it will be destroyed in
02304     // QWidget::destroy() destroyInputContext();
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; // target window, it's parent, root
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         // if the parent window is the root window, an Enlightenment virtual root or
02473         // a NET WM virtual root window, stop here
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     // we have our window
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         // add the border_width for the window managers frame... some window managers
02509         // do not use a border_width of zero for their frames, and if we the left and
02510         // top strut, we ensure that pos() is absolutely correct.  frameGeometry()
02511         // will still be incorrect though... perhaps i should have foffset as well, to
02512         // indicate the frame offset (equal to the border_width on X).
02513         // - Brad
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     // none found, replace one
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 }

Generated on Thu Mar 15 11:55:19 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1