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