src/gui/kernel/qapplication_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 // ### 4.0: examine Q_EXPORT's below. The respective symbols had all
00025 // been in use (e.g. in the KDE wm) before the introduction of a version
00026 // map. One might want to turn some of them into proper public API and
00027 // provide a proper alternative for others. See also the exports in
00028 // qapplication_win.cpp, which suggest a unification.
00029 
00030 #include "qplatformdefs.h"
00031 
00032 #include "qcolormap.h"
00033 #include "qdesktopwidget.h"
00034 #include "qapplication.h"
00035 #include "qapplication_p.h"
00036 #include "qcursor.h"
00037 #include "qwidget.h"
00038 #include "qbitarray.h"
00039 #include "qpainter.h"
00040 #include "qfile.h"
00041 #include "qpixmapcache.h"
00042 #include "qdatetime.h"
00043 #include "qtextcodec.h"
00044 #include "qdatastream.h"
00045 #include "qbuffer.h"
00046 #include "qsocketnotifier.h"
00047 #include "qsessionmanager.h"
00048 #include "qclipboard.h"
00049 #include "qwhatsthis.h"
00050 #include "qsettings.h"
00051 #include "qstylefactory.h"
00052 #include "qfileinfo.h"
00053 #include "qhash.h"
00054 #include "qevent.h"
00055 #include "qevent_p.h"
00056 #include "qvarlengtharray.h"
00057 #include "qdebug.h"
00058 #include <private/qunicodetables_p.h>
00059 #include <private/qcrashhandler_p.h>
00060 #include <private/qcolor_p.h>
00061 #include <private/qcursor_p.h>
00062 #include "qstyle.h"
00063 #include "qmetaobject.h"
00064 
00065 #if !defined(QT_NO_GLIB)
00066 #  include "qguieventdispatcher_glib_p.h"
00067 #endif
00068 #include "qeventdispatcher_x11_p.h"
00069 #include <private/qpaintengine_x11_p.h>
00070 
00071 #include <private/qkeymapper_p.h>
00072 
00073 // Input method stuff
00074 #ifndef QT_NO_IM
00075 #include "qinputcontext.h"
00076 #include "qinputcontextfactory.h"
00077 #endif // QT_NO_IM
00078 
00079 #ifndef QT_NO_XFIXES
00080 #include <X11/extensions/Xfixes.h>
00081 #endif // QT_NO_XFIXES
00082 
00083 #include "qt_x11_p.h"
00084 #include "qx11info_x11.h"
00085 
00086 #define XK_MISCELLANY
00087 #include <X11/keysymdef.h>
00088 #include <X11/extensions/XI.h>
00089 
00090 #include <stdlib.h>
00091 #include <string.h>
00092 #include <ctype.h>
00093 #include <locale.h>
00094 
00095 #include "qwidget_p.h"
00096 
00097 #include <private/qbackingstore_p.h>
00098 
00099 //#define X_NOT_BROKEN
00100 #ifdef X_NOT_BROKEN
00101 // Some X libraries are built with setlocale #defined to _Xsetlocale,
00102 // even though library users are then built WITHOUT such a definition.
00103 // This creates a problem - Qt might setlocale() one value, but then
00104 // X looks and doesn't see the value Qt set. The solution here is to
00105 // implement _Xsetlocale just in case X calls it - redirecting it to
00106 // the real libC version.
00107 //
00108 # ifndef setlocale
00109 extern "C" char *_Xsetlocale(int category, const char *locale);
00110 char *_Xsetlocale(int category, const char *locale)
00111 {
00112     //qDebug("_Xsetlocale(%d,%s),category,locale");
00113     return setlocale(category,locale);
00114 }
00115 # endif // setlocale
00116 #endif // X_NOT_BROKEN
00117 
00118 
00119 /* Warning: if you modify this string, modify the list of atoms in qt_x11_p.h as well! */
00120 static const char * x11_atomnames = {
00121     // window-manager <-> client protocols
00122     "WM_PROTOCOLS\0"
00123     "WM_DELETE_WINDOW\0"
00124     "WM_TAKE_FOCUS\0"
00125     "_NET_WM_PING\0"
00126     "_NET_WM_CONTEXT_HELP\0"
00127 
00128     // ICCCM window state
00129     "WM_STATE\0"
00130     "WM_CHANGE_STATE\0"
00131 
00132     // Session management
00133     "WM_CLIENT_LEADER\0"
00134     "WM_WINDOW_ROLE\0"
00135     "SM_CLIENT_ID\0"
00136 
00137     // Clipboard
00138     "CLIPBOARD\0"
00139     "INCR\0"
00140     "TARGETS\0"
00141     "MULTIPLE\0"
00142     "TIMESTAMP\0"
00143     "CLIP_TEMPORARY\0"
00144     "_QT_SELECTION\0"
00145     "_QT_CLIPBOARD_SENTINEL\0"
00146     "_QT_SELECTION_SENTINEL\0"
00147 
00148     "RESOURCE_MANAGER\0"
00149 
00150     "_XSETROOT_ID\0"
00151 
00152     "_QT_SCROLL_DONE\0"
00153     "_QT_INPUT_ENCODING\0"
00154 
00155     "_MOTIF_WM_HINTS\0"
00156 
00157     "DTWM_IS_RUNNING\0"
00158     "KDE_FULL_SESSION\0"
00159     "KWIN_RUNNING\0"
00160     "KWM_RUNNING\0"
00161     "GNOME_BACKGROUND_PROPERTIES\0"
00162     "ENLIGHTENMENT_DESKTOP\0"
00163     "_SGI_DESKS_MANAGER\0"
00164 
00165     // EWMH (aka NETWM)
00166     "_NET_SUPPORTED\0"
00167     "_NET_VIRTUAL_ROOTS\0"
00168     "_NET_WORKAREA\0"
00169 
00170     "_NET_WM_NAME\0"
00171     "_NET_WM_ICON_NAME\0"
00172     "_NET_WM_ICON\0"
00173 
00174     "_NET_WM_PID\0"
00175 
00176     "_NET_WM_WINDOW_OPACITY\0"
00177 
00178     "_NET_WM_STATE\0"
00179     "_NET_WM_STATE_ABOVE\0"
00180     "_NET_WM_STATE_FULLSCREEN\0"
00181     "_NET_WM_STATE_MAXIMIZED_HORZ\0"
00182     "_NET_WM_STATE_MAXIMIZED_VERT\0"
00183     "_NET_WM_STATE_MODAL\0"
00184     "_NET_WM_STATE_STAYS_ON_TOP\0"
00185 
00186     "_NET_WM_USER_TIME\0"
00187     "_NET_WM_FULL_PLACEMENT\0"
00188 
00189     "_NET_WM_WINDOW_TYPE\0"
00190     "_NET_WM_WINDOW_TYPE_DIALOG\0"
00191     "_NET_WM_WINDOW_TYPE_MENU\0"
00192     "_NET_WM_WINDOW_TYPE_NORMAL\0"
00193     "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
00194     "_NET_WM_WINDOW_TYPE_SPLASH\0"
00195     "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
00196     "_NET_WM_WINDOW_TYPE_UTILITY\0"
00197 
00198     "_KDE_NET_WM_FRAME_STRUT\0"
00199 
00200     "_NET_STARTUP_INFO\0"
00201     "_NET_STARTUP_INFO_BEGIN\0"
00202 
00203     "_NET_SUPPORTING_WM_CHECK\0"
00204 
00205     // Property formats
00206     "COMPOUND_TEXT\0"
00207     "TEXT\0"
00208     "UTF8_STRING\0"
00209 
00210     // xdnd
00211     "XdndEnter\0"
00212     "XdndPosition\0"
00213     "XdndStatus\0"
00214     "XdndLeave\0"
00215     "XdndDrop\0"
00216     "XdndFinished\0"
00217     "XdndTypeList\0"
00218     "XdndActionList\0"
00219 
00220     "XdndSelection\0"
00221 
00222     "XdndAware\0"
00223     "XdndProxy\0"
00224 
00225     "XdndActionCopy\0"
00226     "XdndActionLink\0"
00227     "XdndActionMove\0"
00228     "XdndActionPrivate\0"
00229 
00230     // Motif DND
00231     "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
00232     "_MOTIF_DRAG_INITIATOR_INFO\0"
00233     "_MOTIF_DRAG_RECEIVER_INFO\0"
00234     "_MOTIF_DRAG_WINDOW\0"
00235     "_MOTIF_DRAG_TARGETS\0"
00236 
00237     "XmTRANSFER_SUCCESS\0"
00238     "XmTRANSFER_FAILURE\0"
00239 
00240     // Xkb
00241     "_XKB_RULES_NAMES\0"
00242 };
00243 
00244 Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
00245 
00246 /*****************************************************************************
00247   Internal variables and functions
00248  *****************************************************************************/
00249 static const char *appName = 0;                        // application name
00250 static const char *appClass = 0;                        // application class
00251 static const char *appFont        = 0;                // application font
00252 static const char *appBGCol        = 0;                // application bg color
00253 static const char *appFGCol        = 0;                // application fg color
00254 static const char *appBTNCol        = 0;                // application btn color
00255 static const char *mwGeometry        = 0;                // main widget geometry
00256 static const char *mwTitle        = 0;                // main widget title
00257 char    *qt_ximServer        = 0;                // XIM Server will connect to
00258 #if 0
00259 static bool        noxim                = false;        // connect to xim or not
00260 #endif
00261 static bool        appSync                = false;        // X11 synchronization
00262 #if defined(QT_DEBUG)
00263 static bool        appNoGrab        = false;        // X11 grabbing enabled
00264 static bool        appDoGrab        = false;        // X11 grabbing override (gdb)
00265 #endif
00266 static bool        app_save_rootinfo = false;        // save root info
00267 static bool        app_do_modal        = false;        // modal mode
00268 static Window        curWin = 0;                        // current window
00269 
00270 // detect broken window managers
00271 bool                qt_broken_wm                = false;
00272 static void qt_detect_broken_window_manager();
00273 
00274 
00275 // function to update the workarea of the screen - in qdesktopwidget_x11.cpp
00276 extern void qt_desktopwidget_update_workarea();
00277 
00278 
00279 // modifier masks for alt, meta, super, hyper, and mode_switch - detected when the application starts
00280 // and/or keyboard layout changes
00281 uchar qt_alt_mask = 0;
00282 uchar qt_meta_mask = 0;
00283 uchar qt_super_mask = 0;
00284 uchar qt_hyper_mask = 0;
00285 uchar qt_mode_switch_mask = 0;
00286 
00287 // flags for extensions for special Languages, currently only for RTL languages
00288 bool         qt_use_rtl_extensions = false;
00289 
00290 static Window        mouseActWindow             = 0;        // window where mouse is
00291 static Qt::MouseButton  mouseButtonPressed   = Qt::NoButton; // last mouse button pressed
00292 static Qt::MouseButtons mouseButtonState     = Qt::NoButton; // mouse button state
00293 static Time        mouseButtonPressTime = 0;        // when was a button pressed
00294 static short        mouseXPos, mouseYPos;                // mouse pres position in act window
00295 static short        mouseGlobalXPos, mouseGlobalYPos; // global mouse press position
00296 
00297 extern QWidgetList *qt_modal_stack;                // stack of modal widgets
00298 
00299 // window where mouse buttons have been pressed
00300 static Window pressed_window = XNone;
00301 
00302 // popup control
00303 static bool replayPopupMouseEvent = false;
00304 static bool popupGrabOk;
00305 
00306 bool qt_sm_blockUserInput = false;                // session management
00307 
00308 bool qt_reuse_double_buffer = true;
00309 
00310 Q_GUI_EXPORT int qt_xfocusout_grab_counter = 0;
00311 
00312 #if !defined (QT_NO_TABLET)
00313 Q_GLOBAL_STATIC(QTabletDeviceDataList, tablet_devices)
00314 QTabletDeviceDataList *qt_tablet_devices()
00315 {
00316     return tablet_devices();
00317 }
00318 
00319 extern bool qt_tabletChokeMouse;
00320 #endif
00321 
00322 static bool qt_x11EventFilter(XEvent* ev)
00323 {
00324     long unused;
00325     if (qApp->filterEvent(ev, &unused))
00326         return true;
00327     return qApp->x11EventFilter(ev);
00328 }
00329 
00330 #if !defined(QT_NO_XIM)
00331 XIMStyle        qt_xim_preferred_style = 0;
00332 #endif
00333 int qt_ximComposingKeycode=0;
00334 QTextCodec * qt_input_mapper = 0;
00335 
00336 extern bool     qt_check_clipboard_sentinel(); //def in qclipboard_x11.cpp
00337 extern bool        qt_check_selection_sentinel(); //def in qclipboard_x11.cpp
00338 
00339 static void        qt_save_rootinfo();
00340 Q_GUI_EXPORT bool qt_try_modal(QWidget *, XEvent *);
00341 
00342 QWidget *qt_button_down = 0; // last widget to be pressed with the mouse
00343 static QWidget *qt_popup_down = 0;  // popup that contains the pressed widget
00344 
00345 extern bool qt_xdnd_dragging;
00346 
00347 // gui or non-gui from qapplication.cpp
00348 extern bool qt_is_gui_used;
00349 extern bool qt_app_has_font;
00350 
00351 class QETWidget : public QWidget                // event translator widget
00352 {
00353 public:
00354     bool translateMouseEvent(const XEvent *);
00355     void translatePaintEvent(const XEvent *);
00356     bool translateConfigEvent(const XEvent *);
00357     bool translateCloseEvent(const XEvent *);
00358     bool translateScrollDoneEvent(const XEvent *);
00359     bool translateWheelEvent(int global_x, int global_y, int delta, Qt::MouseButtons buttons,
00360                              Qt::KeyboardModifiers modifiers, Qt::Orientation orient);
00361 #if !defined (QT_NO_TABLET)
00362     bool translateXinputEvent(const XEvent*, const QTabletDeviceData *tablet);
00363 #endif
00364     bool translatePropertyEvent(const XEvent *);
00365 };
00366 
00367 
00368 void QApplicationPrivate::createEventDispatcher()
00369 {
00370     Q_Q(QApplication);
00371 #if !defined(QT_NO_GLIB)
00372     if (qgetenv("QT_NO_GLIB").isEmpty())
00373         eventDispatcher = (q->type() != QApplication::Tty
00374                            ? new QGuiEventDispatcherGlib(q)
00375                            : new QEventDispatcherGlib(q));
00376     else
00377 #endif
00378         eventDispatcher = (q->type() != QApplication::Tty
00379                            ? new QEventDispatcherX11(q)
00380                            : new QEventDispatcherUNIX(q));
00381 }
00382 
00383 /*****************************************************************************
00384   Default X error handlers
00385  *****************************************************************************/
00386 
00387 #if defined(Q_C_CALLBACKS)
00388 extern "C" {
00389 #endif
00390 
00391 static int (*original_x_errhandler)(Display *dpy, XErrorEvent *);
00392 static int (*original_xio_errhandler)(Display *dpy);
00393 
00394 static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
00395 {
00396     if (err->error_code == BadWindow) {
00397         X11->seen_badwindow = true;
00398         if (err->request_code == 25 /* X_SendEvent */ && X11->xdndHandleBadwindow())
00399             return 0;
00400         if (X11->ignore_badwindow)
00401             return 0;
00402     } else if (err->request_code == X11->xinput_major
00403                 && err->error_code == (X11->xinput_errorbase + XI_BadDevice)
00404                 && err->minor_code == 3 /* X_OpenDevice */) {
00405         return 0;
00406     } else if (err->error_code == BadMatch && err->request_code == 42 /* X_SetInputFocus */) {
00407         return 0;
00408     }
00409 
00410     char errstr[256];
00411     XGetErrorText( dpy, err->error_code, errstr, 256 );
00412     char buffer[256];
00413     char request_str[256];
00414     qsnprintf(buffer, 256, "%d", err->request_code);
00415     XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256);
00416     if (err->request_code < 128) {
00417         // X error for a normal protocol request
00418         qWarning( "X Error: %s %d\n"
00419                   "  Major opcode: %d (%s)\n"
00420                   "  Resource id:  0x%lx",
00421                   errstr, err->error_code,
00422                   err->request_code,
00423                   request_str,
00424                   err->resourceid );
00425     } else {
00426         // X error for an extension request
00427         const char *extensionName = 0;
00428         if (err->request_code == X11->xrender_major)
00429             extensionName = "RENDER";
00430         else if (err->request_code == X11->xrandr_major)
00431             extensionName = "RANDR";
00432         else if (err->request_code == X11->xinput_major)
00433             extensionName = "XInputExtension";
00434 
00435         char minor_str[256];
00436         if (extensionName) {
00437             qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code);
00438             XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256);
00439         } else {
00440             extensionName = "Uknown extension";
00441             qsnprintf(minor_str, 256, "Unknown request");
00442         }
00443         qWarning( "X Error: %s %d\n"
00444                   "  Extension:    %d (%s)\n"
00445                   "  Minor opcode: %d (%s)\n"
00446                   "  Resource id:  0x%lx",
00447                   errstr, err->error_code,
00448                   err->request_code,
00449                   extensionName,
00450                   err->minor_code,
00451                   minor_str,
00452                   err->resourceid );
00453     }
00454 
00455     // ### we really should distinguish between severe, non-severe and
00456     // ### application specific errors
00457 
00458     return 0;
00459 }
00460 
00461 
00462 static int qt_xio_errhandler(Display *)
00463 {
00464     qWarning("%s: Fatal IO error: client killed", appName);
00465     QApplicationPrivate::reset_instance_pointer();
00466     exit(1);
00467     //### give the application a chance for a proper shutdown instead,
00468     //### exit(1) doesn't help.
00469     return 0;
00470 }
00471 
00472 #if defined(Q_C_CALLBACKS)
00473 }
00474 #endif
00475 
00476 
00477 static void qt_x11_create_intern_atoms()
00478 {
00479     const char *names[QX11Data::NAtoms];
00480     const char *ptr = x11_atomnames;
00481 
00482     int i = 0;
00483     while (*ptr) {
00484         names[i++] = ptr;
00485         while (*ptr)
00486             ++ptr;
00487         ++ptr;
00488     }
00489 
00490     Q_ASSERT(i == QX11Data::NPredefinedAtoms);
00491 
00492     QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
00493     settings_atom_name += XDisplayName(X11->displayName);
00494     names[i++] = settings_atom_name;
00495 
00496     Q_ASSERT(i == QX11Data::NAtoms);
00497 #if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6)
00498     XInternAtoms(X11->display, (char **)names, i, False, X11->atoms);
00499 #else
00500     for (i = 0; i < QX11Data::NAtoms; ++i)
00501         X11->atoms[i] = XInternAtom(X11->display, (char *)names[i], False);
00502 #endif
00503 }
00504 
00505 Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
00506 {
00507     QByteArray stamp;
00508     QDataStream s(&stamp, QIODevice::WriteOnly);
00509     s << QDateTime::currentDateTime();
00510 
00511     XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0),
00512                     ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8,
00513                     PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
00514 }
00515 
00519 bool QApplicationPrivate::x11_apply_settings()
00520 {
00521     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
00522 
00523     settings.beginGroup(QLatin1String("Qt"));
00524 
00525     /*
00526       Qt settings. This is now they are written into the datastream.
00527 
00528       Palette / *                - QPalette
00529       font                       - QFont
00530       libraryPath                - QStringList
00531       style                      - QString
00532       doubleClickInterval        - int
00533       keyboardInputInterval  - int
00534       cursorFlashTime            - int
00535       wheelScrollLines           - int
00536       colorSpec                  - QString
00537       defaultCodec               - QString
00538       globalStrut/width          - int
00539       globalStrut/height         - int
00540       GUIEffects                 - QStringList
00541       Font Substitutions/ *      - QStringList
00542       Font Substitutions/...     - QStringList
00543     */
00544 
00545     QStringList strlist;
00546     int i;
00547     QPalette pal(Qt::black);
00548     int groupCount = 0;
00549     strlist = settings.value(QLatin1String("Palette/active")).toStringList();
00550     if (strlist.count() == QPalette::NColorRoles) {
00551         ++groupCount;
00552         for (i = 0; i < QPalette::NColorRoles; i++)
00553             pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
00554                          QColor(strlist[i]));
00555     }
00556     strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
00557     if (strlist.count() == QPalette::NColorRoles) {
00558         ++groupCount;
00559         for (i = 0; i < QPalette::NColorRoles; i++)
00560             pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
00561                          QColor(strlist[i]));
00562     }
00563     strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
00564     if (strlist.count() == QPalette::NColorRoles) {
00565         ++groupCount;
00566         for (i = 0; i < QPalette::NColorRoles; i++)
00567             pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
00568                          QColor(strlist[i]));
00569     }
00570 
00571     if (groupCount == QPalette::NColorGroups)
00572         QApplicationPrivate::setSystemPalette(pal);
00573 
00574     if (!qt_app_has_font && !appFont) {
00575         QFont font(QApplication::font());
00576         QString str = settings.value(QLatin1String("font")).toString();
00577         if (!str.isEmpty()) {
00578             font.fromString(str);
00579             if (font != QApplication::font())
00580                 QApplication::setFont(font);
00581         }
00582     }
00583 
00584     // read library (ie. plugin) path list
00585     QString libpathkey =
00586         QString(QLatin1String("%1.%2/libraryPath"))
00587         .arg(QT_VERSION >> 16)
00588         .arg((QT_VERSION & 0xff00) >> 8);
00589     QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
00590     if (! pathlist.isEmpty()) {
00591         QStringList::ConstIterator it = pathlist.constBegin();
00592         while (it != pathlist.constEnd())
00593             QApplication::addLibraryPath(*it++);
00594     }
00595 
00596     // read new QStyle
00597     QString stylename = settings.value(QLatin1String("style")).toString();
00598     if (QCoreApplication::startingUp()) {
00599         if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
00600             QApplicationPrivate::styleOverride = new QString(stylename);
00601     } else {
00602         QApplication::setStyle(stylename);
00603     }
00604 
00605     int num =
00606         settings.value(QLatin1String("doubleClickInterval"),
00607                        QApplication::doubleClickInterval()).toInt();
00608     QApplication::setDoubleClickInterval(num);
00609 
00610     num =
00611         settings.value(QLatin1String("cursorFlashTime"),
00612                        QApplication::cursorFlashTime()).toInt();
00613     QApplication::setCursorFlashTime(num);
00614 
00615     num =
00616         settings.value(QLatin1String("wheelScrollLines"),
00617                        QApplication::wheelScrollLines()).toInt();
00618     QApplication::setWheelScrollLines(num);
00619 
00620     QString colorspec = settings.value(QLatin1String("colorSpec"),
00621                                        QVariant(QLatin1String("default"))).toString();
00622     if (colorspec == QLatin1String("normal"))
00623         QApplication::setColorSpec(QApplication::NormalColor);
00624     else if (colorspec == QLatin1String("custom"))
00625         QApplication::setColorSpec(QApplication::CustomColor);
00626     else if (colorspec == QLatin1String("many"))
00627         QApplication::setColorSpec(QApplication::ManyColor);
00628     else if (colorspec != QLatin1String("default"))
00629         colorspec = QLatin1String("default");
00630 
00631     QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
00632                                           QVariant(QLatin1String("none"))).toString();
00633     if (defaultcodec != QLatin1String("none")) {
00634         QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
00635         if (codec)
00636             QTextCodec::setCodecForTr(codec);
00637     }
00638 
00639     int w = settings.value(QLatin1String("globalStrut/width")).toInt();
00640     int h = settings.value(QLatin1String("globalStrut/height")).toInt();
00641     QSize strut(w, h);
00642     if (strut.isValid())
00643         QApplication::setGlobalStrut(strut);
00644 
00645     QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
00646     QApplication::setEffectEnabled(Qt::UI_General,
00647                                    effects.contains(QLatin1String("general")));
00648     QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
00649                                    effects.contains(QLatin1String("animatemenu")));
00650     QApplication::setEffectEnabled(Qt::UI_FadeMenu,
00651                                    effects.contains(QLatin1String("fademenu")));
00652     QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
00653                                    effects.contains(QLatin1String("animatecombo")));
00654     QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
00655                                    effects.contains(QLatin1String("animatetooltip")));
00656     QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
00657                                    effects.contains(QLatin1String("fadetooltip")));
00658     QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
00659                                    effects.contains(QLatin1String("animatetoolbox")));
00660 
00661     settings.beginGroup(QLatin1String("Font Substitutions"));
00662     QStringList fontsubs = settings.childKeys();
00663     if (!fontsubs.isEmpty()) {
00664         QStringList::Iterator it = fontsubs.begin();
00665         for (; it != fontsubs.end(); ++it) {
00666             QString fam = *it;
00667             QStringList subs = settings.value(fam).toStringList();
00668             QFont::insertSubstitutions(fam, subs);
00669         }
00670     }
00671     settings.endGroup();
00672 
00673     qt_broken_wm =
00674         settings.value(QLatin1String("brokenWindowManager"), qt_broken_wm).toBool();
00675 
00676     qt_use_rtl_extensions =
00677         settings.value(QLatin1String("useRtlExtensions"), false).toBool();
00678 
00679     qt_reuse_double_buffer =
00680         settings.value(QLatin1String("reuseDoubleBuffer"), true).toBool();
00681 
00682 #ifndef QT_NO_XIM
00683     if (qt_xim_preferred_style == 0) {
00684         QString ximInputStyle = settings.value(QLatin1String("XIMInputStyle"),
00685                                                QVariant(QLatin1String("on the spot"))).toString().toLower();
00686         if (ximInputStyle == QLatin1String("on the spot"))
00687             qt_xim_preferred_style = XIMPreeditCallbacks | XIMStatusNothing;
00688         else if (ximInputStyle == QLatin1String("over the spot"))
00689             qt_xim_preferred_style = XIMPreeditPosition | XIMStatusNothing;
00690         else if (ximInputStyle == QLatin1String("off the spot"))
00691             qt_xim_preferred_style = XIMPreeditArea | XIMStatusArea;
00692         else if (ximInputStyle == QLatin1String("root"))
00693             qt_xim_preferred_style = XIMPreeditNothing | XIMStatusNothing;
00694     }
00695 #endif
00696     QStringList inputMethods = QInputContextFactory::keys();
00697     if (inputMethods.size() > 2 && inputMethods.contains(QLatin1String("imsw-multi"))) {
00698         X11->default_im = QLatin1String("imsw-multi");
00699     } else {
00700         X11->default_im = settings.value(QLatin1String("DefaultInputMethod"),
00701                                          QLatin1String("xim")).toString();
00702     }
00703 
00704     settings.endGroup(); // Qt
00705 
00706     return true;
00707 }
00708 
00709 
00713 void QApplicationPrivate::reset_instance_pointer()
00714 { QApplication::self = 0; }
00715 
00716 
00717 // read the _QT_INPUT_ENCODING property and apply the settings to
00718 // the application
00719 static void qt_set_input_encoding()
00720 {
00721     Atom type;
00722     int format;
00723     ulong  nitems, after = 1;
00724     const char *data = 0;
00725 
00726     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
00727                                 ATOM(_QT_INPUT_ENCODING), 0, 1024,
00728                                 False, XA_STRING, &type, &format, &nitems,
00729                                 &after, (unsigned char**)&data);
00730     if (e != Success || !nitems || type == XNone) {
00731         // Always use the locale codec, since we have no examples of non-local
00732         // XIMs, and since we cannot get a sensible answer about the encoding
00733         // from the XIM.
00734         qt_input_mapper = QTextCodec::codecForLocale();
00735 
00736     } else {
00737         if (!qstricmp(data, "locale"))
00738             qt_input_mapper = QTextCodec::codecForLocale();
00739         else
00740             qt_input_mapper = QTextCodec::codecForName(data);
00741         // make sure we have an input codec
00742         if(!qt_input_mapper)
00743             qt_input_mapper = QTextCodec::codecForName("ISO 8859-1");
00744     }
00745     if (qt_input_mapper && qt_input_mapper->mibEnum() == 11) // 8859-8
00746         qt_input_mapper = QTextCodec::codecForName("ISO 8859-8-I");
00747     if(data)
00748         XFree((char *)data);
00749 }
00750 
00751 // set font, foreground and background from x11 resources. The
00752 // arguments may override the resource settings.
00753 static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
00754                                  const char* bg = 0, const char* button = 0)
00755 {
00756 
00757     QString resFont, resFG, resBG, resEF, sysFont, selectBackground, selectForeground;
00758 
00759     QApplication::setEffectEnabled(Qt::UI_General, false);
00760     QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
00761     QApplication::setEffectEnabled(Qt::UI_FadeMenu, false);
00762     QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
00763     QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, false);
00764     QApplication::setEffectEnabled(Qt::UI_FadeTooltip, false);
00765     QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, false);
00766 
00767     bool paletteAlreadySet = false;
00768     if (QApplication::desktopSettingsAware()) {
00769         // first, read from settings
00770         QApplicationPrivate::x11_apply_settings();
00771 
00772         // the call to QApplication::style() below creates the system
00773         // palette, which breaks the logic after the RESOURCE_MANAGER
00774         // loop... so I have to save this value to be able to use it later
00775         paletteAlreadySet = (QApplicationPrivate::sys_pal != 0);
00776 
00777         // second, parse the RESOURCE_MANAGER property
00778         int format;
00779         ulong  nitems, after = 1;
00780         QString res;
00781         long offset = 0;
00782         Atom type = XNone;
00783 
00784         while (after > 0) {
00785             uchar *data = 0;
00786             XGetWindowProperty(X11->display, QX11Info::appRootWindow(0),
00787                                ATOM(RESOURCE_MANAGER),
00788                                offset, 8192, False, AnyPropertyType,
00789                                &type, &format, &nitems, &after,
00790                                &data);
00791             if (type == XA_STRING)
00792                 res += QString::fromLatin1((char*)data);
00793             else
00794                 res += QString::fromLocal8Bit((char*)data);
00795             offset += 2048; // offset is in 32bit quantities... 8192/4 == 2048
00796             if (data)
00797                 XFree((char *)data);
00798         }
00799 
00800         QString key, value;
00801         int l = 0, r;
00802         QString apn = QString::fromLocal8Bit(appName);
00803         QString apc = QString::fromLocal8Bit(appClass);
00804         int apnl = apn.length();
00805         int apcl = apc.length();
00806         int resl = res.length();
00807 
00808         while (l < resl) {
00809             r = res.indexOf(QLatin1Char('\n'), l);
00810             if (r < 0)
00811                 r = resl;
00812             while (QUnicodeTables::isSpace(res.at(l)))
00813                 l++;
00814             bool mine = false;
00815             QChar sc = res.at(l + 1);
00816             if (res.at(l) == QLatin1Char('*') &&
00817                 (sc == QLatin1Char('f') || sc == QLatin1Char('b') || sc == QLatin1Char('g') ||
00818                  sc == QLatin1Char('F') || sc == QLatin1Char('B') || sc == QLatin1Char('G') ||
00819                  sc == QLatin1Char('s') || sc == QLatin1Char('S')
00820                  // capital T only, since we're looking for "Text.selectSomething"
00821                  || sc == QLatin1Char('T'))) {
00822                 // OPTIMIZED, since we only want "*[fbgsT].."
00823                 QString item = res.mid(l, r - l).simplified();
00824                 int i = item.indexOf(QLatin1Char(':'));
00825                 key = item.left(i).trimmed().mid(1).toLower();
00826                 value = item.right(item.length() - i - 1).trimmed();
00827                 mine = true;
00828             } else if (apnl && res.at(l) == apn.at(0) || (appClass && apcl && res.at(l) == apc.at(0))) {
00829                 if (res.mid(l,apnl) == apn && (res.at(l+apnl) == QLatin1Char('.')
00830                                                || res.at(l+apnl) == QLatin1Char('*'))) {
00831                     QString item = res.mid(l, r - l).simplified();
00832                     int i = item.indexOf(QLatin1Char(':'));
00833                     key = item.left(i).trimmed().mid(apnl+1).toLower();
00834                     value = item.right(item.length() - i - 1).trimmed();
00835                     mine = true;
00836                 } else if (res.mid(l,apcl) == apc && (res.at(l+apcl) == QLatin1Char('.')
00837                                                       || res.at(l+apcl) == QLatin1Char('*'))) {
00838                     QString item = res.mid(l, r - l).simplified();
00839                     int i = item.indexOf(QLatin1Char(':'));
00840                     key = item.left(i).trimmed().mid(apcl+1).toLower();
00841                     value = item.right(item.length() - i - 1).trimmed();
00842                     mine = true;
00843                 }
00844             }
00845 
00846             if (mine) {
00847                 if (!font && key == QLatin1String("systemfont"))
00848                     sysFont = value.left(value.lastIndexOf(QLatin1Char(':')));
00849                 if (!font && key == QLatin1String("font"))
00850                     resFont = value;
00851                 else if (!fg && !paletteAlreadySet) {
00852                     if (key == QLatin1String("foreground"))
00853                         resFG = value;
00854                     else if (!bg && key == QLatin1String("background"))
00855                         resBG = value;
00856                     else if (key == QLatin1String("text.selectbackground")) {
00857                         selectBackground = value;
00858                     } else if (key == QLatin1String("text.selectforeground")) {
00859                         selectForeground = value;
00860                     }
00861                 } else if (key == QLatin1String("guieffects"))
00862                     resEF = value;
00863                 // NOTE: if you add more, change the [fbg] stuff above
00864             }
00865 
00866             l = r + 1;
00867         }
00868     }
00869     if (!sysFont.isEmpty())
00870         resFont = sysFont;
00871     if (resFont.isEmpty())
00872         resFont = QString::fromLocal8Bit(font);
00873     if (resFG.isEmpty())
00874         resFG = QString::fromLocal8Bit(fg);
00875     if (resBG.isEmpty())
00876         resBG = QString::fromLocal8Bit(bg);
00877     if (!qt_app_has_font && !resFont.isEmpty()) { // set application font
00878         QFont fnt;
00879         fnt.setRawName(resFont);
00880 
00881         // the font we get may actually be an alias for another font,
00882         // so we reset the application font to the real font info.
00883         if (! fnt.exactMatch()) {
00884             QFontInfo fontinfo(fnt);
00885             fnt.setFamily(fontinfo.family());
00886             fnt.setRawMode(fontinfo.rawMode());
00887 
00888             if (! fnt.rawMode()) {
00889                 fnt.setItalic(fontinfo.italic());
00890                 fnt.setWeight(fontinfo.weight());
00891                 fnt.setUnderline(fontinfo.underline());
00892                 fnt.setStrikeOut(fontinfo.strikeOut());
00893                 fnt.setStyleHint(fontinfo.styleHint());
00894 
00895                 if (fnt.pointSize() <= 0 && fnt.pixelSize() <= 0) {
00896                     // size is all wrong... fix it
00897                     qreal pointSize = fontinfo.pixelSize() * 72. / (float) QX11Info::appDpiY();
00898                     if (pointSize <= 0)
00899                         pointSize = 12;
00900                     fnt.setPointSize(qRound(pointSize));
00901                 }
00902             }
00903         }
00904 
00905         if (fnt != QApplication::font()) {
00906             QApplication::setFont(fnt);
00907         }
00908     }
00909 
00910     if ((button || !resBG.isEmpty() || !resFG.isEmpty())) {// set app colors
00911         (void) QApplication::style();  // trigger creation of application style and system palettes
00912         QColor btn;
00913         QColor bg;
00914         QColor fg;
00915         if (!resBG.isEmpty())
00916             bg = QColor(resBG);
00917         if (!bg.isValid())
00918             bg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Window);
00919 
00920         if (!resFG.isEmpty())
00921             fg = QColor(resFG);
00922         if (!fg.isValid())
00923             fg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::WindowText);
00924 
00925         if (button)
00926             btn = QColor(QString::fromLocal8Bit(button));
00927         else if (!resBG.isEmpty())
00928             btn = bg;
00929         if (!btn.isValid())
00930             btn = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Button);
00931 
00932         int h,s,v;
00933         fg.getHsv(&h,&s,&v);
00934         QColor base = Qt::white;
00935         bool bright_mode = false;
00936         if (v >= 255-50) {
00937             base = btn.dark(150);
00938             bright_mode = true;
00939         }
00940 
00941         QPalette pal(fg, btn, btn.light(), btn.dark(), btn.dark(150), fg, Qt::white, base, bg);
00942         QColor disabled((fg.red()   + btn.red())  / 2,
00943                         (fg.green() + btn.green())/ 2,
00944                         (fg.blue()  + btn.blue()) / 2);
00945         pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.light(125),
00946                           btn.dark(), btn.dark(150), disabled, Qt::white, Qt::white, bg);
00947 
00948         QColor highlight, highlightText;
00949         if (!selectBackground.isEmpty() && !selectForeground.isEmpty()) {
00950             highlight = QColor(selectBackground);
00951             highlightText = QColor(selectForeground);
00952         }
00953 
00954         if (highlight.isValid() && highlightText.isValid()) {
00955             pal.setColor(QPalette::Highlight, highlight);
00956             pal.setColor(QPalette::HighlightedText, highlightText);
00957 
00958             // calculate disabled colors by removing saturation
00959             highlight.setHsv(highlight.hue(), 0, highlight.value(), highlight.alpha());
00960             highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha());
00961             pal.setColor(QPalette::Disabled, QPalette::Highlight, highlight);
00962             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText);
00963         } else if (bright_mode) {
00964             pal.setColor(QPalette::HighlightedText, base);
00965             pal.setColor(QPalette::Highlight, Qt::white);
00966             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base);
00967             pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white);
00968         } else {
00969             pal.setColor(QPalette::HighlightedText, Qt::white);
00970             pal.setColor(QPalette::Highlight, Qt::darkBlue);
00971             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white);
00972             pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
00973         }
00974 
00975         QApplicationPrivate::setSystemPalette(pal);
00976     }
00977 
00978     if (!resEF.isEmpty()) {
00979         QStringList effects = resEF.split(QLatin1Char(' '));
00980         QApplication::setEffectEnabled(Qt::UI_General, effects.contains(QLatin1String("general")));
00981         QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
00982                                        effects.contains(QLatin1String("animatemenu")));
00983         QApplication::setEffectEnabled(Qt::UI_FadeMenu,
00984                                        effects.contains(QLatin1String("fademenu")));
00985         QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
00986                                        effects.contains(QLatin1String("animatecombo")));
00987         QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
00988                                        effects.contains(QLatin1String("animatetooltip")));
00989         QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
00990                                        effects.contains(QLatin1String("fadetooltip")));
00991         QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
00992                                        effects.contains(QLatin1String("animatetoolbox")));
00993     }
00994 }
00995 
00996 
00997 static void qt_detect_broken_window_manager()
00998 {
00999     Atom type;
01000     int format;
01001     ulong nitems, after;
01002     uchar *data = 0;
01003 
01004     // look for SGI's 4Dwm
01005     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
01006                                ATOM(_SGI_DESKS_MANAGER), 0, 1, False, XA_WINDOW,
01007                                &type, &format, &nitems, &after, &data);
01008     if (data)
01009         XFree(data);
01010 
01011     if (e == Success && type == XA_WINDOW && format == 32 && nitems == 1 && after == 0) {
01012         // detected SGI 4Dwm
01013         qt_broken_wm = true;
01014     }
01015 }
01016 
01017 
01018 // update the supported array
01019 static void qt_get_net_supported()
01020 {
01021     Atom type;
01022     int format;
01023     long offset = 0;
01024     unsigned long nitems, after;
01025     unsigned char *data = 0;
01026 
01027     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
01028                                ATOM(_NET_SUPPORTED), 0, 0,
01029                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
01030     if (data)
01031         XFree(data);
01032 
01033     if (X11->net_supported_list)
01034         delete [] X11->net_supported_list;
01035     X11->net_supported_list = 0;
01036 
01037     if (e == Success && type == XA_ATOM && format == 32) {
01038         QBuffer ts;
01039         ts.open(QIODevice::WriteOnly);
01040 
01041         while (after > 0) {
01042             XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
01043                                ATOM(_NET_SUPPORTED), offset, 1024,
01044                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
01045 
01046             if (type == XA_ATOM && format == 32) {
01047                 ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long));
01048                 offset += nitems;
01049             } else
01050                 after = 0;
01051             if (data)
01052                 XFree(data);
01053         }
01054 
01055         // compute nitems
01056         QByteArray buffer(ts.buffer());
01057         nitems = buffer.size() / sizeof(Atom);
01058         X11->net_supported_list = new Atom[nitems + 1];
01059         Atom *a = (Atom *) buffer.data();
01060         uint i;
01061         for (i = 0; i < nitems; i++)
01062             X11->net_supported_list[i] = a[i];
01063         X11->net_supported_list[nitems] = 0;
01064     }
01065 }
01066 
01067 
01068 bool qt_net_supports(Atom atom)
01069 {
01070     if (! X11->net_supported_list)
01071         return false;
01072 
01073     bool supported = false;
01074     int i = 0;
01075     while (X11->net_supported_list[i] != 0) {
01076         if (X11->net_supported_list[i++] == atom) {
01077             supported = true;
01078             break;
01079         }
01080     }
01081 
01082     return supported;
01083 }
01084 
01085 
01086 // update the virtual roots array
01087 static void qt_get_net_virtual_roots()
01088 {
01089     if (X11->net_virtual_root_list)
01090         delete [] X11->net_virtual_root_list;
01091     X11->net_virtual_root_list = 0;
01092 
01093     if (!qt_net_supports(ATOM(_NET_VIRTUAL_ROOTS)))
01094         return;
01095 
01096     Atom type;
01097     int format;
01098     long offset = 0;
01099     unsigned long nitems, after;
01100     unsigned char *data;
01101 
01102     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
01103                                ATOM(_NET_VIRTUAL_ROOTS), 0, 0,
01104                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
01105     if (data)
01106         XFree(data);
01107 
01108     if (e == Success && type == XA_ATOM && format == 32) {
01109         QBuffer ts;
01110         ts.open(QIODevice::WriteOnly);
01111 
01112         while (after > 0) {
01113             XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
01114                                ATOM(_NET_VIRTUAL_ROOTS), offset, 1024,
01115                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
01116 
01117             if (type == XA_ATOM && format == 32) {
01118                 ts.write(reinterpret_cast<char *>(data), nitems * 4);
01119                 offset += nitems;
01120             } else
01121                 after = 0;
01122             if (data)
01123                 XFree(data);
01124         }
01125 
01126         // compute nitems
01127         QByteArray buffer(ts.buffer());
01128         nitems = buffer.size() / sizeof(Window);
01129         X11->net_virtual_root_list = new Window[nitems + 1];
01130         Window *a = (Window *) buffer.data();
01131         uint i;
01132         for (i = 0; i < nitems; i++)
01133             X11->net_virtual_root_list[i] = a[i];
01134         X11->net_virtual_root_list[nitems] = 0;
01135     }
01136 }
01137 
01138 static void qt_net_update_user_time(QWidget *tlw)
01139 {
01140     Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created));
01141     XChangeProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME),
01142                     XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &X11->userTime, 1);
01143 }
01144 
01145 static void qt_check_focus_model()
01146 {
01147     Window fw = XNone;
01148     int unused;
01149     XGetInputFocus(X11->display, &fw, &unused);
01150     if (fw == PointerRoot)
01151         X11->focus_model = QX11Data::FM_PointerRoot;
01152     else
01153         X11->focus_model = QX11Data::FM_Other;
01154 }
01155 
01156 #ifndef QT_NO_TABLET
01157 static bool isXInputSupported(Display *dpy)
01158 {
01159     Bool exists;
01160     XExtensionVersion *version;
01161     exists = XQueryExtension(dpy, "XInputExtension", &X11->xinput_major,
01162                              &X11->xinput_eventbase, &X11->xinput_errorbase);
01163     if (!exists)
01164         return false;
01165     version = XGetExtensionVersion(dpy, "XInputExtension");
01166     if (!version || version == reinterpret_cast<XExtensionVersion *>(NoSuchExtension))
01167         return false;
01168 
01169     XFree(version);
01170     return true;
01171 }
01172 #endif
01173 
01174 /*****************************************************************************
01175   qt_init() - initializes Qt for X11
01176  *****************************************************************************/
01177 
01178 #if !defined(QT_NO_FONTCONFIG)
01179 static void getXDefault(const char *group, const char *key, int *val)
01180 {
01181     char *str = XGetDefault(X11->display, group, key);
01182     if (str) {
01183         char *end = 0;
01184         int v = strtol(str, &end, 0);
01185         if (str != end)
01186             *val = v;
01187     }
01188 }
01189 
01190 static void getXDefault(const char *group, const char *key, double *val)
01191 {
01192     char *str = XGetDefault(X11->display, group, key);
01193     if (str) {
01194         char *end = 0;
01195         double v = strtod(str, &end);
01196         if (str != end)
01197             *val = v;
01198     }
01199 }
01200 
01201 static void getXDefault(const char *group, const char *key, bool *val)
01202 {
01203     char *str = XGetDefault(X11->display, group, key);
01204     if (str) {
01205         char c = str[0];
01206         if (isupper((int)c))
01207             c = tolower(c);
01208         if (c == 't' || c == 'y' || c == '1')
01209             *val = true;
01210         else if (c == 'f' || c == 'n' || c == '0')
01211             *val = false;
01212         if (c == 'o') {
01213             c = str[1];
01214             if (isupper((int)c))
01215                 c = tolower(c);
01216             if (c == 'n')
01217                 *val = true;
01218             if (c == 'f')
01219                 *val = false;
01220         }
01221     }
01222 }
01223 #endif
01224 
01225 // ### This should be static but it isn't because of the friend declaration
01226 // ### in qpaintdevice.h which then should have a static too but can't have
01227 // ### it because "storage class specifiers invalid in friend function
01228 // ### declarations" :-) Ideas anyone?
01229 void qt_init(QApplicationPrivate *priv, int,
01230        Display *display, Qt::HANDLE visual, Qt::HANDLE colormap)
01231 {
01232     X11 = new QX11Data;
01233     X11->display = display;
01234     X11->displayName = 0;
01235     X11->foreignDisplay = (display != 0);
01236     X11->focus_model = -1;
01237 
01238     // RANDR
01239     X11->use_xrandr = false;
01240     X11->xrandr_major = 0;
01241     X11->xrandr_eventbase = 0;
01242     X11->xrandr_errorbase = 0;
01243 
01244     // RENDER
01245     X11->use_xrender = false;
01246     X11->xrender_major = 0;
01247     X11->xrender_version = 0;
01248 
01249     // XFIXES
01250     X11->use_xfixes = false;
01251     X11->xfixes_major = 0;
01252     X11->xfixes_eventbase = 0;
01253     X11->xfixes_errorbase = 0;
01254 
01255     // XInputExtension
01256     X11->use_xinput = false;
01257     X11->xinput_major = 0;
01258     X11->xinput_eventbase = 0;
01259     X11->xinput_errorbase = 0;
01260 
01261     X11->sip_serial = 0;
01262     X11->net_supported_list = 0;
01263     X11->net_virtual_root_list = 0;
01264     X11->wm_client_leader = 0;
01265     X11->screens = 0;
01266     X11->screenCount = 0;
01267     X11->time = CurrentTime;
01268     X11->userTime = CurrentTime;
01269     X11->ignore_badwindow = false;
01270     X11->seen_badwindow = false;
01271 
01272     X11->motifdnd_active = false;
01273 
01274     X11->default_im = QLatin1String("imsw-multi");
01275     priv->inputContext = 0;
01276 
01277     // colormap control
01278     X11->visual_class = -1;
01279     X11->visual_id = -1;
01280     X11->color_count = 0;
01281     X11->custom_cmap = false;
01282 
01283     // outside visual/colormap
01284     X11->visual = reinterpret_cast<Visual *>(visual);
01285     X11->colormap = colormap;
01286 
01287 #ifndef QT_NO_XRENDER
01288     memset(X11->solid_fills, 0, sizeof(X11->solid_fills));
01289     for (int i = 0; i < X11->solid_fill_count; ++i)
01290         X11->solid_fills[i].screen = -1;
01291     memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills));
01292     for (int i = 0; i < X11->pattern_fill_count; ++i)
01293         X11->pattern_fills[i].screen = -1;
01294 #endif
01295 
01296     X11->startupId = 0;
01297 
01298     int argc = priv->argc;
01299     char **argv = priv->argv;
01300 
01301     if (X11->display) {
01302         // Qt part of other application
01303 
01304         // Set application name and class
01305         appName = qstrdup("Qt-subapplication");
01306         char *app_class = 0;
01307         if (argv) {
01308             const char* p = strrchr(argv[0], '/');
01309             app_class = qstrdup(p ? p + 1 : argv[0]);
01310             if (app_class[0])
01311                 app_class[0] = toupper(app_class[0]);
01312         }
01313         appClass = app_class;
01314     } else {
01315         // Qt controls everything (default)
01316 
01317         // Set application name and class
01318         char *app_class = 0;
01319         if (argv && argv[0]) {
01320             const char *p = strrchr(argv[0], '/');
01321             appName = p ? p + 1 : argv[0];
01322             app_class = qstrdup(appName);
01323             if (app_class[0])
01324                 app_class[0] = toupper(app_class[0]);
01325         }
01326         appClass = app_class;
01327     }
01328 
01329     // Install default error handlers
01330     original_x_errhandler = XSetErrorHandler(qt_x_errhandler);
01331     original_xio_errhandler = XSetIOErrorHandler(qt_xio_errhandler);
01332 
01333     // Get command line params
01334     int j = argc ? 1 : 0;
01335     for (int i=1; i<argc; i++) {
01336         if (argv[i] && *argv[i] != '-') {
01337             argv[j++] = argv[i];
01338             continue;
01339         }
01340         QByteArray arg(argv[i]);
01341         if (arg == "-display") {
01342             if (++i < argc && !X11->display)
01343                 X11->displayName = argv[i];
01344         } else if (arg == "-fn" || arg == "-font") {
01345             if (++i < argc)
01346                 appFont = argv[i];
01347         } else if (arg == "-bg" || arg == "-background") {
01348             if (++i < argc)
01349                 appBGCol = argv[i];
01350         } else if (arg == "-btn" || arg == "-button") {
01351             if (++i < argc)
01352                 appBTNCol = argv[i];
01353         } else if (arg == "-fg" || arg == "-foreground") {
01354             if (++i < argc)
01355                 appFGCol = argv[i];
01356         } else if (arg == "-name") {
01357             if (++i < argc)
01358                 appName = argv[i];
01359         } else if (arg == "-title") {
01360             if (++i < argc)
01361                 mwTitle = argv[i];
01362         } else if (arg == "-geometry") {
01363             if (++i < argc)
01364                 mwGeometry = argv[i];
01365         } else if (arg == "-im") {
01366             if (++i < argc)
01367                 qt_ximServer = argv[i];
01368 #if 0
01369         } else if (arg == "-noxim") {
01370             noxim=true;
01371 #endif
01372         } else if (arg == "-ncols") {   // xv and netscape use this name
01373             if (++i < argc)
01374                 X11->color_count = qMax(0,atoi(argv[i]));
01375         } else if (arg == "-visual") {  // xv and netscape use this name
01376             if (++i < argc && !X11->visual) {
01377                 QString s = QString::fromLocal8Bit(argv[i]).toLower();
01378                 if (s == QLatin1String("staticgray"))
01379                     X11->visual_class = StaticGray;
01380                 else if (s == QLatin1String("grayscale"))
01381                     X11->visual_class = XGrayScale;
01382                 else if (s == QLatin1String("staticcolor"))
01383                     X11->visual_class = StaticColor;
01384                 else if (s == QLatin1String("pseudocolor"))
01385                     X11->visual_class = PseudoColor;
01386                 else if (s == QLatin1String("truecolor"))
01387                     X11->visual_class = TrueColor;
01388                 else if (s == QLatin1String("directcolor"))
01389                     X11->visual_class = DirectColor;
01390                 else
01391                     X11->visual_id = static_cast<int>(strtol(argv[i], 0, 0));
01392             }
01393 #ifndef QT_NO_XIM
01394         } else if (arg == "-inputstyle") {
01395             if (++i < argc) {
01396                 QString s = QString::fromLocal8Bit(argv[i]).toLower();
01397                 if (s == QLatin1String("onthespot"))
01398                     qt_xim_preferred_style = XIMPreeditCallbacks |
01399                                              XIMStatusNothing;
01400                 else if (s == QLatin1String("overthespot"))
01401                     qt_xim_preferred_style = XIMPreeditPosition |
01402                                              XIMStatusNothing;
01403                 else if (s == QLatin1String("offthespot"))
01404                     qt_xim_preferred_style = XIMPreeditArea |
01405                                              XIMStatusArea;
01406                 else if (s == QLatin1String("root"))
01407                     qt_xim_preferred_style = XIMPreeditNothing |
01408                                              XIMStatusNothing;
01409             }
01410 #endif
01411         } else if (arg == "-cmap") {    // xv uses this name
01412             if (!X11->colormap)
01413                 X11->custom_cmap = true;
01414         }
01415 #if defined(QT_DEBUG)
01416         else if (arg == "-sync")
01417             appSync = !appSync;
01418         else if (arg == "-nograb")
01419             appNoGrab = !appNoGrab;
01420         else if (arg == "-dograb")
01421             appDoGrab = !appDoGrab;
01422 #endif
01423         else
01424             argv[j++] = argv[i];
01425     }
01426 
01427     priv->argc = j;
01428 
01429 #if defined(QT_DEBUG) && defined(Q_OS_LINUX)
01430     if (!appNoGrab && !appDoGrab) {
01431         QString s;
01432         s.sprintf("/proc/%d/cmdline", getppid());
01433         QFile f(s);
01434         if (f.open(QIODevice::ReadOnly)) {
01435             s.clear();
01436             char c;
01437             while (f.getChar(&c) && c) {
01438                 if (c == '/')
01439                     s.clear();
01440                 else
01441                     s += QLatin1Char(c);
01442             }
01443             if (s == QLatin1String("gdb")) {
01444                 appNoGrab = true;
01445                 qDebug("Qt: gdb: -nograb added to command-line options.\n"
01446                        "\t Use the -dograb option to enforce grabbing.");
01447             }
01448             f.close();
01449         }
01450     }
01451 #endif
01452 
01453     // Connect to X server
01454     if (qt_is_gui_used && !X11->display) {
01455         if ((X11->display = XOpenDisplay(X11->displayName)) == 0) {
01456             qWarning("%s: cannot connect to X server %s", appName,
01457                      XDisplayName(X11->displayName));
01458             QApplicationPrivate::reset_instance_pointer();
01459             exit(1);
01460         }
01461 
01462         if (appSync)                                // if "-sync" argument
01463             XSynchronize(X11->display, true);
01464     }
01465 
01466     // Common code, regardless of whether display is foreign.
01467 
01468     // Get X parameters
01469 
01470     if (qt_is_gui_used) {
01471         X11->defaultScreen = DefaultScreen(X11->display);
01472         X11->screenCount = ScreenCount(X11->display);
01473 
01474         X11->screens = new QX11InfoData[X11->screenCount];
01475 
01476         for (int s = 0; s < X11->screenCount; s++) {
01477             QX11InfoData *screen = X11->screens + s;
01478             screen->ref = 1; // ensures it doesn't get deleted
01479             screen->screen = s;
01480             screen->dpiX = (DisplayWidth(X11->display, s) * 254 + DisplayWidthMM(X11->display, s)*5)
01481                            / (DisplayWidthMM(X11->display, s)*10);
01482             screen->dpiY = (DisplayHeight(X11->display, s) * 254 + DisplayHeightMM(X11->display, s)*5)
01483                            / (DisplayHeightMM(X11->display, s)*10);
01484         }
01485 
01486         QColormap::initialize();
01487 
01488         // Support protocols
01489         X11->xdndSetup();
01490 
01491         // Finally create all atoms
01492         qt_x11_create_intern_atoms();
01493 
01494         // look for broken window managers
01495         qt_detect_broken_window_manager();
01496 
01497         // initialize NET lists
01498         qt_get_net_supported();
01499         qt_get_net_virtual_roots();
01500 
01501 #ifndef QT_NO_XRANDR
01502         // See if XRandR is supported on the connected display
01503         if (XQueryExtension(X11->display, "RANDR", &X11->xrandr_major,
01504                             &X11->xrandr_eventbase, &X11->xrandr_errorbase)
01505             && XRRQueryExtension(X11->display, &X11->xrandr_eventbase, &X11->xrandr_errorbase)) {
01506             // XRandR is supported
01507             X11->use_xrandr = true;
01508         }
01509 #endif // QT_NO_XRANDR
01510 
01511 #ifndef QT_NO_XRENDER
01512         int xrender_eventbase,  xrender_errorbase;
01513         // See if XRender is supported on the connected display
01514         if (XQueryExtension(X11->display, "RENDER", &X11->xrender_major,
01515                             &xrender_eventbase, &xrender_errorbase)
01516             && XRenderQueryExtension(X11->display, &xrender_eventbase,
01517                                      &xrender_errorbase)) {
01518             // XRender is supported, let's see if we have a PictFormat for the
01519             // default visual
01520             XRenderPictFormat *format =
01521                 XRenderFindVisualFormat(X11->display,
01522                                         (Visual *) QX11Info::appVisual(X11->defaultScreen));
01523             // Check the version as well - we need v0.4 or higher
01524             int major = 0;
01525             int minor = 0;
01526             XRenderQueryVersion(X11->display, &major, &minor);
01527             if (qgetenv("QT_X11_NO_XRENDER").isNull() && format != 0) {
01528                 X11->use_xrender = (major >= 0 && minor >= 5);
01529                 X11->xrender_version = major*100+minor;
01530                 // workaround for broken XServer on Ubuntu Breezy (6.8 compiled with 7.0
01531                 // protocol headers)
01532                 if (X11->xrender_version == 10
01533                     && VendorRelease(X11->display) < 60900000
01534                     && QByteArray(ServerVendor(X11->display)).contains("X.Org"))
01535                     X11->xrender_version = 9;
01536             }
01537         }
01538 #endif // QT_NO_XRENDER
01539 
01540 #ifndef QT_NO_XFIXES
01541         // See if Xfixes is supported on the connected display
01542         if (XQueryExtension(X11->display, "XFIXES", &X11->xfixes_major,
01543                             &X11->xfixes_eventbase, &X11->xfixes_errorbase)
01544             && XFixesQueryExtension(X11->display, &X11->xfixes_eventbase,
01545                                     &X11->xfixes_errorbase)) {
01546             // Xfixes is supported.
01547             // Note: the XFixes protocol version is negotiated using QueryVersion.
01548             // We supply the highest version we support, the X server replies with
01549             // the highest version it supports, but no higher than the version we
01550             // asked for. The version sent back is the protocol version the X server
01551             // will use to talk us. If this call is removed, the behavior of the
01552             // X server when it receives an XFixes request is undefined.
01553             int major = 3;
01554             int minor = 0;
01555             XFixesQueryVersion(X11->display, &major, &minor);
01556             X11->use_xfixes = (major >= 2);
01557             X11->xfixes_major = major;
01558         }
01559 #endif // QT_NO_XFIXES
01560 
01561         X11->has_fontconfig = false;
01562 #if !defined(QT_NO_FONTCONFIG)
01563         if (qgetenv("QT_X11_NO_FONTCONFIG").isNull())
01564             X11->has_fontconfig = FcInit();
01565 
01566         int dpi = 0;
01567         getXDefault("Xft", FC_DPI, &dpi);
01568         if (dpi) {
01569             for (int s = 0; s < ScreenCount(X11->display); ++s) {
01570                 QX11Info::setAppDpiX(s, dpi);
01571                 QX11Info::setAppDpiY(s, dpi);
01572             }
01573         }
01574         X11->fc_scale = 1.;
01575         getXDefault("Xft", FC_SCALE, &X11->fc_scale);
01576         for (int s = 0; s < ScreenCount(X11->display); ++s) {
01577             int subpixel = FC_RGBA_UNKNOWN;
01578 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
01579             if (X11->use_xrender) {
01580                 int rsp = XRenderQuerySubpixelOrder(X11->display, s);
01581                 switch (rsp) {
01582                 default:
01583                 case SubPixelUnknown:
01584                     subpixel = FC_RGBA_UNKNOWN;
01585                     break;
01586                 case SubPixelHorizontalRGB:
01587                     subpixel = FC_RGBA_RGB;
01588                     break;
01589                 case SubPixelHorizontalBGR:
01590                     subpixel = FC_RGBA_BGR;
01591                     break;
01592                 case SubPixelVerticalRGB:
01593                     subpixel = FC_RGBA_VRGB;
01594                     break;
01595                 case SubPixelVerticalBGR:
01596                     subpixel = FC_RGBA_VBGR;
01597                     break;
01598                 case SubPixelNone:
01599                     subpixel = FC_RGBA_NONE;
01600                     break;
01601                 }
01602             }
01603 #endif
01604             getXDefault("Xft", FC_RGBA, &subpixel);
01605             X11->screens[s].subpixel = subpixel;
01606         }
01607         X11->fc_antialias = true;
01608         getXDefault("Xft", FC_ANTIALIAS, &X11->fc_antialias);
01609 #ifdef FC_HINT_STYLE
01610         getXDefault("Xft", FC_HINT_STYLE, &X11->fc_hint_style);
01611 #endif
01612 #if 0
01613         // ###### these are implemented by Xft, not sure we need them
01614         getXDefault("Xft", FC_AUTOHINT, &X11->fc_autohint);
01615         getXDefault("Xft", FC_HINTING, &X11->fc_autohint);
01616         getXDefault("Xft", FC_MINSPACE, &X11->fc_autohint);
01617 #endif
01618 #endif // QT_NO_XRENDER
01619 
01620         // initialize key mapper
01621         QKeyMapper::changeKeyboard();
01622 
01623 #ifndef QT_NO_XKB
01624         if (qt_keymapper_private()->useXKB) {
01625             // If XKB is detected, set the GrabsUseXKBState option so input method
01626             // compositions continue to work (ie. deadkeys)
01627             unsigned int state = XkbPCF_GrabsUseXKBStateMask;
01628             (void) XkbSetPerClientControls(X11->display, state, &state);
01629         }
01630 #endif // QT_NO_XKB
01631 
01632         // Misc. initialization
01633 #if 0 //disabled for now..
01634         QSegfaultHandler::initialize(priv->argv, priv->argc);
01635 #endif
01636         QFont::initialize();
01637         QCursorData::initialize();
01638     }
01639 
01640     if(qt_is_gui_used) {
01641         qApp->setObjectName(QString::fromLocal8Bit(appName));
01642 
01643         int screen;
01644         for (screen = 0; screen < X11->screenCount; ++screen) {
01645             XSelectInput(X11->display, QX11Info::appRootWindow(screen),
01646                          KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask);
01647 
01648 #ifndef QT_NO_XRANDR
01649             if (X11->use_xrandr)
01650                 XRRSelectInput(X11->display, QX11Info::appRootWindow(screen), True);
01651 #endif // QT_NO_XRANDR
01652         }
01653     }
01654 
01655     if (qt_is_gui_used) {
01656         // Attempt to determine the current running X11 Desktop Enviornment
01657         // Use dbus if/when we can, but fall back to using windowManagerName() for now
01658 
01659         X11->desktopEnvironment = DE_UNKNOWN;
01660 
01661         // See if the current window manager is using the freedesktop.org spec to give its name
01662         Window windowManagerWindow = XNone;
01663         Atom typeReturned;
01664         int formatReturned;
01665         unsigned long nitemsReturned;
01666         unsigned long unused;
01667         unsigned char *data = 0;
01668         if (XGetWindowProperty(QX11Info::display(), QX11Info::appRootWindow(),
01669                            ATOM(_NET_SUPPORTING_WM_CHECK),
01670                            0, 1024, False, XA_WINDOW, &typeReturned,
01671                            &formatReturned, &nitemsReturned, &unused, &data)
01672               == Success) {
01673             if (typeReturned == XA_WINDOW && formatReturned == 32)
01674                 windowManagerWindow = *((Window*) data);
01675             if (data)
01676                 XFree(data);
01677 
01678             if (windowManagerWindow != XNone) {
01679                 QString wmName;
01680                 Atom utf8atom = ATOM(UTF8_STRING);
01681                 if (XGetWindowProperty(QX11Info::display(), windowManagerWindow, ATOM(_NET_WM_NAME),
01682                                        0, 1024, False, utf8atom, &typeReturned,
01683                                        &formatReturned, &nitemsReturned, &unused, &data)
01684                     == Success) {
01685                     if (typeReturned == utf8atom && formatReturned == 8)
01686                         wmName = QString::fromUtf8((const char*)data);
01687                     if (data)
01688                         XFree(data);
01689                     if (wmName == QLatin1String("KWin"))
01690                         X11->desktopEnvironment = DE_KDE;
01691                     if (wmName == QLatin1String("Metacity"))
01692                         X11->desktopEnvironment = DE_GNOME;
01693                 }
01694             }
01695         }
01696 
01697         // Running a different/newer/older window manager?  Try some other things
01698         if (X11->desktopEnvironment == DE_UNKNOWN){
01699             Atom type;
01700             int format;
01701             unsigned long length, after;
01702             uchar *data = 0;
01703 
01704             if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
01705                                    0, 1, False, AnyPropertyType, &type, &format, &length,
01706                                    &after, &data) == Success && length) {
01707                 // DTWM is running, meaning most likely CDE is running...
01708                 X11->desktopEnvironment = DE_CDE;
01709             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
01710                                           ATOM(GNOME_BACKGROUND_PROPERTIES), 0, 1, False, AnyPropertyType,
01711                                           &type, &format, &length, &after, &data) == Success && length) {
01712                 X11->desktopEnvironment = DE_GNOME;
01713             } else if ((XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KDE_FULL_SESSION),
01714                                            0, 1, False, AnyPropertyType, &type, &format, &length, &after, &data) == Success
01715                         && length)
01716                        || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWIN_RUNNING),
01717                                               0, 1, False, AnyPropertyType, &type, &format, &length,
01718                                               &after, &data) == Success
01719                            && length)
01720                        || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWM_RUNNING),
01721                                               0, 1, False, AnyPropertyType, &type, &format, &length,
01722                                               &after, &data) == Success && length)) {
01723                 X11->desktopEnvironment = DE_KDE;
01724             }
01725             if (data)
01726                 XFree((char *)data);
01727         }
01728 
01729         qt_set_input_encoding();
01730 
01731         qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol);
01732 
01733         // be smart about the size of the default font. most X servers have helvetica
01734         // 12 point available at 2 resolutions:
01735         //     75dpi (12 pixels) and 100dpi (17 pixels).
01736         // At 95 DPI, a 12 point font should be 16 pixels tall - in which case a 17
01737         // pixel font is a closer match than a 12 pixel font
01738         int ptsz = (X11->use_xrender
01739                     ? 9
01740                     : (int) (((QX11Info::appDpiY() >= 95 ? 17. : 12.) *
01741                               72. / (float) QX11Info::appDpiY()) + 0.5));
01742 
01743         if (!qt_app_has_font) {
01744             QFont f(X11->has_fontconfig ? QLatin1String("Sans Serif") : QLatin1String("Helvetica"),
01745                     ptsz);
01746             QApplication::setFont(f);
01747         }
01748 
01749 #if !defined (QT_NO_TABLET)
01750         if (isXInputSupported(X11->display)) {
01751             int ndev,
01752                 i,
01753                 j;
01754             bool gotStylus,
01755                 gotEraser;
01756             XDeviceInfo *devices, *devs;
01757             XInputClassInfo *ip;
01758             XAnyClassPtr any;
01759             XValuatorInfoPtr v;
01760             XAxisInfoPtr a;
01761             XDevice *dev;
01762 
01763 #if !defined(Q_OS_IRIX)
01764             // XFree86 divides a stylus and eraser into 2 devices, so we must do for both...
01765             const QString XFREENAMESTYLUS = QLatin1String("stylus");
01766             const QString XFREENAMEPEN = QLatin1String("pen");
01767             const QString XFREENAMEERASER = QLatin1String("eraser");
01768 #endif
01769 
01770             devices = XListInputDevices(X11->display, &ndev);
01771             if (!devices) {
01772                 qWarning("QApplication: Failed to get list of devices");
01773                 ndev = -1;
01774             }
01775             QTabletEvent::TabletDevice deviceType;
01776             dev = 0;
01777             for (devs = devices, i = 0; i < ndev; i++, devs++) {
01778                 gotStylus = false;
01779                 gotEraser = false;
01780 
01781                 QString devName = QString::fromLocal8Bit(devs->name).toLower();
01782 #if defined(Q_OS_IRIX)
01783                 if (devName == QLatin1String(WACOM_NAME)) {
01784                     deviceType = QTabletEvent::Stylus;
01785                     gotStylus = true;
01786                 }
01787 #else
01788                 if (devName.startsWith(XFREENAMEPEN)
01789                     || devName.startsWith(XFREENAMESTYLUS)) {
01790                     deviceType = QTabletEvent::Stylus;
01791                     gotStylus = true;
01792                 } else if (devName.startsWith(XFREENAMEERASER)) {
01793                     deviceType = QTabletEvent::XFreeEraser;
01794                     gotEraser = true;
01795                 }
01796 #endif
01797 
01798                 if (gotStylus || gotEraser) {
01799                     dev = XOpenDevice(X11->display, devs->id);
01800 
01801                     if (!dev)
01802                         continue;
01803 
01804                     QTabletDeviceData device_data;
01805                     device_data.deviceType = deviceType;
01806                     device_data.eventCount = 0;
01807                     device_data.device = dev;
01808                     device_data.xinput_motion = -1;
01809                     device_data.xinput_key_press = -1;
01810                     device_data.xinput_key_release = -1;
01811                     device_data.xinput_button_press = -1;
01812                     device_data.xinput_button_release = -1;
01813                     device_data.xinput_proximity_in = -1;
01814                     device_data.xinput_proximity_out = -1;
01815 
01816                     if (dev->num_classes > 0) {
01817                         for (ip = dev->classes, j = 0; j < devs->num_classes;
01818                              ip++, j++) {
01819                             switch (ip->input_class) {
01820                             case KeyClass:
01821                                 DeviceKeyPress(dev, device_data.xinput_key_press,
01822                                                device_data.eventList[device_data.eventCount]);
01823                                 if (device_data.eventList[device_data.eventCount])
01824                                     ++device_data.eventCount;
01825                                 DeviceKeyRelease(dev, device_data.xinput_key_release,
01826                                                  device_data.eventList[device_data.eventCount]);
01827                                 if (device_data.eventList[device_data.eventCount])
01828                                     ++device_data.eventCount;
01829                                 break;
01830                             case ButtonClass:
01831                                 DeviceButtonPress(dev, device_data.xinput_button_press,
01832                                                   device_data.eventList[device_data.eventCount]);
01833                                 if (device_data.eventList[device_data.eventCount])
01834                                     ++device_data.eventCount;
01835                                 DeviceButtonRelease(dev, device_data.xinput_button_release,
01836                                                     device_data.eventList[device_data.eventCount]);
01837                                 if (device_data.eventList[device_data.eventCount])
01838                                     ++device_data.eventCount;
01839                                 break;
01840                             case ValuatorClass:
01841                                 // I'm only going to be interested in motion when the
01842                                 // stylus is already down anyway!
01843                                 DeviceMotionNotify(dev, device_data.xinput_motion,
01844                                                    device_data.eventList[device_data.eventCount]);
01845                                 if (device_data.eventList[device_data.eventCount])
01846                                     ++device_data.eventCount;
01847                                 ProximityIn(dev, device_data.xinput_proximity_in, device_data.eventList[device_data.eventCount]);
01848                                 if (device_data.eventList[device_data.eventCount])
01849                                     ++device_data.eventCount;
01850                                 ProximityOut(dev, device_data.xinput_proximity_out, device_data.eventList[device_data.eventCount]);
01851                                 if (device_data.eventList[device_data.eventCount])
01852                                     ++device_data.eventCount;
01853                             default:
01854                                 break;
01855                             }
01856                         }
01857                     }
01858 
01859                     // get the min/max value for pressure!
01860                     any = (XAnyClassPtr) (devs->inputclassinfo);
01861                     for (j = 0; j < devs->num_classes; j++) {
01862                         if (any->c_class == ValuatorClass) {
01863                             v = (XValuatorInfoPtr) any;
01864                             a = (XAxisInfoPtr) ((char *) v +
01865                                                 sizeof (XValuatorInfo));
01866 #if defined (Q_OS_IRIX)
01867                             // I'm not exaclty wild about this, but the
01868                             // dimensions of the tablet are more relevant here
01869                             // than the min and max values from the axis
01870                             // (actually it seems to be 2/3 or what is in the
01871                             // axis.  So we'll try to parse it from this
01872                             // string. --tws
01873                             char returnString[SGIDeviceRtrnLen];
01874                             int tmp;
01875                             if (XSGIMiscQueryExtension(X11->display, &tmp, &tmp)
01876                                 && XSGIDeviceQuery(X11->display, devs->id,
01877                                                    "dimensions", returnString)) {
01878                                 QString str = QLatin1String(returnString);
01879                                 int comma = str.indexOf(',');
01880                                 device_data.minX = 0;
01881                                 device_data.minY = 0;
01882                                 device_data.maxX = str.left(comma).toInt();
01883                                 device_data.maxY = str.mid(comma + 1).toInt();
01884                             } else {
01885                                 device_data.minX = a[WAC_XCOORD_I].min_value;
01886                                 device_data.maxX = a[WAC_XCOORD_I].max_value;
01887                                 device_data.minY = a[WAC_YCOORD_I].min_value;
01888                                 device_data.maxY = a[WAC_YCOORD_I].max_value;
01889                             }
01890                             device_data.minPressure = a[WAC_PRESSURE_I].min_value;
01891                             device_data.maxPressure = a[WAC_PRESSURE_I].max_value;
01892                             device_data.minTanPressure = a[WAC_TAN_PRESSURE_I].min_value;
01893                             device_data.maxTanPressure = a[WAC_TAN_PRESSURE_I].max_value;
01894                             device_data.minZ = a[WAC_ZCOORD_I].min_value;
01895                             device_data.maxZ = a[WAC_ZCOORD_I].max_value;
01896 #else
01897                             device_data.minX = a[0].min_value;
01898                             device_data.maxX = a[0].max_value;
01899                             device_data.minY = a[1].min_value;
01900                             device_data.maxY = a[1].max_value;
01901                             device_data.minPressure = a[2].min_value;
01902                             device_data.maxPressure = a[2].max_value;
01903                             device_data.minTanPressure = 0;
01904                             device_data.maxTanPressure = 0;
01905                             device_data.minZ = 0;
01906                             device_data.maxZ = 0;
01907 #endif
01908 
01909                             // got the max pressure no need to go further...
01910                             break;
01911                         }
01912                         any = (XAnyClassPtr) ((char *) any + any->length);
01913                     } // end of for loop
01914 
01915                     tablet_devices()->append(device_data);
01916                 } // if (gotStylus || gotEraser)
01917             }
01918             XFreeDeviceList(devices);
01919         }
01920 #endif // QT_NO_TABLET
01921 
01922         X11->startupId = getenv("DESKTOP_STARTUP_ID");
01923         putenv(strdup("DESKTOP_STARTUP_ID="));
01924 
01925    } else {
01926         // read some non-GUI settings when not using the X server...
01927 
01928         if (QApplication::desktopSettingsAware()) {
01929             QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
01930             settings.beginGroup(QLatin1String("Qt"));
01931 
01932             // read library (ie. plugin) path list
01933             QString libpathkey = QString(QLatin1String("%1.%2/libraryPath"))
01934                                  .arg(QT_VERSION >> 16)
01935                                  .arg((QT_VERSION & 0xff00) >> 8);
01936             QStringList pathlist =
01937                 settings.value(libpathkey).toString().split(QLatin1Char(':'));
01938             if (! pathlist.isEmpty()) {
01939                 QStringList::ConstIterator it = pathlist.constBegin();
01940                 while (it != pathlist.constEnd())
01941                     QApplication::addLibraryPath(*it++);
01942             }
01943 
01944             QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
01945                                                   QVariant(QLatin1String("none"))).toString();
01946             if (defaultcodec != QLatin1String("none")) {
01947                 QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
01948                 if (codec)
01949                     QTextCodec::setCodecForTr(codec);
01950             }
01951 
01952             settings.endGroup(); // Qt
01953         }
01954     }
01955 }
01956 
01957 
01958     // run-time search for default style
01962 void QApplicationPrivate::x11_initialize_style()
01963 {
01964     if (QApplicationPrivate::app_style)
01965         return;
01966 
01967     switch(X11->desktopEnvironment) {
01968         case DE_KDE:
01969             QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique"));
01970             break;
01971         case DE_GNOME:
01972             QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks"));
01973             break;
01974         case DE_CDE:
01975             QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde"));
01976             break;
01977         default:
01978             // Don't do anything
01979             break;
01980     }
01981 }
01982 
01983 void QApplicationPrivate::initializeWidgetPaletteHash()
01984 {
01985 }
01986 
01987 /*****************************************************************************
01988   qt_cleanup() - cleans up when the application is finished
01989  *****************************************************************************/
01990 
01991 void qt_cleanup()
01992 {
01993     if (app_save_rootinfo)                        // root window must keep state
01994         qt_save_rootinfo();
01995 
01996     if (qt_is_gui_used) {
01997         QPixmapCache::clear();
01998         QCursorData::cleanup();
01999         QFont::cleanup();
02000         QColormap::cleanup();
02001     }
02002 
02003 #ifndef QT_NO_XRENDER
02004     for (int i = 0; i < X11->solid_fill_count; ++i) {
02005         if (X11->solid_fills[i].picture)
02006             XRenderFreePicture(X11->display, X11->solid_fills[i].picture);
02007     }
02008     for (int i = 0; i < X11->pattern_fill_count; ++i) {
02009         if (X11->pattern_fills[i].picture)
02010             XRenderFreePicture(X11->display, X11->pattern_fills[i].picture);
02011     }
02012 #endif
02013 #if !defined (QT_NO_TABLET)
02014     QTabletDeviceDataList *devices = qt_tablet_devices();
02015     for (int i = 0; i < devices->size(); ++i)
02016         XCloseDevice(X11->display, (XDevice*)devices->at(i).device);
02017 #endif
02018 
02019 #if !defined(QT_NO_IM)
02020     delete QApplicationPrivate::inputContext;
02021     QApplicationPrivate::inputContext = 0;
02022 #endif
02023 
02024     // Reset the error handlers
02025     XSetErrorHandler(original_x_errhandler);
02026     XSetIOErrorHandler(original_xio_errhandler);
02027 
02028     if (qt_is_gui_used && !X11->foreignDisplay)
02029         XCloseDisplay(X11->display);                // close X display
02030     X11->display = 0;
02031 
02032     delete [] X11->screens;
02033 
02034     if (X11->foreignDisplay) {
02035         delete [] (char *)appName;
02036         appName = 0;
02037     }
02038 
02039     delete [] (char *)appClass;
02040     appClass = 0;
02041 
02042     if (X11->net_supported_list)
02043         delete [] X11->net_supported_list;
02044     X11->net_supported_list = 0;
02045 
02046     if (X11->net_virtual_root_list)
02047         delete [] X11->net_virtual_root_list;
02048     X11->net_virtual_root_list = 0;
02049 
02050     delete X11;
02051     X11 = 0;
02052 }
02053 
02054 
02055 /*****************************************************************************
02056   Platform specific global and internal functions
02057  *****************************************************************************/
02058 
02059 void qt_save_rootinfo()                                // save new root info
02060 {
02061     Atom type;
02062     int format;
02063     unsigned long length, after;
02064     uchar *data = 0;
02065 
02066     if (ATOM(_XSETROOT_ID)) {                        // kill old pixmap
02067         if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
02068                                  ATOM(_XSETROOT_ID), 0, 1,
02069                                  True, AnyPropertyType, &type, &format,
02070                                  &length, &after, &data) == Success) {
02071             if (type == XA_PIXMAP && format == 32 && length == 1 &&
02072                  after == 0 && data) {
02073                 XKillClient(X11->display, *((Pixmap*)data));
02074             }
02075             Pixmap dummy = XCreatePixmap(X11->display, QX11Info::appRootWindow(),
02076                                           1, 1, 1);
02077             XChangeProperty(X11->display, QX11Info::appRootWindow(),
02078                              ATOM(_XSETROOT_ID), XA_PIXMAP, 32,
02079                              PropModeReplace, (uchar *)&dummy, 1);
02080             XSetCloseDownMode(X11->display, RetainPermanent);
02081         }
02082     }
02083     if (data)
02084         XFree((char *)data);
02085 }
02086 
02087 void qt_updated_rootinfo()
02088 {
02089     app_save_rootinfo = true;
02090 }
02091 
02092 bool qt_wstate_iconified(WId winid)
02093 {
02094     Atom type;
02095     int format;
02096     unsigned long length, after;
02097     uchar *data = 0;
02098     int r = XGetWindowProperty(X11->display, winid, ATOM(WM_STATE), 0, 2,
02099                                  False, AnyPropertyType, &type, &format,
02100                                  &length, &after, &data);
02101     bool iconic = false;
02102     if (r == Success && data && format == 32) {
02103         // quint32 *wstate = (quint32*)data;
02104         unsigned long *wstate = (unsigned long *) data;
02105         iconic = (*wstate == IconicState);
02106         XFree((char *)data);
02107     }
02108     return iconic;
02109 }
02110 
02111 QString QApplicationPrivate::appName() const
02112 {
02113     return QString::fromLocal8Bit(::appName);
02114 }
02115 
02116 const char *QX11Info::appClass()                                // get application class
02117 {
02118     return ::appClass;
02119 }
02120 
02121 bool qt_nograb()                                // application no-grab option
02122 {
02123 #if defined(QT_DEBUG)
02124     return appNoGrab;
02125 #else
02126     return false;
02127 #endif
02128 }
02129 
02130 
02131 /*****************************************************************************
02132   Platform specific QApplication members
02133  *****************************************************************************/
02134 
02162 #ifdef QT3_SUPPORT
02163 void QApplication::setMainWidget(QWidget *mainWidget)
02164 {
02165 #ifndef QT_NO_DEBUG
02166     if (mainWidget && mainWidget->parentWidget() && mainWidget->isWindow())
02167         qWarning("QApplication::setMainWidget: New main widget (%s/%s) "
02168                   "has a parent",
02169                   mainWidget->metaObject()->className(), mainWidget->objectName().toLocal8Bit().constData());
02170 #endif
02171     mainWidget->d_func()->createWinId();
02172     QApplicationPrivate::main_widget = mainWidget;
02173     if (QApplicationPrivate::main_widget) // give WM command line
02174         QApplicationPrivate::applyX11SpecificCommandLineArguments(QApplicationPrivate::main_widget);
02175 }
02176 #endif
02177 
02178 void QApplicationPrivate::applyX11SpecificCommandLineArguments(QWidget *main_widget)
02179 {
02180     static bool beenHereDoneThat = false;
02181     if (beenHereDoneThat)
02182         return;
02183     beenHereDoneThat = true;
02184     Q_ASSERT(main_widget->testAttribute(Qt::WA_WState_Created));
02185     XSetWMProperties(X11->display, main_widget->internalWinId(), 0, 0, qApp->d_func()->argv, qApp->d_func()->argc, 0, 0, 0);
02186     if (mwTitle) {
02187         XStoreName(X11->display, main_widget->internalWinId(), (char*)mwTitle);
02188         QByteArray net_wm_name = QString::fromLocal8Bit(mwTitle).toUtf8();
02189         XChangeProperty(X11->display, main_widget->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
02190                         PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
02191     }
02192     if (mwGeometry) { // parse geometry
02193         int x, y;
02194         int w, h;
02195         int m = XParseGeometry((char*)mwGeometry, &x, &y, (uint*)&w, (uint*)&h);
02196         QSize minSize = main_widget->minimumSize();
02197         QSize maxSize = main_widget->maximumSize();
02198         if ((m & XValue) == 0)
02199             x = main_widget->geometry().x();
02200         if ((m & YValue) == 0)
02201             y = main_widget->geometry().y();
02202         if ((m & WidthValue) == 0)
02203             w = main_widget->width();
02204         if ((m & HeightValue) == 0)
02205             h = main_widget->height();
02206         w = qMin(w,maxSize.width());
02207         h = qMin(h,maxSize.height());
02208         w = qMax(w,minSize.width());
02209         h = qMax(h,minSize.height());
02210         if ((m & XNegative)) {
02211             x = QApplication::desktop()->width()  + x - w;
02212         }
02213         if ((m & YNegative)) {
02214             y = QApplication::desktop()->height() + y - h;
02215         }
02216         main_widget->setGeometry(x, y, w, h);
02217     }
02218 }
02219 
02220 #ifndef QT_NO_CURSOR
02221 
02222 /*****************************************************************************
02223   QApplication cursor stack
02224  *****************************************************************************/
02225 
02226 extern void qt_x11_enforce_cursor(QWidget * w);
02227 
02257 void QApplication::setOverrideCursor(const QCursor &cursor)
02258 {
02259     qApp->d_func()->cursor_list.prepend(cursor);
02260 
02261     QWidgetList all = allWidgets();
02262     for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
02263         register QWidget *w = *it;
02264         if (w->testAttribute(Qt::WA_SetCursor))
02265             qt_x11_enforce_cursor(w);
02266     }
02267     XFlush(X11->display);                                // make X execute it NOW
02268 }
02269 
02281 void QApplication::restoreOverrideCursor()
02282 {
02283     if (qApp->d_func()->cursor_list.isEmpty())
02284         return;
02285     qApp->d_func()->cursor_list.removeFirst();
02286 
02287     if (QWidgetPrivate::mapper != 0 && !closingDown()) {
02288         QWidgetList all = allWidgets();
02289         for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
02290             register QWidget *w = *it;
02291             if (w->testAttribute(Qt::WA_SetCursor))
02292                 qt_x11_enforce_cursor(w);
02293         }
02294         XFlush(X11->display);
02295     }
02296 }
02297 
02298 #endif
02299 
02300 
02301 /*****************************************************************************
02302   Routines to find a Qt widget from a screen position
02303  *****************************************************************************/
02304 
02305 Window QX11Data::findClientWindow(Window win, Atom property, bool leaf)
02306 {
02307     Atom   type = XNone;
02308     int           format, i;
02309     ulong  nitems, after;
02310     uchar *data = 0;
02311     Window root, parent, target=0, *children=0;
02312     uint   nchildren;
02313     if (XGetWindowProperty(X11->display, win, property, 0, 0, false, AnyPropertyType,
02314                              &type, &format, &nitems, &after, &data) == Success) {
02315         if (data)
02316             XFree((char *)data);
02317         if (type)
02318             return win;
02319     }
02320     if (!XQueryTree(X11->display,win,&root,&parent,&children,&nchildren)) {
02321         if (children)
02322             XFree((char *)children);
02323         return 0;
02324     }
02325     for (i=nchildren-1; !target && i >= 0; i--)
02326         target = X11->findClientWindow(children[i], property, leaf);
02327     if (children)
02328         XFree((char *)children);
02329     return target;
02330 }
02331 
02332 QWidget *QApplication::topLevelAt(const QPoint &p)
02333 {
02334     int screen = QCursor::x11Screen();
02335     int unused;
02336 
02337     int x = p.x();
02338     int y = p.y();
02339     Window target;
02340     if (!XTranslateCoordinates(X11->display,
02341                                QX11Info::appRootWindow(screen),
02342                                QX11Info::appRootWindow(screen),
02343                                x, y, &unused, &unused, &target)) {
02344         return 0;
02345     }
02346     if (!target || target == QX11Info::appRootWindow(screen))
02347         return 0;
02348     QWidget *w;
02349     w = QWidget::find((WId)target);
02350 
02351     if (!w) {
02352         X11->ignoreBadwindow();
02353         target = X11->findClientWindow(target, ATOM(WM_STATE), true);
02354         if (X11->badwindow())
02355             return 0;
02356         w = QWidget::find((WId)target);
02357         if (!w) {
02358             // Perhaps the widget at (x,y) is inside a foreign application?
02359             // Search all toplevel widgets to see if one is within target
02360             QWidgetList list = QApplication::topLevelWidgets();
02361             for (int i = 0; i < list.count(); ++i) {
02362                 QWidget *widget = list.at(i);
02363                 Window ctarget = target;
02364                 if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
02365                     Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
02366                     Window wid = widget->internalWinId();
02367                     while (ctarget && !w) {
02368                         XTranslateCoordinates(X11->display,
02369                                               QX11Info::appRootWindow(screen),
02370                                               ctarget, x, y, &unused, &unused, &ctarget);
02371                         if (ctarget == wid) {
02372                             // Found!
02373                             w = widget;
02374                             break;
02375                         }
02376                     }
02377                 }
02378                 if (w)
02379                     break;
02380             }
02381         }
02382     }
02383     return w ? w->window() : 0;
02384 }
02385 
02391 void QApplication::syncX()
02392 {
02393     if (X11->display)
02394         XSync(X11->display, False);                        // don't discard events
02395 }
02396 
02397 
02403 void QApplication::beep()
02404 {
02405     if (X11->display)
02406         XBell(X11->display, 0);
02407     else
02408         printf("\7");
02409 }
02410 
02411 
02412 
02413 /*****************************************************************************
02414   Special lookup functions for windows that have been reparented recently
02415  *****************************************************************************/
02416 
02417 static QWidgetMapper *wPRmapper = 0;                // alternative widget mapper
02418 
02419 void qPRCreate(const QWidget *widget, Window oldwin)
02420 {                                                // QWidget::reparent mechanism
02421     if (!wPRmapper)
02422         wPRmapper = new QWidgetMapper;
02423 
02424     QETWidget *w = static_cast<QETWidget *>(const_cast<QWidget *>(widget));
02425     wPRmapper->insert((int)oldwin, w);        // add old window to mapper
02426     w->setAttribute(Qt::WA_WState_Reparented);        // set reparented flag
02427 }
02428 
02429 void qPRCleanup(QWidget *widget)
02430 {
02431     QETWidget *etw = static_cast<QETWidget *>(const_cast<QWidget *>(widget));
02432     if (!(wPRmapper && widget->testAttribute(Qt::WA_WState_Reparented)))
02433         return;                                        // not a reparented widget
02434     for (QWidgetMapper::ConstIterator it = wPRmapper->constBegin(); it != wPRmapper->constEnd(); ++it) {
02435         QWidget *w = *it;
02436         int key = it.key();
02437         if (w == etw) {                       // found widget
02438             etw->setAttribute(Qt::WA_WState_Reparented, false); // clear flag
02439             wPRmapper->remove(key);// old window no longer needed
02440             if (wPRmapper->size() == 0) {        // became empty
02441                 delete wPRmapper;                // then reset alt mapper
02442                 wPRmapper = 0;
02443             }
02444             return;
02445         }
02446     }
02447 }
02448 
02449 static QETWidget *qPRFindWidget(Window oldwin)
02450 {
02451     return wPRmapper ? (QETWidget*)wPRmapper->value((int)oldwin, 0) : 0;
02452 }
02453 
02457 int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
02458 {
02459     QETWidget *widget = (QETWidget*)w;
02460     if (event->xclient.format == 32 && event->xclient.message_type) {
02461         if (event->xclient.message_type == ATOM(WM_PROTOCOLS)) {
02462             Atom a = event->xclient.data.l[0];
02463             if (a == ATOM(WM_DELETE_WINDOW)) {
02464                 if (passive_only) return 0;
02465                 widget->translateCloseEvent(event);
02466             }
02467             else if (a == ATOM(WM_TAKE_FOCUS)) {
02468                 if ((ulong) event->xclient.data.l[1] > X11->time)
02469                     X11->time = event->xclient.data.l[1];
02470                 QWidget *amw = activeModalWidget();
02471                 if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
02472                     QWidget *p = amw->parentWidget();
02473                     while (p && p != widget)
02474                         p = p->parentWidget();
02475                     if (!p || !X11->net_supported_list)
02476                         amw->raise(); // help broken window managers
02477                     amw->activateWindow();
02478                 }
02479 #ifndef QT_NO_WHATSTHIS
02480             } else if (a == ATOM(_NET_WM_CONTEXT_HELP)) {
02481                 QWhatsThis::enterWhatsThisMode();
02482 #endif // QT_NO_WHATSTHIS
02483             } else if (a == ATOM(_NET_WM_PING)) {
02484                 // avoid send/reply loops
02485                 Window root = RootWindow(X11->display, w->x11Info().screen());
02486                 if (event->xclient.window != root) {
02487                     event->xclient.window = root;
02488                     XSendEvent(event->xclient.display, event->xclient.window,
02489                                 False, SubstructureNotifyMask|SubstructureRedirectMask, event);
02490                 }
02491             }
02492         } else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
02493             widget->translateScrollDoneEvent(event);
02494         } else if (event->xclient.message_type == ATOM(XdndPosition)) {
02495             X11->xdndHandlePosition(widget, event, passive_only);
02496         } else if (event->xclient.message_type == ATOM(XdndEnter)) {
02497             X11->xdndHandleEnter(widget, event, passive_only);
02498         } else if (event->xclient.message_type == ATOM(XdndStatus)) {
02499             X11->xdndHandleStatus(widget, event, passive_only);
02500         } else if (event->xclient.message_type == ATOM(XdndLeave)) {
02501             X11->xdndHandleLeave(widget, event, passive_only);
02502         } else if (event->xclient.message_type == ATOM(XdndDrop)) {
02503             X11->xdndHandleDrop(widget, event, passive_only);
02504         } else if (event->xclient.message_type == ATOM(XdndFinished)) {
02505             X11->xdndHandleFinished(widget, event, passive_only);
02506         } else {
02507             if (passive_only) return 0;
02508             // All other are interactions
02509         }
02510     } else {
02511         X11->motifdndHandle(widget, event, passive_only);
02512     }
02513 
02514     return 0;
02515 }
02516 
02528 int QApplication::x11ProcessEvent(XEvent* event)
02529 {
02530     Q_D(QApplication);
02531     switch (event->type) {
02532     case ButtonPress:
02533         pressed_window = event->xbutton.window;
02534         X11->userTime = event->xbutton.time;
02535         // fallthrough intended
02536     case ButtonRelease:
02537         X11->time = event->xbutton.time;
02538         break;
02539     case MotionNotify:
02540         X11->time = event->xmotion.time;
02541         break;
02542     case XKeyPress:
02543         X11->userTime = event->xkey.time;
02544         // fallthrough intended
02545     case XKeyRelease:
02546         X11->time = event->xkey.time;
02547         break;
02548     case PropertyNotify:
02549         X11->time = event->xproperty.time;
02550         break;
02551     case EnterNotify:
02552     case LeaveNotify:
02553         X11->time = event->xcrossing.time;
02554         break;
02555     case SelectionClear:
02556         X11->time = event->xselectionclear.time;
02557         break;
02558     default:
02559         break;
02560     }
02561 
02562     QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
02563 
02564     if (wPRmapper) {                                // just did a widget reparent?
02565         if (widget == 0) {                        // not in std widget mapper
02566             switch (event->type) {                // only for mouse/key events
02567             case ButtonPress:
02568             case ButtonRelease:
02569             case MotionNotify:
02570             case XKeyPress:
02571             case XKeyRelease:
02572                 widget = qPRFindWidget(event->xany.window);
02573                 break;
02574             }
02575         }
02576         else if (widget->testAttribute(Qt::WA_WState_Reparented))
02577             qPRCleanup(widget);                // remove from alt mapper
02578     }
02579 
02580     QETWidget *keywidget=0;
02581     bool grabbed=false;
02582     if (event->type==XKeyPress || event->type==XKeyRelease) {
02583         keywidget = (QETWidget*)QWidget::keyboardGrabber();
02584         if (keywidget) {
02585             grabbed = true;
02586         } else if (!keywidget) {
02587             if (d->inPopupMode()) // no focus widget, see if we have a popup
02588                 keywidget = (QETWidget*) (activePopupWidget()->focusWidget() ? activePopupWidget()->focusWidget() : activePopupWidget());
02589             else if (QApplicationPrivate::focus_widget)
02590                 keywidget = (QETWidget*)QApplicationPrivate::focus_widget;
02591             else if (widget)
02592                 keywidget = (QETWidget*)widget->window();
02593         }
02594     }
02595 
02596 #ifndef QT_NO_IM
02597     // Filtering input events by the input context. It has to be taken
02598     // place before any other key event consumers such as eventfilters
02599     // and accelerators because some input methods require quite
02600     // various key combination and sequences. It often conflicts with
02601     // accelerators and so on, so we must give the input context the
02602     // filtering opportunity first to ensure all input methods work
02603     // properly regardless of application design.
02604 
02605     if(keywidget && keywidget->isEnabled() && keywidget->testAttribute(Qt::WA_InputMethodEnabled)) {
02606         // block user interaction during session management
02607   if((event->type==XKeyPress || event->type==XKeyRelease) && qt_sm_blockUserInput)
02608       return true;
02609 
02610         // for XIM handling
02611   QInputContext *qic = keywidget->inputContext();
02612   if(qic && qic->x11FilterEvent(keywidget, event))
02613       return true;
02614 
02615   // filterEvent() accepts QEvent *event rather than preexpanded
02616   // key event attribute values. This is intended to pass other
02617   // QInputEvent in future. Other non IM-related events should
02618   // not be forwarded to input contexts to prevent weird event
02619   // handling.
02620   if ((event->type == XKeyPress || event->type == XKeyRelease)) {
02621       int code = -1;
02622       int count = 0;
02623       Qt::KeyboardModifiers modifiers;
02624       QEvent::Type type;
02625       QString text;
02626             KeySym keySym;
02627 
02628             qt_keymapper_private()->translateKeyEventInternal(keywidget, event, keySym, count,
02629                                                               text, modifiers, code, type, false);
02630 
02631       // both key press/release is required for some complex
02632       // input methods. don't eliminate anything.
02633       QKeyEventEx keyevent(type, code, modifiers, text, false, qMax(qMax(count, 1), text.length()),
02634                                  event->xkey.keycode, keySym, event->xkey.state);
02635       if(qic && qic->filterEvent(&keyevent))
02636     return true;
02637   }
02638     } else
02639 #endif // QT_NO_IM
02640         {
02641             if (XFilterEvent(event, XNone))
02642                 return true;
02643         }
02644 
02645     if (qt_x11EventFilter(event))                // send through app filter
02646         return 1;
02647 
02648     if (event->type == MappingNotify) {
02649         // keyboard mapping changed
02650         XRefreshKeyboardMapping(&event->xmapping);
02651 
02652         QKeyMapper::changeKeyboard();
02653         return 0;
02654     }
02655 
02656     if (!widget) {                                // don't know this windows
02657         QWidget* popup = QApplication::activePopupWidget();
02658         if (popup) {
02659 
02660             /*
02661               That is more than suboptimal. The real solution should
02662               do some keyevent and buttonevent translation, so that
02663               the popup still continues to work as the user expects.
02664               Unfortunately this translation is currently only
02665               possible with a known widget. I'll change that soon
02666               (Matthias).
02667             */
02668 
02669             // Danger - make sure we don't lock the server
02670             switch (event->type) {
02671             case ButtonPress:
02672             case ButtonRelease:
02673             case XKeyPress:
02674             case XKeyRelease:
02675                 do {
02676                     popup->close();
02677                 } while ((popup = qApp->activePopupWidget()));
02678                 return 1;
02679             }
02680         }
02681         return -1;
02682     }
02683 
02684     if (event->type == XKeyPress || event->type == XKeyRelease)
02685         widget = keywidget; // send XKeyEvents through keywidget->x11Event()
02686 
02687     if (app_do_modal)                                // modal event handling
02688         if (!qt_try_modal(widget, event)) {
02689             if (event->type == ClientMessage && !widget->x11Event(event))
02690                 x11ClientMessage(widget, event, true);
02691             return 1;
02692         }
02693 
02694 
02695     if (widget->x11Event(event))                // send through widget filter
02696         return 1;
02697 #if !defined (QT_NO_TABLET)
02698     QTabletDeviceDataList *tablets = qt_tablet_devices();
02699     for (int i = 0; i < tablets->size(); ++i) {
02700         const QTabletDeviceData &tab = tablets->at(i);
02701         if (event->type == tab.xinput_motion
02702             || event->type == tab.xinput_button_release
02703             || event->type == tab.xinput_button_press
02704             || event->type == tab.xinput_proximity_in
02705             || event->type == tab.xinput_proximity_out) {
02706             widget->translateXinputEvent(event, &tab);
02707             return 0;
02708         }
02709     }
02710 #endif
02711 
02712 #ifndef QT_NO_XRANDR
02713     if (X11->use_xrandr && event->type == (X11->xrandr_eventbase + RRScreenChangeNotify)) {
02714         // update Xlib internals with the latest screen configuration
02715         XRRUpdateConfiguration(event);
02716 
02717         // update the size for desktop widget
02718         int scr = XRRRootToScreen(X11->display, event->xany.window);
02719         QWidget *w = desktop()->screen(scr);
02720         QSize oldSize(w->size());
02721         w->data->crect.setWidth(DisplayWidth(X11->display, scr));
02722         w->data->crect.setHeight(DisplayHeight(X11->display, scr));
02723         if (w->size() != oldSize) {
02724             QResizeEvent e(w->size(), oldSize);
02725             QApplication::sendEvent(w, &e);
02726             emit desktop()->resized(scr);
02727         }
02728     }
02729 #endif // QT_NO_XRANDR
02730 
02731     switch (event->type) {
02732 
02733     case ButtonRelease:                        // mouse event
02734         if (!d->inPopupMode() && !QWidget::mouseGrabber() && pressed_window != widget->internalWinId()
02735             && (widget = (QETWidget*) QWidget::find((WId)pressed_window)) == 0)
02736             break;
02737         // fall through intended
02738     case ButtonPress:
02739         if (event->xbutton.root != RootWindow(X11->display, widget->x11Info().screen())
02740             && ! qt_xdnd_dragging) {
02741             while (activePopupWidget())
02742                 activePopupWidget()->close();
02743             return 1;
02744         }
02745         if (event->type == ButtonPress)
02746             qt_net_update_user_time(widget->window());
02747         // fall through intended
02748     case MotionNotify:
02749 #if !defined(QT_NO_TABLET)
02750         if (!qt_tabletChokeMouse) {
02751 #endif
02752             if (widget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
02753                 QPoint pos(event->xbutton.x, event->xbutton.y);
02754                 pos = widget->d_func()->mapFromWS(pos);
02755                 QWidget *window = widget->window();
02756                 pos = widget->mapTo(window, pos);
02757                 if (QWidget *child = window->childAt(pos)) {
02758                     widget = static_cast<QETWidget *>(child);
02759                     pos = child->mapFrom(window, pos);
02760                     event->xbutton.x = pos.x();
02761                     event->xbutton.y = pos.y();
02762                 }
02763             }
02764             widget->translateMouseEvent(event);
02765 #if !defined(QT_NO_TABLET)
02766         } else {
02767             qt_tabletChokeMouse = false;
02768         }
02769 #endif
02770         break;
02771 
02772     case XKeyPress:                                // keyboard event
02773         qt_net_update_user_time(widget->window());
02774         // fallthrough intended
02775     case XKeyRelease:
02776         {
02777             if (keywidget && keywidget->isEnabled()) { // should always exist
02778                 // qDebug("sending key event");
02779                 qt_keymapper_private()->translateKeyEvent(keywidget, event, grabbed);
02780             }
02781             break;
02782         }
02783 
02784     case GraphicsExpose:
02785     case Expose:                                // paint event
02786         widget->translatePaintEvent(event);
02787         break;
02788 
02789     case ConfigureNotify:                        // window move/resize event
02790         if (event->xconfigure.event == event->xconfigure.window)
02791             widget->translateConfigEvent(event);
02792         break;
02793 
02794     case XFocusIn: {                                // got focus
02795         if ((widget->windowType() == Qt::Desktop))
02796             break;
02797         if (d->inPopupMode()) // some delayed focus event to ignore
02798             break;
02799         if (!widget->isWindow())
02800             break;
02801         if (event->xfocus.detail != NotifyAncestor &&
02802             event->xfocus.detail != NotifyInferior &&
02803             event->xfocus.detail != NotifyNonlinear)
02804             break;
02805         setActiveWindow(widget);
02806         if (X11->focus_model == QX11Data::FM_PointerRoot) {
02807             // We got real input focus from somewhere, but we were in PointerRoot
02808             // mode, so we don't trust this event.  Check the focus model to make
02809             // sure we know what focus mode we are using...
02810             qt_check_focus_model();
02811         }
02812     }
02813         break;
02814 
02815     case XFocusOut:                                // lost focus
02816         if ((widget->windowType() == Qt::Desktop))
02817             break;
02818         if (!widget->isWindow())
02819             break;
02820         if (event->xfocus.mode == NotifyGrab) {
02821             qt_xfocusout_grab_counter++;
02822             break;
02823         }
02824         if (event->xfocus.detail != NotifyAncestor &&
02825             event->xfocus.detail != NotifyNonlinearVirtual &&
02826             event->xfocus.detail != NotifyNonlinear)
02827             break;
02828         if (!d->inPopupMode() && widget == QApplicationPrivate::active_window)
02829             setActiveWindow(0);
02830         break;
02831 
02832     case EnterNotify: {                        // enter window
02833         if (QWidget::mouseGrabber()  && widget != QWidget::mouseGrabber())
02834             break;
02835         if (d->inPopupMode() && widget->window() != activePopupWidget())
02836             break;
02837         if (event->xcrossing.mode != NotifyNormal ||
02838             event->xcrossing.detail == NotifyVirtual  ||
02839             event->xcrossing.detail == NotifyNonlinearVirtual)
02840             break;
02841         if (event->xcrossing.focus &&
02842             !(widget->windowType() == Qt::Desktop) && !widget->isActiveWindow()) {
02843             if (X11->focus_model == QX11Data::FM_Unknown) // check focus model
02844                 qt_check_focus_model();
02845             if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode
02846                 setActiveWindow(widget);
02847         }
02848         QApplicationPrivate::dispatchEnterLeave(widget, QWidget::find(curWin));
02849         curWin = widget->internalWinId();
02850         widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
02851     }
02852         break;
02853 
02854     case LeaveNotify: {                        // leave window
02855         if (QWidget::mouseGrabber()  && widget != QWidget::mouseGrabber())
02856             break;
02857         if (curWin && widget->internalWinId() != curWin)
02858             break;
02859         if (event->xcrossing.mode != NotifyNormal)
02860             break;
02861         if (!(widget->windowType() == Qt::Desktop))
02862             widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
02863 
02864         QWidget* enter = 0;
02865         XEvent ev;
02866         while (XCheckMaskEvent(X11->display, EnterWindowMask | LeaveWindowMask , &ev)
02867                && !qt_x11EventFilter(&ev)) {
02868             QWidget* event_widget = QWidget::find(ev.xcrossing.window);
02869             if(event_widget && event_widget->x11Event(&ev))
02870                 break;
02871             if (ev.type == LeaveNotify
02872                 || ev.xcrossing.mode != NotifyNormal
02873                 || ev.xcrossing.detail == NotifyVirtual
02874                 || ev.xcrossing.detail == NotifyNonlinearVirtual)
02875                 continue;
02876             enter = event_widget;
02877             if (ev.xcrossing.focus &&
02878                 enter && !(enter->windowType() == Qt::Desktop) && !enter->isActiveWindow()) {
02879                 if (X11->focus_model == QX11Data::FM_Unknown) // check focus model
02880                     qt_check_focus_model();
02881                 if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode
02882                     setActiveWindow(enter);
02883             }
02884             break;
02885         }
02886 
02887         if ((! enter || (enter->windowType() == Qt::Desktop)) &&
02888             event->xcrossing.focus && widget == QApplicationPrivate::active_window &&
02889             X11->focus_model == QX11Data::FM_PointerRoot // PointerRoot mode
02890             ) {
02891             setActiveWindow(0);
02892         }
02893 
02894         if (!curWin)
02895             QApplicationPrivate::dispatchEnterLeave(widget, 0);
02896 
02897         QApplicationPrivate::dispatchEnterLeave(enter, widget);
02898         if (enter && QApplicationPrivate::tryModalHelper(enter, 0)) {
02899             curWin = enter->internalWinId();
02900             static_cast<QETWidget *>(enter)->translateMouseEvent(&ev); //we don't get MotionNotify, emulate it
02901         } else {
02902             curWin = 0;
02903         }
02904     }
02905         break;
02906 
02907     case UnmapNotify:                                // window hidden
02908         if (widget->isWindow()) {
02909             Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
02910             widget->d_func()->topData()->waitingForMapNotify = 0;
02911 
02912             if (widget->windowType() != Qt::Popup) {
02913                 widget->setAttribute(Qt::WA_Mapped, false);
02914                 if (widget->isVisible()) {
02915                     widget->d_func()->topData()->spont_unmapped = 1;
02916                     QHideEvent e;
02917                     QApplication::sendSpontaneousEvent(widget, &e);
02918                     widget->d_func()->hideChildren(true);
02919                 }
02920             }
02921 
02922             if (!widget->d_func()->topData()->validWMState) {
02923                 int idx = X11->deferred_map.indexOf(widget);
02924                 if (idx != -1) {
02925                     X11->deferred_map.removeAt(idx);
02926                     Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
02927                     XMapWindow(X11->display, widget->internalWinId());
02928                 }
02929             }
02930         }
02931         break;
02932 
02933     case MapNotify:                                // window shown
02934         if (widget->isWindow()) {
02935             widget->d_func()->topData()->waitingForMapNotify = 0;
02936 
02937             if (widget->windowType() != Qt::Popup) {
02938                 widget->setAttribute(Qt::WA_Mapped);
02939                 if (widget->d_func()->topData()->spont_unmapped) {
02940                     widget->d_func()->topData()->spont_unmapped = 0;
02941                     widget->d_func()->showChildren(true);
02942                     QShowEvent e;
02943                     QApplication::sendSpontaneousEvent(widget, &e);
02944 
02945                     // show() must have been called on this widget in
02946                     // order to reach this point, but we could have
02947                     // cleared these 2 attributes in case something
02948                     // previously forced us into WithdrawnState
02949                     // (e.g. kdocker)
02950                     widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
02951                     widget->setAttribute(Qt::WA_WState_Visible, true);
02952                 }
02953             }
02954         }
02955         break;
02956 
02957     case ClientMessage:                        // client message
02958         return x11ClientMessage(widget,event,False);
02959 
02960     case ReparentNotify:                        // window manager reparents
02961         while (XCheckTypedWindowEvent(X11->display,
02962                                       widget->internalWinId(),
02963                                       ReparentNotify,
02964                                       event))
02965             ;        // skip old reparent events
02966         if (widget->isWindow()) {
02967             QTLWExtra *topData = widget->d_func()->topData();
02968 
02969             // store the parent. Useful for many things, embedding for instance.
02970             topData->parentWinId = event->xreparent.parent;
02971 
02972             // the widget frame strut should also be invalidated
02973             topData->frameStrut.setCoords(0, 0, 0, 0);
02974 
02975             // work around broken window managers... if we get a
02976             // ReparentNotify before the MapNotify, we assume that
02977             // we're being managed by a reparenting window
02978             // manager.
02979             //
02980             // however, the WM_STATE property may not have been set
02981             // yet, but we are going to assume that it will
02982             // be... otherwise we could try to map again after getting
02983             // an UnmapNotify... which could then, in turn, trigger a
02984             // race in the window manager which causes the window to
02985             // disappear when it really should be hidden.
02986             if (topData->waitingForMapNotify && !topData->validWMState)
02987                 topData->validWMState = 1;
02988 
02989             if (X11->focus_model != QX11Data::FM_Unknown) {
02990                 // toplevel reparented...
02991                 QWidget *newparent = QWidget::find(event->xreparent.parent);
02992                 if (! newparent || (newparent->windowType() == Qt::Desktop)) {
02993                     // we dont' know about the new parent (or we've been
02994                     // reparented to root), perhaps a window manager
02995                     // has been (re)started?  reset the focus model to unknown
02996                     X11->focus_model = QX11Data::FM_Unknown;
02997                 }
02998             }
02999         }
03000         break;
03001 
03002     case SelectionRequest: {
03003         XSelectionRequestEvent *req = &event->xselectionrequest;
03004         if (! req)
03005             break;
03006 
03007         if (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)) {
03008             X11->xdndHandleSelectionRequest(req);
03009 
03010         } else if (qt_clipboard) {
03011             QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
03012             QApplication::sendSpontaneousEvent(qt_clipboard, &e);
03013         }
03014         break;
03015     }
03016     case SelectionClear: {
03017         XSelectionClearEvent *req = &event->xselectionclear;
03018         // don't deliver dnd events to the clipboard, it gets confused
03019         if (! req || ATOM(XdndSelection) && req->selection == ATOM(XdndSelection))
03020             break;
03021 
03022         if (qt_clipboard) {
03023             QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
03024             QApplication::sendSpontaneousEvent(qt_clipboard, &e);
03025         }
03026         break;
03027     }
03028 
03029     case SelectionNotify: {
03030         XSelectionEvent *req = &event->xselection;
03031         // don't deliver dnd events to the clipboard, it gets confused
03032         if (! req || ATOM(XdndSelection) && req->selection == ATOM(XdndSelection))
03033             break;
03034 
03035         if (qt_clipboard) {
03036             QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
03037             QApplication::sendSpontaneousEvent(qt_clipboard, &e);
03038         }
03039         break;
03040     }
03041 
03042     case PropertyNotify:
03043         // some properties changed
03044         if (event->xproperty.window == QX11Info::appRootWindow(0)) {
03045             // root properties for the first screen
03046             if (event->xproperty.atom == ATOM(_QT_CLIPBOARD_SENTINEL)) {
03047                 if (qt_check_clipboard_sentinel())
03048                     emit clipboard()->dataChanged();
03049             } else if (event->xproperty.atom == ATOM(_QT_SELECTION_SENTINEL)) {
03050                 if (qt_check_selection_sentinel())
03051                     emit clipboard()->selectionChanged();
03052             } else if (QApplicationPrivate::obey_desktop_settings) {
03053                 if (event->xproperty.atom == ATOM(RESOURCE_MANAGER))
03054                     qt_set_x11_resources();
03055                 else if (event->xproperty.atom == ATOM(_QT_SETTINGS_TIMESTAMP))
03056                     QApplicationPrivate::x11_apply_settings();
03057             }
03058         }
03059         if (event->xproperty.window == QX11Info::appRootWindow()) {
03060             // root properties for the default screen
03061             if (event->xproperty.atom == ATOM(_QT_INPUT_ENCODING)) {
03062                 qt_set_input_encoding();
03063             } else if (event->xproperty.atom == ATOM(_NET_SUPPORTED)) {
03064                 qt_get_net_supported();
03065             } else if (event->xproperty.atom == ATOM(_NET_VIRTUAL_ROOTS)) {
03066                 qt_get_net_virtual_roots();
03067             } else if (event->xproperty.atom == ATOM(_NET_WORKAREA)) {
03068                 qt_desktopwidget_update_workarea();
03069             }
03070         } else if (widget) {
03071             widget->translatePropertyEvent(event);
03072         }  else {
03073             return -1; // don't know this window
03074         }
03075         break;
03076 
03077     default:
03078         break;
03079     }
03080 
03081     return 0;
03082 }
03083 
03101 bool QApplication::x11EventFilter(XEvent *)
03102 {
03103     return false;
03104 }
03105 
03106 
03107 
03108 /*****************************************************************************
03109   Modal widgets; Since Xlib has little support for this we roll our own
03110   modal widget mechanism.
03111   A modal widget without a parent becomes application-modal.
03112   A modal widget with a parent becomes modal to its parent and grandparents..
03113 
03114   QApplicationPrivate::enterModal()
03115         Enters modal state
03116         Arguments:
03117             QWidget *widget        A modal widget
03118 
03119   QApplicationPrivate::leaveModal()
03120         Leaves modal state for a widget
03121         Arguments:
03122             QWidget *widget        A modal widget
03123  *****************************************************************************/
03124 
03125 bool QApplicationPrivate::modalState()
03126 {
03127     return app_do_modal;
03128 }
03129 
03130 void QApplicationPrivate::enterModal_sys(QWidget *widget)
03131 {
03132     if (!qt_modal_stack)
03133         qt_modal_stack = new QWidgetList;
03134 
03135     QApplicationPrivate::dispatchEnterLeave(0, QWidget::find((WId)curWin));
03136     qt_modal_stack->insert(0, widget);
03137     app_do_modal = true;
03138     curWin = 0;
03139 }
03140 
03141 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
03142 {
03143     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
03144         if (qt_modal_stack->isEmpty()) {
03145             delete qt_modal_stack;
03146             qt_modal_stack = 0;
03147             QPoint p(QCursor::pos());
03148             QWidget* w = QApplication::widgetAt(p.x(), p.y());
03149             QApplicationPrivate::dispatchEnterLeave(w, QWidget::find(curWin)); // send synthetic enter event
03150             curWin = w? w->internalWinId() : 0;
03151         }
03152     }
03153     app_do_modal = qt_modal_stack != 0;
03154 }
03155 
03156 bool qt_try_modal(QWidget *widget, XEvent *event)
03157 {
03158     if (qt_xdnd_dragging) {
03159         // allow mouse events while DnD is active
03160         switch (event->type) {
03161         case ButtonPress:
03162         case ButtonRelease:
03163         case MotionNotify:
03164             return true;
03165         default:
03166             break;
03167         }
03168     }
03169 
03170     // allow mouse release events to be sent to widgets that have been pressed
03171     if (event->type == ButtonRelease && widget == qt_button_down)
03172         return true;
03173 
03174     if (QApplicationPrivate::tryModalHelper(widget))
03175         return true;
03176 
03177     // disallow mouse/key events
03178     switch (event->type) {
03179     case ButtonPress:
03180     case ButtonRelease:
03181     case MotionNotify:
03182     case XKeyPress:
03183     case XKeyRelease:
03184     case EnterNotify:
03185     case LeaveNotify:
03186     case ClientMessage:
03187         return false;
03188     default:
03189         break;
03190     }
03191 
03192     return true;
03193 }
03194 
03195 
03196 /*****************************************************************************
03197   Popup widget mechanism
03198 
03199   openPopup()
03200         Adds a widget to the list of popup widgets
03201         Arguments:
03202             QWidget *widget        The popup widget to be added
03203 
03204   closePopup()
03205         Removes a widget from the list of popup widgets
03206         Arguments:
03207             QWidget *widget        The popup widget to be removed
03208  *****************************************************************************/
03209 
03210 
03211 static int openPopupCount = 0;
03212 void QApplicationPrivate::openPopup(QWidget *popup)
03213 {
03214     Q_Q(QApplication);
03215     openPopupCount++;
03216     if (!QApplicationPrivate::popupWidgets) {                        // create list
03217         QApplicationPrivate::popupWidgets = new QWidgetList;
03218     }
03219     QApplicationPrivate::popupWidgets->append(popup);                // add to end of list
03220     Display *dpy = X11->display;
03221     if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard
03222         Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
03223         int r = XGrabKeyboard(dpy, popup->internalWinId(), false,
03224                               GrabModeAsync, GrabModeAsync, X11->time);
03225         if ((popupGrabOk = (r == GrabSuccess))) {
03226             r = XGrabPointer(dpy, popup->internalWinId(), true,
03227                              (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
03228                               | EnterWindowMask | LeaveWindowMask | PointerMotionMask),
03229                              GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time);
03230             if (!(popupGrabOk = (r == GrabSuccess)))
03231                 XUngrabKeyboard(dpy, X11->time);
03232         }
03233     }
03234 
03235     // popups are not focus-handled by the window system (the first
03236     // popup grabbed the keyboard), so we have to do that manually: A
03237     // new popup gets the focus
03238     if (popup->focusWidget()) {
03239         popup->focusWidget()->setFocus(Qt::PopupFocusReason);
03240     } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
03241         if (QWidget *fw = QApplication::focusWidget()) {
03242             QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
03243             q->sendEvent(fw, &e);
03244         }
03245     }
03246 }
03247 
03248 void QApplicationPrivate::closePopup(QWidget *popup)
03249 {
03250     Q_Q(QApplication);
03251     if (!QApplicationPrivate::popupWidgets)
03252         return;
03253     QApplicationPrivate::popupWidgets->removeAll(popup);
03254     if (popup == qt_popup_down) {
03255         qt_button_down = 0;
03256         qt_popup_down = 0;
03257     }
03258     if (QApplicationPrivate::popupWidgets->count() == 0) {                // this was the last popup
03259         delete QApplicationPrivate::popupWidgets;
03260         QApplicationPrivate::popupWidgets = 0;
03261         if (!qt_nograb() && popupGrabOk) {        // grabbing not disabled
03262             Display *dpy = X11->display;
03263             if (popup->geometry().contains(QPoint(mouseGlobalXPos, mouseGlobalYPos))
03264                 || popup->testAttribute(Qt::WA_NoMouseReplay)) {
03265                 // mouse release event or inside
03266                 replayPopupMouseEvent = false;
03267             } else {                                // mouse press event
03268                 mouseButtonPressTime -= 10000;        // avoid double click
03269                 replayPopupMouseEvent = true;
03270             }
03271             XUngrabPointer(dpy, X11->time);
03272             XUngrabKeyboard(dpy, X11->time);
03273             XFlush(dpy);
03274         }
03275         if (QApplicationPrivate::active_window) {
03276             if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
03277                 if (fw != QApplication::focusWidget()) {
03278                     fw->setFocus(Qt::PopupFocusReason);
03279                 } else {
03280                     QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
03281                     q->sendEvent(fw, &e);
03282                 }
03283             }
03284         }
03285     } else {
03286         // popups are not focus-handled by the window system (the
03287         // first popup grabbed the keyboard), so we have to do that
03288         // manually: A popup was closed, so the previous popup gets
03289         // the focus.
03290         QWidget* aw = QApplicationPrivate::popupWidgets->last();
03291         if (QWidget *fw = aw->focusWidget())
03292             fw->setFocus(Qt::PopupFocusReason);
03293 
03294         // regrab the keyboard and mouse in case 'popup' lost the grab
03295         if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard
03296             Display *dpy = X11->display;
03297             Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created));
03298             int r = XGrabKeyboard(dpy, aw->internalWinId(), false,
03299                                   GrabModeAsync, GrabModeAsync, X11->time);
03300             if ((popupGrabOk = (r == GrabSuccess))) {
03301                 r = XGrabPointer(dpy, aw->internalWinId(), true,
03302                                  (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
03303                                   | EnterWindowMask | LeaveWindowMask | PointerMotionMask),
03304                                  GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time);
03305                 if (!(popupGrabOk = (r == GrabSuccess)))
03306                     XUngrabKeyboard(dpy, X11->time);
03307             }
03308         }
03309     }
03310 }
03311 
03312 /*****************************************************************************
03313   Event translation; translates X11 events to Qt events
03314  *****************************************************************************/
03315 
03316 //
03317 // Mouse event translation
03318 //
03319 // Xlib doesn't give mouse double click events, so we generate them by
03320 // comparing window, time and position between two mouse press events.
03321 //
03322 
03323 static Qt::MouseButtons translateMouseButtons(int s)
03324 {
03325     Qt::MouseButtons ret = 0;
03326     if (s & Button1Mask)
03327         ret |= Qt::LeftButton;
03328     if (s & Button2Mask)
03329         ret |= Qt::MidButton;
03330     if (s & Button3Mask)
03331         ret |= Qt::RightButton;
03332     return ret;
03333 }
03334 
03335 Qt::KeyboardModifiers QX11Data::translateModifiers(int s)
03336 {
03337     Qt::KeyboardModifiers ret = 0;
03338     if (s & ShiftMask)
03339         ret |= Qt::ShiftModifier;
03340     if (s & ControlMask)
03341         ret |= Qt::ControlModifier;
03342     if (s & qt_alt_mask)
03343         ret |= Qt::AltModifier;
03344     if (s & qt_meta_mask)
03345         ret |= Qt::MetaModifier;
03346     if (s & qt_mode_switch_mask)
03347         ret |= Qt::GroupSwitchModifier;
03348     return ret;
03349 }
03350 
03351 bool QETWidget::translateMouseEvent(const XEvent *event)
03352 {
03353     Q_D(QWidget);
03354     static bool manualGrab = false;
03355     QEvent::Type type;                                // event parameters
03356     QPoint pos;
03357     QPoint globalPos;
03358     Qt::MouseButton button = Qt::NoButton;
03359     Qt::MouseButtons buttons;
03360     Qt::KeyboardModifiers modifiers;
03361     XEvent nextEvent;
03362 
03363     if (qt_sm_blockUserInput) // block user interaction during session management
03364         return true;
03365 
03366     if (event->type == MotionNotify) { // mouse move
03367         if (event->xmotion.root != RootWindow(X11->display, x11Info().screen()) &&
03368             ! qt_xdnd_dragging)
03369             return false;
03370 
03371         XMotionEvent lastMotion = event->xmotion;
03372         while(XPending(X11->display))  { // compress mouse moves
03373             XNextEvent(X11->display, &nextEvent);
03374             if (nextEvent.type == ConfigureNotify
03375                 || nextEvent.type == PropertyNotify
03376                 || nextEvent.type == Expose
03377                 || nextEvent.type == GraphicsExpose
03378                 || nextEvent.type == NoExpose
03379                 || nextEvent.type == KeymapNotify
03380                 || ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
03381                     && qt_button_down == this)
03382                 || (nextEvent.type == ClientMessage
03383                     && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) {
03384                 qApp->x11ProcessEvent(&nextEvent);
03385                 continue;
03386             } else if (nextEvent.type != MotionNotify ||
03387                        nextEvent.xmotion.window != event->xmotion.window ||
03388                        nextEvent.xmotion.state != event->xmotion.state) {
03389                 XPutBackEvent(X11->display, &nextEvent);
03390                 break;
03391             }
03392             if (!qt_x11EventFilter(&nextEvent)
03393                 && !x11Event(&nextEvent)) // send event through filter
03394                 lastMotion = nextEvent.xmotion;
03395             else
03396                 break;
03397         }
03398         type = QEvent::MouseMove;
03399         pos.rx() = lastMotion.x;
03400         pos.ry() = lastMotion.y;
03401         pos = d->mapFromWS(pos);
03402         globalPos.rx() = lastMotion.x_root;
03403         globalPos.ry() = lastMotion.y_root;
03404         buttons = translateMouseButtons(lastMotion.state);
03405         modifiers = X11->translateModifiers(lastMotion.state);
03406         if (qt_button_down && !buttons)
03407             qt_button_down = 0;
03408     } else if (event->type == EnterNotify || event->type == LeaveNotify) {
03409         XEvent *xevent = (XEvent *)event;
03410         //unsigned int xstate = event->xcrossing.state;
03411         type = QEvent::MouseMove;
03412         pos.rx() = xevent->xcrossing.x;
03413         pos.ry() = xevent->xcrossing.y;
03414         pos = d->mapFromWS(pos);
03415         globalPos.rx() = xevent->xcrossing.x_root;
03416         globalPos.ry() = xevent->xcrossing.y_root;
03417         buttons = translateMouseButtons(xevent->xcrossing.state);
03418         modifiers = X11->translateModifiers(xevent->xcrossing.state);
03419         if (qt_button_down && !buttons)
03420             qt_button_down = 0;
03421         if (qt_button_down)
03422             return true;
03423     } else {                                        // button press or release
03424         pos.rx() = event->xbutton.x;
03425         pos.ry() = event->xbutton.y;
03426         pos = d->mapFromWS(pos);
03427         globalPos.rx() = event->xbutton.x_root;
03428         globalPos.ry() = event->xbutton.y_root;
03429         buttons = translateMouseButtons(event->xbutton.state);
03430         modifiers = X11->translateModifiers(event->xbutton.state);
03431         switch (event->xbutton.button) {
03432         case Button1: button = Qt::LeftButton; break;
03433         case Button2: button = Qt::MidButton; break;
03434         case Button3: button = Qt::RightButton; break;
03435         case Button4:
03436         case Button5:
03437         case 6:
03438         case 7:
03439             // the fancy mouse wheel.
03440 
03441             // We are only interested in ButtonPress.
03442             if (event->type == ButtonPress){
03443                 // compress wheel events (the X Server will simply
03444                 // send a button press for each single notch,
03445                 // regardless whether the application can catch up
03446                 // or not)
03447                 int delta = 1;
03448                 XEvent xevent;
03449                 while (XCheckTypedWindowEvent(X11->display, internalWinId(), ButtonPress, &xevent)){
03450                     if (xevent.xbutton.button != event->xbutton.button){
03451                         XPutBackEvent(X11->display, &xevent);
03452                         break;
03453                     }
03454                     delta++;
03455                 }
03456 
03457                 // the delta is defined as multiples of
03458                 // WHEEL_DELTA, which is set to 120. Future wheels
03459                 // may offer a finer-resolution. A positive delta
03460                 // indicates forward rotation, a negative one
03461                 // backward rotation respectively.
03462                 int btn = event->xbutton.button;
03463                 delta *= 120 * ((btn == Button4 || btn == 6) ? 1 : -1);
03464                 bool hor = ((btn == Button4 || btn == Button5) && (modifiers & Qt::AltModifier) ||
03465                             (btn == 6 || btn == 7));
03466                 translateWheelEvent(globalPos.x(), globalPos.y(), delta, buttons,
03467                                     modifiers, (hor) ? Qt::Horizontal: Qt::Vertical);
03468             }
03469             return true;
03470         case 8: button = Qt::XButton1; break;
03471         case 9: button = Qt::XButton2; break;
03472         }
03473         if (event->type == ButtonPress) {        // mouse button pressed
03474             buttons |= button;
03475 #if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET)
03476             TabletDeviceDataList *tablets = qt_tablet_devices();
03477             for (int i = 0; i < tablets->size(); ++i) {
03478                 const TabletDeviceData &tab = tablets->at(i);
03479                 XEvent myEv;
03480                 if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) {
03481                         if (translateXinputEvent(&myEv, &tab)) {
03482                             //Spontaneous event sent.  Check if we need to continue.
03483                             if (qt_tabletChokeMouse) {
03484                                 qt_tabletChokeMouse = false;
03485                                 return false;
03486                             }
03487                         }
03488                 }
03489             }
03490 #endif
03491             qt_button_down = childAt(pos);        //magic for masked widgets
03492             if (!qt_button_down)
03493                 qt_button_down = this;
03494             if (mouseActWindow == event->xbutton.window &&
03495                 mouseButtonPressed == button &&
03496                 (long)event->xbutton.time -(long)mouseButtonPressTime
03497                 < QApplication::doubleClickInterval() &&
03498                 qAbs(event->xbutton.x - mouseXPos) < 5 &&
03499                 qAbs(event->xbutton.y - mouseYPos) < 5) {
03500                 type = QEvent::MouseButtonDblClick;
03501                 mouseButtonPressTime -= 2000;        // no double-click next time
03502             } else {
03503                 type = QEvent::MouseButtonPress;
03504                 mouseButtonPressTime = event->xbutton.time;
03505             }
03506             mouseButtonPressed = button;        // save event params for
03507             mouseXPos = event->xbutton.x;                // future double click tests
03508             mouseYPos = event->xbutton.y;
03509             mouseGlobalXPos = globalPos.x();
03510             mouseGlobalYPos = globalPos.y();
03511         } else {                                // mouse button released
03512             buttons &= ~button;
03513 #if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET)
03514             TabletDeviceDataList *tablets = qt_tablet_devices();
03515             for (int i = 0; i < tablets->size(); ++i) {
03516                 const TabletDeviceData &tab = tablets->at(i);
03517                 XEvent myEv;
03518                 if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) {
03519                         if (translateXinputEvent(&myEv, &tab)) {
03520                             //Spontaneous event sent.  Check if we need to continue.
03521                             if (qt_tabletChokeMouse) {
03522                                 qt_tabletChokeMouse = false;
03523                                 return false;
03524                             }
03525                         }
03526                 }
03527             }
03528 #endif
03529             if (manualGrab) {                        // release manual grab
03530                 manualGrab = false;
03531                 XUngrabPointer(X11->display, X11->time);
03532                 XFlush(X11->display);
03533             }
03534 
03535             type = QEvent::MouseButtonRelease;
03536         }
03537     }
03538     mouseActWindow = internalWinId();                        // save some event params
03539     mouseButtonState = buttons;
03540     if (type == 0)                                // don't send event
03541         return false;
03542 
03543     if (qApp->d_func()->inPopupMode()) {                        // in popup mode
03544         QWidget *activePopupWidget = qApp->activePopupWidget();
03545         QWidget *popup = qApp->activePopupWidget();
03546         if (popup != this) {
03547             if (event->type == LeaveNotify)
03548                 return false;
03549             if ((windowType() == Qt::Popup) && rect().contains(pos))
03550                 popup = this;
03551             else                                // send to last popup
03552                 pos = popup->mapFromGlobal(globalPos);
03553         }
03554         bool releaseAfter = false;
03555         QWidget *popupChild  = popup->childAt(pos);
03556 
03557         if (popup != qt_popup_down){
03558             qt_button_down = 0;
03559             qt_popup_down = 0;
03560         }
03561 
03562         switch (type) {
03563         case QEvent::MouseButtonPress:
03564         case QEvent::MouseButtonDblClick:
03565             qt_button_down = popupChild;
03566             qt_popup_down = popup;
03567             break;
03568         case QEvent::MouseButtonRelease:
03569             releaseAfter = true;
03570             break;
03571         default:
03572             break;                                // nothing for mouse move
03573         }
03574 
03575         int oldOpenPopupCount = openPopupCount;
03576 
03577         // deliver event
03578         replayPopupMouseEvent = false;
03579         if (qt_button_down) {
03580             QMouseEvent e(type, qt_button_down->mapFromGlobal(globalPos),
03581                           globalPos, button, buttons, modifiers);
03582             QApplication::sendSpontaneousEvent(qt_button_down, &e);
03583         } else if (popupChild) {
03584             QMouseEvent e(type, popupChild->mapFromGlobal(globalPos),
03585                           globalPos, button, buttons, modifiers);
03586             QApplication::sendSpontaneousEvent(popupChild, &e);
03587         } else {
03588             QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
03589             QApplication::sendSpontaneousEvent(popup, &e);
03590         }
03591 
03592         if (qApp->activePopupWidget() != activePopupWidget
03593             && replayPopupMouseEvent) {
03594             // the active popup was closed, replay the mouse event
03595             if (!(windowType() == Qt::Popup)) {
03596                 if (buttons == button)
03597                     qt_button_down = this;
03598                 QMouseEvent e(type, mapFromGlobal(globalPos), globalPos, button,
03599                               buttons, modifiers);
03600                 QApplication::sendSpontaneousEvent(this, &e);
03601 
03602                 if (type == QEvent::MouseButtonPress
03603                     && button == Qt::RightButton
03604                     && (openPopupCount == oldOpenPopupCount)) {
03605                     QContextMenuEvent e(QContextMenuEvent::Mouse, mapFromGlobal(globalPos), globalPos);
03606                     QApplication::sendSpontaneousEvent(this, &e);
03607                 }
03608             }
03609             replayPopupMouseEvent = false;
03610         } else if (type == QEvent::MouseButtonPress
03611                    && button == Qt::RightButton
03612                    && (openPopupCount == oldOpenPopupCount)) {
03613             QWidget *popupEvent = popup;
03614             if (qt_button_down)
03615                 popupEvent = qt_button_down;
03616             else if(popupChild)
03617                 popupEvent = popupChild;
03618             QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos);
03619             QApplication::sendSpontaneousEvent(popupEvent, &e);
03620         }
03621 
03622         if (releaseAfter) {
03623             qt_button_down = 0;
03624             qt_popup_down = 0;
03625         }
03626         if (!qApp->d_func()->inPopupMode()) {
03627              if (type != QEvent::MouseButtonRelease && !buttons &&
03628                  QWidget::find((WId)mouseActWindow)) {
03629                  manualGrab = true;                // need to manually grab
03630                  XGrabPointer(X11->display, mouseActWindow, False,
03631                               (uint)(ButtonPressMask | ButtonReleaseMask |
03632                                      ButtonMotionMask |
03633                                      EnterWindowMask | LeaveWindowMask),
03634                               GrabModeAsync, GrabModeAsync,
03635                               XNone, XNone, CurrentTime);
03636              }
03637         }
03638 
03639     } else {
03640         QWidget *widget = this;
03641         QWidget *w = QWidget::mouseGrabber();
03642 
03643         if (((type == QEvent::MouseMove && buttons)
03644              || (type == QEvent::MouseButtonRelease))
03645             && !qt_button_down && !w)
03646             return false; // don't send event
03647 
03648 
03649         if (!w)
03650             w = qt_button_down;
03651 
03652         if (w && w != this) {
03653             widget = w;
03654             pos = w->mapFromGlobal(globalPos);
03655         }
03656 
03657 
03658         if (type == QEvent::MouseButtonRelease && !buttons) {
03659             // no more buttons pressed on the widget
03660             qt_button_down = 0;
03661         }
03662 
03663         int oldOpenPopupCount = openPopupCount;
03664 
03665         QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
03666         QApplication::sendSpontaneousEvent(widget, &e);
03667 
03668         if (type == QEvent::MouseButtonPress
03669             && button == Qt::RightButton
03670             && (openPopupCount == oldOpenPopupCount)) {
03671             QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos);
03672             QApplication::sendSpontaneousEvent(widget, &e);
03673         }
03674     }
03675     return true;
03676 }
03677 
03678 
03679 //
03680 // Wheel event translation
03681 //
03682 bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta,
03683                                     Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
03684                                     Qt::Orientation orient)
03685 {
03686     // send the event to the widget or its ancestors
03687     {
03688         QWidget* popup = qApp->activePopupWidget();
03689         if (popup && window() != popup)
03690             popup->close();
03691         QWheelEvent e(mapFromGlobal(QPoint(global_x, global_y)),
03692                        QPoint(global_x, global_y), delta, buttons, modifiers, orient);
03693         if (QApplication::sendSpontaneousEvent(this, &e))
03694             return true;
03695     }
03696 
03697     // send the event to the widget that has the focus or its ancestors, if different
03698     QWidget *w = this;
03699     if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
03700         QWidget* popup = qApp->activePopupWidget();
03701         if (popup && w != popup)
03702             popup->hide();
03703         QWheelEvent e(mapFromGlobal(QPoint(global_x, global_y)),
03704                        QPoint(global_x, global_y), delta, buttons, modifiers, orient);
03705         if (QApplication::sendSpontaneousEvent(w, &e))
03706             return true;
03707     }
03708     return false;
03709 }
03710 
03711 
03712 //
03713 // XInput Translation Event
03714 //
03715 #if !defined (QT_NO_TABLET)
03716 bool QETWidget::translateXinputEvent(const XEvent *ev, const QTabletDeviceData *tablet)
03717 {
03718 #if defined (Q_OS_IRIX)
03719     // Wacom has put defines in their wacom.h file so it would be quite wise
03720     // to use them, need to think of a decent way of not using
03721     // it when it doesn't exist...
03722     XDeviceState *s;
03723     XInputClass *iClass;
03724     XValuatorState *vs;
03725     int j;
03726 #endif
03727 
03728     Q_ASSERT(tablet != 0);
03729 
03730     QWidget *w = this;
03731     QPoint global,
03732         curr;
03733     QPointF hiRes;
03734     qreal pressure = 0;
03735     int xTilt = 0,
03736         yTilt = 0,
03737         z = 0;
03738     qreal tangentialPressure = 0;
03739     qreal rotation = 0;
03740     int deviceType = QTabletEvent::NoDevice;
03741     int pointerType = QTabletEvent::UnknownPointer;
03742     XEvent xinputMotionEvent;
03743     XEvent mouseMotionEvent;
03744     const XDeviceMotionEvent *motion = 0;
03745     XDeviceButtonEvent *button = 0;
03746     const XProximityNotifyEvent *proximity = 0;
03747     QEvent::Type t;
03748     Qt::KeyboardModifiers modifiers = 0;
03749 #if !defined (Q_OS_IRIX)
03750     XID device_id;
03751 #endif
03752 
03753     if (ev->type == tablet->xinput_motion) {
03754         motion = reinterpret_cast<const XDeviceMotionEvent*>(ev);
03755         for (;;) {
03756             if (!XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent))
03757                 break;
03758             if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEvent)) {
03759                 XPutBackEvent(X11->display, &mouseMotionEvent);
03760                 break;
03761             }
03762             if (mouseMotionEvent.xmotion.time != motion->time) {
03763                 XPutBackEvent(X11->display, &mouseMotionEvent);
03764                 XPutBackEvent(X11->display, &xinputMotionEvent);
03765 
03766             }
03767             motion = (reinterpret_cast<const XDeviceMotionEvent*>(&xinputMotionEvent));
03768             break;
03769         }
03770         t = QEvent::TabletMove;
03771         global = QPoint(motion->x_root, motion->y_root);
03772         curr = QPoint(motion->x, motion->y);
03773 #if !defined (Q_OS_IRIX)
03774         device_id = motion->deviceid;
03775 #endif
03776     } else if (ev->type == tablet->xinput_button_press || ev->type == tablet->xinput_button_release) {
03777         if (ev->type == tablet->xinput_button_press) {
03778             t = QEvent::TabletPress;
03779         } else {
03780             t = QEvent::TabletRelease;
03781         }
03782         button = (XDeviceButtonEvent*)ev;
03783 
03784         global = QPoint(button->x_root, button->y_root);
03785         curr = QPoint(button->x, button->y);
03786 #if !defined (Q_OS_IRIX)
03787         device_id = button->deviceid;
03788 #endif
03789     } else { // Proximity
03790         if (ev->type == tablet->xinput_proximity_in)
03791             t = QEvent::TabletEnterProximity;
03792         else
03793             t = QEvent::TabletLeaveProximity;
03794         proximity = (const XProximityNotifyEvent*)ev;
03795 #if !defined (Q_OS_IRIX)
03796         device_id = proximity->deviceid;
03797 #endif
03798     }
03799 
03800     qint64 uid;
03801     QRect screenArea = qApp->desktop()->screenGeometry(this);
03802 #if defined (Q_OS_IRIX)
03803     s = XQueryDeviceState(X11->display, static_cast<XDevice *>(tablet->device));
03804     if (!s)
03805         return false;
03806     iClass = s->data;
03807     for (j = 0; j < s->num_classes; j++) {
03808         if (iClass->c_class == ValuatorClass) {
03809             vs = reinterpret_cast<XValuatorState *>(iClass);
03810             // figure out what device we have, based on bitmasking...
03811             if (vs->valuators[WAC_TRANSDUCER_I]
03812                  & WAC_TRANSDUCER_PROX_MSK) {
03813                 switch (vs->valuators[WAC_TRANSDUCER_I]
03814                          & WAC_TRANSDUCER_MSK) {
03815                 case WAC_PUCK_ID:
03816                     pointerType = QTabletEvent::Puck;
03817                     break;
03818                 case WAC_STYLUS_ID:
03819                     pointerType = QTabletEvent::Pen;
03820                     break;
03821                 case WAC_ERASER_ID:
03822                     pointerType = QTabletEvent::Eraser;
03823                     break;
03824                 }
03825                 // Get a Unique Id for the device, Wacom gives us this ability
03826                 uid = vs->valuators[WAC_TRANSDUCER_I] & WAC_TRANSDUCER_ID_MSK;
03827                 uid = (uid << 24) | vs->valuators[WAC_SERIAL_NUM_I];
03828                 switch (WAC_TRANSDUCER_I & 0x0F0600) {
03829                 case 0x080200:
03830                     deviceType = QTabletEvent::Stylus;
03831                     break;
03832                 case 0x090200:
03833                     deviceType = QTabletEvent::Airbrush;
03834                     break;
03835                 case 0x000400:
03836                     deviceType = QTabletEvent::FourDMouse;
03837                     break;
03838                 case 0x000600:
03839                     deviceType = QTabletEvent::Puck;
03840                     break;
03841                 case 0x080400:
03842                     deviceType = QTabletEvent::RotationStylus;
03843                     break;
03844                 }
03845             } else {
03846                 pointerType = QTabletEvent::UnknownPointer;
03847                 deviceType = QTabletEvent::NoDevice;
03848                 uid = 0;
03849             }
03850 
03851             if (!proximity) {
03852                 // apparently Wacom needs a cast for the +/- values to make sense
03853                 xTilt = short(vs->valuators[WAC_XTILT_I]);
03854                 yTilt = short(vs->valuators[WAC_YTILT_I]);
03855                 pressure = vs->valuators[WAC_PRESSURE_I];
03856                 if (deviceType == QTabletEvent::FourDMouse
03857                         || deviceType == QTabletEvent::RotationStylus) {
03858                     rotation = vs->valuators[WAC_ROTATION_I] / 64.0;
03859                     if (deviceType == QTabletEvent::FourDMouse)
03860                         z = vs->valuators[WAC_ZCOORD_I];
03861                 } else if (deviceType == QTabletEvent::Airbrush) {
03862                     tangentialPressure = vs->valuators[WAC_TAN_PRESSURE_I]
03863                                             / qreal(tablet->maxTanPressure - tablet->minTanPressure);
03864                 }
03865 
03866                 hiRes = tablet->scaleCoord(vs->valuators[WAC_XCOORD_I], vs->valuators[WAC_YCOORD_I],
03867                                            screenArea.x(), screenArea.width(),
03868                                            screenArea.y(), screenArea.height());
03869             }
03870             break;
03871         }
03872         iClass = reinterpret_cast<XInputClass*>(reinterpret_cast<char*>(iClass) + iClass->length);
03873     }
03874     XFreeDeviceState(s);
03875 #else
03876     QTabletDeviceDataList *tablet_list = qt_tablet_devices();
03877     for (int i = 0; i < tablet_list->size(); ++i) {
03878         const QTabletDeviceData &t = tablet_list->at(i);
03879         if (device_id == static_cast<XDevice *>(t.device)->device_id) {
03880             deviceType = t.deviceType;
03881             if (deviceType == QTabletEvent::XFreeEraser) {
03882                 deviceType = QTabletEvent::Stylus;
03883                 pointerType = QTabletEvent::Eraser;
03884             } else if (deviceType == QTabletEvent::Stylus) {
03885                 pointerType = QTabletEvent::Pen;
03886             }
03887             // qDebug() << ((XDevice*)t.device)->device_id;
03888             break;
03889         }
03890     }
03891 
03892     uint hibyte1 = 0;  // ID
03893     uint hibyte2 = 0;  // Serial # part 1
03894     uint hibyte3 = 0;  // Serial # part 2
03895     if (motion) {
03896         hibyte1 = (motion->axis_data[3] & 0xffff0000) >> 16;
03897         hibyte2 = (motion->axis_data[4] & 0xffff0000) >> 16;
03898         hibyte3 = (motion->axis_data[5] & 0xffff0000) >> 16;
03899         xTilt = short(motion->axis_data[3] & 0xffff);
03900         yTilt = short(motion->axis_data[4] & 0xffff);
03901         pressure = motion->axis_data[2];
03902         modifiers = X11->translateModifiers(motion->state);
03903         hiRes = tablet->scaleCoord(motion->axis_data[0], motion->axis_data[1],
03904                                     screenArea.x(), screenArea.width(),
03905                                     screenArea.y(), screenArea.height());
03906     } else if (button) {
03907         hibyte1 = (button->axis_data[3] & 0xffff0000) >> 16;
03908         hibyte2 = (button->axis_data[4] & 0xffff0000) >> 16;
03909         hibyte3 = (button->axis_data[5] & 0xffff0000) >> 16;
03910         xTilt = short(button->axis_data[3] & 0xffff);
03911         yTilt = short(button->axis_data[4] & 0xffff);
03912         pressure = button->axis_data[2];
03913         hiRes = tablet->scaleCoord(button->axis_data[0], button->axis_data[1],
03914                                     screenArea.x(), screenArea.width(),
03915                                     screenArea.y(), screenArea.height());
03916         modifiers = X11->translateModifiers(button->state);
03917     } else if (proximity) {
03918         hibyte1 = (proximity->axis_data[3] & 0xffff0000) >> 16;
03919         hibyte2 = (proximity->axis_data[4] & 0xffff0000) >> 16;
03920         hibyte3 = (proximity->axis_data[5] & 0xffff0000) >> 16;
03921         pressure = 0;
03922         modifiers = 0;
03923     }
03924     // There are newer drivers out that do report the serial number.
03925     // But the older ones  will have values of 0xffff or 0;
03926     if (hibyte1 == 0 || hibyte1 == 0xffff) {
03927         uid = -1;
03928     } else {
03929         uid = hibyte1 & 0x0f06;
03930         uid = (uid << 24) | ((hibyte2 << 16) | hibyte3);
03931     }
03932 #endif
03933     QTabletEvent e(t, curr, global, hiRes,
03934                    deviceType, pointerType,
03935                    qreal(pressure / qreal(tablet->maxPressure - tablet->minPressure)),
03936                    xTilt, yTilt, tangentialPressure, rotation, z, modifiers, uid);
03937     if (proximity)
03938         QApplication::sendSpontaneousEvent(qApp, &e);
03939     else
03940         QApplication::sendSpontaneousEvent(w, &e);
03941     return true;
03942 }
03943 #endif
03944 
03945 bool QETWidget::translatePropertyEvent(const XEvent *event)
03946 {
03947     Q_D(QWidget);
03948     if (!isWindow()) return true;
03949 
03950     Atom ret;
03951     int format, e;
03952     unsigned char *data = 0;
03953     unsigned long nitems, after;
03954 
03955     if (event->xproperty.atom == ATOM(_KDE_NET_WM_FRAME_STRUT)) {
03956         QTLWExtra *topData = d->topData();
03957         topData->frameStrut.setCoords(0, 0, 0, 0);
03958         this->data->fstrut_dirty = 1;
03959 
03960         if (event->xproperty.state == PropertyNewValue) {
03961             e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_KDE_NET_WM_FRAME_STRUT),
03962                                    0, 4, // struts are 4 longs
03963                                    False, XA_CARDINAL, &ret, &format, &nitems, &after, &data);
03964 
03965             if (e == Success && ret == XA_CARDINAL &&
03966                 format == 32 && nitems == 4) {
03967                 long *strut = (long *) data;
03968                 topData->frameStrut.setCoords(strut[0], strut[1], strut[2], strut[3]);
03969                 this->data->fstrut_dirty = 0;
03970             }
03971         }
03972     } else if (event->xproperty.atom == ATOM(_NET_WM_STATE)) {
03973         bool max = false;
03974         bool full = false;
03975         Qt::WindowStates oldState = Qt::WindowStates(this->data->window_state);
03976 
03977         if (event->xproperty.state == PropertyNewValue) {
03978             // using length of 1024 should be safe for all current and
03979             // possible NET states...
03980             e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_NET_WM_STATE), 0, 1024,
03981                                    False, XA_ATOM, &ret, &format, &nitems, &after, &data);
03982 
03983             if (e == Success && ret == XA_ATOM && format == 32 && nitems > 0) {
03984                 Atom *states = (Atom *) data;
03985 
03986                 unsigned long i;
03987                 for (i = 0; i < nitems; i++) {
03988                     if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_VERT)
03989                         || states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
03990                         max = true;
03991                     else if (states[i] == ATOM(_NET_WM_STATE_FULLSCREEN))
03992                         full = true;
03993                 }
03994             }
03995         }
03996 
03997         bool send_event = false;
03998 
03999         if (qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
04000             && qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) {
04001             if (max && !isMaximized()) {
04002                 this->data->window_state = this->data->window_state | Qt::WindowMaximized;
04003                 send_event = true;
04004             } else if (!max && isMaximized()) {
04005                 this->data->window_state &= !Qt::WindowMaximized;
04006                 send_event = true;
04007             }
04008         }
04009 
04010         if (qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN))) {
04011             if (full && !isFullScreen()) {
04012                 this->data->window_state = this->data->window_state | Qt::WindowFullScreen;
04013                 send_event = true;
04014             } else if (!full && isFullScreen()) {
04015                 this->data->window_state &= ~Qt::WindowFullScreen;
04016                 send_event = true;
04017             }
04018         }
04019 
04020         if (send_event) {
04021             QWindowStateChangeEvent e(oldState);
04022             QApplication::sendSpontaneousEvent(this, &e);
04023         }
04024     } else if (event->xproperty.atom == ATOM(WM_STATE)) {
04025         // the widget frame strut should also be invalidated
04026         d->topData()->frameStrut.setCoords(0, 0, 0, 0);
04027         this->data->fstrut_dirty = 1;
04028 
04029         if (event->xproperty.state == PropertyDelete) {
04030             // the window manager has removed the WM State property,
04031             // so it is now in the withdrawn state (ICCCM 4.1.3.1) and
04032             // we are free to reuse this window
04033             d->topData()->parentWinId = 0;
04034             d->topData()->validWMState = 0;
04035             // map the window if we were waiting for a transition to
04036             // withdrawn
04037             if (X11->deferred_map.removeAll(this)) {
04038                 XMapWindow(X11->display, internalWinId());
04039             } else if (isVisible() && !testAttribute(Qt::WA_Mapped)) {
04040                 // so that show() will work again. As stated in the
04041                 // ICCCM section 4.1.4: "Only the client can effect a
04042                 // transition into or out of the Withdrawn state.",
04043                 // but apparently this particular window manager
04044                 // doesn't seem to care
04045                 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
04046                 setAttribute(Qt::WA_WState_Visible, false);
04047             }
04048         } else {
04049             // the window manager has changed the WM State property...
04050             // we are wanting to see if we are withdrawn so that we
04051             // can reuse this window...
04052             e = XGetWindowProperty(X11->display, internalWinId(), ATOM(WM_STATE), 0, 2, False,
04053                                    ATOM(WM_STATE), &ret, &format, &nitems, &after, &data);
04054 
04055             if (e == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) {
04056                 long *state = (long *) data;
04057                 switch (state[0]) {
04058                 case WithdrawnState:
04059                     // if we are in the withdrawn state, we are free
04060                     // to reuse this window provided we remove the
04061                     // WM_STATE property (ICCCM 4.1.3.1)
04062                     XDeleteProperty(X11->display, internalWinId(), ATOM(WM_STATE));
04063 
04064                     // set the parent id to zero, so that show() will
04065                     // work again
04066                     d->topData()->parentWinId = 0;
04067                     d->topData()->validWMState = 0;
04068                     // map the window if we were waiting for a
04069                     // transition to withdrawn
04070                     if (X11->deferred_map.removeAll(this)) {
04071                         XMapWindow(X11->display, internalWinId());
04072                     } else if (isVisible() && !testAttribute(Qt::WA_Mapped)) {
04073                         // so that show() will work again. As stated
04074                         // in the ICCCM section 4.1.4: "Only the
04075                         // client can effect a transition into or out
04076                         // of the Withdrawn state.", but apparently
04077                         // this particular window manager doesn't seem
04078                         // to care
04079                         setAttribute(Qt::WA_WState_ExplicitShowHide, false);
04080                         setAttribute(Qt::WA_WState_Visible, false);
04081                     }
04082                     break;
04083 
04084                 case IconicState:
04085                     d->topData()->validWMState = 1;
04086                     if (!isMinimized()) {
04087                         // window was minimized
04088                         this->data->window_state = this->data->window_state | Qt::WindowMinimized;
04089                         QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state & ~Qt::WindowMinimized));
04090                         QApplication::sendSpontaneousEvent(this, &e);
04091                     }
04092                     break;
04093 
04094                 default:
04095                     d->topData()->validWMState = 1;
04096                     if (isMinimized()) {
04097                         // window was un-minimized
04098                         this->data->window_state &= ~Qt::WindowMinimized;
04099                         QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state | Qt::WindowMinimized));
04100                         QApplication::sendSpontaneousEvent(this, &e);
04101                     }
04102                     break;
04103                 }
04104             }
04105         }
04106     } else if (event->xproperty.atom == ATOM(_NET_WM_WINDOW_OPACITY)) {
04107         // the window opacity was changed
04108         if (event->xproperty.state == PropertyNewValue) {
04109             e = XGetWindowProperty(event->xclient.display,
04110                                    event->xclient.window,
04111                                    ATOM(_NET_WM_WINDOW_OPACITY),
04112                                    0, 1, False, XA_CARDINAL,
04113                                    &ret, &format, &nitems, &after, &data);
04114 
04115             if (e == Success && ret == XA_CARDINAL && format == 32 && nitems == 1
04116                 && after == 0 && data) {
04117                 ulong value = *(ulong*)(data);
04118                 d->topData()->opacity = uint(value >> 24);
04119             }
04120         } else
04121             d->topData()->opacity = 255;
04122     }
04123 
04124     if (data)
04125         XFree(data);
04126 
04127     return true;
04128 }
04129 
04130 //
04131 // Paint event translation
04132 //
04133 // When receiving many expose events, we compress them (union of all expose
04134 // rectangles) into one event which is sent to the widget.
04135 
04136 struct PaintEventInfo {
04137     Window window;
04138 };
04139 
04140 #if defined(Q_C_CALLBACKS)
04141 extern "C" {
04142 #endif
04143 
04144 static Bool isPaintOrScrollDoneEvent(Display *, XEvent *ev, XPointer a)
04145 {
04146     PaintEventInfo *info = (PaintEventInfo *)a;
04147     if (ev->type == Expose || ev->type == GraphicsExpose
04148       ||    ev->type == ClientMessage
04149          && ev->xclient.message_type == ATOM(_QT_SCROLL_DONE))
04150     {
04151         if (ev->xexpose.window == info->window)
04152             return True;
04153     }
04154     return False;
04155 }
04156 
04157 #if defined(Q_C_CALLBACKS)
04158 }
04159 #endif
04160 
04161 
04162 
04163 static
04164 bool translateBySips(QWidget* that, QRect& paintRect)
04165 {
04166     int dx=0, dy=0;
04167     int sips=0;
04168     for (int i = 0; i < X11->sip_list.size(); ++i) {
04169         const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
04170         if (sip.scrolled_widget == that) {
04171             if (sips) {
04172                 dx += sip.dx;
04173                 dy += sip.dy;
04174             }
04175             sips++;
04176         }
04177     }
04178     if (sips > 1) {
04179         paintRect.translate(dx, dy);
04180         return true;
04181     }
04182     return false;
04183 }
04184 
04185 bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
04186 {
04187     return QCoreApplication::sendSpontaneousEvent(receiver, event);
04188 }
04189 
04190 void QETWidget::translatePaintEvent(const XEvent *event)
04191 {
04192     Q_D(QWidget);
04193     QRect  paintRect(event->xexpose.x, event->xexpose.y,
04194                      event->xexpose.width, event->xexpose.height);
04195     XEvent xevent;
04196     PaintEventInfo info;
04197     info.window = internalWinId();
04198     translateBySips(this, paintRect);
04199     paintRect = d->mapFromWS(paintRect);
04200 
04201     QRegion paintRegion = paintRect;
04202 
04203     // WARNING: this is O(number_of_events * number_of_matching_events)
04204     while (XCheckIfEvent(X11->display,&xevent,isPaintOrScrollDoneEvent,
04205                          (XPointer)&info) &&
04206            !qt_x11EventFilter(&xevent)  &&
04207            !x11Event(&xevent)) // send event through filter
04208     {
04209         if (xevent.type == Expose || xevent.type == GraphicsExpose) {
04210             QRect exposure(xevent.xexpose.x,
04211                            xevent.xexpose.y,
04212                            xevent.xexpose.width,
04213                            xevent.xexpose.height);
04214             translateBySips(this, exposure);
04215             exposure = d->mapFromWS(exposure);
04216             paintRegion |= exposure;
04217         } else {
04218             translateScrollDoneEvent(&xevent);
04219         }
04220     }
04221 
04222     if (!paintRegion.isEmpty() && !(!testAttribute(Qt::WA_StaticContents) && testAttribute(Qt::WA_WState_ConfigPending))) {
04223         extern void qt_syncBackingStore(QRegion rgn, QWidget *widget);
04224         qt_syncBackingStore(paintRegion, this);
04225     }
04226 }
04227 
04228 //
04229 // Scroll-done event translation.
04230 //
04231 
04232 bool QETWidget::translateScrollDoneEvent(const XEvent *event)
04233 {
04234     long id = event->xclient.data.l[0];
04235 
04236     // Remove any scroll-in-progress record for the given id.
04237     for (int i = 0; i < X11->sip_list.size(); ++i) {
04238         const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
04239         if (sip.id == id) {
04240             X11->sip_list.removeAt(i);
04241             return true;
04242         }
04243     }
04244 
04245     return false;
04246 }
04247 
04248 //
04249 // ConfigureNotify (window move and resize) event translation
04250 
04251 bool QETWidget::translateConfigEvent(const XEvent *event)
04252 {
04253     Q_D(QWidget);
04254     bool wasResize = testAttribute(Qt::WA_WState_ConfigPending); // set in QWidget::setGeometry_sys()
04255     setAttribute(Qt::WA_WState_ConfigPending, false);
04256 
04257     if (isWindow()) {
04258         QPoint newCPos(geometry().topLeft());
04259         QSize  newSize(event->xconfigure.width, event->xconfigure.height);
04260 
04261         bool trust = (d->topData()->parentWinId == XNone ||
04262                       d->topData()->parentWinId == QX11Info::appRootWindow());
04263 
04264         if (event->xconfigure.send_event || trust) {
04265             // if a ConfigureNotify comes from a real sendevent request, we can
04266             // trust its values.
04267             newCPos.rx() = event->xconfigure.x + event->xconfigure.border_width;
04268             newCPos.ry() = event->xconfigure.y + event->xconfigure.border_width;
04269         }
04270 
04271         if (isVisible())
04272             QApplication::syncX();
04273 
04274         if (d->extra->compress_events) {
04275             // ConfigureNotify compression for faster opaque resizing
04276             XEvent otherEvent;
04277             while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify,
04278                                           &otherEvent)) {
04279                 if (qt_x11EventFilter(&otherEvent))
04280                     continue;
04281 
04282                 if (x11Event(&otherEvent))
04283                     continue;
04284 
04285                 if (otherEvent.xconfigure.event != otherEvent.xconfigure.window)
04286                     continue;
04287 
04288                 newSize.setWidth(otherEvent.xconfigure.width);
04289                 newSize.setHeight(otherEvent.xconfigure.height);
04290 
04291                 if (otherEvent.xconfigure.send_event || trust) {
04292                     newCPos.rx() = otherEvent.xconfigure.x +
04293                                    otherEvent.xconfigure.border_width;
04294                     newCPos.ry() = otherEvent.xconfigure.y +
04295                                    otherEvent.xconfigure.border_width;
04296                 }
04297             }
04298         }
04299 
04300         QRect cr (geometry());
04301         if (newCPos != cr.topLeft()) { // compare with cpos (exluding frame)
04302             QPoint oldPos = geometry().topLeft();
04303             cr.moveTopLeft(newCPos);
04304             data->crect = cr;
04305             if (isVisible()) {
04306                 QMoveEvent e(newCPos, oldPos); // pos (including frame), not cpos
04307                 QApplication::sendSpontaneousEvent(this, &e);
04308             } else {
04309                 setAttribute(Qt::WA_PendingMoveEvent, true);
04310             }
04311         }
04312         if (newSize != cr.size()) { // size changed
04313             QSize oldSize = size();
04314             cr.setSize(newSize);
04315             data->crect = cr;
04316 
04317             uint old_state = data->window_state;
04318             if (!qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
04319                 && !qt_net_supports(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
04320                 data->window_state &= ~Qt::WindowMaximized;
04321             if (!qt_net_supports(ATOM(_NET_WM_STATE_FULLSCREEN)))
04322                 data->window_state &= ~Qt::WindowFullScreen;
04323 
04324             if (old_state != data->window_state) {
04325                 QWindowStateChangeEvent e((Qt::WindowStates) old_state);
04326                 QApplication::sendEvent(this, &e);
04327             }
04328 
04329             if (isVisible()) {
04330                 QResizeEvent e(newSize, oldSize);
04331                 QApplication::sendSpontaneousEvent(this, &e);
04332             } else {
04333                 setAttribute(Qt::WA_PendingResizeEvent, true);
04334             }
04335             wasResize = true;
04336         }
04337 
04338     } else {
04339         XEvent xevent;
04340         while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
04341                !qt_x11EventFilter(&xevent)  &&
04342                !x11Event(&xevent)) // send event through filter
04343             ;
04344     }
04345 
04346     if (wasResize && !testAttribute(Qt::WA_StaticContents)) {
04347         XEvent xevent;
04348         PaintEventInfo info;
04349         info.window = internalWinId();
04350         while (XCheckIfEvent(X11->display,&xevent,isPaintOrScrollDoneEvent,
04351                              (XPointer)&info) &&
04352                !qt_x11EventFilter(&xevent)  &&
04353                !x11Event(&xevent)) // send event through filter
04354             ;
04355         if(QWidgetBackingStore::paintOnScreen(this)) {
04356             repaint();
04357         } else {
04358             extern void qt_syncBackingStore(QRegion rgn, QWidget *widget);
04359             qt_syncBackingStore(d->clipRect(), this);
04360         }
04361     }
04362     return true;
04363 }
04364 
04365 //
04366 // Close window event translation.
04367 //
04368 bool QETWidget::translateCloseEvent(const XEvent *)
04369 {
04370     Q_D(QWidget);
04371     return d->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
04372 }
04373 
04374 
04393 void QApplication::setCursorFlashTime(int msecs)
04394 {
04395     QApplicationPrivate::cursor_flash_time = msecs;
04396 }
04397 
04398 int QApplication::cursorFlashTime()
04399 {
04400     return QApplicationPrivate::cursor_flash_time;
04401 }
04402 
04415 void QApplication::setDoubleClickInterval(int ms)
04416 {
04417     QApplicationPrivate::mouse_double_click_time = ms;
04418 }
04419 
04420 int QApplication::doubleClickInterval()
04421 {
04422     return QApplicationPrivate::mouse_double_click_time;
04423 }
04424 
04435 void QApplication::setKeyboardInputInterval(int ms)
04436 {
04437     QApplicationPrivate::keyboard_input_time = ms;
04438 }
04439 
04440 int QApplication::keyboardInputInterval()
04441 {
04442     return QApplicationPrivate::keyboard_input_time;
04443 }
04444 
04445 
04454 void QApplication::setWheelScrollLines(int n)
04455 {
04456     QApplicationPrivate::wheel_scroll_lines = n;
04457 }
04458 
04459 int QApplication::wheelScrollLines()
04460 {
04461     return QApplicationPrivate::wheel_scroll_lines;
04462 }
04463 
04473 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
04474 {
04475     switch (effect) {
04476     case Qt::UI_AnimateMenu:
04477         if (enable) QApplicationPrivate::fade_menu = false;
04478         QApplicationPrivate::animate_menu = enable;
04479         break;
04480     case Qt::UI_FadeMenu:
04481         if (enable)
04482             QApplicationPrivate::animate_menu = true;
04483         QApplicationPrivate::fade_menu = enable;
04484         break;
04485     case Qt::UI_AnimateCombo:
04486         QApplicationPrivate::animate_combo = enable;
04487         break;
04488     case Qt::UI_AnimateTooltip:
04489         if (enable) QApplicationPrivate::fade_tooltip = false;
04490         QApplicationPrivate::animate_tooltip = enable;
04491         break;
04492     case Qt::UI_FadeTooltip:
04493         if (enable)
04494             QApplicationPrivate::animate_tooltip = true;
04495         QApplicationPrivate::fade_tooltip = enable;
04496         break;
04497     case Qt::UI_AnimateToolBox:
04498         QApplicationPrivate::animate_toolbox = enable;
04499         break;
04500     default:
04501         QApplicationPrivate::animate_ui = enable;
04502         break;
04503     }
04504 }
04505 
04517 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
04518 {
04519     if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
04520         return false;
04521 
04522     switch(effect) {
04523     case Qt::UI_AnimateMenu:
04524         return QApplicationPrivate::animate_menu;
04525     case Qt::UI_FadeMenu:
04526         return QApplicationPrivate::fade_menu;
04527     case Qt::UI_AnimateCombo:
04528         return QApplicationPrivate::animate_combo;
04529     case Qt::UI_AnimateTooltip:
04530         return QApplicationPrivate::animate_tooltip;
04531     case Qt::UI_FadeTooltip:
04532         return QApplicationPrivate::fade_tooltip;
04533     case Qt::UI_AnimateToolBox:
04534         return QApplicationPrivate::animate_toolbox;
04535     default:
04536         return QApplicationPrivate::animate_ui;
04537     }
04538 }
04539 
04540 /*****************************************************************************
04541   Session management support
04542  *****************************************************************************/
04543 
04544 #ifndef QT_NO_SESSIONMANAGER
04545 
04546 #include <X11/SM/SMlib.h>
04547 
04548 class QSessionManagerPrivate : public QObjectPrivate
04549 {
04550 public:
04551     QSessionManagerPrivate(QSessionManager* mgr, QString& id, QString& key)
04552         : QObjectPrivate(), sm(mgr), sessionId(id), sessionKey(key), eventLoop(0) {}
04553     QSessionManager* sm;
04554     QStringList restartCommand;
04555     QStringList discardCommand;
04556     QString& sessionId;
04557     QString& sessionKey;
04558     QSessionManager::RestartHint restartHint;
04559     QEventLoop *eventLoop;
04560 };
04561 
04562 class QSmSocketReceiver : public QObject
04563 {
04564     Q_OBJECT
04565 public:
04566     QSmSocketReceiver(int socket)
04567         {
04568             QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this);
04569             connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int)));
04570         }
04571 
04572 public slots:
04573      void socketActivated(int);
04574 };
04575 
04576 
04577 static SmcConn smcConnection = 0;
04578 static bool sm_interactionActive;
04579 static bool sm_smActive;
04580 static int sm_interactStyle;
04581 static int sm_saveType;
04582 static bool sm_cancel;
04583 // static bool sm_waitingForPhase2;  ### never used?!?
04584 static bool sm_waitingForInteraction;
04585 static bool sm_isshutdown;
04586 // static bool sm_shouldbefast;  ### never used?!?
04587 static bool sm_phase2;
04588 static bool sm_in_phase2;
04589 
04590 static QSmSocketReceiver* sm_receiver = 0;
04591 
04592 static void resetSmState();
04593 static void sm_setProperty(const char* name, const char* type,
04594                             int num_vals, SmPropValue* vals);
04595 static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
04596                                   int saveType, Bool shutdown , int interactStyle, Bool fast);
04597 static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData) ;
04598 static void sm_dieCallback(SmcConn smcConn, SmPointer clientData) ;
04599 static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData);
04600 static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer clientData);
04601 static void sm_interactCallback(SmcConn smcConn, SmPointer clientData);
04602 static void sm_performSaveYourself(QSessionManagerPrivate*);
04603 
04604 static void resetSmState()
04605 {
04606 //    sm_waitingForPhase2 = false; ### never used?!?
04607     sm_waitingForInteraction = false;
04608     sm_interactionActive = false;
04609     sm_interactStyle = SmInteractStyleNone;
04610     sm_smActive = false;
04611     qt_sm_blockUserInput = false;
04612     sm_isshutdown = false;
04613 //    sm_shouldbefast = false; ### never used?!?
04614     sm_phase2 = false;
04615     sm_in_phase2 = false;
04616 }
04617 
04618 
04619 // theoretically it's possible to set several properties at once. For
04620 // simplicity, however, we do just one property at a time
04621 static void sm_setProperty(const char* name, const char* type,
04622                             int num_vals, SmPropValue* vals)
04623 {
04624     if (num_vals) {
04625       SmProp prop;
04626       prop.name = (char*)name;
04627       prop.type = (char*)type;
04628       prop.num_vals = num_vals;
04629       prop.vals = vals;
04630 
04631       SmProp* props[1];
04632       props[0] = &prop;
04633       SmcSetProperties(smcConnection, 1, props);
04634     }
04635     else {
04636       char* names[1];
04637       names[0] = (char*) name;
04638       SmcDeleteProperties(smcConnection, 1, names);
04639     }
04640 }
04641 
04642 static void sm_setProperty(const QString& name, const QString& value)
04643 {
04644     QByteArray v = value.toUtf8();
04645     SmPropValue prop;
04646     prop.length = v.length();
04647     prop.value = (SmPointer) v.constData();
04648     sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop);
04649 }
04650 
04651 static void sm_setProperty(const QString& name, const QStringList& value)
04652 {
04653     SmPropValue *prop = new SmPropValue[value.count()];
04654     int count = 0;
04655     QList<QByteArray> vl;
04656     for (QStringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
04657       prop[count].length = (*it).length();
04658       vl.append((*it).toUtf8());
04659       prop[count].value = (char*)vl.last().data();
04660       ++count;
04661     }
04662     sm_setProperty(name.toLatin1().data(), SmLISTofARRAY8, count, prop);
04663     delete [] prop;
04664 }
04665 
04666 
04667 // workaround for broken libsm, see below
04668 struct QT_smcConn {
04669     unsigned int save_yourself_in_progress : 1;
04670     unsigned int shutdown_in_progress : 1;
04671 };
04672 
04673 static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
04674                                   int saveType, Bool shutdown , int interactStyle, Bool /*fast*/)
04675 {
04676     if (smcConn != smcConnection)
04677         return;
04678     sm_cancel = false;
04679     sm_smActive = true;
04680     sm_isshutdown = shutdown;
04681     sm_saveType = saveType;
04682     sm_interactStyle = interactStyle;
04683 //    sm_shouldbefast = fast; ### never used?!?
04684 
04685     // ugly workaround for broken libSM. libSM should do that _before_
04686     // actually invoking the callback in sm_process.c
04687     ((QT_smcConn*)smcConn)->save_yourself_in_progress = true;
04688     if (sm_isshutdown)
04689         ((QT_smcConn*)smcConn)->shutdown_in_progress = true;
04690 
04691     sm_performSaveYourself((QSessionManagerPrivate*) clientData);
04692     if (!sm_isshutdown) // we cannot expect a confirmation message in that case
04693         resetSmState();
04694 }
04695 
04696 static void sm_performSaveYourself(QSessionManagerPrivate* smd)
04697 {
04698     if (sm_isshutdown)
04699         qt_sm_blockUserInput = true;
04700 
04701     QSessionManager* sm = smd->sm;
04702 
04703     // generate a new session key
04704     timeval tv;
04705     gettimeofday(&tv, 0);
04706     smd->sessionKey  = QString::number(qulonglong(tv.tv_sec)) + QLatin1Char('_') + QString::number(qulonglong(tv.tv_usec));
04707 
04708     QStringList arguments = qApp->arguments();
04709     QString argument0 = arguments.isEmpty() ? qApp->applicationFilePath() : arguments.at(0);
04710 
04711     // tell the session manager about our program in best POSIX style
04712     sm_setProperty(QString::fromLatin1(SmProgram), argument0);
04713     // tell the session manager about our user as well.
04714     struct passwd *entryPtr = 0;
04715 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
04716     QVarLengthArray<char, 1024> buf(sysconf(_SC_GETPW_R_SIZE_MAX));
04717     struct passwd entry;
04718     getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr);
04719 #else
04720     entryPtr = getpwuid(geteuid());
04721 #endif
04722     if (entryPtr)
04723         sm_setProperty(QString::fromLatin1(SmUserID), QString::fromLatin1(entryPtr->pw_name));
04724 
04725     // generate a restart and discard command that makes sense
04726     QStringList restart;
04727     restart  << argument0 << QLatin1String("-session")
04728              << smd->sessionId + QLatin1Char('_') + smd->sessionKey;
04729     if (qstricmp(appName, QX11Info::appClass()) != 0)
04730         restart << QLatin1String("-name") << qAppName();
04731     sm->setRestartCommand(restart);
04732     QStringList discard;
04733     sm->setDiscardCommand(discard);
04734 
04735     switch (sm_saveType) {
04736     case SmSaveBoth:
04737         qApp->commitData(*sm);
04738         if (sm_isshutdown && sm_cancel)
04739             break; // we cancelled the shutdown, no need to save state
04740     // fall through
04741     case SmSaveLocal:
04742         qApp->saveState(*sm);
04743         break;
04744     case SmSaveGlobal:
04745         qApp->commitData(*sm);
04746         break;
04747     default:
04748         break;
04749     }
04750 
04751     if (sm_phase2 && !sm_in_phase2) {
04752         SmcRequestSaveYourselfPhase2(smcConnection, sm_saveYourselfPhase2Callback, (SmPointer*) smd);
04753         qt_sm_blockUserInput = false;
04754     }
04755     else {
04756         // close eventual interaction monitors and cancel the
04757         // shutdown, if required. Note that we can only cancel when
04758         // performing a shutdown, it does not work for checkpoints
04759         if (sm_interactionActive) {
04760             SmcInteractDone(smcConnection, sm_isshutdown && sm_cancel);
04761             sm_interactionActive = false;
04762         }
04763         else if (sm_cancel && sm_isshutdown) {
04764             if (sm->allowsErrorInteraction()) {
04765                 SmcInteractDone(smcConnection, True);
04766                 sm_interactionActive = false;
04767             }
04768         }
04769 
04770         // set restart and discard command in session manager
04771         sm_setProperty(QString::fromLatin1(SmRestartCommand), sm->restartCommand());
04772         sm_setProperty(QString::fromLatin1(SmDiscardCommand), sm->discardCommand());
04773 
04774         // set the restart hint
04775         SmPropValue prop;
04776         prop.length = sizeof(int);
04777         int value = sm->restartHint();
04778         prop.value = (SmPointer) &value;
04779         sm_setProperty(SmRestartStyleHint, SmCARD8, 1, &prop);
04780 
04781         // we are done
04782         SmcSaveYourselfDone(smcConnection, !sm_cancel);
04783     }
04784 }
04785 
04786 static void sm_dieCallback(SmcConn smcConn, SmPointer /* clientData */)
04787 {
04788     if (smcConn != smcConnection)
04789         return;
04790     resetSmState();
04791     QEvent quitEvent(QEvent::Quit);
04792     QApplication::sendEvent(qApp, &quitEvent);
04793 }
04794 
04795 static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData)
04796 {
04797     if (smcConn != smcConnection)
04798         return;
04799     if (sm_waitingForInteraction)
04800         ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
04801     resetSmState();
04802 }
04803 
04804 static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer /*clientData */)
04805 {
04806     if (smcConn != smcConnection)
04807         return;
04808     resetSmState();
04809 }
04810 
04811 static void sm_interactCallback(SmcConn smcConn, SmPointer clientData)
04812 {
04813     if (smcConn != smcConnection)
04814         return;
04815     if (sm_waitingForInteraction)
04816         ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
04817 }
04818 
04819 static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData)
04820 {
04821     if (smcConn != smcConnection)
04822         return;
04823     sm_in_phase2 = true;
04824     sm_performSaveYourself((QSessionManagerPrivate*) clientData);
04825 }
04826 
04827 
04828 void QSmSocketReceiver::socketActivated(int)
04829 {
04830     IceProcessMessages(SmcGetIceConnection(smcConnection), 0, 0);
04831 }
04832 
04833 
04834 #undef Bool
04835 #include "qapplication_x11.moc"
04836 
04837 QSessionManager::QSessionManager(QApplication * app, QString &id, QString& key)
04838     : QObject(*new QSessionManagerPrivate(this, id, key), app)
04839 {
04840     Q_D(QSessionManager);
04841     d->restartHint = RestartIfRunning;
04842 
04843     resetSmState();
04844     char cerror[256];
04845     char* myId = 0;
04846     QByteArray b_id = id.toLatin1();
04847     char* prevId = b_id.data();
04848 
04849     SmcCallbacks cb;
04850     cb.save_yourself.callback = sm_saveYourselfCallback;
04851     cb.save_yourself.client_data = (SmPointer) d;
04852     cb.die.callback = sm_dieCallback;
04853     cb.die.client_data = (SmPointer) d;
04854     cb.save_complete.callback = sm_saveCompleteCallback;
04855     cb.save_complete.client_data = (SmPointer) d;
04856     cb.shutdown_cancelled.callback = sm_shutdownCancelledCallback;
04857     cb.shutdown_cancelled.client_data = (SmPointer) d;
04858 
04859     // avoid showing a warning message below
04860     if (qgetenv("SESSION_MANAGER").isEmpty())
04861         return;
04862 
04863     smcConnection = SmcOpenConnection(0, 0, 1, 0,
04864                                        SmcSaveYourselfProcMask |
04865                                        SmcDieProcMask |
04866                                        SmcSaveCompleteProcMask |
04867                                        SmcShutdownCancelledProcMask,
04868                                        &cb,
04869                                        prevId,
04870                                        &myId,
04871                                        256, cerror);
04872 
04873     id = QString::fromLatin1(myId);
04874     ::free(myId); // it was allocated by C
04875 
04876     QString error = QString::fromLocal8Bit(cerror);
04877     if (!smcConnection) {
04878         qWarning("Qt: Session management error: %s", qPrintable(error));
04879     }
04880     else {
04881         sm_receiver = new QSmSocketReceiver(IceConnectionNumber(SmcGetIceConnection(smcConnection)));
04882     }
04883 }
04884 
04885 QSessionManager::~QSessionManager()
04886 {
04887     if (smcConnection)
04888         SmcCloseConnection(smcConnection, 0, 0);
04889     smcConnection = 0;
04890     delete sm_receiver;
04891 }
04892 
04893 QString QSessionManager::sessionId() const
04894 {
04895     Q_D(const QSessionManager);
04896     return d->sessionId;
04897 }
04898 
04899 QString QSessionManager::sessionKey() const
04900 {
04901     Q_D(const QSessionManager);
04902     return d->sessionKey;
04903 }
04904 
04905 
04906 void* QSessionManager::handle() const
04907 {
04908     return (void*) smcConnection;
04909 }
04910 
04911 
04912 bool QSessionManager::allowsInteraction()
04913 {
04914     Q_D(QSessionManager);
04915     if (sm_interactionActive)
04916         return true;
04917 
04918     if (sm_waitingForInteraction)
04919         return false;
04920 
04921     if (sm_interactStyle == SmInteractStyleAny) {
04922         sm_waitingForInteraction =  SmcInteractRequest(smcConnection, SmDialogNormal,
04923                                                         sm_interactCallback, (SmPointer*) d);
04924     }
04925     if (sm_waitingForInteraction) {
04926         QEventLoop eventLoop;
04927         d->eventLoop = &eventLoop;
04928         (void) eventLoop.exec();
04929         d->eventLoop = 0;
04930 
04931         sm_waitingForInteraction = false;
04932         if (sm_smActive) { // not cancelled
04933             sm_interactionActive = true;
04934             qt_sm_blockUserInput = false;
04935             return true;
04936         }
04937     }
04938     return false;
04939 }
04940 
04941 bool QSessionManager::allowsErrorInteraction()
04942 {
04943     Q_D(QSessionManager);
04944     if (sm_interactionActive)
04945         return true;
04946 
04947     if (sm_waitingForInteraction)
04948         return false;
04949 
04950     if (sm_interactStyle == SmInteractStyleAny || sm_interactStyle == SmInteractStyleErrors) {
04951         sm_waitingForInteraction =  SmcInteractRequest(smcConnection, SmDialogError,
04952                                                         sm_interactCallback, (SmPointer*) d);
04953     }
04954     if (sm_waitingForInteraction) {
04955         QEventLoop eventLoop;
04956         d->eventLoop = &eventLoop;
04957         (void) eventLoop.exec();
04958         d->eventLoop = 0;
04959 
04960         sm_waitingForInteraction = false;
04961         if (sm_smActive) { // not cancelled
04962             sm_interactionActive = true;
04963             qt_sm_blockUserInput = false;
04964             return true;
04965         }
04966     }
04967     return false;
04968 }
04969 
04970 void QSessionManager::release()
04971 {
04972     if (sm_interactionActive) {
04973         SmcInteractDone(smcConnection, False);
04974         sm_interactionActive = false;
04975         if (sm_smActive && sm_isshutdown)
04976             qt_sm_blockUserInput = true;
04977     }
04978 }
04979 
04980 void QSessionManager::cancel()
04981 {
04982     sm_cancel = true;
04983 }
04984 
04985 void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
04986 {
04987     Q_D(QSessionManager);
04988     d->restartHint = hint;
04989 }
04990 
04991 QSessionManager::RestartHint QSessionManager::restartHint() const
04992 {
04993     Q_D(const QSessionManager);
04994     return d->restartHint;
04995 }
04996 
04997 void QSessionManager::setRestartCommand(const QStringList& command)
04998 {
04999     Q_D(QSessionManager);
05000     d->restartCommand = command;
05001 }
05002 
05003 QStringList QSessionManager::restartCommand() const
05004 {
05005     Q_D(const QSessionManager);
05006     return d->restartCommand;
05007 }
05008 
05009 void QSessionManager::setDiscardCommand(const QStringList& command)
05010 {
05011     Q_D(QSessionManager);
05012     d->discardCommand = command;
05013 }
05014 
05015 QStringList QSessionManager::discardCommand() const
05016 {
05017     Q_D(const QSessionManager);
05018     return d->discardCommand;
05019 }
05020 
05021 void QSessionManager::setManagerProperty(const QString& name, const QString& value)
05022 {
05023     sm_setProperty(name, value);
05024 }
05025 
05026 void QSessionManager::setManagerProperty(const QString& name, const QStringList& value)
05027 {
05028     sm_setProperty(name, value);
05029 }
05030 
05031 bool QSessionManager::isPhase2() const
05032 {
05033     return sm_in_phase2;
05034 }
05035 
05036 void QSessionManager::requestPhase2()
05037 {
05038     sm_phase2 = true;
05039 }
05040 
05041 #endif // QT_NO_SESSIONMANAGER

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