src/gui/kernel/qapplication_x11.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 // ### 4.0: examine Q_EXPORT's below. The respective symbols had all
       
    43 // been in use (e.g. in the KDE wm) before the introduction of a version
       
    44 // map. One might want to turn some of them into proper public API and
       
    45 // provide a proper alternative for others. See also the exports in
       
    46 // qapplication_win.cpp, which suggest a unification.
       
    47 
       
    48 #include "qplatformdefs.h"
       
    49 
       
    50 #include "qcolormap.h"
       
    51 #include "qdesktopwidget.h"
       
    52 #include "qapplication.h"
       
    53 #include "qapplication_p.h"
       
    54 #include "qcursor.h"
       
    55 #include "qwidget.h"
       
    56 #include "qbitarray.h"
       
    57 #include "qpainter.h"
       
    58 #include "qfile.h"
       
    59 #include "qpixmapcache.h"
       
    60 #include "qdatetime.h"
       
    61 #include "qtextcodec.h"
       
    62 #include "qdatastream.h"
       
    63 #include "qbuffer.h"
       
    64 #include "qsocketnotifier.h"
       
    65 #include "qsessionmanager.h"
       
    66 #include "qclipboard.h"
       
    67 #include "qwhatsthis.h"
       
    68 #include "qsettings.h"
       
    69 #include "qstylefactory.h"
       
    70 #include "qfileinfo.h"
       
    71 #include "qdir.h"
       
    72 #include "qhash.h"
       
    73 #include "qevent.h"
       
    74 #include "qevent_p.h"
       
    75 #include "qvarlengtharray.h"
       
    76 #include "qdebug.h"
       
    77 #include <private/qunicodetables_p.h>
       
    78 #include <private/qcrashhandler_p.h>
       
    79 #include <private/qcolor_p.h>
       
    80 #include <private/qcursor_p.h>
       
    81 #include <private/qiconloader_p.h>
       
    82 #include <private/gtksymbols_p.h>
       
    83 #include "qstyle.h"
       
    84 #include "qmetaobject.h"
       
    85 #include "qtimer.h"
       
    86 #include "qlibrary.h"
       
    87 #include <private/qgraphicssystemfactory_p.h>
       
    88 #include "qguiplatformplugin_p.h"
       
    89 #include "qkde_p.h"
       
    90 
       
    91 #if !defined (QT_NO_TABLET)
       
    92 extern "C" {
       
    93 #   define class c_class  //XIproto.h has a name member named 'class' which the c++ compiler doesn't like
       
    94 #   include <wacomcfg.h>
       
    95 #   undef class
       
    96 }
       
    97 #endif
       
    98 
       
    99 //#define ALIEN_DEBUG
       
   100 
       
   101 #if !defined(QT_NO_GLIB)
       
   102 #  include "qguieventdispatcher_glib_p.h"
       
   103 #endif
       
   104 #include "qeventdispatcher_x11_p.h"
       
   105 #include <private/qpaintengine_x11_p.h>
       
   106 
       
   107 #include <private/qkeymapper_p.h>
       
   108 
       
   109 // Input method stuff
       
   110 #ifndef QT_NO_IM
       
   111 #include "qinputcontext.h"
       
   112 #include "qinputcontextfactory.h"
       
   113 #endif // QT_NO_IM
       
   114 
       
   115 #ifndef QT_NO_XFIXES
       
   116 #include <X11/extensions/Xfixes.h>
       
   117 #endif // QT_NO_XFIXES
       
   118 
       
   119 #include "qt_x11_p.h"
       
   120 #include "qx11info_x11.h"
       
   121 
       
   122 #define XK_MISCELLANY
       
   123 #include <X11/keysymdef.h>
       
   124 #if !defined(QT_NO_XINPUT)
       
   125 #include <X11/extensions/XI.h>
       
   126 #endif
       
   127 
       
   128 #include <stdlib.h>
       
   129 #include <string.h>
       
   130 #include <ctype.h>
       
   131 #include <locale.h>
       
   132 
       
   133 #include "qwidget_p.h"
       
   134 
       
   135 #include <private/qbackingstore_p.h>
       
   136 
       
   137 #ifdef QT_RX71_MULTITOUCH
       
   138 #  include <qsocketnotifier.h>
       
   139 #  include <linux/input.h>
       
   140 #  include <errno.h>
       
   141 #endif
       
   142 
       
   143 #if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4)
       
   144 # define QT_NO_UNSETENV
       
   145 #endif
       
   146 
       
   147 QT_BEGIN_NAMESPACE
       
   148 
       
   149 //#define X_NOT_BROKEN
       
   150 #ifdef X_NOT_BROKEN
       
   151 // Some X libraries are built with setlocale #defined to _Xsetlocale,
       
   152 // even though library users are then built WITHOUT such a definition.
       
   153 // This creates a problem - Qt might setlocale() one value, but then
       
   154 // X looks and doesn't see the value Qt set. The solution here is to
       
   155 // implement _Xsetlocale just in case X calls it - redirecting it to
       
   156 // the real libC version.
       
   157 //
       
   158 # ifndef setlocale
       
   159 extern "C" char *_Xsetlocale(int category, const char *locale);
       
   160 char *_Xsetlocale(int category, const char *locale)
       
   161 {
       
   162     //qDebug("_Xsetlocale(%d,%s),category,locale");
       
   163     return setlocale(category,locale);
       
   164 }
       
   165 # endif // setlocale
       
   166 #endif // X_NOT_BROKEN
       
   167 
       
   168 /* Warning: if you modify this string, modify the list of atoms in qt_x11_p.h as well! */
       
   169 static const char * x11_atomnames = {
       
   170     // window-manager <-> client protocols
       
   171     "WM_PROTOCOLS\0"
       
   172     "WM_DELETE_WINDOW\0"
       
   173     "WM_TAKE_FOCUS\0"
       
   174     "_NET_WM_PING\0"
       
   175     "_NET_WM_CONTEXT_HELP\0"
       
   176     "_NET_WM_SYNC_REQUEST\0"
       
   177     "_NET_WM_SYNC_REQUEST_COUNTER\0"
       
   178 
       
   179     // ICCCM window state
       
   180     "WM_STATE\0"
       
   181     "WM_CHANGE_STATE\0"
       
   182 
       
   183     // Session management
       
   184     "WM_CLIENT_LEADER\0"
       
   185     "WM_WINDOW_ROLE\0"
       
   186     "SM_CLIENT_ID\0"
       
   187 
       
   188     // Clipboard
       
   189     "CLIPBOARD\0"
       
   190     "INCR\0"
       
   191     "TARGETS\0"
       
   192     "MULTIPLE\0"
       
   193     "TIMESTAMP\0"
       
   194     "SAVE_TARGETS\0"
       
   195     "CLIP_TEMPORARY\0"
       
   196     "_QT_SELECTION\0"
       
   197     "_QT_CLIPBOARD_SENTINEL\0"
       
   198     "_QT_SELECTION_SENTINEL\0"
       
   199     "CLIPBOARD_MANAGER\0"
       
   200 
       
   201     "RESOURCE_MANAGER\0"
       
   202 
       
   203     "_XSETROOT_ID\0"
       
   204 
       
   205     "_QT_SCROLL_DONE\0"
       
   206     "_QT_INPUT_ENCODING\0"
       
   207 
       
   208     "_MOTIF_WM_HINTS\0"
       
   209 
       
   210     "DTWM_IS_RUNNING\0"
       
   211     "KDE_FULL_SESSION\0"
       
   212     "KWIN_RUNNING\0"
       
   213     "KWM_RUNNING\0"
       
   214     "GNOME_BACKGROUND_PROPERTIES\0"
       
   215     "ENLIGHTENMENT_DESKTOP\0"
       
   216     "_SGI_DESKS_MANAGER\0"
       
   217 
       
   218     // EWMH (aka NETWM)
       
   219     "_NET_SUPPORTED\0"
       
   220     "_NET_VIRTUAL_ROOTS\0"
       
   221     "_NET_WORKAREA\0"
       
   222 
       
   223     "_NET_MOVERESIZE_WINDOW\0"
       
   224     "_NET_WM_MOVERESIZE\0"
       
   225 
       
   226     "_NET_WM_NAME\0"
       
   227     "_NET_WM_ICON_NAME\0"
       
   228     "_NET_WM_ICON\0"
       
   229 
       
   230     "_NET_WM_PID\0"
       
   231 
       
   232     "_NET_WM_WINDOW_OPACITY\0"
       
   233 
       
   234     "_NET_WM_STATE\0"
       
   235     "_NET_WM_STATE_ABOVE\0"
       
   236     "_NET_WM_STATE_BELOW\0"
       
   237     "_NET_WM_STATE_FULLSCREEN\0"
       
   238     "_NET_WM_STATE_MAXIMIZED_HORZ\0"
       
   239     "_NET_WM_STATE_MAXIMIZED_VERT\0"
       
   240     "_NET_WM_STATE_MODAL\0"
       
   241     "_NET_WM_STATE_STAYS_ON_TOP\0"
       
   242     "_NET_WM_STATE_DEMANDS_ATTENTION\0"
       
   243 
       
   244     "_NET_WM_USER_TIME\0"
       
   245     "_NET_WM_USER_TIME_WINDOW\0"
       
   246     "_NET_WM_FULL_PLACEMENT\0"
       
   247 
       
   248     "_NET_WM_WINDOW_TYPE\0"
       
   249     "_NET_WM_WINDOW_TYPE_DESKTOP\0"
       
   250     "_NET_WM_WINDOW_TYPE_DOCK\0"
       
   251     "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
       
   252     "_NET_WM_WINDOW_TYPE_MENU\0"
       
   253     "_NET_WM_WINDOW_TYPE_UTILITY\0"
       
   254     "_NET_WM_WINDOW_TYPE_SPLASH\0"
       
   255     "_NET_WM_WINDOW_TYPE_DIALOG\0"
       
   256     "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
       
   257     "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
       
   258     "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
       
   259     "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
       
   260     "_NET_WM_WINDOW_TYPE_COMBO\0"
       
   261     "_NET_WM_WINDOW_TYPE_DND\0"
       
   262     "_NET_WM_WINDOW_TYPE_NORMAL\0"
       
   263     "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
       
   264 
       
   265     "_KDE_NET_WM_FRAME_STRUT\0"
       
   266 
       
   267     "_NET_STARTUP_INFO\0"
       
   268     "_NET_STARTUP_INFO_BEGIN\0"
       
   269 
       
   270     "_NET_SUPPORTING_WM_CHECK\0"
       
   271 
       
   272     "_NET_WM_CM_S0\0"
       
   273 
       
   274     "_NET_SYSTEM_TRAY_VISUAL\0"
       
   275 
       
   276     // Property formats
       
   277     "COMPOUND_TEXT\0"
       
   278     "TEXT\0"
       
   279     "UTF8_STRING\0"
       
   280 
       
   281     // xdnd
       
   282     "XdndEnter\0"
       
   283     "XdndPosition\0"
       
   284     "XdndStatus\0"
       
   285     "XdndLeave\0"
       
   286     "XdndDrop\0"
       
   287     "XdndFinished\0"
       
   288     "XdndTypeList\0"
       
   289     "XdndActionList\0"
       
   290 
       
   291     "XdndSelection\0"
       
   292 
       
   293     "XdndAware\0"
       
   294     "XdndProxy\0"
       
   295 
       
   296     "XdndActionCopy\0"
       
   297     "XdndActionLink\0"
       
   298     "XdndActionMove\0"
       
   299     "XdndActionPrivate\0"
       
   300 
       
   301     // Motif DND
       
   302     "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
       
   303     "_MOTIF_DRAG_INITIATOR_INFO\0"
       
   304     "_MOTIF_DRAG_RECEIVER_INFO\0"
       
   305     "_MOTIF_DRAG_WINDOW\0"
       
   306     "_MOTIF_DRAG_TARGETS\0"
       
   307 
       
   308     "XmTRANSFER_SUCCESS\0"
       
   309     "XmTRANSFER_FAILURE\0"
       
   310 
       
   311     // Xkb
       
   312     "_XKB_RULES_NAMES\0"
       
   313 
       
   314     // XEMBED
       
   315     "_XEMBED\0"
       
   316     "_XEMBED_INFO\0"
       
   317 
       
   318     "Wacom Stylus\0"
       
   319     "Wacom Cursor\0"
       
   320     "Wacom Eraser\0"
       
   321 };
       
   322 
       
   323 Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
       
   324 
       
   325 /*****************************************************************************
       
   326   Internal variables and functions
       
   327  *****************************************************************************/
       
   328 static const char *appName = 0;                        // application name
       
   329 static const char *appClass = 0;                        // application class
       
   330 static const char *appFont        = 0;                // application font
       
   331 static const char *appBGCol        = 0;                // application bg color
       
   332 static const char *appFGCol        = 0;                // application fg color
       
   333 static const char *appBTNCol        = 0;                // application btn color
       
   334 static const char *mwGeometry        = 0;                // main widget geometry
       
   335 static const char *mwTitle        = 0;                // main widget title
       
   336 char    *qt_ximServer        = 0;                // XIM Server will connect to
       
   337 static bool        appSync                = false;        // X11 synchronization
       
   338 #if defined(QT_DEBUG)
       
   339 static bool        appNoGrab        = false;        // X11 grabbing enabled
       
   340 static bool        appDoGrab        = false;        // X11 grabbing override (gdb)
       
   341 #endif
       
   342 static bool        app_save_rootinfo = false;        // save root info
       
   343 static bool        app_do_modal        = false;        // modal mode
       
   344 static Window        curWin = 0;                        // current window
       
   345 
       
   346 
       
   347 // function to update the workarea of the screen - in qdesktopwidget_x11.cpp
       
   348 extern void qt_desktopwidget_update_workarea();
       
   349 
       
   350 // Function to change the window manager state (from qwidget_x11.cpp)
       
   351 extern void qt_change_net_wm_state(const QWidget *w, bool set, Atom one, Atom two = 0);
       
   352 
       
   353 // modifier masks for alt, meta, super, hyper, and mode_switch - detected when the application starts
       
   354 // and/or keyboard layout changes
       
   355 uchar qt_alt_mask = 0;
       
   356 uchar qt_meta_mask = 0;
       
   357 uchar qt_super_mask = 0;
       
   358 uchar qt_hyper_mask = 0;
       
   359 uchar qt_mode_switch_mask = 0;
       
   360 
       
   361 // flags for extensions for special Languages, currently only for RTL languages
       
   362 bool         qt_use_rtl_extensions = false;
       
   363 
       
   364 static Window        mouseActWindow             = 0;        // window where mouse is
       
   365 static Qt::MouseButton  mouseButtonPressed   = Qt::NoButton; // last mouse button pressed
       
   366 static Qt::MouseButtons mouseButtonState     = Qt::NoButton; // mouse button state
       
   367 static Time        mouseButtonPressTime = 0;        // when was a button pressed
       
   368 static short        mouseXPos, mouseYPos;                // mouse pres position in act window
       
   369 static short        mouseGlobalXPos, mouseGlobalYPos; // global mouse press position
       
   370 
       
   371 extern QWidgetList *qt_modal_stack;                // stack of modal widgets
       
   372 
       
   373 // window where mouse buttons have been pressed
       
   374 static Window pressed_window = XNone;
       
   375 
       
   376 // popup control
       
   377 static bool replayPopupMouseEvent = false;
       
   378 static bool popupGrabOk;
       
   379 
       
   380 bool qt_sm_blockUserInput = false;                // session management
       
   381 
       
   382 Q_GUI_EXPORT int qt_xfocusout_grab_counter = 0;
       
   383 
       
   384 #if !defined (QT_NO_TABLET)
       
   385 Q_GLOBAL_STATIC(QTabletDeviceDataList, tablet_devices)
       
   386 QTabletDeviceDataList *qt_tablet_devices()
       
   387 {
       
   388     return tablet_devices();
       
   389 }
       
   390 
       
   391 extern bool qt_tabletChokeMouse;
       
   392 #endif
       
   393 
       
   394 static bool qt_x11EventFilter(XEvent* ev)
       
   395 {
       
   396     long unused;
       
   397     if (qApp->filterEvent(ev, &unused))
       
   398         return true;
       
   399     return qApp->x11EventFilter(ev);
       
   400 }
       
   401 
       
   402 #if !defined(QT_NO_XIM)
       
   403 XIMStyle        qt_xim_preferred_style = 0;
       
   404 #endif
       
   405 int qt_ximComposingKeycode=0;
       
   406 QTextCodec * qt_input_mapper = 0;
       
   407 
       
   408 extern bool qt_check_clipboard_sentinel(); //def in qclipboard_x11.cpp
       
   409 extern bool qt_check_selection_sentinel(); //def in qclipboard_x11.cpp
       
   410 extern bool qt_xfixes_clipboard_changed(Window clipboardOwner, Time timestamp); //def in qclipboard_x11.cpp
       
   411 extern bool qt_xfixes_selection_changed(Window selectionOwner, Time timestamp); //def in qclipboard_x11.cpp
       
   412 
       
   413 static void        qt_save_rootinfo();
       
   414 Q_GUI_EXPORT bool qt_try_modal(QWidget *, XEvent *);
       
   415 
       
   416 QWidget *qt_button_down = 0; // last widget to be pressed with the mouse
       
   417 QPointer<QWidget> qt_last_mouse_receiver = 0;
       
   418 static QWidget *qt_popup_down = 0;  // popup that contains the pressed widget
       
   419 
       
   420 extern bool qt_xdnd_dragging;
       
   421 
       
   422 // gui or non-gui from qapplication.cpp
       
   423 extern bool qt_is_gui_used;
       
   424 
       
   425 /*!
       
   426     \internal
       
   427     Try to resolve a \a symbol from \a library with the version specified
       
   428     by \a vernum.
       
   429 
       
   430     Note that, in the case of the Xfixes library, \a vernum is not the same as
       
   431     \c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes
       
   432     version.
       
   433 */
       
   434 static void* qt_load_library_runtime(const char *library, int vernum,
       
   435                                      int highestVernum, const char *symbol)
       
   436 {
       
   437     QList<int> versions;
       
   438     // we try to load in the following order:
       
   439     // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) )
       
   440     if (vernum != -1)
       
   441         versions << vernum;
       
   442     versions << -1;
       
   443     if (vernum != -1) {
       
   444         for(int i = highestVernum; i > vernum; --i)
       
   445             versions << i;
       
   446     }
       
   447     Q_FOREACH(int version, versions) {
       
   448         QLatin1String libName(library);
       
   449         QLibrary xfixesLib(libName, version);
       
   450         if (xfixesLib.load()) {
       
   451             void *ptr = xfixesLib.resolve(symbol);
       
   452             if (ptr)
       
   453                 return ptr;
       
   454         }
       
   455     }
       
   456     return 0;
       
   457 }
       
   458 
       
   459 #ifndef QT_NO_XINPUT
       
   460 # ifdef QT_RUNTIME_XINPUT
       
   461 #  define XINPUT_LOAD_RUNTIME(vernum, symbol, symbol_type) \
       
   462     (symbol_type)qt_load_library_runtime("libXi", vernum, 6, #symbol);
       
   463 #  define XINPUT_LOAD(symbol) \
       
   464     XINPUT_LOAD_RUNTIME(1, symbol, Ptr##symbol)
       
   465 # else // not runtime XInput
       
   466 #  define XINPUT_LOAD(symbol) symbol
       
   467 # endif // QT_RUNTIME_XINPUT
       
   468 #else // not using Xinput at all
       
   469 # define XINPUT_LOAD(symbol) 0
       
   470 #endif // QT_NO_XINPUT
       
   471 
       
   472 #ifndef QT_NO_XFIXES
       
   473 # ifdef QT_RUNTIME_XFIXES
       
   474 #  define XFIXES_LOAD_RUNTIME(vernum, symbol, symbol_type) \
       
   475     (symbol_type)qt_load_library_runtime("libXfixes", vernum, 4, #symbol);
       
   476 #  define XFIXES_LOAD_V1(symbol) \
       
   477     XFIXES_LOAD_RUNTIME(1, symbol, Ptr##symbol)
       
   478 #  define XFIXES_LOAD_V2(symbol) \
       
   479     XFIXES_LOAD_RUNTIME(2, symbol, Ptr##symbol)
       
   480 
       
   481 # else // not runtime Xfixes
       
   482 
       
   483 #  if XFIXES_MAJOR >= 2
       
   484 #   define XFIXES_LOAD_V1(symbol) symbol
       
   485 #   define XFIXES_LOAD_V2(symbol) symbol
       
   486 #  elif XFIXES_MAJOR >= 1
       
   487 #   define XFIXES_LOAD_V1(symbol) symbol
       
   488 #   define XFIXES_LOAD_V2(symbol) 0
       
   489 #  else
       
   490 #   error Unsupported version of Xfixes
       
   491 #  endif
       
   492 # endif // QT_RUNTIME_XFIXES
       
   493 #else // not using Xfixes at all
       
   494 # define XFIXES_LOAD_V1(symbol) 0
       
   495 # define XFIXES_LOAD_V2(symbol) 0
       
   496 #endif // QT_NO_XFIXES
       
   497 
       
   498 #ifndef QT_NO_XFIXES
       
   499 
       
   500 struct qt_xfixes_selection_event_data
       
   501 {
       
   502     // which selection to filter out.
       
   503     Atom selection;
       
   504 };
       
   505 
       
   506 #if defined(Q_C_CALLBACKS)
       
   507 extern "C" {
       
   508 #endif
       
   509 
       
   510 static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
       
   511 {
       
   512     qt_xfixes_selection_event_data *data =
       
   513         reinterpret_cast<qt_xfixes_selection_event_data*>(arg);
       
   514     if (event->type == X11->xfixes_eventbase + XFixesSelectionNotify) {
       
   515         XFixesSelectionNotifyEvent *xfixes_event = reinterpret_cast<XFixesSelectionNotifyEvent*>(event);
       
   516         if (xfixes_event->selection == data->selection)
       
   517             return true;
       
   518     }
       
   519     return false;
       
   520 }
       
   521 
       
   522 #if defined(Q_C_CALLBACKS)
       
   523 }
       
   524 #endif
       
   525 
       
   526 #endif // QT_NO_XFIXES
       
   527 
       
   528 class QETWidget : public QWidget                // event translator widget
       
   529 {
       
   530 public:
       
   531     QWidgetPrivate* d_func() { return QWidget::d_func(); }
       
   532     bool translateMouseEvent(const XEvent *);
       
   533     void translatePaintEvent(const XEvent *);
       
   534     bool translateConfigEvent(const XEvent *);
       
   535     bool translateCloseEvent(const XEvent *);
       
   536     bool translateScrollDoneEvent(const XEvent *);
       
   537     bool translateWheelEvent(int global_x, int global_y, int delta, Qt::MouseButtons buttons,
       
   538                              Qt::KeyboardModifiers modifiers, Qt::Orientation orient);
       
   539 #if !defined (QT_NO_TABLET)
       
   540     bool translateXinputEvent(const XEvent*, QTabletDeviceData *tablet);
       
   541 #endif
       
   542     bool translatePropertyEvent(const XEvent *);
       
   543 
       
   544     void doDeferredMap()
       
   545     {
       
   546         Q_ASSERT(testAttribute(Qt::WA_WState_Created));
       
   547         if (!testAttribute(Qt::WA_Resized)) {
       
   548             adjustSize();
       
   549             setAttribute(Qt::WA_Resized, false);
       
   550         }
       
   551 
       
   552         /*
       
   553           workaround for WM's that throw away ConfigureRequests from the following:
       
   554 
       
   555           window->hide();
       
   556           window->move(x, y); // could also be resize(), move()+resize(), or setGeometry()
       
   557           window->show();
       
   558         */
       
   559         QRect r = geometry();
       
   560 
       
   561         XMoveResizeWindow(X11->display,
       
   562                           internalWinId(),
       
   563                           r.x(),
       
   564                           r.y(),
       
   565                           r.width(),
       
   566                           r.height());
       
   567 
       
   568         // static gravity!
       
   569         XSizeHints sh;
       
   570         long unused;
       
   571         XGetWMNormalHints(X11->display, internalWinId(), &sh, &unused);
       
   572         sh.flags |= USPosition | PPosition | USSize | PSize | PWinGravity;
       
   573         sh.x = r.x();
       
   574         sh.y = r.y();
       
   575         sh.width = r.width();
       
   576         sh.height = r.height();
       
   577         sh.win_gravity = StaticGravity;
       
   578         XSetWMNormalHints(X11->display, internalWinId(), &sh);
       
   579 
       
   580         setAttribute(Qt::WA_Mapped);
       
   581         if (testAttribute(Qt::WA_DontShowOnScreen))
       
   582             return;
       
   583         d_func()->topData()->waitingForMapNotify = 1;
       
   584         XMapWindow(X11->display, internalWinId());
       
   585     }
       
   586 };
       
   587 
       
   588 
       
   589 void QApplicationPrivate::createEventDispatcher()
       
   590 {
       
   591     Q_Q(QApplication);
       
   592 #if !defined(QT_NO_GLIB)
       
   593     if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
       
   594         eventDispatcher = (q->type() != QApplication::Tty
       
   595                            ? new QGuiEventDispatcherGlib(q)
       
   596                            : new QEventDispatcherGlib(q));
       
   597     else
       
   598 #endif
       
   599         eventDispatcher = (q->type() != QApplication::Tty
       
   600                            ? new QEventDispatcherX11(q)
       
   601                            : new QEventDispatcherUNIX(q));
       
   602 }
       
   603 
       
   604 /*****************************************************************************
       
   605   Default X error handlers
       
   606  *****************************************************************************/
       
   607 
       
   608 #if defined(Q_C_CALLBACKS)
       
   609 extern "C" {
       
   610 #endif
       
   611 
       
   612 static int (*original_x_errhandler)(Display *dpy, XErrorEvent *);
       
   613 static int (*original_xio_errhandler)(Display *dpy);
       
   614 
       
   615 static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
       
   616 {
       
   617     switch (err->error_code) {
       
   618     case BadAtom:
       
   619         if (err->request_code == 20 /* X_GetProperty */
       
   620             && (err->resourceid == XA_RESOURCE_MANAGER
       
   621                 || err->resourceid == XA_RGB_DEFAULT_MAP
       
   622                 || err->resourceid == ATOM(_NET_SUPPORTED)
       
   623                 || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK)
       
   624                 || err->resourceid == ATOM(KDE_FULL_SESSION)
       
   625                 || err->resourceid == ATOM(KWIN_RUNNING)
       
   626                 || err->resourceid == ATOM(XdndProxy)
       
   627                 || err->resourceid == ATOM(XdndAware))) {
       
   628             // Perhaps we're running under SECURITY reduction? :/
       
   629             return 0;
       
   630         }
       
   631         break;
       
   632 
       
   633     case BadWindow:
       
   634         if (err->request_code == 2 /* X_ChangeWindowAttributes */
       
   635             || err->request_code == 38 /* X_QueryPointer */) {
       
   636             for (int i = 0; i < ScreenCount(dpy); ++i) {
       
   637                 if (err->resourceid == RootWindow(dpy, i)) {
       
   638                     // Perhaps we're running under SECURITY reduction? :/
       
   639                     return 0;
       
   640                 }
       
   641             }
       
   642         }
       
   643         X11->seen_badwindow = true;
       
   644         if (err->request_code == 25 /* X_SendEvent */) {
       
   645             for (int i = 0; i < ScreenCount(dpy); ++i) {
       
   646                 if (err->resourceid == RootWindow(dpy, i)) {
       
   647                     // Perhaps we're running under SECURITY reduction? :/
       
   648                     return 0;
       
   649                 }
       
   650             }
       
   651             if (X11->xdndHandleBadwindow()) {
       
   652                 qDebug("xdndHandleBadwindow returned true");
       
   653                 return 0;
       
   654             }
       
   655         }
       
   656         if (X11->ignore_badwindow)
       
   657             return 0;
       
   658         break;
       
   659 
       
   660     case BadMatch:
       
   661         if (err->request_code == 42 /* X_SetInputFocus */)
       
   662             return 0;
       
   663         break;
       
   664 
       
   665     default:
       
   666 #if !defined(QT_NO_XINPUT)
       
   667         if (err->request_code == X11->xinput_major
       
   668             && err->error_code == (X11->xinput_errorbase + XI_BadDevice)
       
   669             && err->minor_code == 3 /* X_OpenDevice */) {
       
   670             return 0;
       
   671         }
       
   672 #endif
       
   673         break;
       
   674     }
       
   675 
       
   676     char errstr[256];
       
   677     XGetErrorText( dpy, err->error_code, errstr, 256 );
       
   678     char buffer[256];
       
   679     char request_str[256];
       
   680     qsnprintf(buffer, 256, "%d", err->request_code);
       
   681     XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256);
       
   682     if (err->request_code < 128) {
       
   683         // X error for a normal protocol request
       
   684         qWarning( "X Error: %s %d\n"
       
   685                   "  Major opcode: %d (%s)\n"
       
   686                   "  Resource id:  0x%lx",
       
   687                   errstr, err->error_code,
       
   688                   err->request_code,
       
   689                   request_str,
       
   690                   err->resourceid );
       
   691     } else {
       
   692         // X error for an extension request
       
   693         const char *extensionName = 0;
       
   694         if (err->request_code == X11->xrender_major)
       
   695             extensionName = "RENDER";
       
   696         else if (err->request_code == X11->xrandr_major)
       
   697             extensionName = "RANDR";
       
   698         else if (err->request_code == X11->xinput_major)
       
   699             extensionName = "XInputExtension";
       
   700         else if (err->request_code == X11->mitshm_major)
       
   701             extensionName = "MIT-SHM";
       
   702 
       
   703         char minor_str[256];
       
   704         if (extensionName) {
       
   705             qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code);
       
   706             XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256);
       
   707         } else {
       
   708             extensionName = "Uknown extension";
       
   709             qsnprintf(minor_str, 256, "Unknown request");
       
   710         }
       
   711         qWarning( "X Error: %s %d\n"
       
   712                   "  Extension:    %d (%s)\n"
       
   713                   "  Minor opcode: %d (%s)\n"
       
   714                   "  Resource id:  0x%lx",
       
   715                   errstr, err->error_code,
       
   716                   err->request_code,
       
   717                   extensionName,
       
   718                   err->minor_code,
       
   719                   minor_str,
       
   720                   err->resourceid );
       
   721     }
       
   722 
       
   723     // ### we really should distinguish between severe, non-severe and
       
   724     // ### application specific errors
       
   725 
       
   726     return 0;
       
   727 }
       
   728 
       
   729 
       
   730 static int qt_xio_errhandler(Display *)
       
   731 {
       
   732     qWarning("%s: Fatal IO error: client killed", appName);
       
   733     QApplicationPrivate::reset_instance_pointer();
       
   734     exit(1);
       
   735     //### give the application a chance for a proper shutdown instead,
       
   736     //### exit(1) doesn't help.
       
   737     return 0;
       
   738 }
       
   739 
       
   740 #if defined(Q_C_CALLBACKS)
       
   741 }
       
   742 #endif
       
   743 
       
   744 #ifndef QT_NO_XSYNC
       
   745 struct qt_sync_request_event_data
       
   746 {
       
   747     WId window;
       
   748 };
       
   749 
       
   750 #if defined(Q_C_CALLBACKS)
       
   751 extern "C" {
       
   752 #endif
       
   753 
       
   754 static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
       
   755 {
       
   756     qt_sync_request_event_data *data =
       
   757         reinterpret_cast<qt_sync_request_event_data*>(arg);
       
   758     if (event->type == ClientMessage &&
       
   759         event->xany.window == data->window &&
       
   760         event->xclient.message_type == ATOM(WM_PROTOCOLS) &&
       
   761         (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) {
       
   762         QWidget *w = QWidget::find(event->xany.window);
       
   763         if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) {
       
   764             const ulong timestamp = (const ulong) event->xclient.data.l[1];
       
   765             if (timestamp > X11->time)
       
   766                 X11->time = timestamp;
       
   767             if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
       
   768                 tlw->syncRequestTimestamp = timestamp;
       
   769                 tlw->newCounterValueLo = event->xclient.data.l[2];
       
   770                 tlw->newCounterValueHi = event->xclient.data.l[3];
       
   771             }
       
   772         }
       
   773         return true;
       
   774     }
       
   775     return false;
       
   776 }
       
   777 
       
   778 #if defined(Q_C_CALLBACKS)
       
   779 }
       
   780 #endif
       
   781 #endif // QT_NO_XSYNC
       
   782 
       
   783 static void qt_x11_create_intern_atoms()
       
   784 {
       
   785     const char *names[QX11Data::NAtoms];
       
   786     const char *ptr = x11_atomnames;
       
   787 
       
   788     int i = 0;
       
   789     while (*ptr) {
       
   790         names[i++] = ptr;
       
   791         while (*ptr)
       
   792             ++ptr;
       
   793         ++ptr;
       
   794     }
       
   795 
       
   796     Q_ASSERT(i == QX11Data::NPredefinedAtoms);
       
   797 
       
   798     QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
       
   799     settings_atom_name += XDisplayName(X11->displayName);
       
   800     names[i++] = settings_atom_name;
       
   801 
       
   802     Q_ASSERT(i == QX11Data::NAtoms);
       
   803 #if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6)
       
   804     XInternAtoms(X11->display, (char **)names, i, False, X11->atoms);
       
   805 #else
       
   806     for (i = 0; i < QX11Data::NAtoms; ++i)
       
   807         X11->atoms[i] = XInternAtom(X11->display, (char *)names[i], False);
       
   808 #endif
       
   809 }
       
   810 
       
   811 Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
       
   812 {
       
   813     QByteArray stamp;
       
   814     QDataStream s(&stamp, QIODevice::WriteOnly);
       
   815     s << QDateTime::currentDateTime();
       
   816 
       
   817     XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0),
       
   818                     ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8,
       
   819                     PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
       
   820 }
       
   821 
       
   822 /*! \internal
       
   823     apply the settings to the application
       
   824 */
       
   825 bool QApplicationPrivate::x11_apply_settings()
       
   826 {
       
   827     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
       
   828 
       
   829     settings.beginGroup(QLatin1String("Qt"));
       
   830 
       
   831     /*
       
   832       Qt settings. This is now they are written into the datastream.
       
   833 
       
   834       Palette / *                - QPalette
       
   835       font                       - QFont
       
   836       libraryPath                - QStringList
       
   837       style                      - QString
       
   838       doubleClickInterval        - int
       
   839       keyboardInputInterval  - int
       
   840       cursorFlashTime            - int
       
   841       wheelScrollLines           - int
       
   842       colorSpec                  - QString
       
   843       defaultCodec               - QString
       
   844       globalStrut/width          - int
       
   845       globalStrut/height         - int
       
   846       GUIEffects                 - QStringList
       
   847       Font Substitutions/ *      - QStringList
       
   848       Font Substitutions/...     - QStringList
       
   849     */
       
   850 
       
   851     QStringList strlist;
       
   852     int i;
       
   853     QPalette pal(Qt::black);
       
   854     int groupCount = 0;
       
   855     strlist = settings.value(QLatin1String("Palette/active")).toStringList();
       
   856     if (!strlist.isEmpty()) {
       
   857         ++groupCount;
       
   858         for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
       
   859             pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
       
   860                          QColor(strlist[i]));
       
   861     }
       
   862     strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
       
   863     if (!strlist.isEmpty()) {
       
   864         ++groupCount;
       
   865         for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
       
   866             pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
       
   867                          QColor(strlist[i]));
       
   868     }
       
   869     strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
       
   870     if (!strlist.isEmpty()) {
       
   871         ++groupCount;
       
   872         for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
       
   873             pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
       
   874                          QColor(strlist[i]));
       
   875     }
       
   876 
       
   877     // ### Fix properly for 4.6
       
   878     bool usingGtkSettings = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle");
       
   879     if (!usingGtkSettings) {
       
   880         if (groupCount == QPalette::NColorGroups)
       
   881             QApplicationPrivate::setSystemPalette(pal);
       
   882     }
       
   883 
       
   884     if (!appFont) {
       
   885         // ### Fix properly for 4.6
       
   886         if (!usingGtkSettings) {
       
   887             QFont font(QApplication::font());
       
   888             QString fontDescription;
       
   889             // Override Qt font if KDE4 settings can be used
       
   890             if (X11->desktopVersion == 4) {
       
   891                 QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
       
   892                 fontDescription = kdeSettings.value(QLatin1String("font")).toString();
       
   893                 if (fontDescription.isEmpty()) {
       
   894                     // KDE stores fonts without quotes
       
   895                     fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(","));
       
   896                 }
       
   897             }
       
   898             if (fontDescription.isEmpty())
       
   899                 fontDescription = settings.value(QLatin1String("font")).toString();
       
   900             if (!fontDescription .isEmpty()) {
       
   901                 font.fromString(fontDescription );
       
   902                 QApplicationPrivate::setSystemFont(font);
       
   903             }
       
   904         }
       
   905     }
       
   906 
       
   907     // read library (ie. plugin) path list
       
   908     QString libpathkey =
       
   909         QString::fromLatin1("%1.%2/libraryPath")
       
   910         .arg(QT_VERSION >> 16)
       
   911         .arg((QT_VERSION & 0xff00) >> 8);
       
   912     QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':'));
       
   913     if (! pathlist.isEmpty()) {
       
   914         QStringList::ConstIterator it = pathlist.constBegin();
       
   915         while (it != pathlist.constEnd())
       
   916             QApplication::addLibraryPath(*it++);
       
   917     }
       
   918 
       
   919     // read new QStyle
       
   920     QString stylename = settings.value(QLatin1String("style")).toString();
       
   921 
       
   922     if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) {
       
   923         stylename = qt_guiPlatformPlugin()->styleName();
       
   924     }
       
   925 
       
   926     static QString currentStyleName = stylename;
       
   927     if (QCoreApplication::startingUp()) {
       
   928         if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
       
   929             QApplicationPrivate::styleOverride = stylename;
       
   930     } else {
       
   931         if (currentStyleName != stylename) {
       
   932             currentStyleName = stylename;
       
   933             QApplication::setStyle(stylename);
       
   934         }
       
   935     }
       
   936 
       
   937     int num =
       
   938         settings.value(QLatin1String("doubleClickInterval"),
       
   939                        QApplication::doubleClickInterval()).toInt();
       
   940     QApplication::setDoubleClickInterval(num);
       
   941 
       
   942     num =
       
   943         settings.value(QLatin1String("cursorFlashTime"),
       
   944                        QApplication::cursorFlashTime()).toInt();
       
   945     QApplication::setCursorFlashTime(num);
       
   946 
       
   947     num =
       
   948         settings.value(QLatin1String("wheelScrollLines"),
       
   949                        QApplication::wheelScrollLines()).toInt();
       
   950     QApplication::setWheelScrollLines(num);
       
   951 
       
   952     QString colorspec = settings.value(QLatin1String("colorSpec"),
       
   953                                        QVariant(QLatin1String("default"))).toString();
       
   954     if (colorspec == QLatin1String("normal"))
       
   955         QApplication::setColorSpec(QApplication::NormalColor);
       
   956     else if (colorspec == QLatin1String("custom"))
       
   957         QApplication::setColorSpec(QApplication::CustomColor);
       
   958     else if (colorspec == QLatin1String("many"))
       
   959         QApplication::setColorSpec(QApplication::ManyColor);
       
   960     else if (colorspec != QLatin1String("default"))
       
   961         colorspec = QLatin1String("default");
       
   962 
       
   963     QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
       
   964                                           QVariant(QLatin1String("none"))).toString();
       
   965     if (defaultcodec != QLatin1String("none")) {
       
   966         QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
       
   967         if (codec)
       
   968             QTextCodec::setCodecForTr(codec);
       
   969     }
       
   970 
       
   971     int w = settings.value(QLatin1String("globalStrut/width")).toInt();
       
   972     int h = settings.value(QLatin1String("globalStrut/height")).toInt();
       
   973     QSize strut(w, h);
       
   974     if (strut.isValid())
       
   975         QApplication::setGlobalStrut(strut);
       
   976 
       
   977     QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList();
       
   978     QApplication::setEffectEnabled(Qt::UI_General,
       
   979                                    effects.contains(QLatin1String("general")));
       
   980     QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
       
   981                                    effects.contains(QLatin1String("animatemenu")));
       
   982     QApplication::setEffectEnabled(Qt::UI_FadeMenu,
       
   983                                    effects.contains(QLatin1String("fademenu")));
       
   984     QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
       
   985                                    effects.contains(QLatin1String("animatecombo")));
       
   986     QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
       
   987                                    effects.contains(QLatin1String("animatetooltip")));
       
   988     QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
       
   989                                    effects.contains(QLatin1String("fadetooltip")));
       
   990     QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
       
   991                                    effects.contains(QLatin1String("animatetoolbox")));
       
   992 
       
   993     if (!X11->has_fontconfig) {
       
   994         settings.beginGroup(QLatin1String("Font Substitutions"));
       
   995         QStringList fontsubs = settings.childKeys();
       
   996         if (!fontsubs.isEmpty()) {
       
   997             QStringList::Iterator it = fontsubs.begin();
       
   998             for (; it != fontsubs.end(); ++it) {
       
   999                 QString fam = *it;
       
  1000                 QStringList subs = settings.value(fam).toStringList();
       
  1001                 QFont::insertSubstitutions(fam, subs);
       
  1002             }
       
  1003         }
       
  1004         settings.endGroup();
       
  1005     }
       
  1006 
       
  1007     qt_use_rtl_extensions =
       
  1008         settings.value(QLatin1String("useRtlExtensions"), false).toBool();
       
  1009 
       
  1010 #ifndef QT_NO_XIM
       
  1011     if (qt_xim_preferred_style == 0) {
       
  1012         QString ximInputStyle = settings.value(QLatin1String("XIMInputStyle"),
       
  1013                                                QVariant(QLatin1String("on the spot"))).toString().toLower();
       
  1014         if (ximInputStyle == QLatin1String("on the spot"))
       
  1015             qt_xim_preferred_style = XIMPreeditCallbacks | XIMStatusNothing;
       
  1016         else if (ximInputStyle == QLatin1String("over the spot"))
       
  1017             qt_xim_preferred_style = XIMPreeditPosition | XIMStatusNothing;
       
  1018         else if (ximInputStyle == QLatin1String("off the spot"))
       
  1019             qt_xim_preferred_style = XIMPreeditArea | XIMStatusArea;
       
  1020         else if (ximInputStyle == QLatin1String("root"))
       
  1021             qt_xim_preferred_style = XIMPreeditNothing | XIMStatusNothing;
       
  1022     }
       
  1023 #endif
       
  1024     QStringList inputMethods = QInputContextFactory::keys();
       
  1025     if (inputMethods.size() > 2 && inputMethods.contains(QLatin1String("imsw-multi"))) {
       
  1026         X11->default_im = QLatin1String("imsw-multi");
       
  1027     } else {
       
  1028         X11->default_im = settings.value(QLatin1String("DefaultInputMethod"),
       
  1029                                          QLatin1String("xim")).toString();
       
  1030     }
       
  1031 
       
  1032     settings.endGroup(); // Qt
       
  1033 
       
  1034     return true;
       
  1035 }
       
  1036 
       
  1037 
       
  1038 /*! \internal
       
  1039     Resets the QApplication::instance() pointer to zero
       
  1040 */
       
  1041 void QApplicationPrivate::reset_instance_pointer()
       
  1042 { QApplication::self = 0; }
       
  1043 
       
  1044 
       
  1045 // read the _QT_INPUT_ENCODING property and apply the settings to
       
  1046 // the application
       
  1047 static void qt_set_input_encoding()
       
  1048 {
       
  1049     Atom type;
       
  1050     int format;
       
  1051     ulong  nitems, after = 1;
       
  1052     unsigned char *data = 0;
       
  1053 
       
  1054     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  1055                                 ATOM(_QT_INPUT_ENCODING), 0, 1024,
       
  1056                                 False, XA_STRING, &type, &format, &nitems,
       
  1057                                 &after, &data);
       
  1058     if (e != Success || !nitems || type == XNone) {
       
  1059         // Always use the locale codec, since we have no examples of non-local
       
  1060         // XIMs, and since we cannot get a sensible answer about the encoding
       
  1061         // from the XIM.
       
  1062         qt_input_mapper = QTextCodec::codecForLocale();
       
  1063 
       
  1064     } else {
       
  1065         if (!qstricmp((char *)data, "locale"))
       
  1066             qt_input_mapper = QTextCodec::codecForLocale();
       
  1067         else
       
  1068             qt_input_mapper = QTextCodec::codecForName((char *)data);
       
  1069         // make sure we have an input codec
       
  1070         if(!qt_input_mapper)
       
  1071             qt_input_mapper = QTextCodec::codecForName("ISO 8859-1");
       
  1072     }
       
  1073     if (qt_input_mapper && qt_input_mapper->mibEnum() == 11) // 8859-8
       
  1074         qt_input_mapper = QTextCodec::codecForName("ISO 8859-8-I");
       
  1075     if(data)
       
  1076         XFree((char *)data);
       
  1077 }
       
  1078 
       
  1079 // set font, foreground and background from x11 resources. The
       
  1080 // arguments may override the resource settings.
       
  1081 static void qt_set_x11_resources(const char* font = 0, const char* fg = 0,
       
  1082                                  const char* bg = 0, const char* button = 0)
       
  1083 {
       
  1084 
       
  1085     QString resFont, resFG, resBG, resButton, resEF, sysFont, selectBackground, selectForeground;
       
  1086 
       
  1087     QApplication::setEffectEnabled(Qt::UI_General, false);
       
  1088     QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
       
  1089     QApplication::setEffectEnabled(Qt::UI_FadeMenu, false);
       
  1090     QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false);
       
  1091     QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, false);
       
  1092     QApplication::setEffectEnabled(Qt::UI_FadeTooltip, false);
       
  1093     QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, false);
       
  1094 
       
  1095     bool paletteAlreadySet = false;
       
  1096     if (QApplication::desktopSettingsAware()) {
       
  1097         // first, read from settings
       
  1098         QApplicationPrivate::x11_apply_settings();
       
  1099         // the call to QApplication::style() below creates the system
       
  1100         // palette, which breaks the logic after the RESOURCE_MANAGER
       
  1101         // loop... so I have to save this value to be able to use it later
       
  1102         paletteAlreadySet = (QApplicationPrivate::sys_pal != 0);
       
  1103 
       
  1104         // second, parse the RESOURCE_MANAGER property
       
  1105         int format;
       
  1106         ulong  nitems, after = 1;
       
  1107         QString res;
       
  1108         long offset = 0;
       
  1109         Atom type = XNone;
       
  1110 
       
  1111         while (after > 0) {
       
  1112             uchar *data = 0;
       
  1113             if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(0),
       
  1114                                    ATOM(RESOURCE_MANAGER),
       
  1115                                    offset, 8192, False, AnyPropertyType,
       
  1116                                    &type, &format, &nitems, &after,
       
  1117                                    &data) != Success) {
       
  1118                 res = QString();
       
  1119                 break;
       
  1120             }
       
  1121             if (type == XA_STRING)
       
  1122                 res += QString::fromLatin1((char*)data);
       
  1123             else
       
  1124                 res += QString::fromLocal8Bit((char*)data);
       
  1125             offset += 2048; // offset is in 32bit quantities... 8192/4 == 2048
       
  1126             if (data)
       
  1127                 XFree((char *)data);
       
  1128         }
       
  1129 
       
  1130         QString key, value;
       
  1131         int l = 0, r;
       
  1132         QString apn = QString::fromLocal8Bit(appName);
       
  1133         QString apc = QString::fromLocal8Bit(appClass);
       
  1134         int apnl = apn.length();
       
  1135         int apcl = apc.length();
       
  1136         int resl = res.length();
       
  1137 
       
  1138         while (l < resl) {
       
  1139             r = res.indexOf(QLatin1Char('\n'), l);
       
  1140             if (r < 0)
       
  1141                 r = resl;
       
  1142             while (res.at(l).isSpace())
       
  1143                 l++;
       
  1144             bool mine = false;
       
  1145             QChar sc = res.at(l + 1);
       
  1146             if (res.at(l) == QLatin1Char('*') &&
       
  1147                 (sc == QLatin1Char('f') || sc == QLatin1Char('b') || sc == QLatin1Char('g') ||
       
  1148                  sc == QLatin1Char('F') || sc == QLatin1Char('B') || sc == QLatin1Char('G') ||
       
  1149                  sc == QLatin1Char('s') || sc == QLatin1Char('S')
       
  1150                  // capital T only, since we're looking for "Text.selectSomething"
       
  1151                  || sc == QLatin1Char('T'))) {
       
  1152                 // OPTIMIZED, since we only want "*[fbgsT].."
       
  1153                 QString item = res.mid(l, r - l).simplified();
       
  1154                 int i = item.indexOf(QLatin1Char(':'));
       
  1155                 key = item.left(i).trimmed().mid(1).toLower();
       
  1156                 value = item.right(item.length() - i - 1).trimmed();
       
  1157                 mine = true;
       
  1158             } else if ((apnl && res.at(l) == apn.at(0)) || (appClass && apcl && res.at(l) == apc.at(0))) {
       
  1159                 if (res.mid(l,apnl) == apn && (res.at(l+apnl) == QLatin1Char('.')
       
  1160                                                || res.at(l+apnl) == QLatin1Char('*'))) {
       
  1161                     QString item = res.mid(l, r - l).simplified();
       
  1162                     int i = item.indexOf(QLatin1Char(':'));
       
  1163                     key = item.left(i).trimmed().mid(apnl+1).toLower();
       
  1164                     value = item.right(item.length() - i - 1).trimmed();
       
  1165                     mine = true;
       
  1166                 } else if (res.mid(l,apcl) == apc && (res.at(l+apcl) == QLatin1Char('.')
       
  1167                                                       || res.at(l+apcl) == QLatin1Char('*'))) {
       
  1168                     QString item = res.mid(l, r - l).simplified();
       
  1169                     int i = item.indexOf(QLatin1Char(':'));
       
  1170                     key = item.left(i).trimmed().mid(apcl+1).toLower();
       
  1171                     value = item.right(item.length() - i - 1).trimmed();
       
  1172                     mine = true;
       
  1173                 }
       
  1174             }
       
  1175 
       
  1176             if (mine) {
       
  1177                 if (!font && key == QLatin1String("systemfont"))
       
  1178                     sysFont = value.left(value.lastIndexOf(QLatin1Char(':')));
       
  1179                 if (!font && key == QLatin1String("font"))
       
  1180                     resFont = value;
       
  1181                 else if (!fg && !paletteAlreadySet) {
       
  1182                     if (key == QLatin1String("foreground"))
       
  1183                         resFG = value;
       
  1184                     else if (!bg && key == QLatin1String("background"))
       
  1185                         resBG = value;
       
  1186                     else if (!bg && !button && key == QLatin1String("button.background"))
       
  1187                         resButton = value;
       
  1188                     else if (key == QLatin1String("text.selectbackground")) {
       
  1189                         selectBackground = value;
       
  1190                     } else if (key == QLatin1String("text.selectforeground")) {
       
  1191                         selectForeground = value;
       
  1192                     }
       
  1193                 } else if (key == QLatin1String("guieffects"))
       
  1194                     resEF = value;
       
  1195                 // NOTE: if you add more, change the [fbg] stuff above
       
  1196             }
       
  1197 
       
  1198             l = r + 1;
       
  1199         }
       
  1200     }
       
  1201     if (!sysFont.isEmpty())
       
  1202         resFont = sysFont;
       
  1203     if (resFont.isEmpty())
       
  1204         resFont = QString::fromLocal8Bit(font);
       
  1205     if (resFG.isEmpty())
       
  1206         resFG = QString::fromLocal8Bit(fg);
       
  1207     if (resBG.isEmpty())
       
  1208         resBG = QString::fromLocal8Bit(bg);
       
  1209     if (resButton.isEmpty())
       
  1210         resButton = QString::fromLocal8Bit(button);
       
  1211     if (!resFont.isEmpty()
       
  1212         && !X11->has_fontconfig
       
  1213         && !QApplicationPrivate::sys_font) {
       
  1214         // set application font
       
  1215         QFont fnt;
       
  1216         fnt.setRawName(resFont);
       
  1217 
       
  1218         // the font we get may actually be an alias for another font,
       
  1219         // so we reset the application font to the real font info.
       
  1220         if (! fnt.exactMatch()) {
       
  1221             QFontInfo fontinfo(fnt);
       
  1222             fnt.setFamily(fontinfo.family());
       
  1223             fnt.setRawMode(fontinfo.rawMode());
       
  1224 
       
  1225             if (! fnt.rawMode()) {
       
  1226                 fnt.setItalic(fontinfo.italic());
       
  1227                 fnt.setWeight(fontinfo.weight());
       
  1228                 fnt.setUnderline(fontinfo.underline());
       
  1229                 fnt.setStrikeOut(fontinfo.strikeOut());
       
  1230                 fnt.setStyleHint(fontinfo.styleHint());
       
  1231 
       
  1232                 if (fnt.pointSize() <= 0 && fnt.pixelSize() <= 0) {
       
  1233                     // size is all wrong... fix it
       
  1234                     qreal pointSize = fontinfo.pixelSize() * 72. / (float) QX11Info::appDpiY();
       
  1235                     if (pointSize <= 0)
       
  1236                         pointSize = 12;
       
  1237                     fnt.setPointSize(qRound(pointSize));
       
  1238                 }
       
  1239             }
       
  1240         }
       
  1241 
       
  1242         QApplicationPrivate::setSystemFont(fnt);
       
  1243     }
       
  1244     // QGtkStyle sets it's own system palette
       
  1245     bool gtkStyle = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle");
       
  1246     bool kdeColors = (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE);
       
  1247     if (!gtkStyle && (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty()))) {// set app colors
       
  1248         bool allowX11ColorNames = QColor::allowX11ColorNames();
       
  1249         QColor::setAllowX11ColorNames(true);
       
  1250 
       
  1251         (void) QApplication::style();  // trigger creation of application style and system palettes
       
  1252         QColor btn;
       
  1253         QColor bg;
       
  1254         QColor fg;
       
  1255         QColor bfg;
       
  1256         QColor wfg;
       
  1257         if (!resBG.isEmpty())
       
  1258             bg = QColor(resBG);
       
  1259         if (!bg.isValid())
       
  1260             bg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Window);
       
  1261 
       
  1262         if (!resFG.isEmpty())
       
  1263             fg = QColor(resFG);
       
  1264         if (!fg.isValid())
       
  1265             fg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::WindowText);
       
  1266 
       
  1267         if (!resButton.isEmpty())
       
  1268             btn = QColor(resButton);
       
  1269         else if (!resBG.isEmpty())
       
  1270             btn = bg;
       
  1271         if (!btn.isValid())
       
  1272             btn = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Button);
       
  1273 
       
  1274         int h,s,v;
       
  1275         fg.getHsv(&h,&s,&v);
       
  1276         QColor base = Qt::white;
       
  1277         bool bright_mode = false;
       
  1278         if (v >= 255 - 50) {
       
  1279             base = btn.darker(150);
       
  1280             bright_mode = true;
       
  1281         }
       
  1282 
       
  1283         QPalette pal(fg, btn, btn.lighter(125), btn.darker(130), btn.darker(120), wfg.isValid() ? wfg : fg, Qt::white, base, bg);
       
  1284         QColor disabled((fg.red()   + btn.red())  / 2,
       
  1285                         (fg.green() + btn.green())/ 2,
       
  1286                         (fg.blue()  + btn.blue()) / 2);
       
  1287         pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.lighter(125),
       
  1288                           btn.darker(130), btn.darker(150), disabled, Qt::white, Qt::white, bg);
       
  1289 
       
  1290         QColor highlight, highlightText;
       
  1291         if (!selectBackground.isEmpty() && !selectForeground.isEmpty()) {
       
  1292             highlight = QColor(selectBackground);
       
  1293             highlightText = QColor(selectForeground);
       
  1294         }
       
  1295 
       
  1296         if (highlight.isValid() && highlightText.isValid()) {
       
  1297             pal.setColor(QPalette::Highlight, highlight);
       
  1298             pal.setColor(QPalette::HighlightedText, highlightText);
       
  1299 
       
  1300             // calculate disabled colors by removing saturation
       
  1301             highlight.setHsv(highlight.hue(), 0, highlight.value(), highlight.alpha());
       
  1302             highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha());
       
  1303             pal.setColor(QPalette::Disabled, QPalette::Highlight, highlight);
       
  1304             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText);
       
  1305         } else if (bright_mode) {
       
  1306             pal.setColor(QPalette::HighlightedText, base);
       
  1307             pal.setColor(QPalette::Highlight, Qt::white);
       
  1308             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base);
       
  1309             pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white);
       
  1310         } else {
       
  1311             pal.setColor(QPalette::HighlightedText, Qt::white);
       
  1312             pal.setColor(QPalette::Highlight, Qt::darkBlue);
       
  1313             pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white);
       
  1314             pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue);
       
  1315         }
       
  1316 
       
  1317         pal = qt_guiPlatformPlugin()->palette().resolve(pal);
       
  1318         QApplicationPrivate::setSystemPalette(pal);
       
  1319         QColor::setAllowX11ColorNames(allowX11ColorNames);
       
  1320     }
       
  1321 
       
  1322     if (!resEF.isEmpty()) {
       
  1323         QStringList effects = resEF.split(QLatin1Char(' '));
       
  1324         QApplication::setEffectEnabled(Qt::UI_General, effects.contains(QLatin1String("general")));
       
  1325         QApplication::setEffectEnabled(Qt::UI_AnimateMenu,
       
  1326                                        effects.contains(QLatin1String("animatemenu")));
       
  1327         QApplication::setEffectEnabled(Qt::UI_FadeMenu,
       
  1328                                        effects.contains(QLatin1String("fademenu")));
       
  1329         QApplication::setEffectEnabled(Qt::UI_AnimateCombo,
       
  1330                                        effects.contains(QLatin1String("animatecombo")));
       
  1331         QApplication::setEffectEnabled(Qt::UI_AnimateTooltip,
       
  1332                                        effects.contains(QLatin1String("animatetooltip")));
       
  1333         QApplication::setEffectEnabled(Qt::UI_FadeTooltip,
       
  1334                                        effects.contains(QLatin1String("fadetooltip")));
       
  1335         QApplication::setEffectEnabled(Qt::UI_AnimateToolBox,
       
  1336                                        effects.contains(QLatin1String("animatetoolbox")));
       
  1337     }
       
  1338 
       
  1339     QIconLoader::instance()->updateSystemTheme();
       
  1340 }
       
  1341 
       
  1342 
       
  1343 // update the supported array
       
  1344 static void qt_get_net_supported()
       
  1345 {
       
  1346     Atom type;
       
  1347     int format;
       
  1348     long offset = 0;
       
  1349     unsigned long nitems, after;
       
  1350     unsigned char *data = 0;
       
  1351 
       
  1352     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  1353                                ATOM(_NET_SUPPORTED), 0, 0,
       
  1354                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
       
  1355     if (data)
       
  1356         XFree(data);
       
  1357 
       
  1358     if (X11->net_supported_list)
       
  1359         delete [] X11->net_supported_list;
       
  1360     X11->net_supported_list = 0;
       
  1361 
       
  1362     if (e == Success && type == XA_ATOM && format == 32) {
       
  1363         QBuffer ts;
       
  1364         ts.open(QIODevice::WriteOnly);
       
  1365 
       
  1366         while (after > 0) {
       
  1367             XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  1368                                ATOM(_NET_SUPPORTED), offset, 1024,
       
  1369                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
       
  1370 
       
  1371             if (type == XA_ATOM && format == 32) {
       
  1372                 ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long));
       
  1373                 offset += nitems;
       
  1374             } else
       
  1375                 after = 0;
       
  1376             if (data)
       
  1377                 XFree(data);
       
  1378         }
       
  1379 
       
  1380         // compute nitems
       
  1381         QByteArray buffer(ts.buffer());
       
  1382         nitems = buffer.size() / sizeof(Atom);
       
  1383         X11->net_supported_list = new Atom[nitems + 1];
       
  1384         Atom *a = (Atom *) buffer.data();
       
  1385         uint i;
       
  1386         for (i = 0; i < nitems; i++)
       
  1387             X11->net_supported_list[i] = a[i];
       
  1388         X11->net_supported_list[nitems] = 0;
       
  1389     }
       
  1390 }
       
  1391 
       
  1392 
       
  1393 bool QX11Data::isSupportedByWM(Atom atom)
       
  1394 {
       
  1395     if (!X11->net_supported_list)
       
  1396         return false;
       
  1397 
       
  1398     bool supported = false;
       
  1399     int i = 0;
       
  1400     while (X11->net_supported_list[i] != 0) {
       
  1401         if (X11->net_supported_list[i++] == atom) {
       
  1402             supported = true;
       
  1403             break;
       
  1404         }
       
  1405     }
       
  1406 
       
  1407     return supported;
       
  1408 }
       
  1409 
       
  1410 
       
  1411 // update the virtual roots array
       
  1412 static void qt_get_net_virtual_roots()
       
  1413 {
       
  1414     if (X11->net_virtual_root_list)
       
  1415         delete [] X11->net_virtual_root_list;
       
  1416     X11->net_virtual_root_list = 0;
       
  1417 
       
  1418     if (!X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)))
       
  1419         return;
       
  1420 
       
  1421     Atom type;
       
  1422     int format;
       
  1423     long offset = 0;
       
  1424     unsigned long nitems, after;
       
  1425     unsigned char *data;
       
  1426 
       
  1427     int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  1428                                ATOM(_NET_VIRTUAL_ROOTS), 0, 0,
       
  1429                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
       
  1430     if (data)
       
  1431         XFree(data);
       
  1432 
       
  1433     if (e == Success && type == XA_ATOM && format == 32) {
       
  1434         QBuffer ts;
       
  1435         ts.open(QIODevice::WriteOnly);
       
  1436 
       
  1437         while (after > 0) {
       
  1438             XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  1439                                ATOM(_NET_VIRTUAL_ROOTS), offset, 1024,
       
  1440                                False, XA_ATOM, &type, &format, &nitems, &after, &data);
       
  1441 
       
  1442             if (type == XA_ATOM && format == 32) {
       
  1443                 ts.write(reinterpret_cast<char *>(data), nitems * 4);
       
  1444                 offset += nitems;
       
  1445             } else
       
  1446                 after = 0;
       
  1447             if (data)
       
  1448                 XFree(data);
       
  1449         }
       
  1450 
       
  1451         // compute nitems
       
  1452         QByteArray buffer(ts.buffer());
       
  1453         nitems = buffer.size() / sizeof(Window);
       
  1454         X11->net_virtual_root_list = new Window[nitems + 1];
       
  1455         Window *a = (Window *) buffer.data();
       
  1456         uint i;
       
  1457         for (i = 0; i < nitems; i++)
       
  1458             X11->net_virtual_root_list[i] = a[i];
       
  1459         X11->net_virtual_root_list[nitems] = 0;
       
  1460     }
       
  1461 }
       
  1462 
       
  1463 void qt_net_remove_user_time(QWidget *tlw)
       
  1464 {
       
  1465     Q_ASSERT(tlw);
       
  1466     QTLWExtra *extra = tlw->d_func()->maybeTopData();
       
  1467     if (extra && extra->userTimeWindow) {
       
  1468         Q_ASSERT(tlw->internalWinId());
       
  1469         XDeleteProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME_WINDOW));
       
  1470         XDestroyWindow(X11->display, extra->userTimeWindow);
       
  1471         extra->userTimeWindow = 0;
       
  1472     }
       
  1473 }
       
  1474 
       
  1475 void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp)
       
  1476 {
       
  1477     Q_ASSERT(tlw);
       
  1478     Q_ASSERT(tlw->isWindow());
       
  1479     Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created));
       
  1480     QTLWExtra *extra = tlw->d_func()->topData();
       
  1481     WId wid = tlw->internalWinId();
       
  1482     const bool isSupportedByWM = X11->isSupportedByWM(ATOM(_NET_WM_USER_TIME_WINDOW));
       
  1483     if (extra->userTimeWindow || isSupportedByWM) {
       
  1484         if (!extra->userTimeWindow) {
       
  1485             extra->userTimeWindow = XCreateSimpleWindow(X11->display,
       
  1486                                                         tlw->internalWinId(),
       
  1487                                                         -1, -1, 1, 1, 0, 0, 0);
       
  1488             wid = extra->userTimeWindow;
       
  1489             XChangeProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME_WINDOW),
       
  1490                             XA_WINDOW, 32, PropModeReplace,
       
  1491                             (unsigned char *)&wid, 1);
       
  1492             XDeleteProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME));
       
  1493         } else if (!isSupportedByWM) {
       
  1494             // WM no longer supports it, then we should remove the
       
  1495             // _NET_WM_USER_TIME_WINDOW atom.
       
  1496             qt_net_remove_user_time(tlw);
       
  1497         } else {
       
  1498             wid = extra->userTimeWindow;
       
  1499         }
       
  1500     }
       
  1501     XChangeProperty(X11->display, wid, ATOM(_NET_WM_USER_TIME),
       
  1502                     XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &timestamp, 1);
       
  1503 }
       
  1504 
       
  1505 static void qt_check_focus_model()
       
  1506 {
       
  1507     Window fw = XNone;
       
  1508     int unused;
       
  1509     XGetInputFocus(X11->display, &fw, &unused);
       
  1510     if (fw == PointerRoot)
       
  1511         X11->focus_model = QX11Data::FM_PointerRoot;
       
  1512     else
       
  1513         X11->focus_model = QX11Data::FM_Other;
       
  1514 }
       
  1515 
       
  1516 #ifndef QT_NO_TABLET
       
  1517 
       
  1518 #if !defined (Q_OS_IRIX)
       
  1519 // from include/Xwacom.h
       
  1520 #  define XWACOM_PARAM_TOOLID 322
       
  1521 #  define XWACOM_PARAM_TOOLSERIAL 323
       
  1522 
       
  1523 typedef WACOMCONFIG * (*PtrWacomConfigInit) (Display*, WACOMERRORFUNC);
       
  1524 typedef WACOMDEVICE * (*PtrWacomConfigOpenDevice) (WACOMCONFIG*, const char*);
       
  1525 typedef int *(*PtrWacomConfigGetRawParam) (WACOMDEVICE*, int, int*, int, unsigned*);
       
  1526 typedef int (*PtrWacomConfigCloseDevice) (WACOMDEVICE *);
       
  1527 typedef void (*PtrWacomConfigTerm) (WACOMCONFIG *);
       
  1528 
       
  1529 static PtrWacomConfigInit ptrWacomConfigInit = 0;
       
  1530 static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0;
       
  1531 static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0;
       
  1532 static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0;
       
  1533 static PtrWacomConfigTerm ptrWacomConfigTerm = 0;
       
  1534 Q_GLOBAL_STATIC(QByteArray, wacomDeviceName)
       
  1535 #endif
       
  1536 
       
  1537 #endif
       
  1538 
       
  1539 /*****************************************************************************
       
  1540   qt_init() - initializes Qt for X11
       
  1541  *****************************************************************************/
       
  1542 
       
  1543 #if !defined(QT_NO_FONTCONFIG)
       
  1544 static void getXDefault(const char *group, const char *key, int *val)
       
  1545 {
       
  1546     char *str = XGetDefault(X11->display, group, key);
       
  1547     if (str) {
       
  1548         char *end = 0;
       
  1549         int v = strtol(str, &end, 0);
       
  1550         if (str != end)
       
  1551             *val = v;
       
  1552     }
       
  1553 }
       
  1554 
       
  1555 static void getXDefault(const char *group, const char *key, double *val)
       
  1556 {
       
  1557     char *str = XGetDefault(X11->display, group, key);
       
  1558     if (str) {
       
  1559         bool ok;
       
  1560         double v = QByteArray(str).toDouble(&ok);
       
  1561         if (ok)
       
  1562             *val = v;
       
  1563     }
       
  1564 }
       
  1565 
       
  1566 static void getXDefault(const char *group, const char *key, bool *val)
       
  1567 {
       
  1568     char *str = XGetDefault(X11->display, group, key);
       
  1569     if (str) {
       
  1570         char c = str[0];
       
  1571         if (isupper((int)c))
       
  1572             c = tolower(c);
       
  1573         if (c == 't' || c == 'y' || c == '1')
       
  1574             *val = true;
       
  1575         else if (c == 'f' || c == 'n' || c == '0')
       
  1576             *val = false;
       
  1577         if (c == 'o') {
       
  1578             c = str[1];
       
  1579             if (isupper((int)c))
       
  1580                 c = tolower(c);
       
  1581             if (c == 'n')
       
  1582                 *val = true;
       
  1583             if (c == 'f')
       
  1584                 *val = false;
       
  1585         }
       
  1586     }
       
  1587 }
       
  1588 #endif
       
  1589 
       
  1590 // ### This should be static but it isn't because of the friend declaration
       
  1591 // ### in qpaintdevice.h which then should have a static too but can't have
       
  1592 // ### it because "storage class specifiers invalid in friend function
       
  1593 // ### declarations" :-) Ideas anyone?
       
  1594 void qt_init(QApplicationPrivate *priv, int,
       
  1595 	     Display *display, Qt::HANDLE visual, Qt::HANDLE colormap)
       
  1596 {
       
  1597     X11 = new QX11Data;
       
  1598     X11->display = display;
       
  1599     X11->displayName = 0;
       
  1600     X11->foreignDisplay = (display != 0);
       
  1601     X11->focus_model = -1;
       
  1602 
       
  1603     // RANDR
       
  1604     X11->use_xrandr = false;
       
  1605     X11->xrandr_major = 0;
       
  1606     X11->xrandr_eventbase = 0;
       
  1607     X11->xrandr_errorbase = 0;
       
  1608 
       
  1609     // RENDER
       
  1610     X11->use_xrender = false;
       
  1611     X11->xrender_major = 0;
       
  1612     X11->xrender_version = 0;
       
  1613 
       
  1614     // XFIXES
       
  1615     X11->use_xfixes = false;
       
  1616     X11->xfixes_major = 0;
       
  1617     X11->xfixes_eventbase = 0;
       
  1618     X11->xfixes_errorbase = 0;
       
  1619 
       
  1620     // XInputExtension
       
  1621     X11->use_xinput = false;
       
  1622     X11->xinput_major = 0;
       
  1623     X11->xinput_eventbase = 0;
       
  1624     X11->xinput_errorbase = 0;
       
  1625 
       
  1626     // MIT-SHM
       
  1627     X11->use_mitshm = false;
       
  1628     X11->mitshm_major = 0;
       
  1629 
       
  1630     X11->sip_serial = 0;
       
  1631     X11->net_supported_list = 0;
       
  1632     X11->net_virtual_root_list = 0;
       
  1633     X11->wm_client_leader = 0;
       
  1634     X11->screens = 0;
       
  1635     X11->argbVisuals = 0;
       
  1636     X11->argbColormaps = 0;
       
  1637     X11->screenCount = 0;
       
  1638     X11->time = CurrentTime;
       
  1639     X11->userTime = CurrentTime;
       
  1640     X11->ignore_badwindow = false;
       
  1641     X11->seen_badwindow = false;
       
  1642 
       
  1643     X11->motifdnd_active = false;
       
  1644 
       
  1645     X11->default_im = QLatin1String("imsw-multi");
       
  1646     priv->inputContext = 0;
       
  1647 
       
  1648     // colormap control
       
  1649     X11->visual_class = -1;
       
  1650     X11->visual_id = -1;
       
  1651     X11->color_count = 0;
       
  1652     X11->custom_cmap = false;
       
  1653 
       
  1654     // outside visual/colormap
       
  1655     X11->visual = reinterpret_cast<Visual *>(visual);
       
  1656     X11->colormap = colormap;
       
  1657 
       
  1658     // Fontconfig
       
  1659     X11->has_fontconfig = false;
       
  1660 #if !defined(QT_NO_FONTCONFIG)
       
  1661     if (qgetenv("QT_X11_NO_FONTCONFIG").isNull())
       
  1662         X11->has_fontconfig = FcInit();
       
  1663     X11->fc_antialias = true;
       
  1664 #endif
       
  1665 
       
  1666 #ifndef QT_NO_XRENDER
       
  1667     memset(X11->solid_fills, 0, sizeof(X11->solid_fills));
       
  1668     for (int i = 0; i < X11->solid_fill_count; ++i)
       
  1669         X11->solid_fills[i].screen = -1;
       
  1670     memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills));
       
  1671     for (int i = 0; i < X11->pattern_fill_count; ++i)
       
  1672         X11->pattern_fills[i].screen = -1;
       
  1673 #endif
       
  1674 
       
  1675     X11->startupId = 0;
       
  1676 
       
  1677     int argc = priv->argc;
       
  1678     char **argv = priv->argv;
       
  1679 
       
  1680     if (X11->display) {
       
  1681         // Qt part of other application
       
  1682 
       
  1683         // Set application name and class
       
  1684         appName = qstrdup("Qt-subapplication");
       
  1685         char *app_class = 0;
       
  1686         if (argv) {
       
  1687             const char* p = strrchr(argv[0], '/');
       
  1688             app_class = qstrdup(p ? p + 1 : argv[0]);
       
  1689             if (app_class[0])
       
  1690                 app_class[0] = toupper(app_class[0]);
       
  1691         }
       
  1692         appClass = app_class;
       
  1693     } else {
       
  1694         // Qt controls everything (default)
       
  1695 
       
  1696         // Set application name and class
       
  1697         char *app_class = 0;
       
  1698         if (argv && argv[0]) {
       
  1699             const char *p = strrchr(argv[0], '/');
       
  1700             appName = p ? p + 1 : argv[0];
       
  1701             app_class = qstrdup(appName);
       
  1702             if (app_class[0])
       
  1703                 app_class[0] = toupper(app_class[0]);
       
  1704         }
       
  1705         appClass = app_class;
       
  1706     }
       
  1707 
       
  1708     // Install default error handlers
       
  1709     original_x_errhandler = XSetErrorHandler(qt_x_errhandler);
       
  1710     original_xio_errhandler = XSetIOErrorHandler(qt_xio_errhandler);
       
  1711 
       
  1712     // Get command line params
       
  1713     int j = argc ? 1 : 0;
       
  1714     for (int i=1; i<argc; i++) {
       
  1715         if (argv[i] && *argv[i] != '-') {
       
  1716             argv[j++] = argv[i];
       
  1717             continue;
       
  1718         }
       
  1719         QByteArray arg(argv[i]);
       
  1720         if (arg == "-display") {
       
  1721             if (++i < argc && !X11->display)
       
  1722                 X11->displayName = argv[i];
       
  1723         } else if (arg == "-fn" || arg == "-font") {
       
  1724             if (++i < argc)
       
  1725                 appFont = argv[i];
       
  1726         } else if (arg == "-bg" || arg == "-background") {
       
  1727             if (++i < argc)
       
  1728                 appBGCol = argv[i];
       
  1729         } else if (arg == "-btn" || arg == "-button") {
       
  1730             if (++i < argc)
       
  1731                 appBTNCol = argv[i];
       
  1732         } else if (arg == "-fg" || arg == "-foreground") {
       
  1733             if (++i < argc)
       
  1734                 appFGCol = argv[i];
       
  1735         } else if (arg == "-name") {
       
  1736             if (++i < argc)
       
  1737                 appName = argv[i];
       
  1738         } else if (arg == "-title") {
       
  1739             if (++i < argc)
       
  1740                 mwTitle = argv[i];
       
  1741         } else if (arg == "-geometry") {
       
  1742             if (++i < argc)
       
  1743                 mwGeometry = argv[i];
       
  1744         } else if (arg == "-im") {
       
  1745             if (++i < argc)
       
  1746                 qt_ximServer = argv[i];
       
  1747         } else if (arg == "-ncols") {   // xv and netscape use this name
       
  1748             if (++i < argc)
       
  1749                 X11->color_count = qMax(0,atoi(argv[i]));
       
  1750         } else if (arg == "-visual") {  // xv and netscape use this name
       
  1751             if (++i < argc && !X11->visual) {
       
  1752                 QString s = QString::fromLocal8Bit(argv[i]).toLower();
       
  1753                 if (s == QLatin1String("staticgray"))
       
  1754                     X11->visual_class = StaticGray;
       
  1755                 else if (s == QLatin1String("grayscale"))
       
  1756                     X11->visual_class = XGrayScale;
       
  1757                 else if (s == QLatin1String("staticcolor"))
       
  1758                     X11->visual_class = StaticColor;
       
  1759                 else if (s == QLatin1String("pseudocolor"))
       
  1760                     X11->visual_class = PseudoColor;
       
  1761                 else if (s == QLatin1String("truecolor"))
       
  1762                     X11->visual_class = TrueColor;
       
  1763                 else if (s == QLatin1String("directcolor"))
       
  1764                     X11->visual_class = DirectColor;
       
  1765                 else
       
  1766                     X11->visual_id = static_cast<int>(strtol(argv[i], 0, 0));
       
  1767             }
       
  1768 #ifndef QT_NO_XIM
       
  1769         } else if (arg == "-inputstyle") {
       
  1770             if (++i < argc) {
       
  1771                 QString s = QString::fromLocal8Bit(argv[i]).toLower();
       
  1772                 if (s == QLatin1String("onthespot"))
       
  1773                     qt_xim_preferred_style = XIMPreeditCallbacks |
       
  1774                                              XIMStatusNothing;
       
  1775                 else if (s == QLatin1String("overthespot"))
       
  1776                     qt_xim_preferred_style = XIMPreeditPosition |
       
  1777                                              XIMStatusNothing;
       
  1778                 else if (s == QLatin1String("offthespot"))
       
  1779                     qt_xim_preferred_style = XIMPreeditArea |
       
  1780                                              XIMStatusArea;
       
  1781                 else if (s == QLatin1String("root"))
       
  1782                     qt_xim_preferred_style = XIMPreeditNothing |
       
  1783                                              XIMStatusNothing;
       
  1784             }
       
  1785 #endif
       
  1786         } else if (arg == "-cmap") {    // xv uses this name
       
  1787             if (!X11->colormap)
       
  1788                 X11->custom_cmap = true;
       
  1789         }
       
  1790         else if (arg == "-sync")
       
  1791             appSync = !appSync;
       
  1792 #if defined(QT_DEBUG)
       
  1793         else if (arg == "-nograb")
       
  1794             appNoGrab = !appNoGrab;
       
  1795         else if (arg == "-dograb")
       
  1796             appDoGrab = !appDoGrab;
       
  1797 #endif
       
  1798         else
       
  1799             argv[j++] = argv[i];
       
  1800     }
       
  1801 
       
  1802     priv->argc = j;
       
  1803 
       
  1804 #if defined(QT_DEBUG) && defined(Q_OS_LINUX)
       
  1805     if (!appNoGrab && !appDoGrab) {
       
  1806         QString s;
       
  1807         s.sprintf("/proc/%d/cmdline", getppid());
       
  1808         QFile f(s);
       
  1809         if (f.open(QIODevice::ReadOnly)) {
       
  1810             s.clear();
       
  1811             char c;
       
  1812             while (f.getChar(&c) && c) {
       
  1813                 if (c == '/')
       
  1814                     s.clear();
       
  1815                 else
       
  1816                     s += QLatin1Char(c);
       
  1817             }
       
  1818             if (s == QLatin1String("gdb")) {
       
  1819                 appNoGrab = true;
       
  1820                 qDebug("Qt: gdb: -nograb added to command-line options.\n"
       
  1821                        "\t Use the -dograb option to enforce grabbing.");
       
  1822             }
       
  1823             f.close();
       
  1824         }
       
  1825     }
       
  1826 #endif
       
  1827 
       
  1828     // Connect to X server
       
  1829     if (qt_is_gui_used && !X11->display) {
       
  1830         if ((X11->display = XOpenDisplay(X11->displayName)) == 0) {
       
  1831             qWarning("%s: cannot connect to X server %s", appName,
       
  1832                      XDisplayName(X11->displayName));
       
  1833             QApplicationPrivate::reset_instance_pointer();
       
  1834             exit(1);
       
  1835         }
       
  1836 
       
  1837         if (appSync)                                // if "-sync" argument
       
  1838             XSynchronize(X11->display, true);
       
  1839     }
       
  1840 
       
  1841     // Common code, regardless of whether display is foreign.
       
  1842 
       
  1843     // Get X parameters
       
  1844 
       
  1845     if (qt_is_gui_used) {
       
  1846         X11->defaultScreen = DefaultScreen(X11->display);
       
  1847         X11->screenCount = ScreenCount(X11->display);
       
  1848 
       
  1849         X11->screens = new QX11InfoData[X11->screenCount];
       
  1850         X11->argbVisuals = new Visual *[X11->screenCount];
       
  1851         X11->argbColormaps = new Colormap[X11->screenCount];
       
  1852 
       
  1853         for (int s = 0; s < X11->screenCount; s++) {
       
  1854             QX11InfoData *screen = X11->screens + s;
       
  1855             screen->ref = 1; // ensures it doesn't get deleted
       
  1856             screen->screen = s;
       
  1857 
       
  1858             int widthMM = DisplayWidthMM(X11->display, s);
       
  1859             if (widthMM != 0) {
       
  1860                 screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
       
  1861             } else {
       
  1862                 screen->dpiX = 72;
       
  1863             }
       
  1864 
       
  1865             int heightMM = DisplayHeightMM(X11->display, s);
       
  1866             if (heightMM != 0) {
       
  1867                 screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
       
  1868             } else {
       
  1869                 screen->dpiY = 72;
       
  1870             }
       
  1871 
       
  1872             X11->argbVisuals[s] = 0;
       
  1873             X11->argbColormaps[s] = 0;
       
  1874         }
       
  1875 
       
  1876 
       
  1877 #ifndef QT_NO_XRENDER
       
  1878         int xrender_eventbase,  xrender_errorbase;
       
  1879         // See if XRender is supported on the connected display
       
  1880         if (XQueryExtension(X11->display, "RENDER", &X11->xrender_major,
       
  1881                             &xrender_eventbase, &xrender_errorbase)
       
  1882             && XRenderQueryExtension(X11->display, &xrender_eventbase,
       
  1883                                      &xrender_errorbase)) {
       
  1884             // Check the version as well - we need v0.4 or higher
       
  1885             int major = 0;
       
  1886             int minor = 0;
       
  1887             XRenderQueryVersion(X11->display, &major, &minor);
       
  1888             if (qgetenv("QT_X11_NO_XRENDER").isNull()) {
       
  1889                 X11->use_xrender = (major >= 0 && minor >= 5);
       
  1890                 X11->xrender_version = major*100+minor;
       
  1891                 // workaround for broken XServer on Ubuntu Breezy (6.8 compiled with 7.0
       
  1892                 // protocol headers)
       
  1893                 if (X11->xrender_version == 10
       
  1894                     && VendorRelease(X11->display) < 60900000
       
  1895                     && QByteArray(ServerVendor(X11->display)).contains("X.Org"))
       
  1896                     X11->xrender_version = 9;
       
  1897             }
       
  1898         }
       
  1899 #endif // QT_NO_XRENDER
       
  1900 
       
  1901 #ifndef QT_NO_MITSHM
       
  1902         int mitshm_minor;
       
  1903         int mitshm_major;
       
  1904         int mitshm_eventbase;
       
  1905         int mitshm_errorbase;
       
  1906         int mitshm_pixmaps;
       
  1907         if (XQueryExtension(X11->display, "MIT-SHM", &X11->mitshm_major,
       
  1908                             &mitshm_eventbase, &mitshm_errorbase)
       
  1909             && XShmQueryVersion(X11->display, &mitshm_major, &mitshm_minor,
       
  1910                                 &mitshm_pixmaps))
       
  1911         {
       
  1912             QString displayName = QLatin1String(XDisplayName(NULL));
       
  1913 
       
  1914             // MITSHM only works for local displays, so do a quick check here
       
  1915             // to determine whether the display is local or not (not 100 % accurate).
       
  1916             // BGR server layouts are not supported either, since it requires the raster
       
  1917             // engine to work on a QImage with BGR layout.
       
  1918             bool local = displayName.isEmpty() || displayName.lastIndexOf(QLatin1Char(':')) == 0;
       
  1919             if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0)) {
       
  1920                 Visual *defaultVisual = DefaultVisual(X11->display, DefaultScreen(X11->display));
       
  1921                 X11->use_mitshm = mitshm_pixmaps && ((defaultVisual->red_mask == 0xff0000
       
  1922                                                       || defaultVisual->red_mask == 0xf800)
       
  1923                                                      && (defaultVisual->green_mask == 0xff00
       
  1924                                                          || defaultVisual->green_mask == 0x7e0)
       
  1925                                                      && (defaultVisual->blue_mask == 0xff
       
  1926                                                          || defaultVisual->blue_mask == 0x1f));
       
  1927             }
       
  1928         }
       
  1929 #endif // QT_NO_MITSHM
       
  1930 
       
  1931         // initialize the graphics system - order is imporant here - it must be done before
       
  1932         // the QColormap::initialize() call
       
  1933         QApplicationPrivate::graphics_system = QGraphicsSystemFactory::create(QApplicationPrivate::graphics_system_name);
       
  1934         QColormap::initialize();
       
  1935 
       
  1936         // Support protocols
       
  1937         X11->xdndSetup();
       
  1938 
       
  1939         // Finally create all atoms
       
  1940         qt_x11_create_intern_atoms();
       
  1941 
       
  1942         // initialize NET lists
       
  1943         qt_get_net_supported();
       
  1944         qt_get_net_virtual_roots();
       
  1945 
       
  1946 #ifndef QT_NO_XRANDR
       
  1947         // See if XRandR is supported on the connected display
       
  1948         if (XQueryExtension(X11->display, "RANDR", &X11->xrandr_major,
       
  1949                             &X11->xrandr_eventbase, &X11->xrandr_errorbase)) {
       
  1950 
       
  1951 #  ifdef QT_RUNTIME_XRANDR
       
  1952             X11->ptrXRRSelectInput = 0;
       
  1953             X11->ptrXRRUpdateConfiguration = 0;
       
  1954             X11->ptrXRRRootToScreen = 0;
       
  1955             X11->ptrXRRQueryExtension = 0;
       
  1956             QLibrary xrandrLib(QLatin1String("Xrandr"), 2);
       
  1957             if (!xrandrLib.load()) { // try without the version number
       
  1958                 xrandrLib.setFileName(QLatin1String("Xrandr"));
       
  1959                 xrandrLib.load();
       
  1960             }
       
  1961             if (xrandrLib.isLoaded()) {
       
  1962                 X11->ptrXRRSelectInput =
       
  1963                     (PtrXRRSelectInput) xrandrLib.resolve("XRRSelectInput");
       
  1964                 X11->ptrXRRUpdateConfiguration =
       
  1965                     (PtrXRRUpdateConfiguration) xrandrLib.resolve("XRRUpdateConfiguration");
       
  1966                 X11->ptrXRRRootToScreen =
       
  1967                     (PtrXRRRootToScreen) xrandrLib.resolve("XRRRootToScreen");
       
  1968                 X11->ptrXRRQueryExtension =
       
  1969                     (PtrXRRQueryExtension) xrandrLib.resolve("XRRQueryExtension");
       
  1970             }
       
  1971 #  else
       
  1972             X11->ptrXRRSelectInput = XRRSelectInput;
       
  1973             X11->ptrXRRUpdateConfiguration = XRRUpdateConfiguration;
       
  1974             X11->ptrXRRRootToScreen = XRRRootToScreen;
       
  1975             X11->ptrXRRQueryExtension = XRRQueryExtension;
       
  1976 #  endif
       
  1977 
       
  1978             if (X11->ptrXRRQueryExtension
       
  1979                 && X11->ptrXRRQueryExtension(X11->display, &X11->xrandr_eventbase, &X11->xrandr_errorbase)) {
       
  1980                 // XRandR is supported
       
  1981                 X11->use_xrandr = true;
       
  1982             }
       
  1983         }
       
  1984 #endif // QT_NO_XRANDR
       
  1985 
       
  1986 #ifndef QT_NO_XRENDER
       
  1987         if (X11->use_xrender) {
       
  1988             // XRender is supported, let's see if we have a PictFormat for the
       
  1989             // default visual
       
  1990             XRenderPictFormat *format =
       
  1991                 XRenderFindVisualFormat(X11->display,
       
  1992                                         (Visual *) QX11Info::appVisual(X11->defaultScreen));
       
  1993 
       
  1994             if (!format) {
       
  1995                 X11->use_xrender = false;
       
  1996             }
       
  1997         }
       
  1998 #endif // QT_NO_XRENDER
       
  1999 
       
  2000 #ifndef QT_NO_XFIXES
       
  2001         // See if Xfixes is supported on the connected display
       
  2002         if (XQueryExtension(X11->display, "XFIXES", &X11->xfixes_major,
       
  2003                             &X11->xfixes_eventbase, &X11->xfixes_errorbase)) {
       
  2004             X11->ptrXFixesQueryExtension  = XFIXES_LOAD_V1(XFixesQueryExtension);
       
  2005             X11->ptrXFixesQueryVersion    = XFIXES_LOAD_V1(XFixesQueryVersion);
       
  2006             X11->ptrXFixesSetCursorName   = XFIXES_LOAD_V2(XFixesSetCursorName);
       
  2007             X11->ptrXFixesSelectSelectionInput = XFIXES_LOAD_V2(XFixesSelectSelectionInput);
       
  2008 
       
  2009             if(X11->ptrXFixesQueryExtension && X11->ptrXFixesQueryVersion
       
  2010                && X11->ptrXFixesQueryExtension(X11->display, &X11->xfixes_eventbase,
       
  2011                                                &X11->xfixes_errorbase)) {
       
  2012                 // Xfixes is supported.
       
  2013                 // Note: the XFixes protocol version is negotiated using QueryVersion.
       
  2014                 // We supply the highest version we support, the X server replies with
       
  2015                 // the highest version it supports, but no higher than the version we
       
  2016                 // asked for. The version sent back is the protocol version the X server
       
  2017                 // will use to talk us. If this call is removed, the behavior of the
       
  2018                 // X server when it receives an XFixes request is undefined.
       
  2019                 int major = 3;
       
  2020                 int minor = 0;
       
  2021                 X11->ptrXFixesQueryVersion(X11->display, &major, &minor);
       
  2022                 X11->use_xfixes = (major >= 1);
       
  2023                 X11->xfixes_major = major;
       
  2024             }
       
  2025         }
       
  2026 #endif // QT_NO_XFIXES
       
  2027 
       
  2028 #ifndef QT_NO_XCURSOR
       
  2029 #ifdef QT_RUNTIME_XCURSOR
       
  2030         X11->ptrXcursorLibraryLoadCursor = 0;
       
  2031         QLibrary xcursorLib(QLatin1String("Xcursor"), 1);
       
  2032         bool xcursorFound = xcursorLib.load();
       
  2033         if (!xcursorFound) { //try without the version number
       
  2034             xcursorLib.setFileName(QLatin1String("Xcursor"));
       
  2035             xcursorFound = xcursorLib.load();
       
  2036         }
       
  2037         if (xcursorFound) {
       
  2038             X11->ptrXcursorLibraryLoadCursor =
       
  2039                 (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
       
  2040         }
       
  2041 #else
       
  2042         X11->ptrXcursorLibraryLoadCursor = XcursorLibraryLoadCursor;
       
  2043 #endif // QT_RUNTIME_XCURSOR
       
  2044 #endif // QT_NO_XCURSOR
       
  2045 
       
  2046 #ifndef QT_NO_XSYNC
       
  2047         int xsync_evbase, xsync_errbase;
       
  2048         int major, minor;
       
  2049         if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase))
       
  2050             XSyncInitialize(X11->display, &major, &minor);
       
  2051 #endif // QT_NO_XSYNC
       
  2052 
       
  2053 #ifndef QT_NO_XINERAMA
       
  2054 #ifdef QT_RUNTIME_XINERAMA
       
  2055         X11->ptrXineramaQueryExtension = 0;
       
  2056         X11->ptrXineramaIsActive = 0;
       
  2057         X11->ptrXineramaQueryScreens = 0;
       
  2058         QLibrary xineramaLib(QLatin1String("Xinerama"), 1);
       
  2059         bool xineramaFound = xineramaLib.load();
       
  2060         if (!xineramaFound) { //try without the version number
       
  2061             xineramaLib.setFileName(QLatin1String("Xinerama"));
       
  2062             xineramaFound = xineramaLib.load();
       
  2063         }
       
  2064         if (xineramaFound) {
       
  2065             X11->ptrXineramaQueryExtension =
       
  2066                 (PtrXineramaQueryExtension) xineramaLib.resolve("XineramaQueryExtension");
       
  2067             X11->ptrXineramaIsActive =
       
  2068                 (PtrXineramaIsActive) xineramaLib.resolve("XineramaIsActive");
       
  2069             X11->ptrXineramaQueryScreens =
       
  2070                 (PtrXineramaQueryScreens) xineramaLib.resolve("XineramaQueryScreens");
       
  2071         }
       
  2072 #else
       
  2073         X11->ptrXineramaQueryScreens = XineramaQueryScreens;
       
  2074         X11->ptrXineramaIsActive = XineramaIsActive;
       
  2075         X11->ptrXineramaQueryExtension = XineramaQueryExtension;
       
  2076 #endif // QT_RUNTIME_XINERAMA
       
  2077 #endif // QT_NO_XINERAMA
       
  2078 
       
  2079 #ifndef QT_NO_XINPUT
       
  2080         // See if Xinput is supported on the connected display
       
  2081         X11->ptrXCloseDevice = 0;
       
  2082         X11->ptrXListInputDevices = 0;
       
  2083         X11->ptrXOpenDevice = 0;
       
  2084         X11->ptrXFreeDeviceList = 0;
       
  2085         X11->ptrXSelectExtensionEvent = 0;
       
  2086         X11->use_xinput = XQueryExtension(X11->display, "XInputExtension", &X11->xinput_major,
       
  2087                                           &X11->xinput_eventbase, &X11->xinput_errorbase);
       
  2088         if (X11->use_xinput) {
       
  2089             X11->ptrXCloseDevice = XINPUT_LOAD(XCloseDevice);
       
  2090             X11->ptrXListInputDevices = XINPUT_LOAD(XListInputDevices);
       
  2091             X11->ptrXOpenDevice = XINPUT_LOAD(XOpenDevice);
       
  2092             X11->ptrXFreeDeviceList = XINPUT_LOAD(XFreeDeviceList);
       
  2093             X11->ptrXSelectExtensionEvent = XINPUT_LOAD(XSelectExtensionEvent);
       
  2094         }
       
  2095 #endif // QT_NO_XINPUT
       
  2096 
       
  2097 #if !defined(QT_NO_FONTCONFIG)
       
  2098         int dpi = 0;
       
  2099         getXDefault("Xft", FC_DPI, &dpi);
       
  2100         if (dpi) {
       
  2101             for (int s = 0; s < ScreenCount(X11->display); ++s) {
       
  2102                 QX11Info::setAppDpiX(s, dpi);
       
  2103                 QX11Info::setAppDpiY(s, dpi);
       
  2104             }
       
  2105         }
       
  2106         double fc_scale = 1.;
       
  2107         getXDefault("Xft", FC_SCALE, &fc_scale);
       
  2108         X11->fc_scale = fc_scale;
       
  2109         for (int s = 0; s < ScreenCount(X11->display); ++s) {
       
  2110             int subpixel = FC_RGBA_UNKNOWN;
       
  2111 #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
       
  2112             if (X11->use_xrender) {
       
  2113                 int rsp = XRenderQuerySubpixelOrder(X11->display, s);
       
  2114                 switch (rsp) {
       
  2115                 default:
       
  2116                 case SubPixelUnknown:
       
  2117                     subpixel = FC_RGBA_UNKNOWN;
       
  2118                     break;
       
  2119                 case SubPixelHorizontalRGB:
       
  2120                     subpixel = FC_RGBA_RGB;
       
  2121                     break;
       
  2122                 case SubPixelHorizontalBGR:
       
  2123                     subpixel = FC_RGBA_BGR;
       
  2124                     break;
       
  2125                 case SubPixelVerticalRGB:
       
  2126                     subpixel = FC_RGBA_VRGB;
       
  2127                     break;
       
  2128                 case SubPixelVerticalBGR:
       
  2129                     subpixel = FC_RGBA_VBGR;
       
  2130                     break;
       
  2131                 case SubPixelNone:
       
  2132                     subpixel = FC_RGBA_NONE;
       
  2133                     break;
       
  2134                 }
       
  2135             }
       
  2136 #endif
       
  2137 
       
  2138             char *rgba = XGetDefault(X11->display, "Xft", FC_RGBA);
       
  2139             if (rgba) {
       
  2140                 char *end = 0;
       
  2141                 int v = strtol(rgba, &end, 0);
       
  2142                 if (rgba != end) {
       
  2143                     subpixel = v;
       
  2144                 } else if (qstrncmp(rgba, "unknown", 7) == 0) {
       
  2145                     subpixel = FC_RGBA_UNKNOWN;
       
  2146                 } else if (qstrncmp(rgba, "rgb", 3) == 0) {
       
  2147                     subpixel = FC_RGBA_RGB;
       
  2148                 } else if (qstrncmp(rgba, "bgr", 3) == 0) {
       
  2149                     subpixel = FC_RGBA_BGR;
       
  2150                 } else if (qstrncmp(rgba, "vrgb", 4) == 0) {
       
  2151                     subpixel = FC_RGBA_VRGB;
       
  2152                 } else if (qstrncmp(rgba, "vbgr", 4) == 0) {
       
  2153                     subpixel = FC_RGBA_VBGR;
       
  2154                 } else if (qstrncmp(rgba, "none", 4) == 0) {
       
  2155                     subpixel = FC_RGBA_NONE;
       
  2156                 }
       
  2157             }
       
  2158             X11->screens[s].subpixel = subpixel;
       
  2159         }
       
  2160         getXDefault("Xft", FC_ANTIALIAS, &X11->fc_antialias);
       
  2161 #ifdef FC_HINT_STYLE
       
  2162         getXDefault("Xft", FC_HINT_STYLE, &X11->fc_hint_style);
       
  2163 #endif
       
  2164 #if 0
       
  2165         // ###### these are implemented by Xft, not sure we need them
       
  2166         getXDefault("Xft", FC_AUTOHINT, &X11->fc_autohint);
       
  2167         getXDefault("Xft", FC_HINTING, &X11->fc_autohint);
       
  2168         getXDefault("Xft", FC_MINSPACE, &X11->fc_autohint);
       
  2169 #endif
       
  2170 #endif // QT_NO_XRENDER
       
  2171 
       
  2172         // initialize key mapper
       
  2173         QKeyMapper::changeKeyboard();
       
  2174 
       
  2175 #ifndef QT_NO_XKB
       
  2176         if (qt_keymapper_private()->useXKB) {
       
  2177             // If XKB is detected, set the GrabsUseXKBState option so input method
       
  2178             // compositions continue to work (ie. deadkeys)
       
  2179             unsigned int state = XkbPCF_GrabsUseXKBStateMask;
       
  2180             (void) XkbSetPerClientControls(X11->display, state, &state);
       
  2181         }
       
  2182 #endif // QT_NO_XKB
       
  2183 
       
  2184         // Misc. initialization
       
  2185 #if 0 //disabled for now..
       
  2186         QSegfaultHandler::initialize(priv->argv, priv->argc);
       
  2187 #endif
       
  2188         QCursorData::initialize();
       
  2189     }
       
  2190     QFont::initialize();
       
  2191 
       
  2192     if(qt_is_gui_used) {
       
  2193         qApp->setObjectName(QString::fromLocal8Bit(appName));
       
  2194 
       
  2195         int screen;
       
  2196         for (screen = 0; screen < X11->screenCount; ++screen) {
       
  2197             XSelectInput(X11->display, QX11Info::appRootWindow(screen),
       
  2198                          KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask);
       
  2199 
       
  2200 #ifndef QT_NO_XRANDR
       
  2201             if (X11->use_xrandr)
       
  2202                 X11->ptrXRRSelectInput(X11->display, QX11Info::appRootWindow(screen), True);
       
  2203 #endif // QT_NO_XRANDR
       
  2204         }
       
  2205     }
       
  2206 
       
  2207     if (qt_is_gui_used) {
       
  2208         // Attempt to determine the current running X11 Desktop Enviornment
       
  2209         // Use dbus if/when we can, but fall back to using windowManagerName() for now
       
  2210 
       
  2211         X11->compositingManagerRunning = XGetSelectionOwner(X11->display,
       
  2212                                                             ATOM(_NET_WM_CM_S0));
       
  2213         X11->desktopEnvironment = DE_UNKNOWN;
       
  2214         X11->desktopVersion = 0;
       
  2215 
       
  2216         // See if the current window manager is using the freedesktop.org spec to give its name
       
  2217         Window windowManagerWindow = XNone;
       
  2218         Atom typeReturned;
       
  2219         int formatReturned;
       
  2220         unsigned long nitemsReturned;
       
  2221         unsigned long unused;
       
  2222         unsigned char *data = 0;
       
  2223         if (XGetWindowProperty(QX11Info::display(), QX11Info::appRootWindow(),
       
  2224                            ATOM(_NET_SUPPORTING_WM_CHECK),
       
  2225                            0, 1024, False, XA_WINDOW, &typeReturned,
       
  2226                            &formatReturned, &nitemsReturned, &unused, &data)
       
  2227               == Success) {
       
  2228             if (typeReturned == XA_WINDOW && formatReturned == 32)
       
  2229                 windowManagerWindow = *((Window*) data);
       
  2230             if (data)
       
  2231                 XFree(data);
       
  2232 
       
  2233             if (windowManagerWindow != XNone) {
       
  2234                 QString wmName;
       
  2235                 Atom utf8atom = ATOM(UTF8_STRING);
       
  2236                 if (XGetWindowProperty(QX11Info::display(), windowManagerWindow, ATOM(_NET_WM_NAME),
       
  2237                                        0, 1024, False, utf8atom, &typeReturned,
       
  2238                                        &formatReturned, &nitemsReturned, &unused, &data)
       
  2239                     == Success) {
       
  2240                     if (typeReturned == utf8atom && formatReturned == 8)
       
  2241                         wmName = QString::fromUtf8((const char*)data);
       
  2242                     if (data)
       
  2243                         XFree(data);
       
  2244                     if (wmName == QLatin1String("KWin"))
       
  2245                         X11->desktopEnvironment = DE_KDE;
       
  2246                     if (wmName == QLatin1String("Metacity"))
       
  2247                         X11->desktopEnvironment = DE_GNOME;
       
  2248                 }
       
  2249             }
       
  2250         }
       
  2251 
       
  2252         // Running a different/newer/older window manager?  Try some other things
       
  2253         if (X11->desktopEnvironment == DE_UNKNOWN){
       
  2254             Atom type;
       
  2255             int format;
       
  2256             unsigned long length, after;
       
  2257             uchar *data = 0;
       
  2258 
       
  2259             QString session = QString::fromLocal8Bit(qgetenv("DESKTOP_SESSION"));
       
  2260             if (session == QLatin1String("kde")) {
       
  2261                 X11->desktopEnvironment = DE_KDE;
       
  2262             } else if (session == QLatin1String("gnome") || session == QLatin1String("xfce")) {
       
  2263                 X11->desktopEnvironment = DE_GNOME;
       
  2264             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
       
  2265                                           0, 1, False, AnyPropertyType, &type, &format, &length,
       
  2266                                    &after, &data) == Success && length) {
       
  2267                 // DTWM is running, meaning most likely CDE is running...
       
  2268                 X11->desktopEnvironment = DE_CDE;
       
  2269             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  2270                                           ATOM(GNOME_BACKGROUND_PROPERTIES), 0, 1, False, AnyPropertyType,
       
  2271                                           &type, &format, &length, &after, &data) == Success && length) {
       
  2272                 X11->desktopEnvironment = DE_GNOME;
       
  2273             } else if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
       
  2274                 X11->desktopEnvironment = DE_GNOME;
       
  2275             } else if ((XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KDE_FULL_SESSION),
       
  2276                                            0, 1, False, AnyPropertyType, &type, &format, &length, &after, &data) == Success
       
  2277                         && length)
       
  2278                        || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWIN_RUNNING),
       
  2279                                               0, 1, False, AnyPropertyType, &type, &format, &length,
       
  2280                                               &after, &data) == Success
       
  2281                            && length)
       
  2282                        || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWM_RUNNING),
       
  2283                                               0, 1, False, AnyPropertyType, &type, &format, &length,
       
  2284                                               &after, &data) == Success && length)) {
       
  2285                 X11->desktopEnvironment = DE_KDE;
       
  2286             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_SGI_DESKS_MANAGER),
       
  2287                                           0, 1, False, XA_WINDOW, &type, &format, &length, &after, &data) == Success
       
  2288                        && length) {
       
  2289                 X11->desktopEnvironment = DE_4DWM;
       
  2290             }
       
  2291             if (data)
       
  2292                 XFree((char *)data);
       
  2293         }
       
  2294 
       
  2295         if (X11->desktopEnvironment == DE_KDE)
       
  2296             X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
       
  2297 
       
  2298 #if !defined(QT_NO_STYLE_GTK)
       
  2299         if (X11->desktopEnvironment == DE_GNOME) {
       
  2300             static bool menusHaveIcons = QGtk::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true);
       
  2301             QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons);
       
  2302         }
       
  2303 #endif
       
  2304         qt_set_input_encoding();
       
  2305 
       
  2306         qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol);
       
  2307 
       
  2308         // be smart about the size of the default font. most X servers have helvetica
       
  2309         // 12 point available at 2 resolutions:
       
  2310         //     75dpi (12 pixels) and 100dpi (17 pixels).
       
  2311         // At 95 DPI, a 12 point font should be 16 pixels tall - in which case a 17
       
  2312         // pixel font is a closer match than a 12 pixel font
       
  2313         int ptsz = (X11->use_xrender
       
  2314                     ? 9
       
  2315                     : (int) (((QX11Info::appDpiY() >= 95 ? 17. : 12.) *
       
  2316                               72. / (float) QX11Info::appDpiY()) + 0.5));
       
  2317 
       
  2318         if (!QApplicationPrivate::sys_font) {
       
  2319             // no font from settings or RESOURCE_MANAGER, provide a fallback
       
  2320             QFont f(X11->has_fontconfig ? QLatin1String("Sans Serif") : QLatin1String("Helvetica"),
       
  2321                     ptsz);
       
  2322             QApplicationPrivate::setSystemFont(f);
       
  2323         }
       
  2324 
       
  2325 #if !defined (QT_NO_TABLET)
       
  2326         if (X11->use_xinput) {
       
  2327             int ndev,
       
  2328                 i,
       
  2329                 j;
       
  2330             bool gotStylus,
       
  2331                 gotEraser;
       
  2332             XDeviceInfo *devices = 0, *devs;
       
  2333             XInputClassInfo *ip;
       
  2334             XAnyClassPtr any;
       
  2335             XValuatorInfoPtr v;
       
  2336             XAxisInfoPtr a;
       
  2337             XDevice *dev = 0;
       
  2338 
       
  2339             if (X11->ptrXListInputDevices) {
       
  2340                 devices = X11->ptrXListInputDevices(X11->display, &ndev);
       
  2341                 if (!devices)
       
  2342                     qWarning("QApplication: Failed to get list of tablet devices");
       
  2343             }
       
  2344             if (!devices)
       
  2345                 ndev = -1;
       
  2346             QTabletEvent::TabletDevice deviceType;
       
  2347             for (devs = devices, i = 0; i < ndev && devs; i++, devs++) {
       
  2348                 dev = 0;
       
  2349                 deviceType = QTabletEvent::NoDevice;
       
  2350                 gotStylus = false;
       
  2351                 gotEraser = false;
       
  2352 
       
  2353 #if defined(Q_OS_IRIX)
       
  2354                 QString devName = QString::fromLocal8Bit(devs->name).toLower();
       
  2355                 if (devName == QLatin1String(WACOM_NAME)) {
       
  2356                     deviceType = QTabletEvent::Stylus;
       
  2357                     gotStylus = true;
       
  2358                 }
       
  2359 #else
       
  2360                 if (devs->type == ATOM(XWacomStylus)) {
       
  2361                     deviceType = QTabletEvent::Stylus;
       
  2362                     if (wacomDeviceName()->isEmpty())
       
  2363                         wacomDeviceName()->append(devs->name);
       
  2364                     gotStylus = true;
       
  2365                 } else if (devs->type == ATOM(XWacomEraser)) {
       
  2366                     deviceType = QTabletEvent::XFreeEraser;
       
  2367                     gotEraser = true;
       
  2368                 }
       
  2369 #endif
       
  2370                 if (deviceType == QTabletEvent::NoDevice)
       
  2371                     continue;
       
  2372 
       
  2373                 if (gotStylus || gotEraser) {
       
  2374                     if (X11->ptrXOpenDevice)
       
  2375                         dev = X11->ptrXOpenDevice(X11->display, devs->id);
       
  2376 
       
  2377                     if (!dev)
       
  2378                         continue;
       
  2379 
       
  2380                     QTabletDeviceData device_data;
       
  2381                     device_data.deviceType = deviceType;
       
  2382                     device_data.eventCount = 0;
       
  2383                     device_data.device = dev;
       
  2384                     device_data.xinput_motion = -1;
       
  2385                     device_data.xinput_key_press = -1;
       
  2386                     device_data.xinput_key_release = -1;
       
  2387                     device_data.xinput_button_press = -1;
       
  2388                     device_data.xinput_button_release = -1;
       
  2389                     device_data.xinput_proximity_in = -1;
       
  2390                     device_data.xinput_proximity_out = -1;
       
  2391                     device_data.widgetToGetPress = 0;
       
  2392 
       
  2393                     if (dev->num_classes > 0) {
       
  2394                         for (ip = dev->classes, j = 0; j < dev->num_classes;
       
  2395                              ip++, j++) {
       
  2396                             switch (ip->input_class) {
       
  2397                             case KeyClass:
       
  2398                                 DeviceKeyPress(dev, device_data.xinput_key_press,
       
  2399                                                device_data.eventList[device_data.eventCount]);
       
  2400                                 if (device_data.eventList[device_data.eventCount])
       
  2401                                     ++device_data.eventCount;
       
  2402                                 DeviceKeyRelease(dev, device_data.xinput_key_release,
       
  2403                                                  device_data.eventList[device_data.eventCount]);
       
  2404                                 if (device_data.eventList[device_data.eventCount])
       
  2405                                     ++device_data.eventCount;
       
  2406                                 break;
       
  2407                             case ButtonClass:
       
  2408                                 DeviceButtonPress(dev, device_data.xinput_button_press,
       
  2409                                                   device_data.eventList[device_data.eventCount]);
       
  2410                                 if (device_data.eventList[device_data.eventCount])
       
  2411                                     ++device_data.eventCount;
       
  2412                                 DeviceButtonRelease(dev, device_data.xinput_button_release,
       
  2413                                                     device_data.eventList[device_data.eventCount]);
       
  2414                                 if (device_data.eventList[device_data.eventCount])
       
  2415                                     ++device_data.eventCount;
       
  2416                                 break;
       
  2417                             case ValuatorClass:
       
  2418                                 // I'm only going to be interested in motion when the
       
  2419                                 // stylus is already down anyway!
       
  2420                                 DeviceMotionNotify(dev, device_data.xinput_motion,
       
  2421                                                    device_data.eventList[device_data.eventCount]);
       
  2422                                 if (device_data.eventList[device_data.eventCount])
       
  2423                                     ++device_data.eventCount;
       
  2424                                 ProximityIn(dev, device_data.xinput_proximity_in, device_data.eventList[device_data.eventCount]);
       
  2425                                 if (device_data.eventList[device_data.eventCount])
       
  2426                                     ++device_data.eventCount;
       
  2427                                 ProximityOut(dev, device_data.xinput_proximity_out, device_data.eventList[device_data.eventCount]);
       
  2428                                 if (device_data.eventList[device_data.eventCount])
       
  2429                                     ++device_data.eventCount;
       
  2430                             default:
       
  2431                                 break;
       
  2432                             }
       
  2433                         }
       
  2434                     }
       
  2435 
       
  2436                     // get the min/max value for pressure!
       
  2437                     any = (XAnyClassPtr) (devs->inputclassinfo);
       
  2438                     for (j = 0; j < devs->num_classes; j++) {
       
  2439                         if (any->c_class == ValuatorClass) {
       
  2440                             v = (XValuatorInfoPtr) any;
       
  2441                             a = (XAxisInfoPtr) ((char *) v +
       
  2442                                                 sizeof (XValuatorInfo));
       
  2443 #if defined (Q_OS_IRIX)
       
  2444                             // I'm not exaclty wild about this, but the
       
  2445                             // dimensions of the tablet are more relevant here
       
  2446                             // than the min and max values from the axis
       
  2447                             // (actually it seems to be 2/3 or what is in the
       
  2448                             // axis.  So we'll try to parse it from this
       
  2449                             // string. --tws
       
  2450                             char returnString[SGIDeviceRtrnLen];
       
  2451                             int tmp;
       
  2452                             if (XSGIMiscQueryExtension(X11->display, &tmp, &tmp)
       
  2453                                 && XSGIDeviceQuery(X11->display, devs->id,
       
  2454                                                    "dimensions", returnString)) {
       
  2455                                 QString str = QLatin1String(returnString);
       
  2456                                 int comma = str.indexOf(',');
       
  2457                                 device_data.minX = 0;
       
  2458                                 device_data.minY = 0;
       
  2459                                 device_data.maxX = str.left(comma).toInt();
       
  2460                                 device_data.maxY = str.mid(comma + 1).toInt();
       
  2461                             } else {
       
  2462                                 device_data.minX = a[WAC_XCOORD_I].min_value;
       
  2463                                 device_data.maxX = a[WAC_XCOORD_I].max_value;
       
  2464                                 device_data.minY = a[WAC_YCOORD_I].min_value;
       
  2465                                 device_data.maxY = a[WAC_YCOORD_I].max_value;
       
  2466                             }
       
  2467                             device_data.minPressure = a[WAC_PRESSURE_I].min_value;
       
  2468                             device_data.maxPressure = a[WAC_PRESSURE_I].max_value;
       
  2469                             device_data.minTanPressure = a[WAC_TAN_PRESSURE_I].min_value;
       
  2470                             device_data.maxTanPressure = a[WAC_TAN_PRESSURE_I].max_value;
       
  2471                             device_data.minZ = a[WAC_ZCOORD_I].min_value;
       
  2472                             device_data.maxZ = a[WAC_ZCOORD_I].max_value;
       
  2473 #else
       
  2474                             device_data.minX = a[0].min_value;
       
  2475                             device_data.maxX = a[0].max_value;
       
  2476                             device_data.minY = a[1].min_value;
       
  2477                             device_data.maxY = a[1].max_value;
       
  2478                             device_data.minPressure = a[2].min_value;
       
  2479                             device_data.maxPressure = a[2].max_value;
       
  2480                             device_data.minTanPressure = 0;
       
  2481                             device_data.maxTanPressure = 0;
       
  2482                             device_data.minZ = 0;
       
  2483                             device_data.maxZ = 0;
       
  2484 #endif
       
  2485 
       
  2486                             // got the max pressure no need to go further...
       
  2487                             break;
       
  2488                         }
       
  2489                         any = (XAnyClassPtr) ((char *) any + any->length);
       
  2490                     } // end of for loop
       
  2491 
       
  2492                     tablet_devices()->append(device_data);
       
  2493                 } // if (gotStylus || gotEraser)
       
  2494             }
       
  2495             if (X11->ptrXFreeDeviceList)
       
  2496                 X11->ptrXFreeDeviceList(devices);
       
  2497         }
       
  2498 #endif // QT_NO_TABLET
       
  2499 
       
  2500         X11->startupId = getenv("DESKTOP_STARTUP_ID");
       
  2501         if (X11->startupId) {
       
  2502 #ifndef QT_NO_UNSETENV
       
  2503             unsetenv("DESKTOP_STARTUP_ID");
       
  2504 #else
       
  2505             // it's a small memory leak, however we won't crash if Qt is
       
  2506             // unloaded and someones tries to use the envoriment.
       
  2507             putenv(strdup("DESKTOP_STARTUP_ID="));
       
  2508 #endif
       
  2509         }
       
  2510    } else {
       
  2511         // read some non-GUI settings when not using the X server...
       
  2512 
       
  2513         if (QApplication::desktopSettingsAware()) {
       
  2514             QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
       
  2515             settings.beginGroup(QLatin1String("Qt"));
       
  2516 
       
  2517             // read library (ie. plugin) path list
       
  2518             QString libpathkey = QString::fromLatin1("%1.%2/libraryPath")
       
  2519                                  .arg(QT_VERSION >> 16)
       
  2520                                  .arg((QT_VERSION & 0xff00) >> 8);
       
  2521             QStringList pathlist =
       
  2522                 settings.value(libpathkey).toString().split(QLatin1Char(':'));
       
  2523             if (! pathlist.isEmpty()) {
       
  2524                 QStringList::ConstIterator it = pathlist.constBegin();
       
  2525                 while (it != pathlist.constEnd())
       
  2526                     QApplication::addLibraryPath(*it++);
       
  2527             }
       
  2528 
       
  2529             QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
       
  2530                                                   QVariant(QLatin1String("none"))).toString();
       
  2531             if (defaultcodec != QLatin1String("none")) {
       
  2532                 QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
       
  2533                 if (codec)
       
  2534                     QTextCodec::setCodecForTr(codec);
       
  2535             }
       
  2536 
       
  2537             settings.endGroup(); // Qt
       
  2538         }
       
  2539     }
       
  2540 
       
  2541 #if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET)
       
  2542     QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this.
       
  2543     if (wacom.load()) {
       
  2544         // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x
       
  2545         ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit");
       
  2546         ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice");
       
  2547         ptrWacomConfigGetRawParam  = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam");
       
  2548         ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice");
       
  2549         ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm");
       
  2550 
       
  2551         if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0
       
  2552                 || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none.
       
  2553             ptrWacomConfigInit = 0;
       
  2554             ptrWacomConfigOpenDevice = 0;
       
  2555             ptrWacomConfigGetRawParam  = 0;
       
  2556             ptrWacomConfigCloseDevice = 0;
       
  2557             ptrWacomConfigTerm = 0;
       
  2558         }
       
  2559     }
       
  2560 #endif
       
  2561 }
       
  2562 
       
  2563 void QApplicationPrivate::initializeWidgetPaletteHash()
       
  2564 {
       
  2565 }
       
  2566 
       
  2567 /*****************************************************************************
       
  2568   qt_cleanup() - cleans up when the application is finished
       
  2569  *****************************************************************************/
       
  2570 
       
  2571 void qt_cleanup()
       
  2572 {
       
  2573     if (app_save_rootinfo)                        // root window must keep state
       
  2574         qt_save_rootinfo();
       
  2575 
       
  2576     if (qt_is_gui_used) {
       
  2577         QPixmapCache::clear();
       
  2578         QCursorData::cleanup();
       
  2579         QFont::cleanup();
       
  2580         QColormap::cleanup();
       
  2581 
       
  2582 #if !defined (QT_NO_TABLET)
       
  2583         QTabletDeviceDataList *devices = qt_tablet_devices();
       
  2584         if (X11->ptrXCloseDevice)
       
  2585             for (int i = 0; i < devices->size(); ++i)
       
  2586                 X11->ptrXCloseDevice(X11->display, (XDevice*)devices->at(i).device);
       
  2587         devices->clear();
       
  2588 #endif
       
  2589     }
       
  2590 
       
  2591 #ifndef QT_NO_XRENDER
       
  2592     for (int i = 0; i < X11->solid_fill_count; ++i) {
       
  2593         if (X11->solid_fills[i].picture)
       
  2594             XRenderFreePicture(X11->display, X11->solid_fills[i].picture);
       
  2595     }
       
  2596     for (int i = 0; i < X11->pattern_fill_count; ++i) {
       
  2597         if (X11->pattern_fills[i].picture)
       
  2598             XRenderFreePicture(X11->display, X11->pattern_fills[i].picture);
       
  2599     }
       
  2600 #endif
       
  2601 
       
  2602 #if !defined(QT_NO_IM)
       
  2603     delete QApplicationPrivate::inputContext;
       
  2604     QApplicationPrivate::inputContext = 0;
       
  2605 #endif
       
  2606 
       
  2607     // Reset the error handlers
       
  2608     if (qt_is_gui_used)
       
  2609         XSync(X11->display, False); // sync first to process all possible errors
       
  2610     XSetErrorHandler(original_x_errhandler);
       
  2611     XSetIOErrorHandler(original_xio_errhandler);
       
  2612 
       
  2613     if (X11->argbColormaps) {
       
  2614         for (int s = 0; s < X11->screenCount; s++) {
       
  2615             if (X11->argbColormaps[s])
       
  2616                 XFreeColormap(X11->display, X11->argbColormaps[s]);
       
  2617         }
       
  2618     }
       
  2619 
       
  2620     if (qt_is_gui_used && !X11->foreignDisplay)
       
  2621         XCloseDisplay(X11->display);                // close X display
       
  2622     X11->display = 0;
       
  2623 
       
  2624     delete [] X11->screens;
       
  2625     delete [] X11->argbVisuals;
       
  2626     delete [] X11->argbColormaps;
       
  2627 
       
  2628     if (X11->foreignDisplay) {
       
  2629         delete [] (char *)appName;
       
  2630         appName = 0;
       
  2631     }
       
  2632 
       
  2633     delete [] (char *)appClass;
       
  2634     appClass = 0;
       
  2635 
       
  2636     if (X11->net_supported_list)
       
  2637         delete [] X11->net_supported_list;
       
  2638     X11->net_supported_list = 0;
       
  2639 
       
  2640     if (X11->net_virtual_root_list)
       
  2641         delete [] X11->net_virtual_root_list;
       
  2642     X11->net_virtual_root_list = 0;
       
  2643 
       
  2644     delete X11;
       
  2645     X11 = 0;
       
  2646 }
       
  2647 
       
  2648 
       
  2649 /*****************************************************************************
       
  2650   Platform specific global and internal functions
       
  2651  *****************************************************************************/
       
  2652 
       
  2653 void qt_save_rootinfo()                                // save new root info
       
  2654 {
       
  2655     Atom type;
       
  2656     int format;
       
  2657     unsigned long length, after;
       
  2658     uchar *data = 0;
       
  2659 
       
  2660     if (ATOM(_XSETROOT_ID)) {                        // kill old pixmap
       
  2661         if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
       
  2662                                  ATOM(_XSETROOT_ID), 0, 1,
       
  2663                                  True, AnyPropertyType, &type, &format,
       
  2664                                  &length, &after, &data) == Success) {
       
  2665             if (type == XA_PIXMAP && format == 32 && length == 1 &&
       
  2666                  after == 0 && data) {
       
  2667                 XKillClient(X11->display, *((Pixmap*)data));
       
  2668             }
       
  2669             Pixmap dummy = XCreatePixmap(X11->display, QX11Info::appRootWindow(),
       
  2670                                           1, 1, 1);
       
  2671             XChangeProperty(X11->display, QX11Info::appRootWindow(),
       
  2672                              ATOM(_XSETROOT_ID), XA_PIXMAP, 32,
       
  2673                              PropModeReplace, (uchar *)&dummy, 1);
       
  2674             XSetCloseDownMode(X11->display, RetainPermanent);
       
  2675         }
       
  2676     }
       
  2677     if (data)
       
  2678         XFree((char *)data);
       
  2679 }
       
  2680 
       
  2681 void qt_updated_rootinfo()
       
  2682 {
       
  2683     app_save_rootinfo = true;
       
  2684 }
       
  2685 
       
  2686 // ### Cleanup, this function is not in use!
       
  2687 bool qt_wstate_iconified(WId winid)
       
  2688 {
       
  2689     Atom type;
       
  2690     int format;
       
  2691     unsigned long length, after;
       
  2692     uchar *data = 0;
       
  2693     int r = XGetWindowProperty(X11->display, winid, ATOM(WM_STATE), 0, 2,
       
  2694                                  False, AnyPropertyType, &type, &format,
       
  2695                                  &length, &after, &data);
       
  2696     bool iconic = false;
       
  2697     if (r == Success && data && format == 32) {
       
  2698         // quint32 *wstate = (quint32*)data;
       
  2699         unsigned long *wstate = (unsigned long *) data;
       
  2700         iconic = (*wstate == IconicState);
       
  2701         XFree((char *)data);
       
  2702     }
       
  2703     return iconic;
       
  2704 }
       
  2705 
       
  2706 QString QApplicationPrivate::appName() const
       
  2707 {
       
  2708     return QString::fromLocal8Bit(QT_PREPEND_NAMESPACE(appName));
       
  2709 }
       
  2710 
       
  2711 const char *QX11Info::appClass()                                // get application class
       
  2712 {
       
  2713     return QT_PREPEND_NAMESPACE(appClass);
       
  2714 }
       
  2715 
       
  2716 bool qt_nograb()                                // application no-grab option
       
  2717 {
       
  2718 #if defined(QT_DEBUG)
       
  2719     return appNoGrab;
       
  2720 #else
       
  2721     return false;
       
  2722 #endif
       
  2723 }
       
  2724 
       
  2725 
       
  2726 /*****************************************************************************
       
  2727   Platform specific QApplication members
       
  2728  *****************************************************************************/
       
  2729 
       
  2730 #ifdef QT3_SUPPORT
       
  2731 void QApplication::setMainWidget(QWidget *mainWidget)
       
  2732 {
       
  2733 #ifndef QT_NO_DEBUG
       
  2734     if (mainWidget && mainWidget->parentWidget() && mainWidget->isWindow())
       
  2735         qWarning("QApplication::setMainWidget: New main widget (%s/%s) "
       
  2736                   "has a parent",
       
  2737                   mainWidget->metaObject()->className(), mainWidget->objectName().toLocal8Bit().constData());
       
  2738 #endif
       
  2739     if (mainWidget)
       
  2740         mainWidget->d_func()->createWinId();
       
  2741     QApplicationPrivate::main_widget = mainWidget;
       
  2742     if (QApplicationPrivate::main_widget) // give WM command line
       
  2743         QApplicationPrivate::applyX11SpecificCommandLineArguments(QApplicationPrivate::main_widget);
       
  2744 }
       
  2745 #endif
       
  2746 
       
  2747 void QApplicationPrivate::applyX11SpecificCommandLineArguments(QWidget *main_widget)
       
  2748 {
       
  2749     static bool beenHereDoneThat = false;
       
  2750     if (beenHereDoneThat)
       
  2751         return;
       
  2752     beenHereDoneThat = true;
       
  2753     Q_ASSERT(main_widget->testAttribute(Qt::WA_WState_Created));
       
  2754     if (mwTitle) {
       
  2755         XStoreName(X11->display, main_widget->effectiveWinId(), (char*)mwTitle);
       
  2756         QByteArray net_wm_name = QString::fromLocal8Bit(mwTitle).toUtf8();
       
  2757         XChangeProperty(X11->display, main_widget->effectiveWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8,
       
  2758                         PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size());
       
  2759     }
       
  2760     if (mwGeometry) { // parse geometry
       
  2761         int x, y;
       
  2762         int w, h;
       
  2763         int m = XParseGeometry((char*)mwGeometry, &x, &y, (uint*)&w, (uint*)&h);
       
  2764         QSize minSize = main_widget->minimumSize();
       
  2765         QSize maxSize = main_widget->maximumSize();
       
  2766         if ((m & XValue) == 0)
       
  2767             x = main_widget->geometry().x();
       
  2768         if ((m & YValue) == 0)
       
  2769             y = main_widget->geometry().y();
       
  2770         if ((m & WidthValue) == 0)
       
  2771             w = main_widget->width();
       
  2772         if ((m & HeightValue) == 0)
       
  2773             h = main_widget->height();
       
  2774         w = qMin(w,maxSize.width());
       
  2775         h = qMin(h,maxSize.height());
       
  2776         w = qMax(w,minSize.width());
       
  2777         h = qMax(h,minSize.height());
       
  2778         if ((m & XNegative)) {
       
  2779             x = QApplication::desktop()->width()  + x - w;
       
  2780         }
       
  2781         if ((m & YNegative)) {
       
  2782             y = QApplication::desktop()->height() + y - h;
       
  2783         }
       
  2784         main_widget->setGeometry(x, y, w, h);
       
  2785     }
       
  2786 }
       
  2787 
       
  2788 #ifndef QT_NO_CURSOR
       
  2789 
       
  2790 /*****************************************************************************
       
  2791   QApplication cursor stack
       
  2792  *****************************************************************************/
       
  2793 
       
  2794 void QApplication::setOverrideCursor(const QCursor &cursor)
       
  2795 {
       
  2796     qApp->d_func()->cursor_list.prepend(cursor);
       
  2797 
       
  2798     QWidgetList all = allWidgets();
       
  2799     for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
       
  2800         register QWidget *w = *it;
       
  2801         if ((w->testAttribute(Qt::WA_SetCursor) || w->isWindow()) && (w->windowType() != Qt::Desktop))
       
  2802             qt_x11_enforce_cursor(w);
       
  2803     }
       
  2804     XFlush(X11->display);                                // make X execute it NOW
       
  2805 }
       
  2806 
       
  2807 void QApplication::restoreOverrideCursor()
       
  2808 {
       
  2809     if (qApp->d_func()->cursor_list.isEmpty())
       
  2810         return;
       
  2811     qApp->d_func()->cursor_list.removeFirst();
       
  2812 
       
  2813     if (QWidgetPrivate::mapper != 0 && !closingDown()) {
       
  2814         QWidgetList all = allWidgets();
       
  2815         for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) {
       
  2816             register QWidget *w = *it;
       
  2817             if ((w->testAttribute(Qt::WA_SetCursor) || w->isWindow()) && (w->windowType() != Qt::Desktop))
       
  2818                 qt_x11_enforce_cursor(w);
       
  2819         }
       
  2820         XFlush(X11->display);
       
  2821     }
       
  2822 }
       
  2823 
       
  2824 #endif
       
  2825 
       
  2826 
       
  2827 /*****************************************************************************
       
  2828   Routines to find a Qt widget from a screen position
       
  2829  *****************************************************************************/
       
  2830 
       
  2831 Window QX11Data::findClientWindow(Window win, Atom property, bool leaf)
       
  2832 {
       
  2833     Atom   type = XNone;
       
  2834     int           format, i;
       
  2835     ulong  nitems, after;
       
  2836     uchar *data = 0;
       
  2837     Window root, parent, target=0, *children=0;
       
  2838     uint   nchildren;
       
  2839     if (XGetWindowProperty(X11->display, win, property, 0, 0, false, AnyPropertyType,
       
  2840                              &type, &format, &nitems, &after, &data) == Success) {
       
  2841         if (data)
       
  2842             XFree((char *)data);
       
  2843         if (type)
       
  2844             return win;
       
  2845     }
       
  2846     if (!XQueryTree(X11->display,win,&root,&parent,&children,&nchildren)) {
       
  2847         if (children)
       
  2848             XFree((char *)children);
       
  2849         return 0;
       
  2850     }
       
  2851     for (i=nchildren-1; !target && i >= 0; i--)
       
  2852         target = X11->findClientWindow(children[i], property, leaf);
       
  2853     if (children)
       
  2854         XFree((char *)children);
       
  2855     return target;
       
  2856 }
       
  2857 
       
  2858 QWidget *QApplication::topLevelAt(const QPoint &p)
       
  2859 {
       
  2860 #ifdef QT_NO_CURSOR
       
  2861     Q_UNUSED(p);
       
  2862     return 0;
       
  2863 #else
       
  2864     int screen = QCursor::x11Screen();
       
  2865     int unused;
       
  2866 
       
  2867     int x = p.x();
       
  2868     int y = p.y();
       
  2869     Window target;
       
  2870     if (!XTranslateCoordinates(X11->display,
       
  2871                                QX11Info::appRootWindow(screen),
       
  2872                                QX11Info::appRootWindow(screen),
       
  2873                                x, y, &unused, &unused, &target)) {
       
  2874         return 0;
       
  2875     }
       
  2876     if (!target || target == QX11Info::appRootWindow(screen))
       
  2877         return 0;
       
  2878     QWidget *w;
       
  2879     w = QWidget::find((WId)target);
       
  2880 
       
  2881     if (!w) {
       
  2882         X11->ignoreBadwindow();
       
  2883         target = X11->findClientWindow(target, ATOM(WM_STATE), true);
       
  2884         if (X11->badwindow())
       
  2885             return 0;
       
  2886         w = QWidget::find((WId)target);
       
  2887         if (!w) {
       
  2888             // Perhaps the widget at (x,y) is inside a foreign application?
       
  2889             // Search all toplevel widgets to see if one is within target
       
  2890             QWidgetList list = QApplication::topLevelWidgets();
       
  2891             for (int i = 0; i < list.count(); ++i) {
       
  2892                 QWidget *widget = list.at(i);
       
  2893                 Window ctarget = target;
       
  2894                 if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
       
  2895                     Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
       
  2896                     Window wid = widget->internalWinId();
       
  2897                     while (ctarget && !w) {
       
  2898                         X11->ignoreBadwindow();
       
  2899                         if (!XTranslateCoordinates(X11->display,
       
  2900                                                    QX11Info::appRootWindow(screen),
       
  2901                                                    ctarget, x, y, &unused, &unused, &ctarget)
       
  2902                                 || X11->badwindow())
       
  2903                             break;
       
  2904                         if (ctarget == wid) {
       
  2905                             // Found!
       
  2906                             w = widget;
       
  2907                             break;
       
  2908                         }
       
  2909                     }
       
  2910                 }
       
  2911                 if (w)
       
  2912                     break;
       
  2913             }
       
  2914         }
       
  2915     }
       
  2916     return w ? w->window() : 0;
       
  2917 #endif
       
  2918 }
       
  2919 
       
  2920 void QApplication::syncX()
       
  2921 {
       
  2922     if (X11->display)
       
  2923         XSync(X11->display, False);  // don't discard events
       
  2924 }
       
  2925 
       
  2926 
       
  2927 void QApplication::beep()
       
  2928 {
       
  2929     if (X11->display)
       
  2930         XBell(X11->display, 0);
       
  2931     else
       
  2932         printf("\7");
       
  2933 }
       
  2934 
       
  2935 void QApplication::alert(QWidget *widget, int msec)
       
  2936 {
       
  2937     if (!QApplicationPrivate::checkInstance("alert"))
       
  2938         return;
       
  2939 
       
  2940     QWidgetList windowsToMark;
       
  2941     if (!widget) {
       
  2942         windowsToMark += topLevelWidgets();
       
  2943     } else {
       
  2944         windowsToMark.append(widget->window());
       
  2945     }
       
  2946 
       
  2947     for (int i = 0; i < windowsToMark.size(); ++i) {
       
  2948         QWidget *window = windowsToMark.at(i);
       
  2949         if (!window->isActiveWindow()) {
       
  2950             qt_change_net_wm_state(window, true, ATOM(_NET_WM_STATE_DEMANDS_ATTENTION));
       
  2951             if (msec != 0) {
       
  2952                 QTimer *timer = new QTimer(qApp);
       
  2953                 timer->setSingleShot(true);
       
  2954                 connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut()));
       
  2955                 if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(window)) {
       
  2956                     qApp->d_func()->alertTimerHash.remove(window);
       
  2957                     delete oldTimer;
       
  2958                 }
       
  2959                 qApp->d_func()->alertTimerHash.insert(window, timer);
       
  2960                 timer->start(msec);
       
  2961             }
       
  2962         }
       
  2963     }
       
  2964 }
       
  2965 
       
  2966 void QApplicationPrivate::_q_alertTimeOut()
       
  2967 {
       
  2968     if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) {
       
  2969         QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin();
       
  2970         while (it != alertTimerHash.end()) {
       
  2971             if (it.value() == timer) {
       
  2972                 QWidget *window = it.key();
       
  2973                 qt_change_net_wm_state(window, false, ATOM(_NET_WM_STATE_DEMANDS_ATTENTION));
       
  2974                 alertTimerHash.erase(it);
       
  2975                 timer->deleteLater();
       
  2976                 break;
       
  2977             }
       
  2978             ++it;
       
  2979         }
       
  2980     }
       
  2981 }
       
  2982 
       
  2983 /*****************************************************************************
       
  2984   Special lookup functions for windows that have been reparented recently
       
  2985  *****************************************************************************/
       
  2986 
       
  2987 static QWidgetMapper *wPRmapper = 0;                // alternative widget mapper
       
  2988 
       
  2989 void qPRCreate(const QWidget *widget, Window oldwin)
       
  2990 {                                                // QWidget::reparent mechanism
       
  2991     if (!wPRmapper)
       
  2992         wPRmapper = new QWidgetMapper;
       
  2993 
       
  2994     QETWidget *w = static_cast<QETWidget *>(const_cast<QWidget *>(widget));
       
  2995     wPRmapper->insert((int)oldwin, w);        // add old window to mapper
       
  2996     w->setAttribute(Qt::WA_WState_Reparented);        // set reparented flag
       
  2997 }
       
  2998 
       
  2999 void qPRCleanup(QWidget *widget)
       
  3000 {
       
  3001     QETWidget *etw = static_cast<QETWidget *>(const_cast<QWidget *>(widget));
       
  3002     if (!(wPRmapper && widget->testAttribute(Qt::WA_WState_Reparented)))
       
  3003         return;                                        // not a reparented widget
       
  3004     QWidgetMapper::Iterator it = wPRmapper->begin();
       
  3005     while (it != wPRmapper->constEnd()) {
       
  3006         QWidget *w = *it;
       
  3007         if (w == etw) {                       // found widget
       
  3008             etw->setAttribute(Qt::WA_WState_Reparented, false); // clear flag
       
  3009             it = wPRmapper->erase(it);// old window no longer needed
       
  3010         } else {
       
  3011             ++it;
       
  3012         }
       
  3013     }
       
  3014     if (wPRmapper->size() == 0) {        // became empty
       
  3015         delete wPRmapper;                // then reset alt mapper
       
  3016         wPRmapper = 0;
       
  3017     }
       
  3018 }
       
  3019 
       
  3020 static QETWidget *qPRFindWidget(Window oldwin)
       
  3021 {
       
  3022     return wPRmapper ? (QETWidget*)wPRmapper->value((int)oldwin, 0) : 0;
       
  3023 }
       
  3024 
       
  3025 int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
       
  3026 {
       
  3027     if (w && !w->internalWinId())
       
  3028         return 0;
       
  3029     QETWidget *widget = (QETWidget*)w;
       
  3030     if (event->xclient.format == 32 && event->xclient.message_type) {
       
  3031         if (event->xclient.message_type == ATOM(WM_PROTOCOLS)) {
       
  3032             Atom a = event->xclient.data.l[0];
       
  3033             if (a == ATOM(WM_DELETE_WINDOW)) {
       
  3034                 if (passive_only) return 0;
       
  3035                 widget->translateCloseEvent(event);
       
  3036             }
       
  3037             else if (a == ATOM(WM_TAKE_FOCUS)) {
       
  3038                 if ((ulong) event->xclient.data.l[1] > X11->time)
       
  3039                     X11->time = event->xclient.data.l[1];
       
  3040                 QWidget *amw = activeModalWidget();
       
  3041                 if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
       
  3042                     QWidget *p = amw->parentWidget();
       
  3043                     while (p && p != widget)
       
  3044                         p = p->parentWidget();
       
  3045                     if (!p || !X11->net_supported_list)
       
  3046                         amw->raise(); // help broken window managers
       
  3047                     amw->activateWindow();
       
  3048                 }
       
  3049 #ifndef QT_NO_WHATSTHIS
       
  3050             } else if (a == ATOM(_NET_WM_CONTEXT_HELP)) {
       
  3051                 QWhatsThis::enterWhatsThisMode();
       
  3052 #endif // QT_NO_WHATSTHIS
       
  3053             } else if (a == ATOM(_NET_WM_PING)) {
       
  3054                 // avoid send/reply loops
       
  3055                 Window root = RootWindow(X11->display, w->x11Info().screen());
       
  3056                 if (event->xclient.window != root) {
       
  3057                     event->xclient.window = root;
       
  3058                     XSendEvent(event->xclient.display, event->xclient.window,
       
  3059                                 False, SubstructureNotifyMask|SubstructureRedirectMask, event);
       
  3060                 }
       
  3061 #ifndef QT_NO_XSYNC
       
  3062             } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) {
       
  3063                 const ulong timestamp = (const ulong) event->xclient.data.l[1];
       
  3064                 if (timestamp > X11->time)
       
  3065                     X11->time = timestamp;
       
  3066                 if (QTLWExtra *tlw = w->d_func()->maybeTopData()) {
       
  3067                     if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
       
  3068                         tlw->syncRequestTimestamp = timestamp;
       
  3069                         tlw->newCounterValueLo = event->xclient.data.l[2];
       
  3070                         tlw->newCounterValueHi = event->xclient.data.l[3];
       
  3071                     }
       
  3072                 }
       
  3073 #endif
       
  3074             }
       
  3075         } else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
       
  3076             widget->translateScrollDoneEvent(event);
       
  3077         } else if (event->xclient.message_type == ATOM(XdndPosition)) {
       
  3078             X11->xdndHandlePosition(widget, event, passive_only);
       
  3079         } else if (event->xclient.message_type == ATOM(XdndEnter)) {
       
  3080             X11->xdndHandleEnter(widget, event, passive_only);
       
  3081         } else if (event->xclient.message_type == ATOM(XdndStatus)) {
       
  3082             X11->xdndHandleStatus(widget, event, passive_only);
       
  3083         } else if (event->xclient.message_type == ATOM(XdndLeave)) {
       
  3084             X11->xdndHandleLeave(widget, event, passive_only);
       
  3085         } else if (event->xclient.message_type == ATOM(XdndDrop)) {
       
  3086             X11->xdndHandleDrop(widget, event, passive_only);
       
  3087         } else if (event->xclient.message_type == ATOM(XdndFinished)) {
       
  3088             X11->xdndHandleFinished(widget, event, passive_only);
       
  3089         } else {
       
  3090             if (passive_only) return 0;
       
  3091             // All other are interactions
       
  3092         }
       
  3093     } else {
       
  3094         X11->motifdndHandle(widget, event, passive_only);
       
  3095     }
       
  3096 
       
  3097     return 0;
       
  3098 }
       
  3099 
       
  3100 int QApplication::x11ProcessEvent(XEvent* event)
       
  3101 {
       
  3102     Q_D(QApplication);
       
  3103     QScopedLoopLevelCounter loopLevelCounter(d->threadData);
       
  3104 
       
  3105 #ifdef ALIEN_DEBUG
       
  3106     //qDebug() << "QApplication::x11ProcessEvent:" << event->type;
       
  3107 #endif
       
  3108     switch (event->type) {
       
  3109     case ButtonPress:
       
  3110         pressed_window = event->xbutton.window;
       
  3111         X11->userTime = event->xbutton.time;
       
  3112         // fallthrough intended
       
  3113     case ButtonRelease:
       
  3114         X11->time = event->xbutton.time;
       
  3115         break;
       
  3116     case MotionNotify:
       
  3117         X11->time = event->xmotion.time;
       
  3118         break;
       
  3119     case XKeyPress:
       
  3120         X11->userTime = event->xkey.time;
       
  3121         // fallthrough intended
       
  3122     case XKeyRelease:
       
  3123         X11->time = event->xkey.time;
       
  3124         break;
       
  3125     case PropertyNotify:
       
  3126         X11->time = event->xproperty.time;
       
  3127         break;
       
  3128     case EnterNotify:
       
  3129     case LeaveNotify:
       
  3130         X11->time = event->xcrossing.time;
       
  3131         break;
       
  3132     case SelectionClear:
       
  3133         X11->time = event->xselectionclear.time;
       
  3134         break;
       
  3135     default:
       
  3136         break;
       
  3137     }
       
  3138 #ifndef QT_NO_XFIXES
       
  3139     if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) {
       
  3140         XFixesSelectionNotifyEvent *req =
       
  3141             reinterpret_cast<XFixesSelectionNotifyEvent *>(event);
       
  3142         X11->time = req->selection_timestamp;
       
  3143     }
       
  3144 #endif
       
  3145 
       
  3146     QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
       
  3147 
       
  3148     if (wPRmapper) {                                // just did a widget reparent?
       
  3149         if (widget == 0) {                        // not in std widget mapper
       
  3150             switch (event->type) {                // only for mouse/key events
       
  3151             case ButtonPress:
       
  3152             case ButtonRelease:
       
  3153             case MotionNotify:
       
  3154             case XKeyPress:
       
  3155             case XKeyRelease:
       
  3156                 widget = qPRFindWidget(event->xany.window);
       
  3157                 break;
       
  3158             }
       
  3159         }
       
  3160         else if (widget->testAttribute(Qt::WA_WState_Reparented))
       
  3161             qPRCleanup(widget);                // remove from alt mapper
       
  3162     }
       
  3163 
       
  3164     QETWidget *keywidget=0;
       
  3165     bool grabbed=false;
       
  3166     if (event->type==XKeyPress || event->type==XKeyRelease) {
       
  3167         keywidget = (QETWidget*)QWidget::keyboardGrabber();
       
  3168         if (keywidget) {
       
  3169             grabbed = true;
       
  3170         } else if (!keywidget) {
       
  3171             if (d->inPopupMode()) // no focus widget, see if we have a popup
       
  3172                 keywidget = (QETWidget*) (activePopupWidget()->focusWidget() ? activePopupWidget()->focusWidget() : activePopupWidget());
       
  3173             else if (QApplicationPrivate::focus_widget)
       
  3174                 keywidget = (QETWidget*)QApplicationPrivate::focus_widget;
       
  3175             else if (widget)
       
  3176                 keywidget = (QETWidget*)widget->window();
       
  3177         }
       
  3178     }
       
  3179 
       
  3180 #ifndef QT_NO_IM
       
  3181     // Filtering input events by the input context. It has to be taken
       
  3182     // place before any other key event consumers such as eventfilters
       
  3183     // and accelerators because some input methods require quite
       
  3184     // various key combination and sequences. It often conflicts with
       
  3185     // accelerators and so on, so we must give the input context the
       
  3186     // filtering opportunity first to ensure all input methods work
       
  3187     // properly regardless of application design.
       
  3188 
       
  3189     if(keywidget && keywidget->isEnabled() && keywidget->testAttribute(Qt::WA_InputMethodEnabled)) {
       
  3190         // block user interaction during session management
       
  3191 	if((event->type==XKeyPress || event->type==XKeyRelease) && qt_sm_blockUserInput)
       
  3192 	    return true;
       
  3193 
       
  3194         // for XIM handling
       
  3195 	QInputContext *qic = keywidget->inputContext();
       
  3196 	if(qic && qic->x11FilterEvent(keywidget, event))
       
  3197 	    return true;
       
  3198 
       
  3199 	// filterEvent() accepts QEvent *event rather than preexpanded
       
  3200 	// key event attribute values. This is intended to pass other
       
  3201 	// QInputEvent in future. Other non IM-related events should
       
  3202 	// not be forwarded to input contexts to prevent weird event
       
  3203 	// handling.
       
  3204 	if ((event->type == XKeyPress || event->type == XKeyRelease)) {
       
  3205 	    int code = -1;
       
  3206 	    int count = 0;
       
  3207 	    Qt::KeyboardModifiers modifiers;
       
  3208 	    QEvent::Type type;
       
  3209 	    QString text;
       
  3210             KeySym keySym;
       
  3211 
       
  3212             qt_keymapper_private()->translateKeyEventInternal(keywidget, event, keySym, count,
       
  3213                                                               text, modifiers, code, type, false);
       
  3214 
       
  3215 	    // both key press/release is required for some complex
       
  3216 	    // input methods. don't eliminate anything.
       
  3217 	    QKeyEventEx keyevent(type, code, modifiers, text, false, qMax(qMax(count, 1), text.length()),
       
  3218                                  event->xkey.keycode, keySym, event->xkey.state);
       
  3219 	    if(qic && qic->filterEvent(&keyevent))
       
  3220 		return true;
       
  3221 	}
       
  3222     } else
       
  3223 #endif // QT_NO_IM
       
  3224         {
       
  3225             if (XFilterEvent(event, XNone))
       
  3226                 return true;
       
  3227         }
       
  3228 
       
  3229     if (qt_x11EventFilter(event))                // send through app filter
       
  3230         return 1;
       
  3231 
       
  3232     if (event->type == MappingNotify) {
       
  3233         // keyboard mapping changed
       
  3234         XRefreshKeyboardMapping(&event->xmapping);
       
  3235 
       
  3236         QKeyMapper::changeKeyboard();
       
  3237         return 0;
       
  3238     }
       
  3239 
       
  3240     if (!widget) {                                // don't know this windows
       
  3241         QWidget* popup = QApplication::activePopupWidget();
       
  3242         if (popup) {
       
  3243 
       
  3244             /*
       
  3245               That is more than suboptimal. The real solution should
       
  3246               do some keyevent and buttonevent translation, so that
       
  3247               the popup still continues to work as the user expects.
       
  3248               Unfortunately this translation is currently only
       
  3249               possible with a known widget. I'll change that soon
       
  3250               (Matthias).
       
  3251             */
       
  3252 
       
  3253             // Danger - make sure we don't lock the server
       
  3254             switch (event->type) {
       
  3255             case ButtonPress:
       
  3256             case ButtonRelease:
       
  3257             case XKeyPress:
       
  3258             case XKeyRelease:
       
  3259                 do {
       
  3260                     popup->close();
       
  3261                 } while ((popup = qApp->activePopupWidget()));
       
  3262                 return 1;
       
  3263             }
       
  3264         }
       
  3265         return -1;
       
  3266     }
       
  3267 
       
  3268     if (event->type == XKeyPress || event->type == XKeyRelease)
       
  3269         widget = keywidget; // send XKeyEvents through keywidget->x11Event()
       
  3270 
       
  3271     if (app_do_modal)                                // modal event handling
       
  3272         if (!qt_try_modal(widget, event)) {
       
  3273             if (event->type == ClientMessage && !widget->x11Event(event))
       
  3274                 x11ClientMessage(widget, event, true);
       
  3275             return 1;
       
  3276         }
       
  3277 
       
  3278 
       
  3279     if (widget->x11Event(event))                // send through widget filter
       
  3280         return 1;
       
  3281 #if !defined (QT_NO_TABLET)
       
  3282     if (!qt_xdnd_dragging) {
       
  3283         QTabletDeviceDataList *tablets = qt_tablet_devices();
       
  3284         for (int i = 0; i < tablets->size(); ++i) {
       
  3285             QTabletDeviceData &tab = tablets->operator [](i);
       
  3286             if (event->type == tab.xinput_motion
       
  3287             || event->type == tab.xinput_button_release
       
  3288             || event->type == tab.xinput_button_press
       
  3289             || event->type == tab.xinput_proximity_in
       
  3290             || event->type == tab.xinput_proximity_out) {
       
  3291                 widget->translateXinputEvent(event, &tab);
       
  3292                 return 0;
       
  3293             }
       
  3294         }
       
  3295     }
       
  3296 #endif
       
  3297 
       
  3298 #ifndef QT_NO_XRANDR
       
  3299     if (X11->use_xrandr && event->type == (X11->xrandr_eventbase + RRScreenChangeNotify)) {
       
  3300         // update Xlib internals with the latest screen configuration
       
  3301         X11->ptrXRRUpdateConfiguration(event);
       
  3302 
       
  3303         // update the size for desktop widget
       
  3304         int scr = X11->ptrXRRRootToScreen(X11->display, event->xany.window);
       
  3305         QDesktopWidget *desktop = QApplication::desktop();
       
  3306         QWidget *w = desktop->screen(scr);
       
  3307         QSize oldSize(w->size());
       
  3308         w->data->crect.setWidth(DisplayWidth(X11->display, scr));
       
  3309         w->data->crect.setHeight(DisplayHeight(X11->display, scr));
       
  3310         QResizeEvent e(w->size(), oldSize);
       
  3311         QApplication::sendEvent(w, &e);
       
  3312         if (w != desktop)
       
  3313             QApplication::sendEvent(desktop, &e);
       
  3314     }
       
  3315 #endif // QT_NO_XRANDR
       
  3316 
       
  3317 #ifndef QT_NO_XFIXES
       
  3318     if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) {
       
  3319         XFixesSelectionNotifyEvent *req = reinterpret_cast<XFixesSelectionNotifyEvent *>(event);
       
  3320 
       
  3321         // compress all XFixes events related to this selection
       
  3322         // we don't want to handle old SelectionNotify events.
       
  3323         qt_xfixes_selection_event_data xfixes_event;
       
  3324         xfixes_event.selection = req->selection;
       
  3325         for (XEvent ev;;) {
       
  3326             if (!XCheckIfEvent(X11->display, &ev, &qt_xfixes_scanner, (XPointer)&xfixes_event))
       
  3327                 break;
       
  3328         }
       
  3329 
       
  3330         if (req->selection == ATOM(CLIPBOARD)) {
       
  3331             if (qt_xfixes_clipboard_changed(req->owner, req->selection_timestamp)) {
       
  3332                 emit clipboard()->changed(QClipboard::Clipboard);
       
  3333                 emit clipboard()->dataChanged();
       
  3334             }
       
  3335         } else if (req->selection == XA_PRIMARY) {
       
  3336             if (qt_xfixes_selection_changed(req->owner, req->selection_timestamp)) {
       
  3337                 emit clipboard()->changed(QClipboard::Selection);
       
  3338                 emit clipboard()->selectionChanged();
       
  3339             }
       
  3340         }
       
  3341     }
       
  3342 #endif // QT_NO_XFIXES
       
  3343 
       
  3344     switch (event->type) {
       
  3345 
       
  3346     case ButtonRelease:                        // mouse event
       
  3347         if (!d->inPopupMode() && !QWidget::mouseGrabber() && pressed_window != widget->internalWinId()
       
  3348             && (widget = (QETWidget*) QWidget::find((WId)pressed_window)) == 0)
       
  3349             break;
       
  3350         // fall through intended
       
  3351     case ButtonPress:
       
  3352         if (event->xbutton.root != RootWindow(X11->display, widget->x11Info().screen())
       
  3353             && ! qt_xdnd_dragging) {
       
  3354             while (activePopupWidget())
       
  3355                 activePopupWidget()->close();
       
  3356             return 1;
       
  3357         }
       
  3358         if (event->type == ButtonPress)
       
  3359             qt_net_update_user_time(widget->window(), X11->userTime);
       
  3360         // fall through intended
       
  3361     case MotionNotify:
       
  3362 #if !defined(QT_NO_TABLET)
       
  3363         if (!qt_tabletChokeMouse) {
       
  3364 #endif
       
  3365             if (widget->testAttribute(Qt::WA_TransparentForMouseEvents)) {
       
  3366                 QPoint pos(event->xbutton.x, event->xbutton.y);
       
  3367                 pos = widget->d_func()->mapFromWS(pos);
       
  3368                 QWidget *window = widget->window();
       
  3369                 pos = widget->mapTo(window, pos);
       
  3370                 if (QWidget *child = window->childAt(pos)) {
       
  3371                     widget = static_cast<QETWidget *>(child);
       
  3372                     pos = child->mapFrom(window, pos);
       
  3373                     event->xbutton.x = pos.x();
       
  3374                     event->xbutton.y = pos.y();
       
  3375                 }
       
  3376             }
       
  3377             widget->translateMouseEvent(event);
       
  3378 #if !defined(QT_NO_TABLET)
       
  3379         } else {
       
  3380             qt_tabletChokeMouse = false;
       
  3381         }
       
  3382 #endif
       
  3383         break;
       
  3384 
       
  3385     case XKeyPress:                                // keyboard event
       
  3386         qt_net_update_user_time(widget->window(), X11->userTime);
       
  3387         // fallthrough intended
       
  3388     case XKeyRelease:
       
  3389         {
       
  3390             if (keywidget && keywidget->isEnabled()) { // should always exist
       
  3391                 // qDebug("sending key event");
       
  3392                 qt_keymapper_private()->translateKeyEvent(keywidget, event, grabbed);
       
  3393             }
       
  3394             break;
       
  3395         }
       
  3396 
       
  3397     case GraphicsExpose:
       
  3398     case Expose:                                // paint event
       
  3399         widget->translatePaintEvent(event);
       
  3400         break;
       
  3401 
       
  3402     case ConfigureNotify:                        // window move/resize event
       
  3403         if (event->xconfigure.event == event->xconfigure.window)
       
  3404             widget->translateConfigEvent(event);
       
  3405         break;
       
  3406 
       
  3407     case XFocusIn: {                                // got focus
       
  3408         if ((widget->windowType() == Qt::Desktop))
       
  3409             break;
       
  3410         if (d->inPopupMode()) // some delayed focus event to ignore
       
  3411             break;
       
  3412         if (!widget->isWindow())
       
  3413             break;
       
  3414         if (event->xfocus.detail != NotifyAncestor &&
       
  3415             event->xfocus.detail != NotifyInferior &&
       
  3416             event->xfocus.detail != NotifyNonlinear)
       
  3417             break;
       
  3418         setActiveWindow(widget);
       
  3419         if (X11->focus_model == QX11Data::FM_PointerRoot) {
       
  3420             // We got real input focus from somewhere, but we were in PointerRoot
       
  3421             // mode, so we don't trust this event.  Check the focus model to make
       
  3422             // sure we know what focus mode we are using...
       
  3423             qt_check_focus_model();
       
  3424         }
       
  3425     }
       
  3426         break;
       
  3427 
       
  3428     case XFocusOut:                                // lost focus
       
  3429         if ((widget->windowType() == Qt::Desktop))
       
  3430             break;
       
  3431         if (!widget->isWindow())
       
  3432             break;
       
  3433         if (event->xfocus.mode == NotifyGrab) {
       
  3434             qt_xfocusout_grab_counter++;
       
  3435             break;
       
  3436         }
       
  3437         if (event->xfocus.detail != NotifyAncestor &&
       
  3438             event->xfocus.detail != NotifyNonlinearVirtual &&
       
  3439             event->xfocus.detail != NotifyNonlinear)
       
  3440             break;
       
  3441         if (!d->inPopupMode() && widget == QApplicationPrivate::active_window) {
       
  3442             XEvent ev;
       
  3443             bool focus_will_change = false;
       
  3444             if (XCheckTypedEvent(X11->display, XFocusIn, &ev)) {
       
  3445                 // we're about to get an XFocusIn, if we know we will
       
  3446                 // get a new active window, we don't want to set the
       
  3447                 // active window to 0 now
       
  3448                 QWidget *w2 = QWidget::find(ev.xany.window);
       
  3449                 if (w2
       
  3450                     && w2->windowType() != Qt::Desktop
       
  3451                     && !d->inPopupMode() // some delayed focus event to ignore
       
  3452                     && w2->isWindow()
       
  3453                     && (ev.xfocus.detail == NotifyAncestor
       
  3454                         || ev.xfocus.detail == NotifyInferior
       
  3455                         || ev.xfocus.detail == NotifyNonlinear))
       
  3456                     focus_will_change = true;
       
  3457 
       
  3458                 XPutBackEvent(X11->display, &ev);
       
  3459             }
       
  3460             if (!focus_will_change)
       
  3461                 setActiveWindow(0);
       
  3462         }
       
  3463         break;
       
  3464 
       
  3465     case EnterNotify: {                        // enter window
       
  3466         if (QWidget::mouseGrabber() && (!d->inPopupMode() || widget->window() != activePopupWidget()))
       
  3467             break;
       
  3468         if ((event->xcrossing.mode != NotifyNormal
       
  3469              && event->xcrossing.mode != NotifyUngrab)
       
  3470             || event->xcrossing.detail == NotifyVirtual
       
  3471             || event->xcrossing.detail == NotifyNonlinearVirtual)
       
  3472             break;
       
  3473         if (event->xcrossing.focus &&
       
  3474             !(widget->windowType() == Qt::Desktop) && !widget->isActiveWindow()) {
       
  3475             if (X11->focus_model == QX11Data::FM_Unknown) // check focus model
       
  3476                 qt_check_focus_model();
       
  3477             if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode
       
  3478                 setActiveWindow(widget);
       
  3479         }
       
  3480 
       
  3481         if (qt_button_down && !d->inPopupMode())
       
  3482             break;
       
  3483 
       
  3484         QWidget *alien = widget->childAt(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x,
       
  3485                                                                             event->xcrossing.y)));
       
  3486         QWidget *enter = alien ? alien : widget;
       
  3487         QWidget *leave = 0;
       
  3488         if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
       
  3489             leave = qt_last_mouse_receiver;
       
  3490         else
       
  3491             leave = QWidget::find(curWin);
       
  3492 
       
  3493         // ### Alien: enter/leave might be wrong here with overlapping siblings
       
  3494         // if the enter widget is native and stacked under a non-native widget.
       
  3495         QApplicationPrivate::dispatchEnterLeave(enter, leave);
       
  3496         curWin = widget->internalWinId();
       
  3497         qt_last_mouse_receiver = enter;
       
  3498         if (!d->inPopupMode() || widget->window() == activePopupWidget())
       
  3499             widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
       
  3500     }
       
  3501         break;
       
  3502     case LeaveNotify: {                        // leave window
       
  3503         QWidget *mouseGrabber = QWidget::mouseGrabber();
       
  3504         if (mouseGrabber && !d->inPopupMode())
       
  3505             break;
       
  3506         if (curWin && widget->internalWinId() != curWin)
       
  3507             break;
       
  3508         if ((event->xcrossing.mode != NotifyNormal
       
  3509             && event->xcrossing.mode != NotifyUngrab)
       
  3510             || event->xcrossing.detail == NotifyInferior)
       
  3511             break;
       
  3512         if (!(widget->windowType() == Qt::Desktop))
       
  3513             widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
       
  3514 
       
  3515         QWidget* enter = 0;
       
  3516         QPoint enterPoint;
       
  3517         XEvent ev;
       
  3518         while (XCheckMaskEvent(X11->display, EnterWindowMask | LeaveWindowMask , &ev)
       
  3519                && !qt_x11EventFilter(&ev)) {
       
  3520             QWidget* event_widget = QWidget::find(ev.xcrossing.window);
       
  3521             if(event_widget && event_widget->x11Event(&ev))
       
  3522                 break;
       
  3523             if (ev.type == LeaveNotify
       
  3524                 || (ev.xcrossing.mode != NotifyNormal
       
  3525                     && ev.xcrossing.mode != NotifyUngrab)
       
  3526                 || ev.xcrossing.detail == NotifyVirtual
       
  3527                 || ev.xcrossing.detail == NotifyNonlinearVirtual)
       
  3528                 continue;
       
  3529             enter = event_widget;
       
  3530             if (enter)
       
  3531                 enterPoint = enter->d_func()->mapFromWS(QPoint(ev.xcrossing.x, ev.xcrossing.y));
       
  3532             if (ev.xcrossing.focus &&
       
  3533                 enter && !(enter->windowType() == Qt::Desktop) && !enter->isActiveWindow()) {
       
  3534                 if (X11->focus_model == QX11Data::FM_Unknown) // check focus model
       
  3535                     qt_check_focus_model();
       
  3536                 if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode
       
  3537                     setActiveWindow(enter);
       
  3538             }
       
  3539             break;
       
  3540         }
       
  3541 
       
  3542         if ((! enter || (enter->windowType() == Qt::Desktop)) &&
       
  3543             event->xcrossing.focus && widget == QApplicationPrivate::active_window &&
       
  3544             X11->focus_model == QX11Data::FM_PointerRoot // PointerRoot mode
       
  3545             ) {
       
  3546             setActiveWindow(0);
       
  3547         }
       
  3548 
       
  3549         if (qt_button_down && !d->inPopupMode())
       
  3550             break;
       
  3551 
       
  3552         if (!curWin)
       
  3553             QApplicationPrivate::dispatchEnterLeave(widget, 0);
       
  3554 
       
  3555         if (enter) {
       
  3556             QWidget *alienEnter = enter->childAt(enterPoint);
       
  3557             if (alienEnter)
       
  3558                 enter = alienEnter;
       
  3559         }
       
  3560 
       
  3561         QWidget *leave = qt_last_mouse_receiver ? qt_last_mouse_receiver : widget;
       
  3562         QWidget *activePopupWidget = qApp->activePopupWidget();
       
  3563 
       
  3564         if (mouseGrabber && activePopupWidget && leave == activePopupWidget)
       
  3565             enter = mouseGrabber;
       
  3566         else if (enter != widget && mouseGrabber) {
       
  3567             if (!widget->rect().contains(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x,
       
  3568                                                                             event->xcrossing.y))))
       
  3569                 break;
       
  3570         }
       
  3571 
       
  3572         QApplicationPrivate::dispatchEnterLeave(enter, leave);
       
  3573         qt_last_mouse_receiver = enter;
       
  3574 
       
  3575         if (enter && QApplicationPrivate::tryModalHelper(enter, 0)) {
       
  3576             QWidget *nativeEnter = enter->internalWinId() ? enter : enter->nativeParentWidget();
       
  3577             curWin = nativeEnter->internalWinId();
       
  3578             static_cast<QETWidget *>(nativeEnter)->translateMouseEvent(&ev); //we don't get MotionNotify, emulate it
       
  3579         } else {
       
  3580             curWin = 0;
       
  3581             qt_last_mouse_receiver = 0;
       
  3582         }
       
  3583     }
       
  3584         break;
       
  3585 
       
  3586     case UnmapNotify:                                // window hidden
       
  3587         if (widget->isWindow()) {
       
  3588             Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
       
  3589             widget->d_func()->topData()->waitingForMapNotify = 0;
       
  3590 
       
  3591             if (widget->windowType() != Qt::Popup && !widget->testAttribute(Qt::WA_DontShowOnScreen)) {
       
  3592                 widget->setAttribute(Qt::WA_Mapped, false);
       
  3593                 if (widget->isVisible()) {
       
  3594                     widget->d_func()->topData()->spont_unmapped = 1;
       
  3595                     QHideEvent e;
       
  3596                     QApplication::sendSpontaneousEvent(widget, &e);
       
  3597                     widget->d_func()->hideChildren(true);
       
  3598                 }
       
  3599             }
       
  3600 
       
  3601             if (!widget->d_func()->topData()->validWMState && X11->deferred_map.removeAll(widget))
       
  3602                 widget->doDeferredMap();
       
  3603         }
       
  3604         break;
       
  3605 
       
  3606     case MapNotify:                                // window shown
       
  3607         if (widget->isWindow()) {
       
  3608             widget->d_func()->topData()->waitingForMapNotify = 0;
       
  3609 
       
  3610             if (widget->windowType() != Qt::Popup) {
       
  3611                 widget->setAttribute(Qt::WA_Mapped);
       
  3612                 if (widget->d_func()->topData()->spont_unmapped) {
       
  3613                     widget->d_func()->topData()->spont_unmapped = 0;
       
  3614                     widget->d_func()->showChildren(true);
       
  3615                     QShowEvent e;
       
  3616                     QApplication::sendSpontaneousEvent(widget, &e);
       
  3617 
       
  3618                     // show() must have been called on this widget in
       
  3619                     // order to reach this point, but we could have
       
  3620                     // cleared these 2 attributes in case something
       
  3621                     // previously forced us into WithdrawnState
       
  3622                     // (e.g. kdocker)
       
  3623                     widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
       
  3624                     widget->setAttribute(Qt::WA_WState_Visible, true);
       
  3625                 }
       
  3626             }
       
  3627         }
       
  3628         break;
       
  3629 
       
  3630     case ClientMessage:                        // client message
       
  3631         return x11ClientMessage(widget,event,False);
       
  3632 
       
  3633     case ReparentNotify: {                      // window manager reparents
       
  3634         // compress old reparent events to self
       
  3635         XEvent ev;
       
  3636         while (XCheckTypedWindowEvent(X11->display,
       
  3637                                       widget->effectiveWinId(),
       
  3638                                       ReparentNotify,
       
  3639                                       &ev)) {
       
  3640             if (ev.xreparent.window != ev.xreparent.event) {
       
  3641                 XPutBackEvent(X11->display, &ev);
       
  3642                 break;
       
  3643             }
       
  3644         }
       
  3645         if (widget->isWindow()) {
       
  3646             QTLWExtra *topData = widget->d_func()->topData();
       
  3647 
       
  3648             // store the parent. Useful for many things, embedding for instance.
       
  3649             topData->parentWinId = event->xreparent.parent;
       
  3650 
       
  3651             // the widget frame strut should also be invalidated
       
  3652             widget->data->fstrut_dirty = 1;
       
  3653 
       
  3654             // work around broken window managers... if we get a
       
  3655             // ReparentNotify before the MapNotify, we assume that
       
  3656             // we're being managed by a reparenting window
       
  3657             // manager.
       
  3658             //
       
  3659             // however, the WM_STATE property may not have been set
       
  3660             // yet, but we are going to assume that it will
       
  3661             // be... otherwise we could try to map again after getting
       
  3662             // an UnmapNotify... which could then, in turn, trigger a
       
  3663             // race in the window manager which causes the window to
       
  3664             // disappear when it really should be hidden.
       
  3665             if (topData->waitingForMapNotify && !topData->validWMState) {
       
  3666                 topData->waitingForMapNotify = 0;
       
  3667                 topData->validWMState = 1;
       
  3668             }
       
  3669 
       
  3670             if (X11->focus_model != QX11Data::FM_Unknown) {
       
  3671                 // toplevel reparented...
       
  3672                 QWidget *newparent = QWidget::find(event->xreparent.parent);
       
  3673                 if (! newparent || (newparent->windowType() == Qt::Desktop)) {
       
  3674                     // we dont' know about the new parent (or we've been
       
  3675                     // reparented to root), perhaps a window manager
       
  3676                     // has been (re)started?  reset the focus model to unknown
       
  3677                     X11->focus_model = QX11Data::FM_Unknown;
       
  3678                 }
       
  3679             }
       
  3680         }
       
  3681         break;
       
  3682     }
       
  3683     case SelectionRequest: {
       
  3684         XSelectionRequestEvent *req = &event->xselectionrequest;
       
  3685         if (! req)
       
  3686             break;
       
  3687 
       
  3688         if (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)) {
       
  3689             X11->xdndHandleSelectionRequest(req);
       
  3690 
       
  3691         } else if (qt_clipboard) {
       
  3692             QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
       
  3693             QApplication::sendSpontaneousEvent(qt_clipboard, &e);
       
  3694         }
       
  3695         break;
       
  3696     }
       
  3697     case SelectionClear: {
       
  3698         XSelectionClearEvent *req = &event->xselectionclear;
       
  3699         // don't deliver dnd events to the clipboard, it gets confused
       
  3700         if (! req || (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)))
       
  3701             break;
       
  3702 
       
  3703         if (qt_clipboard && !X11->use_xfixes) {
       
  3704             QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
       
  3705             QApplication::sendSpontaneousEvent(qt_clipboard, &e);
       
  3706         }
       
  3707         break;
       
  3708     }
       
  3709 
       
  3710     case SelectionNotify: {
       
  3711         XSelectionEvent *req = &event->xselection;
       
  3712         // don't deliver dnd events to the clipboard, it gets confused
       
  3713         if (! req || (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)))
       
  3714             break;
       
  3715 
       
  3716         if (qt_clipboard) {
       
  3717             QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
       
  3718             QApplication::sendSpontaneousEvent(qt_clipboard, &e);
       
  3719         }
       
  3720         break;
       
  3721     }
       
  3722     case PropertyNotify:
       
  3723         // some properties changed
       
  3724         if (event->xproperty.window == QX11Info::appRootWindow(0)) {
       
  3725             // root properties for the first screen
       
  3726             if (!X11->use_xfixes && event->xproperty.atom == ATOM(_QT_CLIPBOARD_SENTINEL)) {
       
  3727                 if (qt_check_clipboard_sentinel()) {
       
  3728                     emit clipboard()->changed(QClipboard::Clipboard);
       
  3729                     emit clipboard()->dataChanged();
       
  3730                 }
       
  3731             } else if (!X11->use_xfixes && event->xproperty.atom == ATOM(_QT_SELECTION_SENTINEL)) {
       
  3732                 if (qt_check_selection_sentinel()) {
       
  3733                     emit clipboard()->changed(QClipboard::Selection);
       
  3734                     emit clipboard()->selectionChanged();
       
  3735                 }
       
  3736             } else if (QApplicationPrivate::obey_desktop_settings) {
       
  3737                 if (event->xproperty.atom == ATOM(RESOURCE_MANAGER))
       
  3738                     qt_set_x11_resources();
       
  3739                 else if (event->xproperty.atom == ATOM(_QT_SETTINGS_TIMESTAMP))
       
  3740                     qt_set_x11_resources();
       
  3741             }
       
  3742         }
       
  3743         if (event->xproperty.window == QX11Info::appRootWindow()) {
       
  3744             // root properties for the default screen
       
  3745             if (event->xproperty.atom == ATOM(_QT_INPUT_ENCODING)) {
       
  3746                 qt_set_input_encoding();
       
  3747             } else if (event->xproperty.atom == ATOM(_NET_SUPPORTED)) {
       
  3748                 qt_get_net_supported();
       
  3749             } else if (event->xproperty.atom == ATOM(_NET_VIRTUAL_ROOTS)) {
       
  3750                 qt_get_net_virtual_roots();
       
  3751             } else if (event->xproperty.atom == ATOM(_NET_WORKAREA)) {
       
  3752                 qt_desktopwidget_update_workarea();
       
  3753             }
       
  3754         } else if (widget) {
       
  3755             widget->translatePropertyEvent(event);
       
  3756         }  else {
       
  3757             return -1; // don't know this window
       
  3758         }
       
  3759         break;
       
  3760 
       
  3761     default:
       
  3762         break;
       
  3763     }
       
  3764 
       
  3765     return 0;
       
  3766 }
       
  3767 
       
  3768 bool QApplication::x11EventFilter(XEvent *)
       
  3769 {
       
  3770     return false;
       
  3771 }
       
  3772 
       
  3773 
       
  3774 
       
  3775 /*****************************************************************************
       
  3776   Modal widgets; Since Xlib has little support for this we roll our own
       
  3777   modal widget mechanism.
       
  3778   A modal widget without a parent becomes application-modal.
       
  3779   A modal widget with a parent becomes modal to its parent and grandparents..
       
  3780 
       
  3781   QApplicationPrivate::enterModal()
       
  3782         Enters modal state
       
  3783         Arguments:
       
  3784             QWidget *widget        A modal widget
       
  3785 
       
  3786   QApplicationPrivate::leaveModal()
       
  3787         Leaves modal state for a widget
       
  3788         Arguments:
       
  3789             QWidget *widget        A modal widget
       
  3790  *****************************************************************************/
       
  3791 
       
  3792 bool QApplicationPrivate::modalState()
       
  3793 {
       
  3794     return app_do_modal;
       
  3795 }
       
  3796 
       
  3797 void QApplicationPrivate::enterModal_sys(QWidget *widget)
       
  3798 {
       
  3799     if (!qt_modal_stack)
       
  3800         qt_modal_stack = new QWidgetList;
       
  3801 
       
  3802     QWidget *leave = qt_last_mouse_receiver;
       
  3803     if (!leave)
       
  3804         leave = QWidget::find((WId)curWin);
       
  3805     QApplicationPrivate::dispatchEnterLeave(0, leave);
       
  3806     qt_modal_stack->insert(0, widget);
       
  3807     app_do_modal = true;
       
  3808     curWin = 0;
       
  3809     qt_last_mouse_receiver = 0;
       
  3810 }
       
  3811 
       
  3812 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
       
  3813 {
       
  3814     if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
       
  3815         if (qt_modal_stack->isEmpty()) {
       
  3816             delete qt_modal_stack;
       
  3817             qt_modal_stack = 0;
       
  3818             QPoint p(QCursor::pos());
       
  3819             QWidget* w = QApplication::widgetAt(p.x(), p.y());
       
  3820             QWidget *leave = qt_last_mouse_receiver;
       
  3821             if (!leave)
       
  3822                 leave = QWidget::find((WId)curWin);
       
  3823             if (QWidget *grabber = QWidget::mouseGrabber()) {
       
  3824                 w = grabber;
       
  3825                 if (leave == w)
       
  3826                     leave = 0;
       
  3827             }
       
  3828             QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event
       
  3829             curWin = w ? w->effectiveWinId() : 0;
       
  3830             qt_last_mouse_receiver = w;
       
  3831         }
       
  3832     }
       
  3833     app_do_modal = qt_modal_stack != 0;
       
  3834 }
       
  3835 
       
  3836 bool qt_try_modal(QWidget *widget, XEvent *event)
       
  3837 {
       
  3838     if (qt_xdnd_dragging) {
       
  3839         // allow mouse events while DnD is active
       
  3840         switch (event->type) {
       
  3841         case ButtonPress:
       
  3842         case ButtonRelease:
       
  3843         case MotionNotify:
       
  3844             return true;
       
  3845         default:
       
  3846             break;
       
  3847         }
       
  3848     }
       
  3849 
       
  3850     // allow mouse release events to be sent to widgets that have been pressed
       
  3851     if (event->type == ButtonRelease) {
       
  3852         QWidget *alienWidget = widget->childAt(widget->mapFromGlobal(QPoint(event->xbutton.x_root,
       
  3853                                                                             event->xbutton.y_root)));
       
  3854         if (widget == qt_button_down || (alienWidget && alienWidget == qt_button_down))
       
  3855             return true;
       
  3856     }
       
  3857 
       
  3858     if (QApplicationPrivate::tryModalHelper(widget))
       
  3859         return true;
       
  3860 
       
  3861     // disallow mouse/key events
       
  3862     switch (event->type) {
       
  3863     case ButtonPress:
       
  3864     case ButtonRelease:
       
  3865     case MotionNotify:
       
  3866     case XKeyPress:
       
  3867     case XKeyRelease:
       
  3868     case EnterNotify:
       
  3869     case LeaveNotify:
       
  3870     case ClientMessage:
       
  3871         return false;
       
  3872     default:
       
  3873         break;
       
  3874     }
       
  3875 
       
  3876     return true;
       
  3877 }
       
  3878 
       
  3879 
       
  3880 /*****************************************************************************
       
  3881   Popup widget mechanism
       
  3882 
       
  3883   openPopup()
       
  3884         Adds a widget to the list of popup widgets
       
  3885         Arguments:
       
  3886             QWidget *widget        The popup widget to be added
       
  3887 
       
  3888   closePopup()
       
  3889         Removes a widget from the list of popup widgets
       
  3890         Arguments:
       
  3891             QWidget *widget        The popup widget to be removed
       
  3892  *****************************************************************************/
       
  3893 
       
  3894 
       
  3895 static int openPopupCount = 0;
       
  3896 void QApplicationPrivate::openPopup(QWidget *popup)
       
  3897 {
       
  3898     Q_Q(QApplication);
       
  3899     openPopupCount++;
       
  3900     if (!QApplicationPrivate::popupWidgets) {                        // create list
       
  3901         QApplicationPrivate::popupWidgets = new QWidgetList;
       
  3902     }
       
  3903     QApplicationPrivate::popupWidgets->append(popup);                // add to end of list
       
  3904     Display *dpy = X11->display;
       
  3905     if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard
       
  3906         Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
       
  3907         int r = XGrabKeyboard(dpy, popup->effectiveWinId(), false,
       
  3908                               GrabModeAsync, GrabModeAsync, X11->time);
       
  3909         if ((popupGrabOk = (r == GrabSuccess))) {
       
  3910             r = XGrabPointer(dpy, popup->effectiveWinId(), true,
       
  3911                              (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
       
  3912                               | EnterWindowMask | LeaveWindowMask | PointerMotionMask),
       
  3913                              GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time);
       
  3914             if (!(popupGrabOk = (r == GrabSuccess))) {
       
  3915                 // transfer grab back to the keyboard grabber if any
       
  3916                 if (QWidgetPrivate::keyboardGrabber != 0)
       
  3917                     QWidgetPrivate::keyboardGrabber->grabKeyboard();
       
  3918                 else
       
  3919                     XUngrabKeyboard(dpy, X11->time);
       
  3920             }
       
  3921         }
       
  3922     }
       
  3923 
       
  3924     // popups are not focus-handled by the window system (the first
       
  3925     // popup grabbed the keyboard), so we have to do that manually: A
       
  3926     // new popup gets the focus
       
  3927     if (popup->focusWidget()) {
       
  3928         popup->focusWidget()->setFocus(Qt::PopupFocusReason);
       
  3929     } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
       
  3930         if (QWidget *fw = QApplication::focusWidget()) {
       
  3931             QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
       
  3932             q->sendEvent(fw, &e);
       
  3933         }
       
  3934     }
       
  3935 }
       
  3936 
       
  3937 void QApplicationPrivate::closePopup(QWidget *popup)
       
  3938 {
       
  3939     Q_Q(QApplication);
       
  3940     if (!QApplicationPrivate::popupWidgets)
       
  3941         return;
       
  3942     QApplicationPrivate::popupWidgets->removeAll(popup);
       
  3943     if (popup == qt_popup_down) {
       
  3944         qt_button_down = 0;
       
  3945         qt_popup_down = 0;
       
  3946     }
       
  3947     if (QApplicationPrivate::popupWidgets->count() == 0) {                // this was the last popup
       
  3948         delete QApplicationPrivate::popupWidgets;
       
  3949         QApplicationPrivate::popupWidgets = 0;
       
  3950         if (!qt_nograb() && popupGrabOk) {        // grabbing not disabled
       
  3951             Display *dpy = X11->display;
       
  3952             if (popup->geometry().contains(QPoint(mouseGlobalXPos, mouseGlobalYPos))
       
  3953                 || popup->testAttribute(Qt::WA_NoMouseReplay)) {
       
  3954                 // mouse release event or inside
       
  3955                 replayPopupMouseEvent = false;
       
  3956             } else {                                // mouse press event
       
  3957                 mouseButtonPressTime -= 10000;        // avoid double click
       
  3958                 replayPopupMouseEvent = true;
       
  3959             }
       
  3960             // transfer grab back to mouse grabber if any, otherwise release the grab
       
  3961             if (QWidgetPrivate::mouseGrabber != 0)
       
  3962                 QWidgetPrivate::mouseGrabber->grabMouse();
       
  3963             else
       
  3964                 XUngrabPointer(dpy, X11->time);
       
  3965 
       
  3966             // transfer grab back to keyboard grabber if any, otherwise release the grab
       
  3967             if (QWidgetPrivate::keyboardGrabber != 0)
       
  3968                 QWidgetPrivate::keyboardGrabber->grabKeyboard();
       
  3969             else
       
  3970                 XUngrabKeyboard(dpy, X11->time);
       
  3971 
       
  3972             XFlush(dpy);
       
  3973         }
       
  3974         if (QApplicationPrivate::active_window) {
       
  3975             if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
       
  3976                 if (fw != QApplication::focusWidget()) {
       
  3977                     fw->setFocus(Qt::PopupFocusReason);
       
  3978                 } else {
       
  3979                     QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
       
  3980                     q->sendEvent(fw, &e);
       
  3981                 }
       
  3982             }
       
  3983         }
       
  3984     } else {
       
  3985         // popups are not focus-handled by the window system (the
       
  3986         // first popup grabbed the keyboard), so we have to do that
       
  3987         // manually: A popup was closed, so the previous popup gets
       
  3988         // the focus.
       
  3989         QWidget* aw = QApplicationPrivate::popupWidgets->last();
       
  3990         if (QWidget *fw = aw->focusWidget())
       
  3991             fw->setFocus(Qt::PopupFocusReason);
       
  3992 
       
  3993         // regrab the keyboard and mouse in case 'popup' lost the grab
       
  3994         if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard
       
  3995             Display *dpy = X11->display;
       
  3996             Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created));
       
  3997             int r = XGrabKeyboard(dpy, aw->effectiveWinId(), false,
       
  3998                                   GrabModeAsync, GrabModeAsync, X11->time);
       
  3999             if ((popupGrabOk = (r == GrabSuccess))) {
       
  4000                 r = XGrabPointer(dpy, aw->effectiveWinId(), true,
       
  4001                                  (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
       
  4002                                   | EnterWindowMask | LeaveWindowMask | PointerMotionMask),
       
  4003                                  GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time);
       
  4004                 if (!(popupGrabOk = (r == GrabSuccess))) {
       
  4005                     // transfer grab back to keyboard grabber
       
  4006                     if (QWidgetPrivate::keyboardGrabber != 0)
       
  4007                         QWidgetPrivate::keyboardGrabber->grabKeyboard();
       
  4008                     else
       
  4009                         XUngrabKeyboard(dpy, X11->time);
       
  4010                 }
       
  4011             }
       
  4012         }
       
  4013     }
       
  4014 }
       
  4015 
       
  4016 /*****************************************************************************
       
  4017   Event translation; translates X11 events to Qt events
       
  4018  *****************************************************************************/
       
  4019 
       
  4020 //
       
  4021 // Mouse event translation
       
  4022 //
       
  4023 // Xlib doesn't give mouse double click events, so we generate them by
       
  4024 // comparing window, time and position between two mouse press events.
       
  4025 //
       
  4026 
       
  4027 static Qt::MouseButtons translateMouseButtons(int s)
       
  4028 {
       
  4029     Qt::MouseButtons ret = 0;
       
  4030     if (s & Button1Mask)
       
  4031         ret |= Qt::LeftButton;
       
  4032     if (s & Button2Mask)
       
  4033         ret |= Qt::MidButton;
       
  4034     if (s & Button3Mask)
       
  4035         ret |= Qt::RightButton;
       
  4036     return ret;
       
  4037 }
       
  4038 
       
  4039 Qt::KeyboardModifiers QX11Data::translateModifiers(int s)
       
  4040 {
       
  4041     Qt::KeyboardModifiers ret = 0;
       
  4042     if (s & ShiftMask)
       
  4043         ret |= Qt::ShiftModifier;
       
  4044     if (s & ControlMask)
       
  4045         ret |= Qt::ControlModifier;
       
  4046     if (s & qt_alt_mask)
       
  4047         ret |= Qt::AltModifier;
       
  4048     if (s & qt_meta_mask)
       
  4049         ret |= Qt::MetaModifier;
       
  4050     if (s & qt_mode_switch_mask)
       
  4051         ret |= Qt::GroupSwitchModifier;
       
  4052     return ret;
       
  4053 }
       
  4054 
       
  4055 bool QETWidget::translateMouseEvent(const XEvent *event)
       
  4056 {
       
  4057     if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
       
  4058         Q_ASSERT(internalWinId());
       
  4059 
       
  4060     Q_D(QWidget);
       
  4061     QEvent::Type type;                                // event parameters
       
  4062     QPoint pos;
       
  4063     QPoint globalPos;
       
  4064     Qt::MouseButton button = Qt::NoButton;
       
  4065     Qt::MouseButtons buttons;
       
  4066     Qt::KeyboardModifiers modifiers;
       
  4067     XEvent nextEvent;
       
  4068 
       
  4069     if (qt_sm_blockUserInput) // block user interaction during session management
       
  4070         return true;
       
  4071 
       
  4072     if (event->type == MotionNotify) { // mouse move
       
  4073         if (event->xmotion.root != RootWindow(X11->display, x11Info().screen()) &&
       
  4074             ! qt_xdnd_dragging)
       
  4075             return false;
       
  4076 
       
  4077         XMotionEvent lastMotion = event->xmotion;
       
  4078         while(XPending(X11->display))  { // compress mouse moves
       
  4079             XNextEvent(X11->display, &nextEvent);
       
  4080             if (nextEvent.type == ConfigureNotify
       
  4081                 || nextEvent.type == PropertyNotify
       
  4082                 || nextEvent.type == Expose
       
  4083                 || nextEvent.type == GraphicsExpose
       
  4084                 || nextEvent.type == NoExpose
       
  4085                 || nextEvent.type == KeymapNotify
       
  4086                 || ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
       
  4087                     && qt_button_down == this)
       
  4088                 || (nextEvent.type == ClientMessage
       
  4089                     && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) ||
       
  4090                     (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) &&
       
  4091                      (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) {
       
  4092                 qApp->x11ProcessEvent(&nextEvent);
       
  4093                 continue;
       
  4094             } else if (nextEvent.type != MotionNotify ||
       
  4095                        nextEvent.xmotion.window != event->xmotion.window ||
       
  4096                        nextEvent.xmotion.state != event->xmotion.state) {
       
  4097                 XPutBackEvent(X11->display, &nextEvent);
       
  4098                 break;
       
  4099             }
       
  4100             if (!qt_x11EventFilter(&nextEvent)
       
  4101                 && !x11Event(&nextEvent)) // send event through filter
       
  4102                 lastMotion = nextEvent.xmotion;
       
  4103             else
       
  4104                 break;
       
  4105         }
       
  4106         type = QEvent::MouseMove;
       
  4107         pos.rx() = lastMotion.x;
       
  4108         pos.ry() = lastMotion.y;
       
  4109         pos = d->mapFromWS(pos);
       
  4110         globalPos.rx() = lastMotion.x_root;
       
  4111         globalPos.ry() = lastMotion.y_root;
       
  4112         buttons = translateMouseButtons(lastMotion.state);
       
  4113         modifiers = X11->translateModifiers(lastMotion.state);
       
  4114         if (qt_button_down && !buttons)
       
  4115             qt_button_down = 0;
       
  4116     } else if (event->type == EnterNotify || event->type == LeaveNotify) {
       
  4117         XEvent *xevent = (XEvent *)event;
       
  4118         //unsigned int xstate = event->xcrossing.state;
       
  4119         type = QEvent::MouseMove;
       
  4120         pos.rx() = xevent->xcrossing.x;
       
  4121         pos.ry() = xevent->xcrossing.y;
       
  4122         pos = d->mapFromWS(pos);
       
  4123         globalPos.rx() = xevent->xcrossing.x_root;
       
  4124         globalPos.ry() = xevent->xcrossing.y_root;
       
  4125         buttons = translateMouseButtons(xevent->xcrossing.state);
       
  4126         modifiers = X11->translateModifiers(xevent->xcrossing.state);
       
  4127         if (qt_button_down && !buttons)
       
  4128             qt_button_down = 0;
       
  4129         if (qt_button_down)
       
  4130             return true;
       
  4131     } else {                                        // button press or release
       
  4132         pos.rx() = event->xbutton.x;
       
  4133         pos.ry() = event->xbutton.y;
       
  4134         pos = d->mapFromWS(pos);
       
  4135         globalPos.rx() = event->xbutton.x_root;
       
  4136         globalPos.ry() = event->xbutton.y_root;
       
  4137         buttons = translateMouseButtons(event->xbutton.state);
       
  4138         modifiers = X11->translateModifiers(event->xbutton.state);
       
  4139         switch (event->xbutton.button) {
       
  4140         case Button1: button = Qt::LeftButton; break;
       
  4141         case Button2: button = Qt::MidButton; break;
       
  4142         case Button3: button = Qt::RightButton; break;
       
  4143         case Button4:
       
  4144         case Button5:
       
  4145         case 6:
       
  4146         case 7:
       
  4147             // the fancy mouse wheel.
       
  4148 
       
  4149             // We are only interested in ButtonPress.
       
  4150             if (event->type == ButtonPress){
       
  4151                 // compress wheel events (the X Server will simply
       
  4152                 // send a button press for each single notch,
       
  4153                 // regardless whether the application can catch up
       
  4154                 // or not)
       
  4155                 int delta = 1;
       
  4156                 XEvent xevent;
       
  4157                 while (XCheckTypedWindowEvent(X11->display, effectiveWinId(), ButtonPress, &xevent)){
       
  4158                     if (xevent.xbutton.button != event->xbutton.button){
       
  4159                         XPutBackEvent(X11->display, &xevent);
       
  4160                         break;
       
  4161                     }
       
  4162                     delta++;
       
  4163                 }
       
  4164 
       
  4165                 // the delta is defined as multiples of
       
  4166                 // WHEEL_DELTA, which is set to 120. Future wheels
       
  4167                 // may offer a finer-resolution. A positive delta
       
  4168                 // indicates forward rotation, a negative one
       
  4169                 // backward rotation respectively.
       
  4170                 int btn = event->xbutton.button;
       
  4171                 delta *= 120 * ((btn == Button4 || btn == 6) ? 1 : -1);
       
  4172                 bool hor = (((btn == Button4 || btn == Button5) && (modifiers & Qt::AltModifier)) ||
       
  4173                             (btn == 6 || btn == 7));
       
  4174                 translateWheelEvent(globalPos.x(), globalPos.y(), delta, buttons,
       
  4175                                     modifiers, (hor) ? Qt::Horizontal: Qt::Vertical);
       
  4176             }
       
  4177             return true;
       
  4178         case 8: button = Qt::XButton1; break;
       
  4179         case 9: button = Qt::XButton2; break;
       
  4180         }
       
  4181         if (event->type == ButtonPress) {        // mouse button pressed
       
  4182             buttons |= button;
       
  4183 #if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET)
       
  4184             QTabletDeviceDataList *tablets = qt_tablet_devices();
       
  4185             for (int i = 0; i < tablets->size(); ++i) {
       
  4186                 QTabletDeviceData &tab = tablets->operator[](i);
       
  4187                 XEvent myEv;
       
  4188                 if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) {
       
  4189                         if (translateXinputEvent(&myEv, &tab)) {
       
  4190                             //Spontaneous event sent.  Check if we need to continue.
       
  4191                             if (qt_tabletChokeMouse) {
       
  4192                                 qt_tabletChokeMouse = false;
       
  4193                                 return false;
       
  4194                             }
       
  4195                         }
       
  4196                 }
       
  4197             }
       
  4198 #endif
       
  4199             if (!qt_button_down) {
       
  4200                 qt_button_down = childAt(pos);        //magic for masked widgets
       
  4201                 if (!qt_button_down)
       
  4202                     qt_button_down = this;
       
  4203             }
       
  4204             if (mouseActWindow == event->xbutton.window &&
       
  4205                 mouseButtonPressed == button &&
       
  4206                 (long)event->xbutton.time -(long)mouseButtonPressTime
       
  4207                 < QApplication::doubleClickInterval() &&
       
  4208                 qAbs(event->xbutton.x - mouseXPos) < 5 &&
       
  4209                 qAbs(event->xbutton.y - mouseYPos) < 5) {
       
  4210                 type = QEvent::MouseButtonDblClick;
       
  4211                 mouseButtonPressTime -= 2000;        // no double-click next time
       
  4212             } else {
       
  4213                 type = QEvent::MouseButtonPress;
       
  4214                 mouseButtonPressTime = event->xbutton.time;
       
  4215             }
       
  4216             mouseButtonPressed = button;        // save event params for
       
  4217             mouseXPos = event->xbutton.x;                // future double click tests
       
  4218             mouseYPos = event->xbutton.y;
       
  4219             mouseGlobalXPos = globalPos.x();
       
  4220             mouseGlobalYPos = globalPos.y();
       
  4221         } else {                                // mouse button released
       
  4222             buttons &= ~button;
       
  4223 #if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET)
       
  4224             QTabletDeviceDataList *tablets = qt_tablet_devices();
       
  4225             for (int i = 0; i < tablets->size(); ++i) {
       
  4226                 QTabletDeviceData &tab = tablets->operator[](i);
       
  4227                 XEvent myEv;
       
  4228                 if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) {
       
  4229                         if (translateXinputEvent(&myEv, &tab)) {
       
  4230                             //Spontaneous event sent.  Check if we need to continue.
       
  4231                             if (qt_tabletChokeMouse) {
       
  4232                                 qt_tabletChokeMouse = false;
       
  4233                                 return false;
       
  4234                             }
       
  4235                         }
       
  4236                 }
       
  4237             }
       
  4238 #endif
       
  4239             type = QEvent::MouseButtonRelease;
       
  4240         }
       
  4241     }
       
  4242     mouseActWindow = effectiveWinId();                        // save some event params
       
  4243     mouseButtonState = buttons;
       
  4244     if (type == 0)                                // don't send event
       
  4245         return false;
       
  4246 
       
  4247     if (qApp->d_func()->inPopupMode()) {                        // in popup mode
       
  4248         QWidget *activePopupWidget = qApp->activePopupWidget();
       
  4249         QWidget *popup = qApp->activePopupWidget();
       
  4250         if (popup != this) {
       
  4251             if (event->type == LeaveNotify)
       
  4252                 return false;
       
  4253             if ((windowType() == Qt::Popup) && rect().contains(pos) && 0)
       
  4254                 popup = this;
       
  4255             else                                // send to last popup
       
  4256                 pos = popup->mapFromGlobal(globalPos);
       
  4257         }
       
  4258         bool releaseAfter = false;
       
  4259         QWidget *popupChild  = popup->childAt(pos);
       
  4260 
       
  4261         if (popup != qt_popup_down){
       
  4262             qt_button_down = 0;
       
  4263             qt_popup_down = 0;
       
  4264         }
       
  4265 
       
  4266         switch (type) {
       
  4267         case QEvent::MouseButtonPress:
       
  4268         case QEvent::MouseButtonDblClick:
       
  4269             qt_button_down = popupChild;
       
  4270             qt_popup_down = popup;
       
  4271             break;
       
  4272         case QEvent::MouseButtonRelease:
       
  4273             releaseAfter = true;
       
  4274             break;
       
  4275         default:
       
  4276             break;                                // nothing for mouse move
       
  4277         }
       
  4278 
       
  4279         int oldOpenPopupCount = openPopupCount;
       
  4280 
       
  4281         if (popup->isEnabled()) {
       
  4282             // deliver event
       
  4283             replayPopupMouseEvent = false;
       
  4284             QWidget *receiver = popup;
       
  4285             QPoint widgetPos = pos;
       
  4286             if (qt_button_down)
       
  4287                 receiver = qt_button_down;
       
  4288             else if (popupChild)
       
  4289                 receiver = popupChild;
       
  4290             if (receiver != popup)
       
  4291                 widgetPos = receiver->mapFromGlobal(globalPos);
       
  4292             QWidget *alien = childAt(mapFromGlobal(globalPos));
       
  4293             QMouseEvent e(type, widgetPos, globalPos, button, buttons, modifiers);
       
  4294             QApplicationPrivate::sendMouseEvent(receiver, &e, alien, this, &qt_button_down, qt_last_mouse_receiver);
       
  4295         } else {
       
  4296             // close disabled popups when a mouse button is pressed or released
       
  4297             switch (type) {
       
  4298             case QEvent::MouseButtonPress:
       
  4299             case QEvent::MouseButtonDblClick:
       
  4300             case QEvent::MouseButtonRelease:
       
  4301                 popup->close();
       
  4302                 break;
       
  4303             default:
       
  4304                 break;
       
  4305             }
       
  4306         }
       
  4307 
       
  4308         if (qApp->activePopupWidget() != activePopupWidget
       
  4309             && replayPopupMouseEvent) {
       
  4310             // the active popup was closed, replay the mouse event
       
  4311             if (!(windowType() == Qt::Popup)) {
       
  4312 #if 1
       
  4313                 qt_button_down = 0;
       
  4314 #else
       
  4315                 if (buttons == button)
       
  4316                     qt_button_down = this;
       
  4317                 QMouseEvent e(type, mapFromGlobal(globalPos), globalPos, button,
       
  4318                               buttons, modifiers);
       
  4319                 QApplication::sendSpontaneousEvent(this, &e);
       
  4320 
       
  4321                 if (type == QEvent::MouseButtonPress
       
  4322                     && button == Qt::RightButton
       
  4323                     && (openPopupCount == oldOpenPopupCount)) {
       
  4324                     QContextMenuEvent e(QContextMenuEvent::Mouse, mapFromGlobal(globalPos),
       
  4325                                         globalPos, modifiers);
       
  4326                     QApplication::sendSpontaneousEvent(this, &e);
       
  4327                 }
       
  4328 #endif
       
  4329             }
       
  4330             replayPopupMouseEvent = false;
       
  4331         } else if (type == QEvent::MouseButtonPress
       
  4332                    && button == Qt::RightButton
       
  4333                    && (openPopupCount == oldOpenPopupCount)) {
       
  4334             QWidget *popupEvent = popup;
       
  4335             if (qt_button_down)
       
  4336                 popupEvent = qt_button_down;
       
  4337             else if(popupChild)
       
  4338                 popupEvent = popupChild;
       
  4339             QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers);
       
  4340             QApplication::sendSpontaneousEvent(popupEvent, &e);
       
  4341         }
       
  4342 
       
  4343         if (releaseAfter) {
       
  4344             qt_button_down = 0;
       
  4345             qt_popup_down = 0;
       
  4346         }
       
  4347     } else {
       
  4348         QWidget *alienWidget = childAt(pos);
       
  4349         QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type, buttons,
       
  4350                                                                  qt_button_down, alienWidget);
       
  4351         if (!widget) {
       
  4352             if (type == QEvent::MouseButtonRelease)
       
  4353                 QApplicationPrivate::mouse_buttons &= ~button;
       
  4354             return false; // don't send event
       
  4355         }
       
  4356 
       
  4357         int oldOpenPopupCount = openPopupCount;
       
  4358         QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
       
  4359         QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
       
  4360                                             qt_last_mouse_receiver);
       
  4361         if (type == QEvent::MouseButtonPress
       
  4362             && button == Qt::RightButton
       
  4363             && (openPopupCount == oldOpenPopupCount)) {
       
  4364             QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers);
       
  4365             QApplication::sendSpontaneousEvent(widget, &e);
       
  4366         }
       
  4367     }
       
  4368     return true;
       
  4369 }
       
  4370 
       
  4371 
       
  4372 //
       
  4373 // Wheel event translation
       
  4374 //
       
  4375 bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta,
       
  4376                                     Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
       
  4377                                     Qt::Orientation orient)
       
  4378 {
       
  4379     const QPoint globalPos = QPoint(global_x, global_y);
       
  4380     QPoint pos = mapFromGlobal(globalPos);
       
  4381     QWidget *widget = childAt(pos);
       
  4382     if (!widget)
       
  4383         widget = this;
       
  4384     else if (!widget->internalWinId())
       
  4385         pos = widget->mapFromGlobal(globalPos);
       
  4386 
       
  4387 #ifdef ALIEN_DEBUG
       
  4388         qDebug() << "QETWidget::translateWheelEvent: receiver:" << widget << "pos:" << pos;
       
  4389 #endif
       
  4390 
       
  4391     // send the event to the widget or its ancestors
       
  4392     {
       
  4393         QWidget* popup = qApp->activePopupWidget();
       
  4394         if (popup && window() != popup)
       
  4395             popup->close();
       
  4396         QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
       
  4397         if (QApplication::sendSpontaneousEvent(widget, &e))
       
  4398             return true;
       
  4399     }
       
  4400 
       
  4401     // send the event to the widget that has the focus or its ancestors, if different
       
  4402     if (widget != qApp->focusWidget() && (widget = qApp->focusWidget())) {
       
  4403         if (widget && !widget->internalWinId())
       
  4404             pos = widget->mapFromGlobal(globalPos);
       
  4405         QWidget* popup = qApp->activePopupWidget();
       
  4406         if (popup && widget != popup)
       
  4407             popup->hide();
       
  4408         QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
       
  4409         if (QApplication::sendSpontaneousEvent(widget, &e))
       
  4410             return true;
       
  4411     }
       
  4412     return false;
       
  4413 }
       
  4414 
       
  4415 
       
  4416 //
       
  4417 // XInput Translation Event
       
  4418 //
       
  4419 #if !defined (QT_NO_TABLET)
       
  4420 
       
  4421 #if !defined (Q_OS_IRIX)
       
  4422 void fetchWacomToolId(int &deviceType, qint64 &serialId)
       
  4423 {
       
  4424     if (ptrWacomConfigInit == 0) // we actually have the lib
       
  4425         return;
       
  4426     WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0);
       
  4427     if (config == 0)
       
  4428         return;
       
  4429     WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData());
       
  4430     if (device == 0)
       
  4431         return;
       
  4432     unsigned keys[1];
       
  4433     int serialInt;
       
  4434     ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLSERIAL, &serialInt, 1, keys);
       
  4435     serialId = serialInt;
       
  4436     int toolId;
       
  4437     ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLID, &toolId, 1, keys);
       
  4438     switch(toolId) {
       
  4439     case 0x007: /* Mouse 4D and 2D */
       
  4440     case 0x017: /* Intuos3 2D Mouse */
       
  4441     case 0x094:
       
  4442     case 0x09c:
       
  4443         deviceType = QTabletEvent::FourDMouse;
       
  4444         break;
       
  4445     case 0x096: /* Lens cursor */
       
  4446     case 0x097: /* Intuos3 Lens cursor */
       
  4447         deviceType = QTabletEvent::Puck;
       
  4448         break;
       
  4449     case 0x0fa:
       
  4450     case 0x81b: /* Intuos3 Classic Pen Eraser */
       
  4451     case 0x82a: /* Eraser */
       
  4452     case 0x82b: /* Intuos3 Grip Pen Eraser */
       
  4453     case 0x85a:
       
  4454     case 0x91a:
       
  4455     case 0x91b: /* Intuos3 Airbrush Eraser */
       
  4456     case 0xd1a:
       
  4457         deviceType = QTabletEvent::XFreeEraser;
       
  4458         break;
       
  4459     case 0x112:
       
  4460     case 0x912:
       
  4461     case 0x913: /* Intuos3 Airbrush */
       
  4462     case 0xd12:
       
  4463         deviceType = QTabletEvent::Airbrush;
       
  4464         break;
       
  4465     case 0x012:
       
  4466     case 0x022:
       
  4467     case 0x032:
       
  4468     case 0x801: /* Intuos3 Inking pen */
       
  4469     case 0x812: /* Inking pen */
       
  4470     case 0x813: /* Intuos3 Classic Pen */
       
  4471     case 0x822: /* Pen */
       
  4472     case 0x823: /* Intuos3 Grip Pen */
       
  4473     case 0x832: /* Stroke pen */
       
  4474     case 0x842:
       
  4475     case 0x852:
       
  4476     case 0x885: /* Intuos3 Marker Pen */
       
  4477     default: /* Unknown tool */
       
  4478         deviceType = QTabletEvent::Stylus;
       
  4479     }
       
  4480 
       
  4481     /* Close device and return */
       
  4482     ptrWacomConfigCloseDevice (device);
       
  4483     ptrWacomConfigTerm(config);
       
  4484 }
       
  4485 #endif
       
  4486 
       
  4487 struct qt_tablet_motion_data
       
  4488 {
       
  4489     bool filterByWidget;
       
  4490     const QWidget *widget;
       
  4491     const QWidget *etWidget;
       
  4492     int tabletMotionType;
       
  4493     bool error; // found a reason to stop searching
       
  4494 };
       
  4495 
       
  4496 static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg)
       
  4497 {
       
  4498     qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
       
  4499     if (data->error)
       
  4500         return false;
       
  4501 
       
  4502     if (event->type == MotionNotify)
       
  4503         return true;
       
  4504 
       
  4505     data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between.
       
  4506     return false;
       
  4507 }
       
  4508 
       
  4509 static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg)
       
  4510 {
       
  4511     qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
       
  4512     if (data->error)
       
  4513         return false;
       
  4514     if (event->type == data->tabletMotionType) {
       
  4515         const XDeviceMotionEvent *const motion = reinterpret_cast<const XDeviceMotionEvent*>(event);
       
  4516         if (data->filterByWidget) {
       
  4517             const QPoint curr(motion->x, motion->y);
       
  4518             const QWidget *w = data->etWidget;
       
  4519             const QWidget *const child = w->childAt(curr);
       
  4520             if (child) {
       
  4521                 w = child;
       
  4522             }
       
  4523             if (w == data->widget)
       
  4524                 return true;
       
  4525         } else {
       
  4526             return true;
       
  4527         }
       
  4528     }
       
  4529 
       
  4530     data->error = event->type != MotionNotify; // we stop compression when another event gets in between.
       
  4531     return false;
       
  4532 }
       
  4533 
       
  4534 bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet)
       
  4535 {
       
  4536 #if defined (Q_OS_IRIX)
       
  4537     // Wacom has put defines in their wacom.h file so it would be quite wise
       
  4538     // to use them, need to think of a decent way of not using
       
  4539     // it when it doesn't exist...
       
  4540     XDeviceState *s;
       
  4541     XInputClass *iClass;
       
  4542     XValuatorState *vs;
       
  4543     int j;
       
  4544 #endif
       
  4545 
       
  4546     Q_ASSERT(tablet != 0);
       
  4547 
       
  4548     QWidget *w = this;
       
  4549     QPoint global,
       
  4550         curr;
       
  4551     QPointF hiRes;
       
  4552     qreal pressure = 0;
       
  4553     int xTilt = 0,
       
  4554         yTilt = 0,
       
  4555         z = 0;
       
  4556     qreal tangentialPressure = 0;
       
  4557     qreal rotation = 0;
       
  4558     int deviceType = QTabletEvent::NoDevice;
       
  4559     int pointerType = QTabletEvent::UnknownPointer;
       
  4560     const XDeviceMotionEvent *motion = 0;
       
  4561     XDeviceButtonEvent *button = 0;
       
  4562     const XProximityNotifyEvent *proximity = 0;
       
  4563     QEvent::Type t;
       
  4564     Qt::KeyboardModifiers modifiers = 0;
       
  4565 #if !defined (Q_OS_IRIX)
       
  4566     XID device_id;
       
  4567 #endif
       
  4568 
       
  4569     if (ev->type == tablet->xinput_motion) {
       
  4570         motion = reinterpret_cast<const XDeviceMotionEvent*>(ev);
       
  4571         t = QEvent::TabletMove;
       
  4572         global = QPoint(motion->x_root, motion->y_root);
       
  4573         curr = QPoint(motion->x, motion->y);
       
  4574 #if !defined (Q_OS_IRIX)
       
  4575         device_id = motion->deviceid;
       
  4576 #endif
       
  4577     } else if (ev->type == tablet->xinput_button_press || ev->type == tablet->xinput_button_release) {
       
  4578         if (ev->type == tablet->xinput_button_press) {
       
  4579             t = QEvent::TabletPress;
       
  4580         } else {
       
  4581             t = QEvent::TabletRelease;
       
  4582         }
       
  4583         button = (XDeviceButtonEvent*)ev;
       
  4584 
       
  4585         global = QPoint(button->x_root, button->y_root);
       
  4586         curr = QPoint(button->x, button->y);
       
  4587 #if !defined (Q_OS_IRIX)
       
  4588         device_id = button->deviceid;
       
  4589 #endif
       
  4590     } else { // Proximity
       
  4591         if (ev->type == tablet->xinput_proximity_in)
       
  4592             t = QEvent::TabletEnterProximity;
       
  4593         else
       
  4594             t = QEvent::TabletLeaveProximity;
       
  4595         proximity = (const XProximityNotifyEvent*)ev;
       
  4596 #if !defined (Q_OS_IRIX)
       
  4597         device_id = proximity->deviceid;
       
  4598 #endif
       
  4599     }
       
  4600 
       
  4601     qint64 uid = 0;
       
  4602 #if defined (Q_OS_IRIX)
       
  4603     QRect screenArea = qApp->desktop()->screenGeometry(this);
       
  4604     s = XQueryDeviceState(X11->display, static_cast<XDevice *>(tablet->device));
       
  4605     if (!s)
       
  4606         return false;
       
  4607     iClass = s->data;
       
  4608     for (j = 0; j < s->num_classes; j++) {
       
  4609         if (iClass->c_class == ValuatorClass) {
       
  4610             vs = reinterpret_cast<XValuatorState *>(iClass);
       
  4611             // figure out what device we have, based on bitmasking...
       
  4612             if (vs->valuators[WAC_TRANSDUCER_I]
       
  4613                  & WAC_TRANSDUCER_PROX_MSK) {
       
  4614                 switch (vs->valuators[WAC_TRANSDUCER_I]
       
  4615                          & WAC_TRANSDUCER_MSK) {
       
  4616                 case WAC_PUCK_ID:
       
  4617                     pointerType = QTabletEvent::Puck;
       
  4618                     break;
       
  4619                 case WAC_STYLUS_ID:
       
  4620                     pointerType = QTabletEvent::Pen;
       
  4621                     break;
       
  4622                 case WAC_ERASER_ID:
       
  4623                     pointerType = QTabletEvent::Eraser;
       
  4624                     break;
       
  4625                 }
       
  4626                 // Get a Unique Id for the device, Wacom gives us this ability
       
  4627                 uid = vs->valuators[WAC_TRANSDUCER_I] & WAC_TRANSDUCER_ID_MSK;
       
  4628                 uid = (uid << 24) | vs->valuators[WAC_SERIAL_NUM_I];
       
  4629                 switch (WAC_TRANSDUCER_I & 0x0F0600) {
       
  4630                 case 0x080200:
       
  4631                     deviceType = QTabletEvent::Stylus;
       
  4632                     break;
       
  4633                 case 0x090200:
       
  4634                     deviceType = QTabletEvent::Airbrush;
       
  4635                     break;
       
  4636                 case 0x000400:
       
  4637                     deviceType = QTabletEvent::FourDMouse;
       
  4638                     break;
       
  4639                 case 0x000600:
       
  4640                     deviceType = QTabletEvent::Puck;
       
  4641                     break;
       
  4642                 case 0x080400:
       
  4643                     deviceType = QTabletEvent::RotationStylus;
       
  4644                     break;
       
  4645                 }
       
  4646             } else {
       
  4647                 pointerType = QTabletEvent::UnknownPointer;
       
  4648                 deviceType = QTabletEvent::NoDevice;
       
  4649                 uid = 0;
       
  4650             }
       
  4651 
       
  4652             if (!proximity) {
       
  4653                 // apparently Wacom needs a cast for the +/- values to make sense
       
  4654                 xTilt = short(vs->valuators[WAC_XTILT_I]);
       
  4655                 yTilt = short(vs->valuators[WAC_YTILT_I]);
       
  4656                 pressure = vs->valuators[WAC_PRESSURE_I];
       
  4657                 if (deviceType == QTabletEvent::FourDMouse
       
  4658                         || deviceType == QTabletEvent::RotationStylus) {
       
  4659                     rotation = vs->valuators[WAC_ROTATION_I] / 64.0;
       
  4660                     if (deviceType == QTabletEvent::FourDMouse)
       
  4661                         z = vs->valuators[WAC_ZCOORD_I];
       
  4662                 } else if (deviceType == QTabletEvent::Airbrush) {
       
  4663                     tangentialPressure = vs->valuators[WAC_TAN_PRESSURE_I]
       
  4664                                             / qreal(tablet->maxTanPressure - tablet->minTanPressure);
       
  4665                 }
       
  4666 
       
  4667                 hiRes = tablet->scaleCoord(vs->valuators[WAC_XCOORD_I], vs->valuators[WAC_YCOORD_I],
       
  4668                                            screenArea.x(), screenArea.width(),
       
  4669                                            screenArea.y(), screenArea.height());
       
  4670             }
       
  4671             break;
       
  4672         }
       
  4673         iClass = reinterpret_cast<XInputClass*>(reinterpret_cast<char*>(iClass) + iClass->length);
       
  4674     }
       
  4675     XFreeDeviceState(s);
       
  4676 #else
       
  4677     QTabletDeviceDataList *tablet_list = qt_tablet_devices();
       
  4678     for (int i = 0; i < tablet_list->size(); ++i) {
       
  4679         const QTabletDeviceData &t = tablet_list->at(i);
       
  4680         if (device_id == static_cast<XDevice *>(t.device)->device_id) {
       
  4681             deviceType = t.deviceType;
       
  4682             if (t.deviceType == QTabletEvent::XFreeEraser) {
       
  4683                 deviceType = QTabletEvent::Stylus;
       
  4684                 pointerType = QTabletEvent::Eraser;
       
  4685             } else if (t.deviceType == QTabletEvent::Stylus) {
       
  4686                 pointerType = QTabletEvent::Pen;
       
  4687             }
       
  4688             break;
       
  4689         }
       
  4690     }
       
  4691 
       
  4692     fetchWacomToolId(deviceType, uid);
       
  4693 
       
  4694     QRect screenArea = qApp->desktop()->rect();
       
  4695     if (motion) {
       
  4696         xTilt = (short) motion->axis_data[3];
       
  4697         yTilt = (short) motion->axis_data[4];
       
  4698         rotation = ((short) motion->axis_data[5]) / 64.0;
       
  4699         pressure = (short) motion->axis_data[2];
       
  4700         modifiers = X11->translateModifiers(motion->state);
       
  4701         hiRes = tablet->scaleCoord(motion->axis_data[0], motion->axis_data[1],
       
  4702                                     screenArea.x(), screenArea.width(),
       
  4703                                     screenArea.y(), screenArea.height());
       
  4704     } else if (button) {
       
  4705         xTilt = (short) button->axis_data[3];
       
  4706         yTilt = (short) button->axis_data[4];
       
  4707         rotation = ((short) button->axis_data[5]) / 64.0;
       
  4708         pressure = (short) button->axis_data[2];
       
  4709         modifiers = X11->translateModifiers(button->state);
       
  4710         hiRes = tablet->scaleCoord(button->axis_data[0], button->axis_data[1],
       
  4711                                     screenArea.x(), screenArea.width(),
       
  4712                                     screenArea.y(), screenArea.height());
       
  4713     } else if (proximity) {
       
  4714         pressure = 0;
       
  4715         modifiers = 0;
       
  4716     }
       
  4717     if (deviceType == QTabletEvent::Airbrush) {
       
  4718         tangentialPressure = rotation;
       
  4719         rotation = 0.;
       
  4720     }
       
  4721 #endif
       
  4722 
       
  4723     if (tablet->widgetToGetPress) {
       
  4724         w = tablet->widgetToGetPress;
       
  4725     } else {
       
  4726         QWidget *child = w->childAt(curr);
       
  4727         if (child)
       
  4728             w = child;
       
  4729     }
       
  4730     curr = w->mapFromGlobal(global);
       
  4731 
       
  4732     if (t == QEvent::TabletPress) {
       
  4733         tablet->widgetToGetPress = w;
       
  4734     } else if (t == QEvent::TabletRelease && tablet->widgetToGetPress) {
       
  4735         w = tablet->widgetToGetPress;
       
  4736         curr = w->mapFromGlobal(global);
       
  4737         tablet->widgetToGetPress = 0;
       
  4738     }
       
  4739 
       
  4740     QTabletEvent e(t, curr, global, hiRes,
       
  4741                    deviceType, pointerType,
       
  4742                    qreal(pressure / qreal(tablet->maxPressure - tablet->minPressure)),
       
  4743                    xTilt, yTilt, tangentialPressure, rotation, z, modifiers, uid);
       
  4744     if (proximity) {
       
  4745         QApplication::sendSpontaneousEvent(qApp, &e);
       
  4746     } else {
       
  4747         QApplication::sendSpontaneousEvent(w, &e);
       
  4748         const bool accepted = e.isAccepted();
       
  4749         if (!accepted && ev->type == tablet->xinput_motion) {
       
  4750             // If the widget does not accept tablet events, we drop the next ones from the event queue
       
  4751             // for this widget so it is not overloaded with the numerous tablet events.
       
  4752             qt_tablet_motion_data tabletMotionData;
       
  4753             tabletMotionData.tabletMotionType = tablet->xinput_motion;
       
  4754             tabletMotionData.widget = w;
       
  4755             tabletMotionData.etWidget = this;
       
  4756             // if nothing is pressed, the events are filtered by position
       
  4757             tabletMotionData.filterByWidget = (tablet->widgetToGetPress == 0);
       
  4758 
       
  4759             bool reinsertMouseEvent = false;
       
  4760             XEvent mouseMotionEvent;
       
  4761             while (true) {
       
  4762                 // Find first mouse event since we expect them in pairs inside Qt
       
  4763                 tabletMotionData.error =false;
       
  4764                 if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) {
       
  4765                     reinsertMouseEvent = true;
       
  4766                 } else {
       
  4767                     break;
       
  4768                 }
       
  4769 
       
  4770                 // Now discard any duplicate tablet events.
       
  4771                 tabletMotionData.error = false;
       
  4772                 XEvent dummy;
       
  4773                 while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) {
       
  4774                     // just discard the event
       
  4775                 }
       
  4776             }
       
  4777 
       
  4778             if (reinsertMouseEvent) {
       
  4779                 XPutBackEvent(X11->display, &mouseMotionEvent);
       
  4780             }
       
  4781         }
       
  4782     }
       
  4783     return true;
       
  4784 }
       
  4785 #endif
       
  4786 
       
  4787 bool QETWidget::translatePropertyEvent(const XEvent *event)
       
  4788 {
       
  4789     Q_D(QWidget);
       
  4790     if (!isWindow()) return true;
       
  4791 
       
  4792     Atom ret;
       
  4793     int format, e;
       
  4794     unsigned char *data = 0;
       
  4795     unsigned long nitems, after;
       
  4796 
       
  4797     if (event->xproperty.atom == ATOM(_KDE_NET_WM_FRAME_STRUT)) {
       
  4798         this->data->fstrut_dirty = 1;
       
  4799 
       
  4800         if (event->xproperty.state == PropertyNewValue) {
       
  4801             e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_KDE_NET_WM_FRAME_STRUT),
       
  4802                                    0, 4, // struts are 4 longs
       
  4803                                    False, XA_CARDINAL, &ret, &format, &nitems, &after, &data);
       
  4804 
       
  4805             if (e == Success && ret == XA_CARDINAL &&
       
  4806                 format == 32 && nitems == 4) {
       
  4807                 long *strut = (long *) data;
       
  4808                 d->topData()->frameStrut.setCoords(strut[0], strut[2], strut[1], strut[3]);
       
  4809                 this->data->fstrut_dirty = 0;
       
  4810             }
       
  4811         }
       
  4812     } else if (event->xproperty.atom == ATOM(_NET_WM_STATE)) {
       
  4813         bool max = false;
       
  4814         bool full = false;
       
  4815         Qt::WindowStates oldState = Qt::WindowStates(this->data->window_state);
       
  4816 
       
  4817         if (event->xproperty.state == PropertyNewValue) {
       
  4818             // using length of 1024 should be safe for all current and
       
  4819             // possible NET states...
       
  4820             e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_NET_WM_STATE), 0, 1024,
       
  4821                                    False, XA_ATOM, &ret, &format, &nitems, &after, &data);
       
  4822 
       
  4823             if (e == Success && ret == XA_ATOM && format == 32 && nitems > 0) {
       
  4824                 Atom *states = (Atom *) data;
       
  4825 
       
  4826                 unsigned long i;
       
  4827                 uint maximized = 0;
       
  4828                 for (i = 0; i < nitems; i++) {
       
  4829                     if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
       
  4830                         maximized |= 1;
       
  4831                     else if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
       
  4832                         maximized |= 2;
       
  4833                     else if (states[i] == ATOM(_NET_WM_STATE_FULLSCREEN))
       
  4834                         full = true;
       
  4835                 }
       
  4836                 if (maximized == 3) {
       
  4837                     // only set maximized if both horizontal and vertical properties are set
       
  4838                     max = true;
       
  4839                 }
       
  4840             }
       
  4841         }
       
  4842 
       
  4843         bool send_event = false;
       
  4844 
       
  4845         if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
       
  4846             && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) {
       
  4847             if (max && !isMaximized()) {
       
  4848                 this->data->window_state = this->data->window_state | Qt::WindowMaximized;
       
  4849                 send_event = true;
       
  4850             } else if (!max && isMaximized()) {
       
  4851                 this->data->window_state &= ~Qt::WindowMaximized;
       
  4852                 send_event = true;
       
  4853             }
       
  4854         }
       
  4855 
       
  4856         if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
       
  4857             if (full && !isFullScreen()) {
       
  4858                 this->data->window_state = this->data->window_state | Qt::WindowFullScreen;
       
  4859                 send_event = true;
       
  4860             } else if (!full && isFullScreen()) {
       
  4861                 this->data->window_state &= ~Qt::WindowFullScreen;
       
  4862                 send_event = true;
       
  4863             }
       
  4864         }
       
  4865 
       
  4866         if (send_event) {
       
  4867             QWindowStateChangeEvent e(oldState);
       
  4868             QApplication::sendSpontaneousEvent(this, &e);
       
  4869         }
       
  4870     } else if (event->xproperty.atom == ATOM(WM_STATE)) {
       
  4871         // the widget frame strut should also be invalidated
       
  4872         this->data->fstrut_dirty = 1;
       
  4873 
       
  4874         if (event->xproperty.state == PropertyDelete) {
       
  4875             // the window manager has removed the WM State property,
       
  4876             // so it is now in the withdrawn state (ICCCM 4.1.3.1) and
       
  4877             // we are free to reuse this window
       
  4878             d->topData()->parentWinId = 0;
       
  4879             d->topData()->validWMState = 0;
       
  4880             // map the window if we were waiting for a transition to
       
  4881             // withdrawn
       
  4882             if (X11->deferred_map.removeAll(this)) {
       
  4883                 doDeferredMap();
       
  4884             } else if (isVisible()
       
  4885                        && !testAttribute(Qt::WA_Mapped)
       
  4886                        && !testAttribute(Qt::WA_OutsideWSRange)) {
       
  4887                 // so that show() will work again. As stated in the
       
  4888                 // ICCCM section 4.1.4: "Only the client can effect a
       
  4889                 // transition into or out of the Withdrawn state.",
       
  4890                 // but apparently this particular window manager
       
  4891                 // doesn't seem to care
       
  4892                 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
       
  4893                 setAttribute(Qt::WA_WState_Visible, false);
       
  4894             }
       
  4895         } else {
       
  4896             // the window manager has changed the WM State property...
       
  4897             // we are wanting to see if we are withdrawn so that we
       
  4898             // can reuse this window...
       
  4899             e = XGetWindowProperty(X11->display, internalWinId(), ATOM(WM_STATE), 0, 2, False,
       
  4900                                    ATOM(WM_STATE), &ret, &format, &nitems, &after, &data);
       
  4901 
       
  4902             if (e == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) {
       
  4903                 long *state = (long *) data;
       
  4904                 switch (state[0]) {
       
  4905                 case WithdrawnState:
       
  4906                     // if we are in the withdrawn state, we are free
       
  4907                     // to reuse this window provided we remove the
       
  4908                     // WM_STATE property (ICCCM 4.1.3.1)
       
  4909                     XDeleteProperty(X11->display, internalWinId(), ATOM(WM_STATE));
       
  4910 
       
  4911                     // set the parent id to zero, so that show() will
       
  4912                     // work again
       
  4913                     d->topData()->parentWinId = 0;
       
  4914                     d->topData()->validWMState = 0;
       
  4915                     // map the window if we were waiting for a
       
  4916                     // transition to withdrawn
       
  4917                     if (X11->deferred_map.removeAll(this)) {
       
  4918                         doDeferredMap();
       
  4919                     } else if (isVisible()
       
  4920                                && !testAttribute(Qt::WA_Mapped)
       
  4921                                && !testAttribute(Qt::WA_OutsideWSRange)) {
       
  4922                         // so that show() will work again. As stated
       
  4923                         // in the ICCCM section 4.1.4: "Only the
       
  4924                         // client can effect a transition into or out
       
  4925                         // of the Withdrawn state.", but apparently
       
  4926                         // this particular window manager doesn't seem
       
  4927                         // to care
       
  4928                         setAttribute(Qt::WA_WState_ExplicitShowHide, false);
       
  4929                         setAttribute(Qt::WA_WState_Visible, false);
       
  4930                     }
       
  4931                     break;
       
  4932 
       
  4933                 case IconicState:
       
  4934                     d->topData()->validWMState = 1;
       
  4935                     if (!isMinimized()) {
       
  4936                         // window was minimized
       
  4937                         this->data->window_state = this->data->window_state | Qt::WindowMinimized;
       
  4938                         QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state & ~Qt::WindowMinimized));
       
  4939                         QApplication::sendSpontaneousEvent(this, &e);
       
  4940                     }
       
  4941                     break;
       
  4942 
       
  4943                 default:
       
  4944                     d->topData()->validWMState = 1;
       
  4945                     if (isMinimized()) {
       
  4946                         // window was un-minimized
       
  4947                         this->data->window_state &= ~Qt::WindowMinimized;
       
  4948                         QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state | Qt::WindowMinimized));
       
  4949                         QApplication::sendSpontaneousEvent(this, &e);
       
  4950                     }
       
  4951                     break;
       
  4952                 }
       
  4953             }
       
  4954         }
       
  4955     } else if (event->xproperty.atom == ATOM(_NET_WM_WINDOW_OPACITY)) {
       
  4956         // the window opacity was changed
       
  4957         if (event->xproperty.state == PropertyNewValue) {
       
  4958             e = XGetWindowProperty(event->xclient.display,
       
  4959                                    event->xclient.window,
       
  4960                                    ATOM(_NET_WM_WINDOW_OPACITY),
       
  4961                                    0, 1, False, XA_CARDINAL,
       
  4962                                    &ret, &format, &nitems, &after, &data);
       
  4963 
       
  4964             if (e == Success && ret == XA_CARDINAL && format == 32 && nitems == 1
       
  4965                 && after == 0 && data) {
       
  4966                 ulong value = *(ulong*)(data);
       
  4967                 d->topData()->opacity = uint(value >> 24);
       
  4968             }
       
  4969         } else
       
  4970             d->topData()->opacity = 255;
       
  4971     }
       
  4972 
       
  4973     if (data)
       
  4974         XFree(data);
       
  4975 
       
  4976     return true;
       
  4977 }
       
  4978 
       
  4979 
       
  4980 //
       
  4981 // Paint event translation
       
  4982 //
       
  4983 // When receiving many expose events, we compress them (union of all expose
       
  4984 // rectangles) into one event which is sent to the widget.
       
  4985 
       
  4986 struct PaintEventInfo {
       
  4987     Window window;
       
  4988 };
       
  4989 
       
  4990 #if defined(Q_C_CALLBACKS)
       
  4991 extern "C" {
       
  4992 #endif
       
  4993 
       
  4994 static Bool isPaintOrScrollDoneEvent(Display *, XEvent *ev, XPointer a)
       
  4995 {
       
  4996     PaintEventInfo *info = (PaintEventInfo *)a;
       
  4997     if (ev->type == Expose || ev->type == GraphicsExpose
       
  4998         || (ev->type == ClientMessage && ev->xclient.message_type == ATOM(_QT_SCROLL_DONE)))
       
  4999     {
       
  5000         if (ev->xexpose.window == info->window)
       
  5001             return True;
       
  5002     }
       
  5003     return False;
       
  5004 }
       
  5005 
       
  5006 #if defined(Q_C_CALLBACKS)
       
  5007 }
       
  5008 #endif
       
  5009 
       
  5010 
       
  5011 
       
  5012 static
       
  5013 bool translateBySips(QWidget* that, QRect& paintRect)
       
  5014 {
       
  5015     int dx=0, dy=0;
       
  5016     int sips=0;
       
  5017     for (int i = 0; i < X11->sip_list.size(); ++i) {
       
  5018         const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
       
  5019         if (sip.scrolled_widget == that) {
       
  5020             if (sips) {
       
  5021                 dx += sip.dx;
       
  5022                 dy += sip.dy;
       
  5023             }
       
  5024             sips++;
       
  5025         }
       
  5026     }
       
  5027     if (sips > 1) {
       
  5028         paintRect.translate(dx, dy);
       
  5029         return true;
       
  5030     }
       
  5031     return false;
       
  5032 }
       
  5033 
       
  5034 void QETWidget::translatePaintEvent(const XEvent *event)
       
  5035 {
       
  5036     if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
       
  5037         Q_ASSERT(internalWinId());
       
  5038 
       
  5039     Q_D(QWidget);
       
  5040     QRect  paintRect(event->xexpose.x, event->xexpose.y,
       
  5041                      event->xexpose.width, event->xexpose.height);
       
  5042     XEvent xevent;
       
  5043     PaintEventInfo info;
       
  5044     info.window = internalWinId();
       
  5045     translateBySips(this, paintRect);
       
  5046     paintRect = d->mapFromWS(paintRect);
       
  5047 
       
  5048     QRegion paintRegion = paintRect;
       
  5049 
       
  5050     // WARNING: this is O(number_of_events * number_of_matching_events)
       
  5051     while (XCheckIfEvent(X11->display,&xevent,isPaintOrScrollDoneEvent,
       
  5052                          (XPointer)&info) &&
       
  5053            !qt_x11EventFilter(&xevent)  &&
       
  5054            !x11Event(&xevent)) // send event through filter
       
  5055     {
       
  5056         if (xevent.type == Expose || xevent.type == GraphicsExpose) {
       
  5057             QRect exposure(xevent.xexpose.x,
       
  5058                            xevent.xexpose.y,
       
  5059                            xevent.xexpose.width,
       
  5060                            xevent.xexpose.height);
       
  5061             translateBySips(this, exposure);
       
  5062             exposure = d->mapFromWS(exposure);
       
  5063             paintRegion |= exposure;
       
  5064         } else {
       
  5065             translateScrollDoneEvent(&xevent);
       
  5066         }
       
  5067     }
       
  5068 
       
  5069     if (!paintRegion.isEmpty() && !testAttribute(Qt::WA_WState_ConfigPending))
       
  5070         d->syncBackingStore(paintRegion);
       
  5071 }
       
  5072 
       
  5073 //
       
  5074 // Scroll-done event translation.
       
  5075 //
       
  5076 
       
  5077 bool QETWidget::translateScrollDoneEvent(const XEvent *event)
       
  5078 {
       
  5079     long id = event->xclient.data.l[0];
       
  5080 
       
  5081     // Remove any scroll-in-progress record for the given id.
       
  5082     for (int i = 0; i < X11->sip_list.size(); ++i) {
       
  5083         const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i);
       
  5084         if (sip.id == id) {
       
  5085             X11->sip_list.removeAt(i);
       
  5086             return true;
       
  5087         }
       
  5088     }
       
  5089 
       
  5090     return false;
       
  5091 }
       
  5092 
       
  5093 //
       
  5094 // ConfigureNotify (window move and resize) event translation
       
  5095 
       
  5096 bool QETWidget::translateConfigEvent(const XEvent *event)
       
  5097 {
       
  5098     Q_ASSERT((!isWindow() && !testAttribute(Qt::WA_NativeWindow)) ? internalWinId() : true);
       
  5099 
       
  5100     Q_D(QWidget);
       
  5101     bool wasResize = testAttribute(Qt::WA_WState_ConfigPending); // set in QWidget::setGeometry_sys()
       
  5102     setAttribute(Qt::WA_WState_ConfigPending, false);
       
  5103 
       
  5104     if (testAttribute(Qt::WA_OutsideWSRange)) {
       
  5105         // discard events for windows that have a geometry X can't handle
       
  5106         XEvent xevent;
       
  5107         while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
       
  5108                !qt_x11EventFilter(&xevent)  &&
       
  5109                !x11Event(&xevent)) // send event through filter
       
  5110             ;
       
  5111         return true;
       
  5112     }
       
  5113 
       
  5114     const QSize oldSize = size();
       
  5115 
       
  5116     if (isWindow()) {
       
  5117         QPoint newCPos(geometry().topLeft());
       
  5118         QSize  newSize(event->xconfigure.width, event->xconfigure.height);
       
  5119 
       
  5120         bool trust = isVisible()
       
  5121                      && (d->topData()->parentWinId == XNone ||
       
  5122                          d->topData()->parentWinId == QX11Info::appRootWindow());
       
  5123 
       
  5124         if (event->xconfigure.send_event || trust) {
       
  5125             // if a ConfigureNotify comes from a real sendevent request, we can
       
  5126             // trust its values.
       
  5127             newCPos.rx() = event->xconfigure.x + event->xconfigure.border_width;
       
  5128             newCPos.ry() = event->xconfigure.y + event->xconfigure.border_width;
       
  5129         }
       
  5130 
       
  5131         if (isVisible())
       
  5132             QApplication::syncX();
       
  5133 
       
  5134         if (d->extra->compress_events) {
       
  5135             // ConfigureNotify compression for faster opaque resizing
       
  5136             XEvent otherEvent;
       
  5137             while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify,
       
  5138                                           &otherEvent)) {
       
  5139                 if (qt_x11EventFilter(&otherEvent))
       
  5140                     continue;
       
  5141 
       
  5142                 if (x11Event(&otherEvent))
       
  5143                     continue;
       
  5144 
       
  5145                 if (otherEvent.xconfigure.event != otherEvent.xconfigure.window)
       
  5146                     continue;
       
  5147 
       
  5148                 newSize.setWidth(otherEvent.xconfigure.width);
       
  5149                 newSize.setHeight(otherEvent.xconfigure.height);
       
  5150 
       
  5151                 if (otherEvent.xconfigure.send_event || trust) {
       
  5152                     newCPos.rx() = otherEvent.xconfigure.x +
       
  5153                                    otherEvent.xconfigure.border_width;
       
  5154                     newCPos.ry() = otherEvent.xconfigure.y +
       
  5155                                    otherEvent.xconfigure.border_width;
       
  5156                 }
       
  5157             }
       
  5158 #ifndef QT_NO_XSYNC
       
  5159             qt_sync_request_event_data sync_event;
       
  5160             sync_event.window = internalWinId();
       
  5161             for (XEvent ev;;) {
       
  5162                 if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
       
  5163                     break;
       
  5164             }
       
  5165 #endif // QT_NO_XSYNC
       
  5166         }
       
  5167 
       
  5168         QRect cr (geometry());
       
  5169         if (newCPos != cr.topLeft()) { // compare with cpos (exluding frame)
       
  5170             QPoint oldPos = geometry().topLeft();
       
  5171             cr.moveTopLeft(newCPos);
       
  5172             data->crect = cr;
       
  5173             if (isVisible()) {
       
  5174                 QMoveEvent e(newCPos, oldPos); // pos (including frame), not cpos
       
  5175                 QApplication::sendSpontaneousEvent(this, &e);
       
  5176             } else {
       
  5177                 setAttribute(Qt::WA_PendingMoveEvent, true);
       
  5178             }
       
  5179         }
       
  5180         if (newSize != cr.size()) { // size changed
       
  5181             cr.setSize(newSize);
       
  5182             data->crect = cr;
       
  5183 
       
  5184             uint old_state = data->window_state;
       
  5185             if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
       
  5186                 && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)))
       
  5187                 data->window_state &= ~Qt::WindowMaximized;
       
  5188             if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN)))
       
  5189                 data->window_state &= ~Qt::WindowFullScreen;
       
  5190 
       
  5191             if (old_state != data->window_state) {
       
  5192                 QWindowStateChangeEvent e((Qt::WindowStates) old_state);
       
  5193                 QApplication::sendEvent(this, &e);
       
  5194             }
       
  5195 
       
  5196             if (!isVisible())
       
  5197                 setAttribute(Qt::WA_PendingResizeEvent, true);
       
  5198             wasResize = true;
       
  5199         }
       
  5200 
       
  5201     } else {
       
  5202         XEvent xevent;
       
  5203         while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
       
  5204                !qt_x11EventFilter(&xevent)  &&
       
  5205                !x11Event(&xevent)) // send event through filter
       
  5206             ;
       
  5207     }
       
  5208 
       
  5209     if (wasResize) {
       
  5210         static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
       
  5211         if (d->extra->compress_events && !slowResize && !data->in_show && isVisible()) {
       
  5212             QApplication::syncX();
       
  5213             XEvent otherEvent;
       
  5214             while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify, &otherEvent)
       
  5215                    && !qt_x11EventFilter(&otherEvent) && !x11Event(&otherEvent)
       
  5216                    && otherEvent.xconfigure.event == otherEvent.xconfigure.window) {
       
  5217                 data->crect.setWidth(otherEvent.xconfigure.width);
       
  5218                 data->crect.setHeight(otherEvent.xconfigure.height);
       
  5219             }
       
  5220         }
       
  5221 
       
  5222         if (isVisible() && data->crect.size() != oldSize) {
       
  5223             Q_ASSERT(d->extra->topextra);
       
  5224             QWidgetBackingStore *bs = d->extra->topextra->backingStore;
       
  5225             const bool hasStaticContents = bs && bs->hasStaticContents();
       
  5226             // If we have a backing store with static contents, we have to disable the top-level
       
  5227             // resize optimization in order to get invalidated regions for resized widgets.
       
  5228             // The optimization discards all invalidateBuffer() calls since we're going to
       
  5229             // repaint everything anyways, but that's not the case with static contents.
       
  5230             if (!slowResize && !hasStaticContents)
       
  5231                 d->extra->topextra->inTopLevelResize = true;
       
  5232             QResizeEvent e(data->crect.size(), oldSize);
       
  5233             QApplication::sendSpontaneousEvent(this, &e);
       
  5234         }
       
  5235 
       
  5236         const bool waitingForMapNotify = d->extra->topextra && d->extra->topextra->waitingForMapNotify;
       
  5237         if (!waitingForMapNotify) {
       
  5238             if (d->paintOnScreen()) {
       
  5239                 QRegion updateRegion(rect());
       
  5240                 if (testAttribute(Qt::WA_StaticContents))
       
  5241                     updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
       
  5242                 d->syncBackingStore(updateRegion);
       
  5243             } else {
       
  5244                 d->syncBackingStore();
       
  5245             }
       
  5246         }
       
  5247 
       
  5248         if (d->extra && d->extra->topextra)
       
  5249             d->extra->topextra->inTopLevelResize = false;
       
  5250     }
       
  5251 #ifndef QT_NO_XSYNC
       
  5252     if (QTLWExtra *tlwExtra = d->maybeTopData()) {
       
  5253         if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) {
       
  5254             XSyncValue value;
       
  5255             XSyncIntsToValue(&value,
       
  5256                              tlwExtra->newCounterValueLo,
       
  5257                              tlwExtra->newCounterValueHi);
       
  5258 
       
  5259             XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value);
       
  5260             tlwExtra->newCounterValueHi = 0;
       
  5261             tlwExtra->newCounterValueLo = 0;
       
  5262         }
       
  5263     }
       
  5264 #endif
       
  5265     return true;
       
  5266 }
       
  5267 
       
  5268 //
       
  5269 // Close window event translation.
       
  5270 //
       
  5271 bool QETWidget::translateCloseEvent(const XEvent *)
       
  5272 {
       
  5273     Q_D(QWidget);
       
  5274     return d->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
       
  5275 }
       
  5276 
       
  5277 
       
  5278 void QApplication::setCursorFlashTime(int msecs)
       
  5279 {
       
  5280     QApplicationPrivate::cursor_flash_time = msecs;
       
  5281 }
       
  5282 
       
  5283 int QApplication::cursorFlashTime()
       
  5284 {
       
  5285     return QApplicationPrivate::cursor_flash_time;
       
  5286 }
       
  5287 
       
  5288 void QApplication::setDoubleClickInterval(int ms)
       
  5289 {
       
  5290     QApplicationPrivate::mouse_double_click_time = ms;
       
  5291 }
       
  5292 
       
  5293 int QApplication::doubleClickInterval()
       
  5294 {
       
  5295     return QApplicationPrivate::mouse_double_click_time;
       
  5296 }
       
  5297 
       
  5298 void QApplication::setKeyboardInputInterval(int ms)
       
  5299 {
       
  5300     QApplicationPrivate::keyboard_input_time = ms;
       
  5301 }
       
  5302 
       
  5303 int QApplication::keyboardInputInterval()
       
  5304 {
       
  5305     return QApplicationPrivate::keyboard_input_time;
       
  5306 }
       
  5307 
       
  5308 void QApplication::setWheelScrollLines(int n)
       
  5309 {
       
  5310     QApplicationPrivate::wheel_scroll_lines = n;
       
  5311 }
       
  5312 
       
  5313 int QApplication::wheelScrollLines()
       
  5314 {
       
  5315     return QApplicationPrivate::wheel_scroll_lines;
       
  5316 }
       
  5317 
       
  5318 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
       
  5319 {
       
  5320     switch (effect) {
       
  5321     case Qt::UI_AnimateMenu:
       
  5322         if (enable) QApplicationPrivate::fade_menu = false;
       
  5323         QApplicationPrivate::animate_menu = enable;
       
  5324         break;
       
  5325     case Qt::UI_FadeMenu:
       
  5326         if (enable)
       
  5327             QApplicationPrivate::animate_menu = true;
       
  5328         QApplicationPrivate::fade_menu = enable;
       
  5329         break;
       
  5330     case Qt::UI_AnimateCombo:
       
  5331         QApplicationPrivate::animate_combo = enable;
       
  5332         break;
       
  5333     case Qt::UI_AnimateTooltip:
       
  5334         if (enable) QApplicationPrivate::fade_tooltip = false;
       
  5335         QApplicationPrivate::animate_tooltip = enable;
       
  5336         break;
       
  5337     case Qt::UI_FadeTooltip:
       
  5338         if (enable)
       
  5339             QApplicationPrivate::animate_tooltip = true;
       
  5340         QApplicationPrivate::fade_tooltip = enable;
       
  5341         break;
       
  5342     case Qt::UI_AnimateToolBox:
       
  5343         QApplicationPrivate::animate_toolbox = enable;
       
  5344         break;
       
  5345     default:
       
  5346         QApplicationPrivate::animate_ui = enable;
       
  5347         break;
       
  5348     }
       
  5349 }
       
  5350 
       
  5351 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
       
  5352 {
       
  5353     if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
       
  5354         return false;
       
  5355 
       
  5356     switch(effect) {
       
  5357     case Qt::UI_AnimateMenu:
       
  5358         return QApplicationPrivate::animate_menu;
       
  5359     case Qt::UI_FadeMenu:
       
  5360         return QApplicationPrivate::fade_menu;
       
  5361     case Qt::UI_AnimateCombo:
       
  5362         return QApplicationPrivate::animate_combo;
       
  5363     case Qt::UI_AnimateTooltip:
       
  5364         return QApplicationPrivate::animate_tooltip;
       
  5365     case Qt::UI_FadeTooltip:
       
  5366         return QApplicationPrivate::fade_tooltip;
       
  5367     case Qt::UI_AnimateToolBox:
       
  5368         return QApplicationPrivate::animate_toolbox;
       
  5369     default:
       
  5370         return QApplicationPrivate::animate_ui;
       
  5371     }
       
  5372 }
       
  5373 
       
  5374 /*****************************************************************************
       
  5375   Session management support
       
  5376  *****************************************************************************/
       
  5377 
       
  5378 #ifndef QT_NO_SESSIONMANAGER
       
  5379 
       
  5380 QT_BEGIN_INCLUDE_NAMESPACE
       
  5381 #include <X11/SM/SMlib.h>
       
  5382 QT_END_INCLUDE_NAMESPACE
       
  5383 
       
  5384 class QSessionManagerPrivate : public QObjectPrivate
       
  5385 {
       
  5386 public:
       
  5387     QSessionManagerPrivate(QSessionManager* mgr, QString& id, QString& key)
       
  5388         : QObjectPrivate(), sm(mgr), sessionId(id), sessionKey(key),
       
  5389             restartHint(QSessionManager::RestartIfRunning), eventLoop(0) {}
       
  5390     QSessionManager* sm;
       
  5391     QStringList restartCommand;
       
  5392     QStringList discardCommand;
       
  5393     QString& sessionId;
       
  5394     QString& sessionKey;
       
  5395     QSessionManager::RestartHint restartHint;
       
  5396     QEventLoop *eventLoop;
       
  5397 };
       
  5398 
       
  5399 class QSmSocketReceiver : public QObject
       
  5400 {
       
  5401     Q_OBJECT
       
  5402 public:
       
  5403     QSmSocketReceiver(int socket)
       
  5404         {
       
  5405             QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this);
       
  5406             connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int)));
       
  5407         }
       
  5408 
       
  5409 public slots:
       
  5410      void socketActivated(int);
       
  5411 };
       
  5412 
       
  5413 
       
  5414 static SmcConn smcConnection = 0;
       
  5415 static bool sm_interactionActive;
       
  5416 static bool sm_smActive;
       
  5417 static int sm_interactStyle;
       
  5418 static int sm_saveType;
       
  5419 static bool sm_cancel;
       
  5420 // static bool sm_waitingForPhase2;  ### never used?!?
       
  5421 static bool sm_waitingForInteraction;
       
  5422 static bool sm_isshutdown;
       
  5423 // static bool sm_shouldbefast;  ### never used?!?
       
  5424 static bool sm_phase2;
       
  5425 static bool sm_in_phase2;
       
  5426 
       
  5427 static QSmSocketReceiver* sm_receiver = 0;
       
  5428 
       
  5429 static void resetSmState();
       
  5430 static void sm_setProperty(const char* name, const char* type,
       
  5431                             int num_vals, SmPropValue* vals);
       
  5432 static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
       
  5433                                   int saveType, Bool shutdown , int interactStyle, Bool fast);
       
  5434 static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData) ;
       
  5435 static void sm_dieCallback(SmcConn smcConn, SmPointer clientData) ;
       
  5436 static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData);
       
  5437 static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer clientData);
       
  5438 static void sm_interactCallback(SmcConn smcConn, SmPointer clientData);
       
  5439 static void sm_performSaveYourself(QSessionManagerPrivate*);
       
  5440 
       
  5441 static void resetSmState()
       
  5442 {
       
  5443 //    sm_waitingForPhase2 = false; ### never used?!?
       
  5444     sm_waitingForInteraction = false;
       
  5445     sm_interactionActive = false;
       
  5446     sm_interactStyle = SmInteractStyleNone;
       
  5447     sm_smActive = false;
       
  5448     qt_sm_blockUserInput = false;
       
  5449     sm_isshutdown = false;
       
  5450 //    sm_shouldbefast = false; ### never used?!?
       
  5451     sm_phase2 = false;
       
  5452     sm_in_phase2 = false;
       
  5453 }
       
  5454 
       
  5455 
       
  5456 // theoretically it's possible to set several properties at once. For
       
  5457 // simplicity, however, we do just one property at a time
       
  5458 static void sm_setProperty(const char* name, const char* type,
       
  5459                             int num_vals, SmPropValue* vals)
       
  5460 {
       
  5461     if (num_vals) {
       
  5462       SmProp prop;
       
  5463       prop.name = (char*)name;
       
  5464       prop.type = (char*)type;
       
  5465       prop.num_vals = num_vals;
       
  5466       prop.vals = vals;
       
  5467 
       
  5468       SmProp* props[1];
       
  5469       props[0] = &prop;
       
  5470       SmcSetProperties(smcConnection, 1, props);
       
  5471     }
       
  5472     else {
       
  5473       char* names[1];
       
  5474       names[0] = (char*) name;
       
  5475       SmcDeleteProperties(smcConnection, 1, names);
       
  5476     }
       
  5477 }
       
  5478 
       
  5479 static void sm_setProperty(const QString& name, const QString& value)
       
  5480 {
       
  5481     QByteArray v = value.toUtf8();
       
  5482     SmPropValue prop;
       
  5483     prop.length = v.length();
       
  5484     prop.value = (SmPointer) v.constData();
       
  5485     sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop);
       
  5486 }
       
  5487 
       
  5488 static void sm_setProperty(const QString& name, const QStringList& value)
       
  5489 {
       
  5490     SmPropValue *prop = new SmPropValue[value.count()];
       
  5491     int count = 0;
       
  5492     QList<QByteArray> vl;
       
  5493     for (QStringList::ConstIterator it = value.begin(); it != value.end(); ++it) {
       
  5494       prop[count].length = (*it).length();
       
  5495       vl.append((*it).toUtf8());
       
  5496       prop[count].value = (char*)vl.last().data();
       
  5497       ++count;
       
  5498     }
       
  5499     sm_setProperty(name.toLatin1().data(), SmLISTofARRAY8, count, prop);
       
  5500     delete [] prop;
       
  5501 }
       
  5502 
       
  5503 
       
  5504 // workaround for broken libsm, see below
       
  5505 struct QT_smcConn {
       
  5506     unsigned int save_yourself_in_progress : 1;
       
  5507     unsigned int shutdown_in_progress : 1;
       
  5508 };
       
  5509 
       
  5510 static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
       
  5511                                   int saveType, Bool shutdown , int interactStyle, Bool /*fast*/)
       
  5512 {
       
  5513     if (smcConn != smcConnection)
       
  5514         return;
       
  5515     sm_cancel = false;
       
  5516     sm_smActive = true;
       
  5517     sm_isshutdown = shutdown;
       
  5518     sm_saveType = saveType;
       
  5519     sm_interactStyle = interactStyle;
       
  5520 //    sm_shouldbefast = fast; ### never used?!?
       
  5521 
       
  5522     // ugly workaround for broken libSM. libSM should do that _before_
       
  5523     // actually invoking the callback in sm_process.c
       
  5524     ((QT_smcConn*)smcConn)->save_yourself_in_progress = true;
       
  5525     if (sm_isshutdown)
       
  5526         ((QT_smcConn*)smcConn)->shutdown_in_progress = true;
       
  5527 
       
  5528     sm_performSaveYourself((QSessionManagerPrivate*) clientData);
       
  5529     if (!sm_isshutdown) // we cannot expect a confirmation message in that case
       
  5530         resetSmState();
       
  5531 }
       
  5532 
       
  5533 static void sm_performSaveYourself(QSessionManagerPrivate* smd)
       
  5534 {
       
  5535     if (sm_isshutdown)
       
  5536         qt_sm_blockUserInput = true;
       
  5537 
       
  5538     QSessionManager* sm = smd->sm;
       
  5539 
       
  5540     // generate a new session key
       
  5541     timeval tv;
       
  5542     gettimeofday(&tv, 0);
       
  5543     smd->sessionKey  = QString::number(qulonglong(tv.tv_sec)) + QLatin1Char('_') + QString::number(qulonglong(tv.tv_usec));
       
  5544 
       
  5545     QStringList arguments = qApp->arguments();
       
  5546     QString argument0 = arguments.isEmpty() ? qApp->applicationFilePath() : arguments.at(0);
       
  5547 
       
  5548     // tell the session manager about our program in best POSIX style
       
  5549     sm_setProperty(QString::fromLatin1(SmProgram), argument0);
       
  5550     // tell the session manager about our user as well.
       
  5551     struct passwd *entryPtr = 0;
       
  5552 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
       
  5553     QVarLengthArray<char, 1024> buf(sysconf(_SC_GETPW_R_SIZE_MAX));
       
  5554     struct passwd entry;
       
  5555     getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr);
       
  5556 #else
       
  5557     entryPtr = getpwuid(geteuid());
       
  5558 #endif
       
  5559     if (entryPtr)
       
  5560         sm_setProperty(QString::fromLatin1(SmUserID), QString::fromLatin1(entryPtr->pw_name));
       
  5561 
       
  5562     // generate a restart and discard command that makes sense
       
  5563     QStringList restart;
       
  5564     restart  << argument0 << QLatin1String("-session")
       
  5565              << smd->sessionId + QLatin1Char('_') + smd->sessionKey;
       
  5566     if (qstricmp(appName, QX11Info::appClass()) != 0)
       
  5567         restart << QLatin1String("-name") << qAppName();
       
  5568     sm->setRestartCommand(restart);
       
  5569     QStringList discard;
       
  5570     sm->setDiscardCommand(discard);
       
  5571 
       
  5572     switch (sm_saveType) {
       
  5573     case SmSaveBoth:
       
  5574         qApp->commitData(*sm);
       
  5575         if (sm_isshutdown && sm_cancel)
       
  5576             break; // we cancelled the shutdown, no need to save state
       
  5577     // fall through
       
  5578     case SmSaveLocal:
       
  5579         qApp->saveState(*sm);
       
  5580         break;
       
  5581     case SmSaveGlobal:
       
  5582         qApp->commitData(*sm);
       
  5583         break;
       
  5584     default:
       
  5585         break;
       
  5586     }
       
  5587 
       
  5588     if (sm_phase2 && !sm_in_phase2) {
       
  5589         SmcRequestSaveYourselfPhase2(smcConnection, sm_saveYourselfPhase2Callback, (SmPointer*) smd);
       
  5590         qt_sm_blockUserInput = false;
       
  5591     }
       
  5592     else {
       
  5593         // close eventual interaction monitors and cancel the
       
  5594         // shutdown, if required. Note that we can only cancel when
       
  5595         // performing a shutdown, it does not work for checkpoints
       
  5596         if (sm_interactionActive) {
       
  5597             SmcInteractDone(smcConnection, sm_isshutdown && sm_cancel);
       
  5598             sm_interactionActive = false;
       
  5599         }
       
  5600         else if (sm_cancel && sm_isshutdown) {
       
  5601             if (sm->allowsErrorInteraction()) {
       
  5602                 SmcInteractDone(smcConnection, True);
       
  5603                 sm_interactionActive = false;
       
  5604             }
       
  5605         }
       
  5606 
       
  5607         // set restart and discard command in session manager
       
  5608         sm_setProperty(QString::fromLatin1(SmRestartCommand), sm->restartCommand());
       
  5609         sm_setProperty(QString::fromLatin1(SmDiscardCommand), sm->discardCommand());
       
  5610 
       
  5611         // set the restart hint
       
  5612         SmPropValue prop;
       
  5613         prop.length = sizeof(int);
       
  5614         int value = sm->restartHint();
       
  5615         prop.value = (SmPointer) &value;
       
  5616         sm_setProperty(SmRestartStyleHint, SmCARD8, 1, &prop);
       
  5617 
       
  5618         // we are done
       
  5619         SmcSaveYourselfDone(smcConnection, !sm_cancel);
       
  5620     }
       
  5621 }
       
  5622 
       
  5623 static void sm_dieCallback(SmcConn smcConn, SmPointer /* clientData */)
       
  5624 {
       
  5625     if (smcConn != smcConnection)
       
  5626         return;
       
  5627     resetSmState();
       
  5628     QEvent quitEvent(QEvent::Quit);
       
  5629     QApplication::sendEvent(qApp, &quitEvent);
       
  5630 }
       
  5631 
       
  5632 static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData)
       
  5633 {
       
  5634     if (smcConn != smcConnection)
       
  5635         return;
       
  5636     if (sm_waitingForInteraction)
       
  5637         ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
       
  5638     resetSmState();
       
  5639 }
       
  5640 
       
  5641 static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer /*clientData */)
       
  5642 {
       
  5643     if (smcConn != smcConnection)
       
  5644         return;
       
  5645     resetSmState();
       
  5646 }
       
  5647 
       
  5648 static void sm_interactCallback(SmcConn smcConn, SmPointer clientData)
       
  5649 {
       
  5650     if (smcConn != smcConnection)
       
  5651         return;
       
  5652     if (sm_waitingForInteraction)
       
  5653         ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
       
  5654 }
       
  5655 
       
  5656 static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData)
       
  5657 {
       
  5658     if (smcConn != smcConnection)
       
  5659         return;
       
  5660     sm_in_phase2 = true;
       
  5661     sm_performSaveYourself((QSessionManagerPrivate*) clientData);
       
  5662 }
       
  5663 
       
  5664 
       
  5665 void QSmSocketReceiver::socketActivated(int)
       
  5666 {
       
  5667     IceProcessMessages(SmcGetIceConnection(smcConnection), 0, 0);
       
  5668 }
       
  5669 
       
  5670 
       
  5671 #undef Bool
       
  5672 QT_BEGIN_INCLUDE_NAMESPACE
       
  5673 #include "qapplication_x11.moc"
       
  5674 QT_END_INCLUDE_NAMESPACE
       
  5675 
       
  5676 QSessionManager::QSessionManager(QApplication * app, QString &id, QString& key)
       
  5677     : QObject(*new QSessionManagerPrivate(this, id, key), app)
       
  5678 {
       
  5679     Q_D(QSessionManager);
       
  5680     d->restartHint = RestartIfRunning;
       
  5681 
       
  5682     resetSmState();
       
  5683     char cerror[256];
       
  5684     char* myId = 0;
       
  5685     QByteArray b_id = id.toLatin1();
       
  5686     char* prevId = b_id.data();
       
  5687 
       
  5688     SmcCallbacks cb;
       
  5689     cb.save_yourself.callback = sm_saveYourselfCallback;
       
  5690     cb.save_yourself.client_data = (SmPointer) d;
       
  5691     cb.die.callback = sm_dieCallback;
       
  5692     cb.die.client_data = (SmPointer) d;
       
  5693     cb.save_complete.callback = sm_saveCompleteCallback;
       
  5694     cb.save_complete.client_data = (SmPointer) d;
       
  5695     cb.shutdown_cancelled.callback = sm_shutdownCancelledCallback;
       
  5696     cb.shutdown_cancelled.client_data = (SmPointer) d;
       
  5697 
       
  5698     // avoid showing a warning message below
       
  5699     if (qgetenv("SESSION_MANAGER").isEmpty())
       
  5700         return;
       
  5701 
       
  5702     smcConnection = SmcOpenConnection(0, 0, 1, 0,
       
  5703                                        SmcSaveYourselfProcMask |
       
  5704                                        SmcDieProcMask |
       
  5705                                        SmcSaveCompleteProcMask |
       
  5706                                        SmcShutdownCancelledProcMask,
       
  5707                                        &cb,
       
  5708                                        prevId,
       
  5709                                        &myId,
       
  5710                                        256, cerror);
       
  5711 
       
  5712     id = QString::fromLatin1(myId);
       
  5713     ::free(myId); // it was allocated by C
       
  5714 
       
  5715     QString error = QString::fromLocal8Bit(cerror);
       
  5716     if (!smcConnection) {
       
  5717         qWarning("Qt: Session management error: %s", qPrintable(error));
       
  5718     }
       
  5719     else {
       
  5720         sm_receiver = new QSmSocketReceiver(IceConnectionNumber(SmcGetIceConnection(smcConnection)));
       
  5721     }
       
  5722 }
       
  5723 
       
  5724 QSessionManager::~QSessionManager()
       
  5725 {
       
  5726     if (smcConnection)
       
  5727         SmcCloseConnection(smcConnection, 0, 0);
       
  5728     smcConnection = 0;
       
  5729     delete sm_receiver;
       
  5730 }
       
  5731 
       
  5732 QString QSessionManager::sessionId() const
       
  5733 {
       
  5734     Q_D(const QSessionManager);
       
  5735     return d->sessionId;
       
  5736 }
       
  5737 
       
  5738 QString QSessionManager::sessionKey() const
       
  5739 {
       
  5740     Q_D(const QSessionManager);
       
  5741     return d->sessionKey;
       
  5742 }
       
  5743 
       
  5744 
       
  5745 void* QSessionManager::handle() const
       
  5746 {
       
  5747     return (void*) smcConnection;
       
  5748 }
       
  5749 
       
  5750 
       
  5751 bool QSessionManager::allowsInteraction()
       
  5752 {
       
  5753     Q_D(QSessionManager);
       
  5754     if (sm_interactionActive)
       
  5755         return true;
       
  5756 
       
  5757     if (sm_waitingForInteraction)
       
  5758         return false;
       
  5759 
       
  5760     if (sm_interactStyle == SmInteractStyleAny) {
       
  5761         sm_waitingForInteraction =  SmcInteractRequest(smcConnection, SmDialogNormal,
       
  5762                                                         sm_interactCallback, (SmPointer*) d);
       
  5763     }
       
  5764     if (sm_waitingForInteraction) {
       
  5765         QEventLoop eventLoop;
       
  5766         d->eventLoop = &eventLoop;
       
  5767         (void) eventLoop.exec();
       
  5768         d->eventLoop = 0;
       
  5769 
       
  5770         sm_waitingForInteraction = false;
       
  5771         if (sm_smActive) { // not cancelled
       
  5772             sm_interactionActive = true;
       
  5773             qt_sm_blockUserInput = false;
       
  5774             return true;
       
  5775         }
       
  5776     }
       
  5777     return false;
       
  5778 }
       
  5779 
       
  5780 bool QSessionManager::allowsErrorInteraction()
       
  5781 {
       
  5782     Q_D(QSessionManager);
       
  5783     if (sm_interactionActive)
       
  5784         return true;
       
  5785 
       
  5786     if (sm_waitingForInteraction)
       
  5787         return false;
       
  5788 
       
  5789     if (sm_interactStyle == SmInteractStyleAny || sm_interactStyle == SmInteractStyleErrors) {
       
  5790         sm_waitingForInteraction =  SmcInteractRequest(smcConnection, SmDialogError,
       
  5791                                                         sm_interactCallback, (SmPointer*) d);
       
  5792     }
       
  5793     if (sm_waitingForInteraction) {
       
  5794         QEventLoop eventLoop;
       
  5795         d->eventLoop = &eventLoop;
       
  5796         (void) eventLoop.exec();
       
  5797         d->eventLoop = 0;
       
  5798 
       
  5799         sm_waitingForInteraction = false;
       
  5800         if (sm_smActive) { // not cancelled
       
  5801             sm_interactionActive = true;
       
  5802             qt_sm_blockUserInput = false;
       
  5803             return true;
       
  5804         }
       
  5805     }
       
  5806     return false;
       
  5807 }
       
  5808 
       
  5809 void QSessionManager::release()
       
  5810 {
       
  5811     if (sm_interactionActive) {
       
  5812         SmcInteractDone(smcConnection, False);
       
  5813         sm_interactionActive = false;
       
  5814         if (sm_smActive && sm_isshutdown)
       
  5815             qt_sm_blockUserInput = true;
       
  5816     }
       
  5817 }
       
  5818 
       
  5819 void QSessionManager::cancel()
       
  5820 {
       
  5821     sm_cancel = true;
       
  5822 }
       
  5823 
       
  5824 void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
       
  5825 {
       
  5826     Q_D(QSessionManager);
       
  5827     d->restartHint = hint;
       
  5828 }
       
  5829 
       
  5830 QSessionManager::RestartHint QSessionManager::restartHint() const
       
  5831 {
       
  5832     Q_D(const QSessionManager);
       
  5833     return d->restartHint;
       
  5834 }
       
  5835 
       
  5836 void QSessionManager::setRestartCommand(const QStringList& command)
       
  5837 {
       
  5838     Q_D(QSessionManager);
       
  5839     d->restartCommand = command;
       
  5840 }
       
  5841 
       
  5842 QStringList QSessionManager::restartCommand() const
       
  5843 {
       
  5844     Q_D(const QSessionManager);
       
  5845     return d->restartCommand;
       
  5846 }
       
  5847 
       
  5848 void QSessionManager::setDiscardCommand(const QStringList& command)
       
  5849 {
       
  5850     Q_D(QSessionManager);
       
  5851     d->discardCommand = command;
       
  5852 }
       
  5853 
       
  5854 QStringList QSessionManager::discardCommand() const
       
  5855 {
       
  5856     Q_D(const QSessionManager);
       
  5857     return d->discardCommand;
       
  5858 }
       
  5859 
       
  5860 void QSessionManager::setManagerProperty(const QString& name, const QString& value)
       
  5861 {
       
  5862     sm_setProperty(name, value);
       
  5863 }
       
  5864 
       
  5865 void QSessionManager::setManagerProperty(const QString& name, const QStringList& value)
       
  5866 {
       
  5867     sm_setProperty(name, value);
       
  5868 }
       
  5869 
       
  5870 bool QSessionManager::isPhase2() const
       
  5871 {
       
  5872     return sm_in_phase2;
       
  5873 }
       
  5874 
       
  5875 void QSessionManager::requestPhase2()
       
  5876 {
       
  5877     sm_phase2 = true;
       
  5878 }
       
  5879 
       
  5880 #endif // QT_NO_SESSIONMANAGER
       
  5881 
       
  5882 #if defined(QT_RX71_MULTITOUCH)
       
  5883 
       
  5884 static inline int testBit(const char *array, int bit)
       
  5885 {
       
  5886     return (array[bit/8] & (1<<(bit%8)));
       
  5887 }
       
  5888 
       
  5889 static int openRX71Device(const QByteArray &deviceName)
       
  5890 {
       
  5891     int fd = open(deviceName, O_RDONLY | O_NONBLOCK);
       
  5892     if (fd == -1) {
       
  5893         fd = -errno;
       
  5894         return fd;
       
  5895     }
       
  5896 
       
  5897     // fetch the event type mask and check that the device reports absolute coordinates
       
  5898     char eventTypeMask[(EV_MAX + sizeof(char) - 1) * sizeof(char) + 1];
       
  5899     memset(eventTypeMask, 0, sizeof(eventTypeMask));
       
  5900     if (ioctl(fd, EVIOCGBIT(0, sizeof(eventTypeMask)), eventTypeMask) < 0) {
       
  5901         close(fd);
       
  5902         return -1;
       
  5903     }
       
  5904     if (!testBit(eventTypeMask, EV_ABS)) {
       
  5905         close(fd);
       
  5906         return -1;
       
  5907     }
       
  5908 
       
  5909     // make sure that we can get the absolute X and Y positions from the device
       
  5910     char absMask[(ABS_MAX + sizeof(char) - 1) * sizeof(char) + 1];
       
  5911     memset(absMask, 0, sizeof(absMask));
       
  5912     if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absMask)), absMask) < 0) {
       
  5913         close(fd);
       
  5914         return -1;
       
  5915     }
       
  5916     if (!testBit(absMask, ABS_X) || !testBit(absMask, ABS_Y)) {
       
  5917         close(fd);
       
  5918         return -1;
       
  5919     }
       
  5920 
       
  5921     return fd;
       
  5922 }
       
  5923 
       
  5924 void QApplicationPrivate::initializeMultitouch_sys()
       
  5925 {
       
  5926     Q_Q(QApplication);
       
  5927 
       
  5928     QByteArray deviceName = QByteArray("/dev/input/event");
       
  5929     int currentDeviceNumber = 0;
       
  5930     for (;;) {
       
  5931         int fd = openRX71Device(QByteArray(deviceName + QByteArray::number(currentDeviceNumber++)));
       
  5932         if (fd == -ENOENT) {
       
  5933             // no more devices
       
  5934             break;
       
  5935         }
       
  5936         if (fd < 0) {
       
  5937             // not a touch device
       
  5938             continue;
       
  5939         }
       
  5940 
       
  5941         struct input_absinfo abs_x, abs_y, abs_z;
       
  5942         ioctl(fd, EVIOCGABS(ABS_X), &abs_x);
       
  5943         ioctl(fd, EVIOCGABS(ABS_Y), &abs_y);
       
  5944         ioctl(fd, EVIOCGABS(ABS_Z), &abs_z);
       
  5945 
       
  5946         int deviceNumber = allRX71TouchPoints.count();
       
  5947 
       
  5948         QSocketNotifier *socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
       
  5949         QObject::connect(socketNotifier, SIGNAL(activated(int)), q, SLOT(_q_readRX71MultiTouchEvents()));
       
  5950 
       
  5951         RX71TouchPointState touchPointState = {
       
  5952             socketNotifier,
       
  5953             QTouchEvent::TouchPoint(deviceNumber),
       
  5954 
       
  5955             abs_x.minimum, abs_x.maximum, q->desktop()->screenGeometry().width(),
       
  5956             abs_y.minimum, abs_y.maximum, q->desktop()->screenGeometry().height(),
       
  5957             abs_z.minimum, abs_z.maximum
       
  5958         };
       
  5959         allRX71TouchPoints.append(touchPointState);
       
  5960     }
       
  5961 
       
  5962     hasRX71MultiTouch = allRX71TouchPoints.count() > 1;
       
  5963     if (!hasRX71MultiTouch) {
       
  5964         for (int i = 0; i < allRX71TouchPoints.count(); ++i) {
       
  5965             QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier;
       
  5966             close(socketNotifier->socket());
       
  5967             delete socketNotifier;
       
  5968         }
       
  5969         allRX71TouchPoints.clear();
       
  5970     }
       
  5971 }
       
  5972 
       
  5973 void QApplicationPrivate::cleanupMultitouch_sys()
       
  5974 {
       
  5975     hasRX71MultiTouch = false;
       
  5976     for (int i = 0; i < allRX71TouchPoints.count(); ++i) {
       
  5977         QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier;
       
  5978         close(socketNotifier->socket());
       
  5979         delete socketNotifier;
       
  5980     }
       
  5981     allRX71TouchPoints.clear();
       
  5982 }
       
  5983 
       
  5984 bool QApplicationPrivate::readRX71MultiTouchEvents(int deviceNumber)
       
  5985 {
       
  5986     RX71TouchPointState &touchPointState = allRX71TouchPoints[deviceNumber];
       
  5987     QSocketNotifier *socketNotifier = touchPointState.socketNotifier;
       
  5988     int fd = socketNotifier->socket();
       
  5989 
       
  5990     QTouchEvent::TouchPoint &touchPoint = touchPointState.touchPoint;
       
  5991 
       
  5992     bool down = touchPoint.state() != Qt::TouchPointReleased;
       
  5993     if (down)
       
  5994         touchPoint.setState(Qt::TouchPointStationary);
       
  5995 
       
  5996     bool changed = false;
       
  5997     for (;;) {
       
  5998         struct input_event inputEvent;
       
  5999         int bytesRead = read(fd, &inputEvent, sizeof(inputEvent));
       
  6000         if (bytesRead <= 0)
       
  6001             break;
       
  6002         if (bytesRead != sizeof(inputEvent)) {
       
  6003             qWarning("Qt: INTERNAL ERROR: short read in readRX71MultiTouchEvents()");
       
  6004             return false;
       
  6005         }
       
  6006 
       
  6007         switch (inputEvent.type) {
       
  6008         case EV_SYN:
       
  6009             changed = true;
       
  6010             switch (touchPoint.state()) {
       
  6011             case Qt::TouchPointPressed:
       
  6012             case Qt::TouchPointReleased:
       
  6013                 // make sure we don't compress pressed and releases with any other events
       
  6014                 return changed;
       
  6015             default:
       
  6016                 break;
       
  6017             }
       
  6018             continue;
       
  6019         case EV_KEY:
       
  6020         case EV_ABS:
       
  6021             break;
       
  6022         default:
       
  6023             qWarning("Qt: WARNING: unknown event type %d on multitouch device", inputEvent.type);
       
  6024             continue;
       
  6025         }
       
  6026 
       
  6027         QPointF screenPos = touchPoint.screenPos();
       
  6028         switch (inputEvent.code) {
       
  6029         case BTN_TOUCH:
       
  6030             if (!down && inputEvent.value != 0)
       
  6031                 touchPoint.setState(Qt::TouchPointPressed);
       
  6032             else if (down && inputEvent.value == 0)
       
  6033                 touchPoint.setState(Qt::TouchPointReleased);
       
  6034             break;
       
  6035         case ABS_TOOL_WIDTH:
       
  6036         case ABS_VOLUME:
       
  6037         case ABS_PRESSURE:
       
  6038             // ignore for now
       
  6039             break;
       
  6040         case ABS_X:
       
  6041         {
       
  6042             qreal newValue = ((qreal(inputEvent.value - touchPointState.minX)
       
  6043                               / qreal(touchPointState.maxX - touchPointState.minX))
       
  6044                               * touchPointState.scaleX);
       
  6045             screenPos.rx() = newValue;
       
  6046             touchPoint.setScreenPos(screenPos);
       
  6047             break;
       
  6048         }
       
  6049         case ABS_Y:
       
  6050         {
       
  6051             qreal newValue = ((qreal(inputEvent.value - touchPointState.minY)
       
  6052                               / qreal(touchPointState.maxY - touchPointState.minY))
       
  6053                               * touchPointState.scaleY);
       
  6054             screenPos.ry() = newValue;
       
  6055             touchPoint.setScreenPos(screenPos);
       
  6056             break;
       
  6057         }
       
  6058         case ABS_Z:
       
  6059         {
       
  6060             // map Z (signal strength) to pressure for now
       
  6061             qreal newValue = (qreal(inputEvent.value - touchPointState.minZ)
       
  6062                               / qreal(touchPointState.maxZ - touchPointState.minZ));
       
  6063             touchPoint.setPressure(newValue);
       
  6064             break;
       
  6065         }
       
  6066         default:
       
  6067             qWarning("Qt: WARNING: unknown event code %d on multitouch device", inputEvent.code);
       
  6068             continue;
       
  6069         }
       
  6070     }
       
  6071 
       
  6072     if (down && touchPoint.state() != Qt::TouchPointReleased)
       
  6073         touchPoint.setState(changed ? Qt::TouchPointMoved : Qt::TouchPointStationary);
       
  6074 
       
  6075     return changed;
       
  6076 }
       
  6077 
       
  6078 void QApplicationPrivate::_q_readRX71MultiTouchEvents()
       
  6079 {
       
  6080     // read touch events from all devices
       
  6081     bool changed = false;
       
  6082     for (int i = 0; i < allRX71TouchPoints.count(); ++i)
       
  6083         changed = readRX71MultiTouchEvents(i) || changed;
       
  6084     if (!changed)
       
  6085         return;
       
  6086 
       
  6087     QList<QTouchEvent::TouchPoint> touchPoints;
       
  6088     for (int i = 0; i < allRX71TouchPoints.count(); ++i)
       
  6089         touchPoints.append(allRX71TouchPoints.at(i).touchPoint);
       
  6090 
       
  6091     translateRawTouchEvent(0, QTouchEvent::TouchScreen, touchPoints);
       
  6092 }
       
  6093 
       
  6094 #else // !QT_RX71_MULTITOUCH
       
  6095 
       
  6096 void QApplicationPrivate::initializeMultitouch_sys()
       
  6097 { }
       
  6098 void QApplicationPrivate::cleanupMultitouch_sys()
       
  6099 { }
       
  6100 
       
  6101 #endif // QT_RX71_MULTITOUCH
       
  6102 
       
  6103 QT_END_NAMESPACE