1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
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
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
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.
48 #include "qplatformdefs.h"
50 #include "qcolormap.h"
51 #include "qdesktopwidget.h"
52 #include "qapplication.h"
53 #include "qapplication_p.h"
56 #include "qbitarray.h"
59 #include "qpixmapcache.h"
60 #include "qdatetime.h"
61 #include "qtextcodec.h"
62 #include "qdatastream.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"
75 #include "qvarlengtharray.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>
83 #include "qmetaobject.h"
86 #include <private/qgraphicssystemfactory_p.h>
87 #include "qguiplatformplugin_p.h"
90 #if !defined (QT_NO_TABLET)
92 # define class c_class //XIproto.h has a name member named 'class' which the c++ compiler doesn't like
93 # include <wacomcfg.h>
98 #ifndef QT_GUI_DOUBLE_CLICK_RADIUS
99 #define QT_GUI_DOUBLE_CLICK_RADIUS 5
103 //#define ALIEN_DEBUG
105 #if !defined(QT_NO_GLIB)
106 # include "qguieventdispatcher_glib_p.h"
108 #include "qeventdispatcher_x11_p.h"
109 #include <private/qpaintengine_x11_p.h>
111 #include <private/qkeymapper_p.h>
113 // Input method stuff
115 #include "qinputcontext.h"
116 #include "qinputcontextfactory.h"
120 #include <X11/extensions/Xfixes.h>
121 #endif // QT_NO_XFIXES
123 #include "qt_x11_p.h"
124 #include "qx11info_x11.h"
126 #define XK_MISCELLANY
127 #include <X11/keysymdef.h>
128 #if !defined(QT_NO_XINPUT)
129 #include <X11/extensions/XI.h>
137 #include "qwidget_p.h"
139 #include <private/qbackingstore_p.h>
141 #ifdef QT_RX71_MULTITOUCH
142 # include <qsocketnotifier.h>
143 # include <linux/input.h>
147 #if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4)
148 # define QT_NO_UNSETENV
153 //#define 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.
163 extern "C" char *_Xsetlocale(int category, const char *locale);
164 char *_Xsetlocale(int category, const char *locale)
166 //qDebug("_Xsetlocale(%d,%s),category,locale");
167 return setlocale(category,locale);
170 #endif // X_NOT_BROKEN
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
179 "_NET_WM_CONTEXT_HELP\0"
180 "_NET_WM_SYNC_REQUEST\0"
181 "_NET_WM_SYNC_REQUEST_COUNTER\0"
183 // ICCCM window state
187 // Session management
201 "_QT_CLIPBOARD_SENTINEL\0"
202 "_QT_SELECTION_SENTINEL\0"
203 "CLIPBOARD_MANAGER\0"
210 "_QT_INPUT_ENCODING\0"
215 "ENLIGHTENMENT_DESKTOP\0"
217 "_SGI_DESKS_MANAGER\0"
221 "_NET_VIRTUAL_ROOTS\0"
224 "_NET_MOVERESIZE_WINDOW\0"
225 "_NET_WM_MOVERESIZE\0"
228 "_NET_WM_ICON_NAME\0"
233 "_NET_WM_WINDOW_OPACITY\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"
245 "_NET_WM_USER_TIME\0"
246 "_NET_WM_USER_TIME_WINDOW\0"
247 "_NET_WM_FULL_PLACEMENT\0"
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"
266 "_KDE_NET_WM_FRAME_STRUT\0"
268 "_NET_STARTUP_INFO\0"
269 "_NET_STARTUP_INFO_BEGIN\0"
271 "_NET_SUPPORTING_WM_CHECK\0"
275 "_NET_SYSTEM_TRAY_VISUAL\0"
277 "_NET_ACTIVE_WINDOW\0"
302 "XdndActionPrivate\0"
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"
311 "XmTRANSFER_SUCCESS\0"
312 "XmTRANSFER_FAILURE\0"
321 // Wacom old. (before version 0.10)
331 Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
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)
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
355 // function to update the workarea of the screen - in qdesktopwidget_x11.cpp
356 extern void qt_desktopwidget_update_workarea();
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);
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;
369 // flags for extensions for special Languages, currently only for RTL languages
370 bool qt_use_rtl_extensions = false;
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
379 extern QWidgetList *qt_modal_stack; // stack of modal widgets
381 // window where mouse buttons have been pressed
382 static Window pressed_window = XNone;
385 static bool replayPopupMouseEvent = false;
386 static bool popupGrabOk;
388 bool qt_sm_blockUserInput = false; // session management
390 Q_GUI_EXPORT int qt_xfocusout_grab_counter = 0;
392 #if !defined (QT_NO_TABLET)
393 Q_GLOBAL_STATIC(QTabletDeviceDataList, tablet_devices)
394 QTabletDeviceDataList *qt_tablet_devices()
396 return tablet_devices();
399 extern bool qt_tabletChokeMouse;
402 typedef bool(*QX11FilterFunction)(XEvent *event);
404 Q_GLOBAL_STATIC(QList<QX11FilterFunction>, x11Filters)
406 Q_GUI_EXPORT void qt_installX11EventFilter(QX11FilterFunction func)
410 if (QList<QX11FilterFunction> *list = x11Filters())
414 Q_GUI_EXPORT void qt_removeX11EventFilter(QX11FilterFunction func)
418 if (QList<QX11FilterFunction> *list = x11Filters())
419 list->removeOne(func);
423 static bool qt_x11EventFilter(XEvent* ev)
426 if (qApp->filterEvent(ev, &unused))
428 if (const QList<QX11FilterFunction> *list = x11Filters()) {
429 for (QList<QX11FilterFunction>::const_iterator it = list->constBegin(); it != list->constEnd(); ++it) {
435 return qApp->x11EventFilter(ev);
438 #if !defined(QT_NO_XIM)
439 XIMStyle qt_xim_preferred_style = 0;
441 int qt_ximComposingKeycode=0;
442 QTextCodec * qt_input_mapper = 0;
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
449 static void qt_save_rootinfo();
450 Q_GUI_EXPORT bool qt_try_modal(QWidget *, XEvent *);
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
456 extern bool qt_xdnd_dragging;
458 // gui or non-gui from qapplication.cpp
459 extern bool qt_is_gui_used;
463 Try to resolve a \a symbol from \a library with the version specified
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
470 static void* qt_load_library_runtime(const char *library, int vernum,
471 int highestVernum, const char *symbol)
474 // we try to load in the following order:
475 // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) )
480 for(int i = highestVernum; i > vernum; --i)
483 Q_FOREACH(int version, versions) {
484 QLatin1String libName(library);
485 QLibrary xfixesLib(libName, version);
486 void *ptr = xfixesLib.resolve(symbol);
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
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)
515 # else // not runtime Xfixes
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
524 # error Unsupported version of Xfixes
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
534 struct qt_xfixes_selection_event_data
536 // which selection to filter out.
540 #if defined(Q_C_CALLBACKS)
544 static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
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)
556 #if defined(Q_C_CALLBACKS)
560 #endif // QT_NO_XFIXES
562 class QETWidget : public QWidget // event translator widget
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);
576 bool translatePropertyEvent(const XEvent *);
580 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
581 if (!testAttribute(Qt::WA_Resized)) {
583 setAttribute(Qt::WA_Resized, false);
587 workaround for WM's that throw away ConfigureRequests from the following:
590 window->move(x, y); // could also be resize(), move()+resize(), or setGeometry()
593 QRect r = geometry();
595 XMoveResizeWindow(X11->display,
605 XGetWMNormalHints(X11->display, internalWinId(), &sh, &unused);
606 sh.flags |= USPosition | PPosition | USSize | PSize | PWinGravity;
609 sh.width = r.width();
610 sh.height = r.height();
611 sh.win_gravity = StaticGravity;
612 XSetWMNormalHints(X11->display, internalWinId(), &sh);
614 setAttribute(Qt::WA_Mapped);
615 if (testAttribute(Qt::WA_DontShowOnScreen))
617 d_func()->topData()->waitingForMapNotify = 1;
618 XMapWindow(X11->display, internalWinId());
623 void QApplicationPrivate::createEventDispatcher()
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));
633 eventDispatcher = (q->type() != QApplication::Tty
634 ? new QEventDispatcherX11(q)
635 : new QEventDispatcherUNIX(q));
638 /*****************************************************************************
639 Default X error handlers
640 *****************************************************************************/
642 #if defined(Q_C_CALLBACKS)
646 static int (*original_x_errhandler)(Display *dpy, XErrorEvent *);
647 static int (*original_xio_errhandler)(Display *dpy);
649 static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
651 if (X11->display != dpy) {
652 // only handle X errors for our display
656 switch (err->error_code) {
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? :/
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? :/
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? :/
688 if (X11->xdndHandleBadwindow()) {
689 qDebug("xdndHandleBadwindow returned true");
693 if (X11->ignore_badwindow)
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 */) {
709 XGetErrorText( dpy, err->error_code, errstr, 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,
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";
735 else if(err->request_code == X11->xkb_major)
736 extensionName = "XKEYBOARD";
741 qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code);
742 XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256);
744 extensionName = "Uknown extension";
745 qsnprintf(minor_str, 256, "Unknown request");
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,
759 // ### we really should distinguish between severe, non-severe and
760 // ### application specific errors
766 static int qt_xio_errhandler(Display *)
768 qWarning("%s: Fatal IO error: client killed", appName);
769 QApplicationPrivate::reset_instance_pointer();
771 //### give the application a chance for a proper shutdown instead,
772 //### exit(1) doesn't help.
776 #if defined(Q_C_CALLBACKS)
781 struct qt_sync_request_event_data
786 #if defined(Q_C_CALLBACKS)
790 static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
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];
814 #if defined(Q_C_CALLBACKS)
817 #endif // QT_NO_XSYNC
819 static void qt_x11_create_intern_atoms()
821 const char *names[QX11Data::NAtoms];
822 const char *ptr = x11_atomnames;
832 Q_ASSERT(i == QX11Data::NPredefinedAtoms);
834 QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_");
835 settings_atom_name += XDisplayName(X11->displayName);
836 names[i++] = settings_atom_name;
838 Q_ASSERT(i == QX11Data::NAtoms);
839 #if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6)
840 XInternAtoms(X11->display, (char **)names, i, False, X11->atoms);
842 for (i = 0; i < QX11Data::NAtoms; ++i)
843 X11->atoms[i] = XInternAtom(X11->display, (char *)names[i], False);
847 Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
850 QDataStream s(&stamp, QIODevice::WriteOnly);
851 s << QDateTime::currentDateTime();
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());
859 apply the settings to the application
861 bool QApplicationPrivate::x11_apply_settings()
863 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
865 settings.beginGroup(QLatin1String("Qt"));
868 Qt settings. This is now they are written into the datastream.
870 Palette / * - QPalette
872 libraryPath - QStringList
874 doubleClickInterval - int
875 keyboardInputInterval - int
876 cursorFlashTime - int
877 wheelScrollLines - int
879 defaultCodec - QString
880 globalStrut/width - int
881 globalStrut/height - int
882 GUIEffects - QStringList
883 Font Substitutions/ * - QStringList
884 Font Substitutions/... - QStringList
889 QPalette pal(Qt::black);
891 strlist = settings.value(QLatin1String("Palette/active")).toStringList();
892 if (!strlist.isEmpty()) {
894 for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
895 pal.setColor(QPalette::Active, (QPalette::ColorRole) i,
898 strlist = settings.value(QLatin1String("Palette/inactive")).toStringList();
899 if (!strlist.isEmpty()) {
901 for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
902 pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i,
905 strlist = settings.value(QLatin1String("Palette/disabled")).toStringList();
906 if (!strlist.isEmpty()) {
908 for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++)
909 pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i,
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);
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(","));
934 if (fontDescription.isEmpty())
935 fontDescription = settings.value(QLatin1String("font")).toString();
936 if (!fontDescription .isEmpty()) {
937 font.fromString(fontDescription );
938 QApplicationPrivate::setSystemFont(font);
943 // read library (ie. plugin) path list
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++);
956 QString stylename = settings.value(QLatin1String("style")).toString();
958 if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) {
959 stylename = qt_guiPlatformPlugin()->styleName();
962 static QString currentStyleName = stylename;
963 if (QCoreApplication::startingUp()) {
964 if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
965 QApplicationPrivate::styleOverride = stylename;
967 if (currentStyleName != stylename) {
968 currentStyleName = stylename;
969 QApplication::setStyle(stylename);
974 settings.value(QLatin1String("doubleClickInterval"),
975 QApplication::doubleClickInterval()).toInt();
976 QApplication::setDoubleClickInterval(num);
979 settings.value(QLatin1String("cursorFlashTime"),
980 QApplication::cursorFlashTime()).toInt();
981 QApplication::setCursorFlashTime(num);
983 #ifndef QT_NO_WHEELEVENT
985 settings.value(QLatin1String("wheelScrollLines"),
986 QApplication::wheelScrollLines()).toInt();
987 QApplication::setWheelScrollLines(num);
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");
1001 QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
1002 QVariant(QLatin1String("none"))).toString();
1003 if (defaultcodec != QLatin1String("none")) {
1004 QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
1006 QTextCodec::setCodecForTr(codec);
1009 int w = settings.value(QLatin1String("globalStrut/width")).toInt();
1010 int h = settings.value(QLatin1String("globalStrut/height")).toInt();
1012 if (strut.isValid())
1013 QApplication::setGlobalStrut(strut);
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")));
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) {
1038 QStringList subs = settings.value(fam).toStringList();
1039 QFont::insertSubstitutions(fam, subs);
1042 settings.endGroup();
1045 qt_use_rtl_extensions =
1046 settings.value(QLatin1String("useRtlExtensions"), false).toBool();
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;
1062 QStringList inputMethods = QInputContextFactory::keys();
1063 if (inputMethods.size() > 2 && inputMethods.contains(QLatin1String("imsw-multi"))) {
1064 X11->default_im = QLatin1String("imsw-multi");
1066 X11->default_im = settings.value(QLatin1String("DefaultInputMethod"),
1067 QLatin1String("xim")).toString();
1070 settings.endGroup(); // Qt
1077 Resets the QApplication::instance() pointer to zero
1079 void QApplicationPrivate::reset_instance_pointer()
1080 { QApplication::self = 0; }
1083 // read the _QT_INPUT_ENCODING property and apply the settings to
1085 static void qt_set_input_encoding()
1089 ulong nitems, after = 1;
1090 unsigned char *data = 0;
1092 int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
1093 ATOM(_QT_INPUT_ENCODING), 0, 1024,
1094 False, XA_STRING, &type, &format, &nitems,
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
1100 qt_input_mapper = QTextCodec::codecForLocale();
1103 if (!qstricmp((char *)data, "locale"))
1104 qt_input_mapper = QTextCodec::codecForLocale();
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");
1111 if (qt_input_mapper && qt_input_mapper->mibEnum() == 11) // 8859-8
1112 qt_input_mapper = QTextCodec::codecForName("ISO 8859-8-I");
1114 XFree((char *)data);
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)
1123 QString resFont, resFG, resBG, resButton, resEF, sysFont, selectBackground, selectForeground;
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);
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);
1142 // second, parse the RESOURCE_MANAGER property
1144 ulong nitems, after = 1;
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) {
1159 if (type == XA_STRING)
1160 res += QString::fromLatin1((char*)data);
1162 res += QString::fromLocal8Bit((char*)data);
1163 offset += 2048; // offset is in 32bit quantities... 8192/4 == 2048
1165 XFree((char *)data);
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();
1177 r = res.indexOf(QLatin1Char('\n'), l);
1180 while (res.at(l).isSpace())
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();
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();
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();
1215 if (!font && key == QLatin1String("systemfont"))
1216 sysFont = value.left(value.lastIndexOf(QLatin1Char(':')));
1217 if (!font && key == QLatin1String("font"))
1219 else if (!fg && !paletteAlreadySet) {
1220 if (key == QLatin1String("foreground"))
1222 else if (!bg && key == QLatin1String("background"))
1224 else if (!bg && !button && key == QLatin1String("button.background"))
1226 else if (key == QLatin1String("text.selectbackground")) {
1227 selectBackground = value;
1228 } else if (key == QLatin1String("text.selectforeground")) {
1229 selectForeground = value;
1231 } else if (key == QLatin1String("guieffects"))
1233 // NOTE: if you add more, change the [fbg] stuff above
1239 if (!sysFont.isEmpty())
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
1254 fnt.setRawName(resFont);
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());
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());
1270 if (fnt.pointSize() <= 0 && fnt.pixelSize() <= 0) {
1271 // size is all wrong... fix it
1272 qreal pointSize = fontinfo.pixelSize() * 72. / (float) QX11Info::appDpiY();
1275 fnt.setPointSize(qRound(pointSize));
1280 QApplicationPrivate::setSystemFont(fnt);
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);
1289 (void) QApplication::style(); // trigger creation of application style and system palettes
1295 if (!resBG.isEmpty())
1298 bg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Window);
1300 if (!resFG.isEmpty())
1303 fg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::WindowText);
1305 if (!resButton.isEmpty())
1306 btn = QColor(resButton);
1307 else if (!resBG.isEmpty())
1310 btn = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Button);
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);
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);
1328 QColor highlight, highlightText;
1329 if (!selectBackground.isEmpty() && !selectForeground.isEmpty()) {
1330 highlight = QColor(selectBackground);
1331 highlightText = QColor(selectForeground);
1334 if (highlight.isValid() && highlightText.isValid()) {
1335 pal.setColor(QPalette::Highlight, highlight);
1336 pal.setColor(QPalette::HighlightedText, highlightText);
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);
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);
1355 pal = qt_guiPlatformPlugin()->palette().resolve(pal);
1356 QApplicationPrivate::setSystemPalette(pal);
1357 QColor::setAllowX11ColorNames(allowX11ColorNames);
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")));
1377 QIconLoader::instance()->updateSystemTheme();
1381 // update the supported array
1382 static void qt_get_net_supported()
1387 unsigned long nitems, after;
1388 unsigned char *data = 0;
1390 int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
1391 ATOM(_NET_SUPPORTED), 0, 0,
1392 False, XA_ATOM, &type, &format, &nitems, &after, &data);
1396 if (X11->net_supported_list)
1397 delete [] X11->net_supported_list;
1398 X11->net_supported_list = 0;
1400 if (e == Success && type == XA_ATOM && format == 32) {
1402 ts.open(QIODevice::WriteOnly);
1405 XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
1406 ATOM(_NET_SUPPORTED), offset, 1024,
1407 False, XA_ATOM, &type, &format, &nitems, &after, &data);
1409 if (type == XA_ATOM && format == 32) {
1410 ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long));
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();
1424 for (i = 0; i < nitems; i++)
1425 X11->net_supported_list[i] = a[i];
1426 X11->net_supported_list[nitems] = 0;
1431 bool QX11Data::isSupportedByWM(Atom atom)
1433 if (!X11->net_supported_list)
1436 bool supported = false;
1438 while (X11->net_supported_list[i] != 0) {
1439 if (X11->net_supported_list[i++] == atom) {
1449 // update the virtual roots array
1450 static void qt_get_net_virtual_roots()
1452 if (X11->net_virtual_root_list)
1453 delete [] X11->net_virtual_root_list;
1454 X11->net_virtual_root_list = 0;
1456 if (!X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)))
1462 unsigned long nitems, after;
1463 unsigned char *data;
1465 int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
1466 ATOM(_NET_VIRTUAL_ROOTS), 0, 0,
1467 False, XA_ATOM, &type, &format, &nitems, &after, &data);
1471 if (e == Success && type == XA_ATOM && format == 32) {
1473 ts.open(QIODevice::WriteOnly);
1476 XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
1477 ATOM(_NET_VIRTUAL_ROOTS), offset, 1024,
1478 False, XA_ATOM, &type, &format, &nitems, &after, &data);
1480 if (type == XA_ATOM && format == 32) {
1481 ts.write(reinterpret_cast<char *>(data), nitems * 4);
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();
1495 for (i = 0; i < nitems; i++)
1496 X11->net_virtual_root_list[i] = a[i];
1497 X11->net_virtual_root_list[nitems] = 0;
1501 void qt_net_remove_user_time(QWidget *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;
1513 void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp)
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);
1536 wid = extra->userTimeWindow;
1539 XChangeProperty(X11->display, wid, ATOM(_NET_WM_USER_TIME),
1540 XA_CARDINAL, 32, PropModeReplace, (unsigned char *) ×tamp, 1);
1543 static void qt_check_focus_model()
1547 XGetInputFocus(X11->display, &fw, &unused);
1548 if (fw == PointerRoot)
1549 X11->focus_model = QX11Data::FM_PointerRoot;
1551 X11->focus_model = QX11Data::FM_Other;
1554 #ifndef QT_NO_TABLET
1556 #if !defined (Q_OS_IRIX)
1557 // from include/Xwacom.h
1558 # define XWACOM_PARAM_TOOLID 322
1559 # define XWACOM_PARAM_TOOLSERIAL 323
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 *);
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)
1577 /*****************************************************************************
1578 qt_init() - initializes Qt for X11
1579 *****************************************************************************/
1581 #if !defined(QT_NO_FONTCONFIG)
1582 static void getXDefault(const char *group, const char *key, int *val)
1584 char *str = XGetDefault(X11->display, group, key);
1587 int v = strtol(str, &end, 0);
1590 // otherwise use fontconfig to convert the string to integer
1592 FcNameConstant((FcChar8 *) str, val);
1596 static void getXDefault(const char *group, const char *key, double *val)
1598 char *str = XGetDefault(X11->display, group, key);
1601 double v = QByteArray(str).toDouble(&ok);
1607 static void getXDefault(const char *group, const char *key, bool *val)
1609 char *str = XGetDefault(X11->display, group, key);
1612 if (isupper((int)c))
1614 if (c == 't' || c == 'y' || c == '1')
1616 else if (c == 'f' || c == 'n' || c == '0')
1620 if (isupper((int)c))
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)
1639 X11->display = display;
1640 X11->displayName = 0;
1641 X11->foreignDisplay = (display != 0);
1642 X11->focus_model = -1;
1645 X11->use_xrandr = false;
1646 X11->xrandr_major = 0;
1647 X11->xrandr_eventbase = 0;
1648 X11->xrandr_errorbase = 0;
1651 X11->use_xrender = false;
1652 X11->xrender_major = 0;
1653 X11->xrender_version = 0;
1656 X11->use_xfixes = false;
1657 X11->xfixes_major = 0;
1658 X11->xfixes_eventbase = 0;
1659 X11->xfixes_errorbase = 0;
1662 X11->use_xinput = false;
1663 X11->xinput_major = 0;
1664 X11->xinput_eventbase = 0;
1665 X11->xinput_errorbase = 0;
1667 X11->use_xkb = false;
1669 X11->xkb_eventbase = 0;
1670 X11->xkb_errorbase = 0;
1673 X11->use_mitshm = false;
1674 X11->use_mitshm_pixmaps = false;
1675 X11->mitshm_major = 0;
1677 X11->sip_serial = 0;
1678 X11->net_supported_list = 0;
1679 X11->net_virtual_root_list = 0;
1680 X11->wm_client_leader = 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;
1690 X11->motifdnd_active = false;
1692 X11->default_im = QLatin1String("imsw-multi");
1693 priv->inputContext = 0;
1696 X11->visual_class = -1;
1697 X11->visual_id = -1;
1698 X11->color_count = 0;
1699 X11->custom_cmap = false;
1701 // outside visual/colormap
1702 X11->visual = reinterpret_cast<Visual *>(visual);
1703 X11->colormap = colormap;
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;
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;
1724 int argc = priv->argc;
1725 char **argv = priv->argv;
1728 // Qt part of other application
1730 // Set application name and class
1731 appName = qstrdup("Qt-subapplication");
1732 char *app_class = 0;
1734 const char* p = strrchr(argv[0], '/');
1735 app_class = qstrdup(p ? p + 1 : argv[0]);
1737 app_class[0] = toupper(app_class[0]);
1739 appClass = app_class;
1741 // Qt controls everything (default)
1743 // With the threaded QML renderer, we always need this.
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);
1753 app_class[0] = toupper(app_class[0]);
1755 appClass = app_class;
1758 // Install default error handlers
1759 original_x_errhandler = XSetErrorHandler(qt_x_errhandler);
1760 original_xio_errhandler = XSetIOErrorHandler(qt_xio_errhandler);
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];
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") {
1776 } else if (arg == "-bg" || arg == "-background") {
1779 } else if (arg == "-btn" || arg == "-button") {
1781 appBTNCol = argv[i];
1782 } else if (arg == "-fg" || arg == "-foreground") {
1785 } else if (arg == "-name") {
1788 } else if (arg == "-title") {
1791 } else if (arg == "-geometry") {
1793 mwGeometry = argv[i];
1794 } else if (arg == "-im") {
1796 qt_ximServer = argv[i];
1797 } else if (arg == "-ncols") { // xv and netscape use this name
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;
1816 X11->visual_id = static_cast<int>(strtol(argv[i], 0, 0));
1819 } else if (arg == "-inputstyle") {
1821 QString s = QString::fromLocal8Bit(argv[i]).toLower();
1822 if (s == QLatin1String("onthespot"))
1823 qt_xim_preferred_style = XIMPreeditCallbacks |
1825 else if (s == QLatin1String("overthespot"))
1826 qt_xim_preferred_style = XIMPreeditPosition |
1828 else if (s == QLatin1String("offthespot"))
1829 qt_xim_preferred_style = XIMPreeditArea |
1831 else if (s == QLatin1String("root"))
1832 qt_xim_preferred_style = XIMPreeditNothing |
1836 } else if (arg == "-cmap") { // xv uses this name
1838 X11->custom_cmap = true;
1840 else if (arg == "-sync")
1842 #if defined(QT_DEBUG)
1843 else if (arg == "-nograb")
1844 appNoGrab = !appNoGrab;
1845 else if (arg == "-dograb")
1846 appDoGrab = !appDoGrab;
1849 argv[j++] = argv[i];
1854 #if defined(QT_DEBUG) && defined(Q_OS_LINUX)
1855 if (!appNoGrab && !appDoGrab) {
1857 s.sprintf("/proc/%d/cmdline", getppid());
1859 if (f.open(QIODevice::ReadOnly)) {
1862 while (f.getChar(&c) && c) {
1866 s += QLatin1Char(c);
1868 if (s == QLatin1String("gdb")) {
1870 qDebug("Qt: gdb: -nograb added to command-line options.\n"
1871 "\t Use the -dograb option to enforce grabbing.");
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();
1887 if (appSync) // if "-sync" argument
1888 XSynchronize(X11->display, true);
1891 // Common code, regardless of whether display is foreign.
1895 if (qt_is_gui_used) {
1896 X11->defaultScreen = DefaultScreen(X11->display);
1897 X11->screenCount = ScreenCount(X11->display);
1899 X11->screens = new QX11InfoData[X11->screenCount];
1900 X11->argbVisuals = new Visual *[X11->screenCount];
1901 X11->argbColormaps = new Colormap[X11->screenCount];
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
1908 int widthMM = DisplayWidthMM(X11->display, s);
1910 screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
1915 int heightMM = DisplayHeightMM(X11->display, s);
1916 if (heightMM != 0) {
1917 screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
1922 X11->argbVisuals[s] = 0;
1923 X11->argbColormaps[s] = 0;
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
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;
1949 #endif // QT_NO_XRENDER
1951 #ifndef QT_NO_MITSHM
1954 int mitshm_eventbase;
1955 int mitshm_errorbase;
1957 if (XQueryExtension(X11->display, "MIT-SHM", &X11->mitshm_major,
1958 &mitshm_eventbase, &mitshm_errorbase)
1959 && XShmQueryVersion(X11->display, &mitshm_major, &mitshm_minor,
1962 QString displayName = QLatin1String(XDisplayName(NULL));
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;
1980 #endif // QT_NO_MITSHM
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();
1987 // Support protocols
1990 // Finally create all atoms
1991 qt_x11_create_intern_atoms();
1993 // initialize NET lists
1994 qt_get_net_supported();
1995 qt_get_net_virtual_roots();
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)) {
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"));
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");
2022 (PtrXRRSizes) xrandrLib.resolve("XRRSizes");
2025 X11->ptrXRRSelectInput = XRRSelectInput;
2026 X11->ptrXRRUpdateConfiguration = XRRUpdateConfiguration;
2027 X11->ptrXRRRootToScreen = XRRRootToScreen;
2028 X11->ptrXRRQueryExtension = XRRQueryExtension;
2029 X11->ptrXRRSizes = XRRSizes;
2032 if (X11->ptrXRRQueryExtension
2033 && X11->ptrXRRQueryExtension(X11->display, &X11->xrandr_eventbase, &X11->xrandr_errorbase)) {
2034 // XRandR is supported
2035 X11->use_xrandr = true;
2038 #endif // QT_NO_XRANDR
2040 #ifndef QT_NO_XRENDER
2041 if (X11->use_xrender) {
2042 // XRender is supported, let's see if we have a PictFormat for the
2044 XRenderPictFormat *format =
2045 XRenderFindVisualFormat(X11->display,
2046 (Visual *) QX11Info::appVisual(X11->defaultScreen));
2049 X11->use_xrender = false;
2052 #endif // QT_NO_XRENDER
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);
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.
2075 X11->ptrXFixesQueryVersion(X11->display, &major, &minor);
2076 X11->use_xfixes = (major >= 1);
2077 X11->xfixes_major = major;
2080 #endif // QT_NO_XFIXES
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();
2092 X11->ptrXcursorLibraryLoadCursor =
2093 (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor");
2096 X11->ptrXcursorLibraryLoadCursor = XcursorLibraryLoadCursor;
2097 #endif // QT_RUNTIME_XCURSOR
2098 #endif // QT_NO_XCURSOR
2101 int xsync_evbase, xsync_errbase;
2103 if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase))
2104 XSyncInitialize(X11->display, &major, &minor);
2105 #endif // QT_NO_XSYNC
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();
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");
2127 X11->ptrXineramaQueryScreens = XineramaQueryScreens;
2128 X11->ptrXineramaIsActive = XineramaIsActive;
2129 X11->ptrXineramaQueryExtension = XineramaQueryExtension;
2130 #endif // QT_RUNTIME_XINERAMA
2131 #endif // QT_NO_XINERAMA
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);
2149 #endif // QT_NO_XINPUT
2152 int xkblibMajor = XkbMajorVersion;
2153 int xkblibMinor = XkbMinorVersion;
2154 X11->use_xkb = XkbQueryExtension(X11->display,
2156 &X11->xkb_eventbase,
2157 &X11->xkb_errorbase,
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);
2166 // select for group change events
2167 XkbSelectEventDetails(X11->display,
2170 XkbAllStateComponentsMask,
2173 // current group state is queried when creating the keymapper, no need to do it here
2178 #if !defined(QT_NO_FONTCONFIG)
2180 getXDefault("Xft", FC_DPI, &dpi);
2182 for (int s = 0; s < ScreenCount(X11->display); ++s) {
2183 QX11Info::setAppDpiX(s, dpi);
2184 QX11Info::setAppDpiY(s, dpi);
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);
2197 case SubPixelUnknown:
2198 subpixel = FC_RGBA_UNKNOWN;
2200 case SubPixelHorizontalRGB:
2201 subpixel = FC_RGBA_RGB;
2203 case SubPixelHorizontalBGR:
2204 subpixel = FC_RGBA_BGR;
2206 case SubPixelVerticalRGB:
2207 subpixel = FC_RGBA_VRGB;
2209 case SubPixelVerticalBGR:
2210 subpixel = FC_RGBA_VBGR;
2213 subpixel = FC_RGBA_NONE;
2219 char *rgba = XGetDefault(X11->display, "Xft", FC_RGBA);
2222 int v = strtol(rgba, &end, 0);
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;
2239 X11->screens[s].subpixel = subpixel;
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);
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);
2252 #endif // QT_NO_XRENDER
2254 // initialize key mapper
2255 QKeyMapper::changeKeyboard();
2257 // Misc. initialization
2258 #if 0 //disabled for now..
2259 QSegfaultHandler::initialize(priv->argv, priv->argc);
2261 QCursorData::initialize();
2263 QFont::initialize();
2265 if(qt_is_gui_used) {
2266 qApp->setObjectName(QString::fromLocal8Bit(appName));
2269 for (screen = 0; screen < X11->screenCount; ++screen) {
2270 XSelectInput(X11->display, QX11Info::appRootWindow(screen),
2271 KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask);
2273 #ifndef QT_NO_XRANDR
2274 if (X11->use_xrandr)
2275 X11->ptrXRRSelectInput(X11->display, QX11Info::appRootWindow(screen), True);
2276 #endif // QT_NO_XRANDR
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
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;
2298 unsigned long length, after;
2303 if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
2304 X11->desktopEnvironment = DE_KDE;
2305 X11->desktopVersion = qgetenv("KDE_SESSION_VERSION").toInt();
2309 if (qgetenv("DESKTOP_SESSION") == "gnome") {
2310 X11->desktopEnvironment = DE_GNOME;
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;
2320 rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_DT_SAVE_MODE),
2321 0, 2, False, XA_STRING, &type, &format, &length,
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;
2331 // We got the property but it wasn't xfce4. Free data before it gets overwritten.
2336 rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
2337 0, 1, False, AnyPropertyType, &type, &format, &length,
2339 if (rc == Success && length) {
2340 // DTWM is running, meaning most likely CDE is running...
2341 X11->desktopEnvironment = DE_CDE;
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;
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);
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;
2379 XFree((char *)data);
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);
2387 qt_set_input_encoding();
2389 qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol);
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
2398 : (int) (((QX11Info::appDpiY() >= 95 ? 17. : 12.) *
2399 72. / (float) QX11Info::appDpiY()) + 0.5));
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"),
2405 QApplicationPrivate::setSystemFont(f);
2408 #if !defined (QT_NO_TABLET)
2409 if (X11->use_xinput) {
2415 XDeviceInfo *devices = 0, *devs;
2416 XInputClassInfo *ip;
2422 if (X11->ptrXListInputDevices) {
2423 devices = X11->ptrXListInputDevices(X11->display, &ndev);
2425 qWarning("QApplication: Failed to get list of tablet devices");
2429 QTabletEvent::TabletDevice deviceType;
2430 for (devs = devices, i = 0; i < ndev && devs; i++, devs++) {
2432 deviceType = QTabletEvent::NoDevice;
2436 #if defined(Q_OS_IRIX)
2437 QString devName = QString::fromLocal8Bit(devs->name).toLower();
2438 if (devName == QLatin1String(WACOM_NAME)) {
2439 deviceType = QTabletEvent::Stylus;
2443 if (devs->type == ATOM(XWacomStylus) || devs->type == ATOM(XTabletStylus)) {
2444 deviceType = QTabletEvent::Stylus;
2445 if (wacomDeviceName()->isEmpty())
2446 wacomDeviceName()->append(devs->name);
2448 } else if (devs->type == ATOM(XWacomEraser) || devs->type == ATOM(XTabletEraser)) {
2449 deviceType = QTabletEvent::XFreeEraser;
2453 if (deviceType == QTabletEvent::NoDevice)
2456 if (gotStylus || gotEraser) {
2457 if (X11->ptrXOpenDevice)
2458 dev = X11->ptrXOpenDevice(X11->display, devs->id);
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;
2476 if (dev->num_classes > 0) {
2477 for (ip = dev->classes, j = 0; j < dev->num_classes;
2479 switch (ip->input_class) {
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;
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;
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;
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
2533 char returnString[SGIDeviceRtrnLen];
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();
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;
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;
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;
2569 // got the max pressure no need to go further...
2572 any = (XAnyClassPtr) ((char *) any + any->length);
2573 } // end of for loop
2575 tablet_devices()->append(device_data);
2576 } // if (gotStylus || gotEraser)
2578 if (X11->ptrXFreeDeviceList)
2579 X11->ptrXFreeDeviceList(devices);
2581 #endif // QT_NO_TABLET
2583 X11->startupId = getenv("DESKTOP_STARTUP_ID");
2584 if (X11->startupId) {
2585 #ifndef QT_NO_UNSETENV
2586 unsetenv("DESKTOP_STARTUP_ID");
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="));
2594 // read some non-GUI settings when not using the X server...
2596 if (QApplication::desktopSettingsAware()) {
2597 QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
2598 settings.beginGroup(QLatin1String("Qt"));
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++);
2612 QString defaultcodec = settings.value(QLatin1String("defaultCodec"),
2613 QVariant(QLatin1String("none"))).toString();
2614 if (defaultcodec != QLatin1String("none")) {
2615 QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1());
2617 QTextCodec::setCodecForTr(codec);
2620 settings.endGroup(); // Qt
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");
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;
2644 void QApplicationPrivate::initializeWidgetPaletteHash()
2648 /*****************************************************************************
2649 qt_cleanup() - cleans up when the application is finished
2650 *****************************************************************************/
2654 if (app_save_rootinfo) // root window must keep state
2657 if (qt_is_gui_used) {
2658 QPixmapCache::clear();
2659 QCursorData::cleanup();
2661 QColormap::cleanup();
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);
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);
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);
2683 #if !defined(QT_NO_IM)
2684 delete QApplicationPrivate::inputContext;
2685 QApplicationPrivate::inputContext = 0;
2688 // Reset the error handlers
2690 XSync(X11->display, False); // sync first to process all possible errors
2691 XSetErrorHandler(original_x_errhandler);
2692 XSetIOErrorHandler(original_xio_errhandler);
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]);
2701 if (qt_is_gui_used && !X11->foreignDisplay)
2702 XCloseDisplay(X11->display); // close X display
2705 delete [] X11->screens;
2706 delete [] X11->argbVisuals;
2707 delete [] X11->argbColormaps;
2709 if (X11->foreignDisplay) {
2710 delete [] (char *)appName;
2714 delete [] (char *)appClass;
2717 if (X11->net_supported_list)
2718 delete [] X11->net_supported_list;
2719 X11->net_supported_list = 0;
2721 if (X11->net_virtual_root_list)
2722 delete [] X11->net_virtual_root_list;
2723 X11->net_virtual_root_list = 0;
2730 /*****************************************************************************
2731 Platform specific global and internal functions
2732 *****************************************************************************/
2734 void qt_save_rootinfo() // save new root info
2738 unsigned long length, after;
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));
2750 Pixmap dummy = XCreatePixmap(X11->display, QX11Info::appRootWindow(),
2752 XChangeProperty(X11->display, QX11Info::appRootWindow(),
2753 ATOM(_XSETROOT_ID), XA_PIXMAP, 32,
2754 PropModeReplace, (uchar *)&dummy, 1);
2755 XSetCloseDownMode(X11->display, RetainPermanent);
2759 XFree((char *)data);
2762 void qt_updated_rootinfo()
2764 app_save_rootinfo = true;
2767 // ### Cleanup, this function is not in use!
2768 bool qt_wstate_iconified(WId winid)
2772 unsigned long length, after;
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);
2787 QString QApplicationPrivate::appName() const
2789 return QString::fromLocal8Bit(QT_PREPEND_NAMESPACE(appName));
2792 const char *QX11Info::appClass() // get application class
2794 return QT_PREPEND_NAMESPACE(appClass);
2797 bool qt_nograb() // application no-grab option
2799 #if defined(QT_DEBUG)
2807 /*****************************************************************************
2808 Platform specific QApplication members
2809 *****************************************************************************/
2812 void QApplication::setMainWidget(QWidget *mainWidget)
2815 if (mainWidget && mainWidget->parentWidget() && mainWidget->isWindow())
2816 qWarning("QApplication::setMainWidget: New main widget (%s/%s) "
2818 mainWidget->metaObject()->className(), mainWidget->objectName().toLocal8Bit().constData());
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);
2828 void QApplicationPrivate::applyX11SpecificCommandLineArguments(QWidget *main_widget)
2830 static bool beenHereDoneThat = false;
2831 if (beenHereDoneThat)
2833 beenHereDoneThat = true;
2834 Q_ASSERT(main_widget->testAttribute(Qt::WA_WState_Created));
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());
2841 if (mwGeometry) { // parse geometry
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;
2862 if ((m & YNegative)) {
2863 y = QApplication::desktop()->height() + y - h;
2865 main_widget->setGeometry(x, y, w, h);
2869 #ifndef QT_NO_CURSOR
2871 /*****************************************************************************
2872 QApplication cursor stack
2873 *****************************************************************************/
2875 void QApplication::setOverrideCursor(const QCursor &cursor)
2877 qApp->d_func()->cursor_list.prepend(cursor);
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);
2885 XFlush(X11->display); // make X execute it NOW
2888 void QApplication::restoreOverrideCursor()
2890 if (qApp->d_func()->cursor_list.isEmpty())
2892 qApp->d_func()->cursor_list.removeFirst();
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);
2901 XFlush(X11->display);
2908 /*****************************************************************************
2909 Routines to find a Qt widget from a screen position
2910 *****************************************************************************/
2912 Window QX11Data::findClientWindow(Window win, Atom property, bool leaf)
2916 ulong nitems, after;
2918 Window root, parent, target=0, *children=0;
2920 if (XGetWindowProperty(X11->display, win, property, 0, 0, false, AnyPropertyType,
2921 &type, &format, &nitems, &after, &data) == Success) {
2923 XFree((char *)data);
2927 if (!XQueryTree(X11->display,win,&root,&parent,&children,&nchildren)) {
2929 XFree((char *)children);
2932 for (i=nchildren-1; !target && i >= 0; i--)
2933 target = X11->findClientWindow(children[i], property, leaf);
2935 XFree((char *)children);
2939 QWidget *QApplication::topLevelAt(const QPoint &p)
2945 int screen = QCursor::x11Screen();
2951 if (!XTranslateCoordinates(X11->display,
2952 QX11Info::appRootWindow(screen),
2953 QX11Info::appRootWindow(screen),
2954 x, y, &unused, &unused, &target)) {
2957 if (!target || target == QX11Info::appRootWindow(screen))
2960 w = QWidget::find((WId)target);
2963 X11->ignoreBadwindow();
2964 target = X11->findClientWindow(target, ATOM(WM_STATE), true);
2965 if (X11->badwindow())
2967 w = QWidget::find((WId)target);
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())
2985 if (ctarget == wid) {
2997 return w ? w->window() : 0;
3001 void QApplication::syncX()
3004 XSync(X11->display, False); // don't discard events
3008 void QApplication::beep()
3011 XBell(X11->display, 0);
3016 void QApplication::alert(QWidget *widget, int msec)
3018 if (!QApplicationPrivate::checkInstance("alert"))
3021 QWidgetList windowsToMark;
3023 windowsToMark += topLevelWidgets();
3025 windowsToMark.append(widget->window());
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));
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);
3040 qApp->d_func()->alertTimerHash.insert(window, timer);
3047 void QApplicationPrivate::_q_alertTimeOut()
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();
3064 /*****************************************************************************
3065 Special lookup functions for windows that have been reparented recently
3066 *****************************************************************************/
3068 static QWidgetMapper *wPRmapper = 0; // alternative widget mapper
3070 void qPRCreate(const QWidget *widget, Window oldwin)
3071 { // QWidget::reparent mechanism
3073 wPRmapper = new QWidgetMapper;
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
3080 void qPRCleanup(QWidget *widget)
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()) {
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
3095 if (wPRmapper->size() == 0) { // became empty
3096 delete wPRmapper; // then reset alt mapper
3101 static QETWidget *qPRFindWidget(Window oldwin)
3103 return wPRmapper ? (QETWidget*)wPRmapper->value((int)oldwin, 0) : 0;
3106 int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
3108 if (w && !w->internalWinId())
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);
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))
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();
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);
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];
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);
3173 if (passive_only) return 0;
3174 // All other are interactions
3177 X11->motifdndHandle(widget, event, passive_only);
3183 int QApplication::x11ProcessEvent(XEvent* event)
3186 QScopedLoopLevelCounter loopLevelCounter(d->threadData);
3189 //qDebug() << "QApplication::x11ProcessEvent:" << event->type;
3191 switch (event->type) {
3193 pressed_window = event->xbutton.window;
3194 X11->userTime = event->xbutton.time;
3195 // fallthrough intended
3197 X11->time = event->xbutton.time;
3200 X11->time = event->xmotion.time;
3203 X11->userTime = event->xkey.time;
3204 // fallthrough intended
3206 X11->time = event->xkey.time;
3208 case PropertyNotify:
3209 X11->time = event->xproperty.time;
3213 X11->time = event->xcrossing.time;
3215 case SelectionClear:
3216 X11->time = event->xselectionclear.time;
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;
3231 QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
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
3241 widget = qPRFindWidget(event->xany.window);
3245 else if (widget->testAttribute(Qt::WA_WState_Reparented))
3246 qPRCleanup(widget); // remove from alt mapper
3249 QETWidget *keywidget=0;
3251 if (event->type==XKeyPress || event->type==XKeyRelease) {
3252 keywidget = (QETWidget*)QWidget::keyboardGrabber();
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;
3261 keywidget = (QETWidget*)widget->window();
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.
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)
3280 QInputContext *qic = keywidget->inputContext();
3281 if(qic && qic->x11FilterEvent(keywidget, event))
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
3289 if ((event->type == XKeyPress || event->type == XKeyRelease)) {
3292 Qt::KeyboardModifiers modifiers;
3297 qt_keymapper_private()->translateKeyEventInternal(keywidget, event, keySym, count,
3298 text, modifiers, code, type, false);
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))
3310 if (XFilterEvent(event, XNone))
3314 if (qt_x11EventFilter(event)) // send through app filter
3317 if (event->type == MappingNotify) {
3318 // keyboard mapping changed
3319 XRefreshKeyboardMapping(&event->xmapping);
3321 QKeyMapper::changeKeyboard();
3325 else if (X11->use_xkb && event->type == X11->xkb_eventbase) {
3326 XkbAnyEvent *xkbevent = (XkbAnyEvent *) event;
3327 switch (xkbevent->xkb_type) {
3328 case XkbStateNotify:
3330 XkbStateNotifyEvent *xkbstateevent = (XkbStateNotifyEvent *) xkbevent;
3331 if ((xkbstateevent->changed & XkbGroupStateMask) != 0) {
3332 qt_keymapper_private()->xkb_currentGroup = xkbstateevent->group;
3333 QKeyMapper::changeKeyboard();
3343 if (!widget) { // don't know this windows
3344 QWidget* popup = QApplication::activePopupWidget();
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
3356 // Danger - make sure we don't lock the server
3357 switch (event->type) {
3364 } while ((popup = qApp->activePopupWidget()));
3371 if (event->type == XKeyPress || event->type == XKeyRelease)
3372 widget = keywidget; // send XKeyEvents through keywidget->x11Event()
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);
3382 if (widget->x11Event(event)) // send through widget filter
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);
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);
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);
3416 QApplication::sendEvent(desktop, &e);
3418 #endif // QT_NO_XRANDR
3420 #ifndef QT_NO_XFIXES
3421 if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) {
3422 XFixesSelectionNotifyEvent *req = reinterpret_cast<XFixesSelectionNotifyEvent *>(event);
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;
3429 if (!XCheckIfEvent(X11->display, &ev, &qt_xfixes_scanner, (XPointer)&xfixes_event))
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();
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();
3445 #endif // QT_NO_XFIXES
3447 switch (event->type) {
3449 case ButtonRelease: // mouse event
3450 if (!d->inPopupMode() && !QWidget::mouseGrabber() && pressed_window != widget->internalWinId()
3451 && (widget = (QETWidget*) QWidget::find((WId)pressed_window)) == 0)
3453 // fall through intended
3455 if (event->xbutton.root != RootWindow(X11->display, widget->x11Info().screen())
3456 && ! qt_xdnd_dragging) {
3457 while (activePopupWidget())
3458 activePopupWidget()->close();
3461 if (event->type == ButtonPress)
3462 qt_net_update_user_time(widget->window(), X11->userTime);
3463 // fall through intended
3465 #if !defined(QT_NO_TABLET)
3466 if (!qt_tabletChokeMouse) {
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();
3480 widget->translateMouseEvent(event);
3481 #if !defined(QT_NO_TABLET)
3483 qt_tabletChokeMouse = false;
3488 case XKeyPress: // keyboard event
3489 qt_net_update_user_time(widget->window(), X11->userTime);
3490 // fallthrough intended
3493 if (keywidget && keywidget->isEnabled()) { // should always exist
3494 // qDebug("sending key event");
3495 qt_keymapper_private()->translateKeyEvent(keywidget, event, grabbed);
3500 case GraphicsExpose:
3501 case Expose: // paint event
3502 widget->translatePaintEvent(event);
3505 case ConfigureNotify: // window move/resize event
3506 if (event->xconfigure.event == event->xconfigure.window)
3507 widget->translateConfigEvent(event);
3510 case XFocusIn: { // got focus
3511 if ((widget->windowType() == Qt::Desktop))
3513 if (d->inPopupMode()) // some delayed focus event to ignore
3515 if (!widget->isWindow())
3517 if (event->xfocus.detail != NotifyAncestor &&
3518 event->xfocus.detail != NotifyInferior &&
3519 event->xfocus.detail != NotifyNonlinear)
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();
3531 case XFocusOut: // lost focus
3532 if ((widget->windowType() == Qt::Desktop))
3534 if (!widget->isWindow())
3536 if (event->xfocus.mode == NotifyGrab) {
3537 qt_xfocusout_grab_counter++;
3540 if (event->xfocus.detail != NotifyAncestor &&
3541 event->xfocus.detail != NotifyNonlinearVirtual &&
3542 event->xfocus.detail != NotifyNonlinear)
3544 if (!d->inPopupMode() && widget == QApplicationPrivate::active_window) {
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);
3553 && w2->windowType() != Qt::Desktop
3554 && !d->inPopupMode() // some delayed focus event to ignore
3556 && (ev.xfocus.detail == NotifyAncestor
3557 || ev.xfocus.detail == NotifyInferior
3558 || ev.xfocus.detail == NotifyNonlinear))
3559 focus_will_change = true;
3561 XPutBackEvent(X11->display, &ev);
3563 if (!focus_will_change)
3568 case EnterNotify: { // enter window
3569 if (QWidget::mouseGrabber() && (!d->inPopupMode() || widget->window() != activePopupWidget()))
3571 if ((event->xcrossing.mode != NotifyNormal
3572 && event->xcrossing.mode != NotifyUngrab)
3573 || event->xcrossing.detail == NotifyVirtual
3574 || event->xcrossing.detail == NotifyNonlinearVirtual)
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);
3584 if (qt_button_down && !d->inPopupMode())
3587 QWidget *alien = widget->childAt(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x,
3588 event->xcrossing.y)));
3589 QWidget *enter = alien ? alien : widget;
3591 if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId())
3592 leave = qt_last_mouse_receiver;
3594 leave = QWidget::find(curWin);
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
3605 case LeaveNotify: { // leave window
3606 QWidget *mouseGrabber = QWidget::mouseGrabber();
3607 if (mouseGrabber && !d->inPopupMode())
3609 if (curWin && widget->internalWinId() != curWin)
3611 if ((event->xcrossing.mode != NotifyNormal
3612 && event->xcrossing.mode != NotifyUngrab)
3613 || event->xcrossing.detail == NotifyInferior)
3615 if (!(widget->windowType() == Qt::Desktop))
3616 widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it
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))
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)
3632 enter = event_widget;
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);
3645 if ((! enter || (enter->windowType() == Qt::Desktop)) &&
3646 event->xcrossing.focus && widget == QApplicationPrivate::active_window &&
3647 X11->focus_model == QX11Data::FM_PointerRoot // PointerRoot mode
3652 if (qt_button_down && !d->inPopupMode())
3656 QApplicationPrivate::dispatchEnterLeave(widget, 0);
3659 QWidget *alienEnter = enter->childAt(enterPoint);
3664 QWidget *leave = qt_last_mouse_receiver ? qt_last_mouse_receiver : widget;
3665 QWidget *activePopupWidget = qApp->activePopupWidget();
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))))
3675 QApplicationPrivate::dispatchEnterLeave(enter, leave);
3676 qt_last_mouse_receiver = enter;
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
3684 qt_last_mouse_receiver = 0;
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;
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;
3699 QApplication::sendSpontaneousEvent(widget, &e);
3700 widget->d_func()->hideChildren(true);
3704 if (!widget->d_func()->topData()->validWMState && X11->deferred_map.removeAll(widget))
3705 widget->doDeferredMap();
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
3715 bool pendingHide = widget->testAttribute(Qt::WA_WState_ExplicitShowHide) && widget->testAttribute(Qt::WA_WState_Hidden);
3716 widget->d_func()->topData()->waitingForMapNotify = 0;
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);
3724 QApplication::sendSpontaneousEvent(widget, &e);
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
3731 widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
3732 widget->setAttribute(Qt::WA_WState_Visible, true);
3735 if (pendingHide) // hide the window
3736 XWithdrawWindow(X11->display, widget->internalWinId(), widget->x11Info().screen());
3740 case ClientMessage: // client message
3741 return x11ClientMessage(widget,event,False);
3743 case ReparentNotify: { // window manager reparents
3744 // compress old reparent events to self
3746 while (XCheckTypedWindowEvent(X11->display,
3747 widget->effectiveWinId(),
3750 if (ev.xreparent.window != ev.xreparent.event) {
3751 XPutBackEvent(X11->display, &ev);
3755 if (widget->isWindow()) {
3756 QTLWExtra *topData = widget->d_func()->topData();
3758 // store the parent. Useful for many things, embedding for instance.
3759 topData->parentWinId = event->xreparent.parent;
3761 // the widget frame strut should also be invalidated
3762 widget->data->fstrut_dirty = 1;
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
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;
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;
3793 case SelectionRequest: {
3794 XSelectionRequestEvent *req = &event->xselectionrequest;
3798 if (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)) {
3799 X11->xdndHandleSelectionRequest(req);
3801 } else if (qt_clipboard) {
3802 QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
3803 QApplication::sendSpontaneousEvent(qt_clipboard, &e);
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)))
3813 if (qt_clipboard && !X11->use_xfixes) {
3814 QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
3815 QApplication::sendSpontaneousEvent(qt_clipboard, &e);
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)))
3827 QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event));
3828 QApplication::sendSpontaneousEvent(qt_clipboard, &e);
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();
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();
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();
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();
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);
3870 } else if (widget) {
3871 widget->translatePropertyEvent(event);
3873 return -1; // don't know this window
3884 bool QApplication::x11EventFilter(XEvent *)
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..
3897 QApplicationPrivate::enterModal()
3900 QWidget *widget A modal widget
3902 QApplicationPrivate::leaveModal()
3903 Leaves modal state for a widget
3905 QWidget *widget A modal widget
3906 *****************************************************************************/
3908 bool QApplicationPrivate::modalState()
3910 return app_do_modal;
3913 void QApplicationPrivate::enterModal_sys(QWidget *widget)
3915 if (!qt_modal_stack)
3916 qt_modal_stack = new QWidgetList;
3918 QWidget *leave = qt_last_mouse_receiver;
3920 leave = QWidget::find((WId)curWin);
3921 QApplicationPrivate::dispatchEnterLeave(0, leave);
3922 qt_modal_stack->insert(0, widget);
3923 app_do_modal = true;
3925 qt_last_mouse_receiver = 0;
3928 void QApplicationPrivate::leaveModal_sys(QWidget *widget)
3930 if (qt_modal_stack && qt_modal_stack->removeAll(widget)) {
3931 if (qt_modal_stack->isEmpty()) {
3932 delete qt_modal_stack;
3934 QPoint p(QCursor::pos());
3935 QWidget* w = QApplication::widgetAt(p.x(), p.y());
3936 QWidget *leave = qt_last_mouse_receiver;
3938 leave = QWidget::find((WId)curWin);
3939 if (QWidget *grabber = QWidget::mouseGrabber()) {
3944 QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event
3945 curWin = w ? w->effectiveWinId() : 0;
3946 qt_last_mouse_receiver = w;
3949 app_do_modal = qt_modal_stack != 0;
3952 bool qt_try_modal(QWidget *widget, XEvent *event)
3954 if (qt_xdnd_dragging) {
3955 // allow mouse events while DnD is active
3956 switch (event->type) {
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))
3974 if (QApplicationPrivate::tryModalHelper(widget))
3977 // disallow mouse/key events
3978 switch (event->type) {
3996 /*****************************************************************************
3997 Popup widget mechanism
4000 Adds a widget to the list of popup widgets
4002 QWidget *widget The popup widget to be added
4005 Removes a widget from the list of popup widgets
4007 QWidget *widget The popup widget to be removed
4008 *****************************************************************************/
4011 static int openPopupCount = 0;
4012 void QApplicationPrivate::openPopup(QWidget *popup)
4016 if (!QApplicationPrivate::popupWidgets) { // create list
4017 QApplicationPrivate::popupWidgets = new QWidgetList;
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();
4035 XUngrabKeyboard(dpy, X11->time);
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);
4053 void QApplicationPrivate::closePopup(QWidget *popup)
4056 if (!QApplicationPrivate::popupWidgets)
4058 QApplicationPrivate::popupWidgets->removeAll(popup);
4059 if (popup == qt_popup_down) {
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;
4076 // transfer grab back to mouse grabber if any, otherwise release the grab
4077 if (QWidgetPrivate::mouseGrabber != 0)
4078 QWidgetPrivate::mouseGrabber->grabMouse();
4080 XUngrabPointer(dpy, X11->time);
4082 // transfer grab back to keyboard grabber if any, otherwise release the grab
4083 if (QWidgetPrivate::keyboardGrabber != 0)
4084 QWidgetPrivate::keyboardGrabber->grabKeyboard();
4086 XUngrabKeyboard(dpy, X11->time);
4090 if (QApplicationPrivate::active_window) {
4091 if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) {
4092 if (fw != QApplication::focusWidget()) {
4093 fw->setFocus(Qt::PopupFocusReason);
4095 QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
4096 q->sendEvent(fw, &e);
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
4105 QWidget* aw = QApplicationPrivate::popupWidgets->last();
4106 if (QWidget *fw = aw->focusWidget())
4107 fw->setFocus(Qt::PopupFocusReason);
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();
4125 XUngrabKeyboard(dpy, X11->time);
4132 /*****************************************************************************
4133 Event translation; translates X11 events to Qt events
4134 *****************************************************************************/
4137 // Mouse event translation
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.
4143 static Qt::MouseButtons translateMouseButtons(int s)
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;
4155 Qt::KeyboardModifiers QX11Data::translateModifiers(int s)
4157 Qt::KeyboardModifiers ret = 0;
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;
4171 bool QETWidget::translateMouseEvent(const XEvent *event)
4173 if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
4174 Q_ASSERT(internalWinId());
4177 QEvent::Type type; // event parameters
4180 Qt::MouseButton button = Qt::NoButton;
4181 Qt::MouseButtons buttons;
4182 Qt::KeyboardModifiers modifiers;
4185 if (qt_sm_blockUserInput) // block user interaction during session management
4188 if (event->type == MotionNotify) { // mouse move
4189 if (event->xmotion.root != RootWindow(X11->display, x11Info().screen()) &&
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);
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);
4216 if (!qt_x11EventFilter(&nextEvent)
4217 && !x11Event(&nextEvent)) // send event through filter
4218 lastMotion = nextEvent.xmotion;
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)
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)
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;
4263 // the fancy mouse wheel.
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
4273 while (XCheckTypedWindowEvent(X11->display, effectiveWinId(), ButtonPress, &xevent)){
4274 if (xevent.xbutton.button != event->xbutton.button){
4275 XPutBackEvent(X11->display, &xevent);
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);
4294 case 8: button = Qt::XButton1; break;
4295 case 9: button = Qt::XButton2; break;
4297 if (event->type == ButtonPress) { // mouse button pressed
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);
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;
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;
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
4329 type = QEvent::MouseButtonPress;
4330 mouseButtonPressTime = event->xbutton.time;
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
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);
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;
4355 type = QEvent::MouseButtonRelease;
4358 mouseActWindow = effectiveWinId(); // save some event params
4359 mouseButtonState = buttons;
4360 if (type == 0) // don't send event
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)
4369 if ((windowType() == Qt::Popup) && rect().contains(pos) && 0)
4371 else // send to last popup
4372 pos = popup->mapFromGlobal(globalPos);
4374 bool releaseAfter = false;
4375 QWidget *popupChild = popup->childAt(pos);
4377 if (popup != qt_popup_down){
4383 case QEvent::MouseButtonPress:
4384 case QEvent::MouseButtonDblClick:
4385 qt_button_down = popupChild;
4386 qt_popup_down = popup;
4388 case QEvent::MouseButtonRelease:
4389 releaseAfter = true;
4392 break; // nothing for mouse move
4395 int oldOpenPopupCount = openPopupCount;
4397 if (popup->isEnabled()) {
4399 replayPopupMouseEvent = false;
4400 QWidget *receiver = popup;
4401 QPoint widgetPos = pos;
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);
4412 // close disabled popups when a mouse button is pressed or released
4414 case QEvent::MouseButtonPress:
4415 case QEvent::MouseButtonDblClick:
4416 case QEvent::MouseButtonRelease:
4424 if (qApp->activePopupWidget() != activePopupWidget
4425 && replayPopupMouseEvent) {
4426 // the active popup was closed, replay the mouse event
4427 if (!(windowType() == Qt::Popup)) {
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);
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);
4446 replayPopupMouseEvent = false;
4447 } else if (type == QEvent::MouseButtonPress
4448 && button == Qt::RightButton
4449 && (openPopupCount == oldOpenPopupCount)) {
4450 QWidget *popupEvent = popup;
4452 popupEvent = qt_button_down;
4454 popupEvent = popupChild;
4455 QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers);
4456 QApplication::sendSpontaneousEvent(popupEvent, &e);
4464 QWidget *alienWidget = childAt(pos);
4465 QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type, buttons,
4466 qt_button_down, alienWidget);
4468 if (type == QEvent::MouseButtonRelease)
4469 QApplicationPrivate::mouse_buttons &= ~button;
4470 return false; // don't send event
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);
4489 // Wheel event translation
4491 bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta,
4492 Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
4493 Qt::Orientation orient)
4495 const QPoint globalPos = QPoint(global_x, global_y);
4496 QPoint pos = mapFromGlobal(globalPos);
4497 QWidget *widget = childAt(pos);
4500 else if (!widget->internalWinId())
4501 pos = widget->mapFromGlobal(globalPos);
4504 qDebug() << "QETWidget::translateWheelEvent: receiver:" << widget << "pos:" << pos;
4507 // send the event to the widget or its ancestors
4509 QWidget* popup = qApp->activePopupWidget();
4510 if (popup && window() != popup)
4512 #ifndef QT_NO_WHEELEVENT
4513 QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
4514 if (QApplication::sendSpontaneousEvent(widget, &e))
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)
4526 #ifndef QT_NO_WHEELEVENT
4527 QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient);
4528 if (QApplication::sendSpontaneousEvent(widget, &e))
4537 // XInput Translation Event
4539 #if !defined (QT_NO_TABLET)
4541 #if !defined (Q_OS_IRIX)
4542 void fetchWacomToolId(int &deviceType, qint64 &serialId)
4544 if (ptrWacomConfigInit == 0) // we actually have the lib
4546 WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0);
4549 WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData());
4554 ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLSERIAL, &serialInt, 1, keys);
4555 serialId = serialInt;
4557 ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLID, &toolId, 1, keys);
4559 case 0x007: /* Mouse 4D and 2D */
4560 case 0x017: /* Intuos3 2D Mouse */
4563 deviceType = QTabletEvent::FourDMouse;
4565 case 0x096: /* Lens cursor */
4566 case 0x097: /* Intuos3 Lens cursor */
4567 deviceType = QTabletEvent::Puck;
4570 case 0x81b: /* Intuos3 Classic Pen Eraser */
4571 case 0x82a: /* Eraser */
4572 case 0x82b: /* Intuos3 Grip Pen Eraser */
4575 case 0x91b: /* Intuos3 Airbrush Eraser */
4577 deviceType = QTabletEvent::XFreeEraser;
4581 case 0x913: /* Intuos3 Airbrush */
4583 deviceType = QTabletEvent::Airbrush;
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 */
4596 case 0x885: /* Intuos3 Marker Pen */
4597 default: /* Unknown tool */
4598 deviceType = QTabletEvent::Stylus;
4601 /* Close device and return */
4602 ptrWacomConfigCloseDevice (device);
4603 ptrWacomConfigTerm(config);
4607 struct qt_tablet_motion_data
4609 bool filterByWidget;
4610 const QWidget *widget;
4611 const QWidget *etWidget;
4612 int tabletMotionType;
4613 bool error; // found a reason to stop searching
4616 static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg)
4618 qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
4622 if (event->type == MotionNotify)
4625 data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between.
4629 static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg)
4631 qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg;
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);
4643 if (w == data->widget)
4650 data->error = event->type != MotionNotify; // we stop compression when another event gets in between.
4654 bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet)
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...
4661 XInputClass *iClass;
4666 Q_ASSERT(tablet != 0);
4676 qreal tangentialPressure = 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;
4684 Qt::KeyboardModifiers modifiers = 0;
4685 #if !defined (Q_OS_IRIX)
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;
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;
4701 t = QEvent::TabletRelease;
4703 button = (XDeviceButtonEvent*)ev;
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;
4710 } else { // Proximity
4711 if (ev->type == tablet->xinput_proximity_in)
4712 t = QEvent::TabletEnterProximity;
4714 t = QEvent::TabletLeaveProximity;
4715 proximity = (const XProximityNotifyEvent*)ev;
4716 #if !defined (Q_OS_IRIX)
4717 device_id = proximity->deviceid;
4722 #if defined (Q_OS_IRIX)
4723 QRect screenArea = qApp->desktop()->screenGeometry(this);
4724 s = XQueryDeviceState(X11->display, static_cast<XDevice *>(tablet->device));
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) {
4737 pointerType = QTabletEvent::Puck;
4740 pointerType = QTabletEvent::Pen;
4743 pointerType = QTabletEvent::Eraser;
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) {
4751 deviceType = QTabletEvent::Stylus;
4754 deviceType = QTabletEvent::Airbrush;
4757 deviceType = QTabletEvent::FourDMouse;
4760 deviceType = QTabletEvent::Puck;
4763 deviceType = QTabletEvent::RotationStylus;
4767 pointerType = QTabletEvent::UnknownPointer;
4768 deviceType = QTabletEvent::NoDevice;
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);
4787 hiRes = tablet->scaleCoord(vs->valuators[WAC_XCOORD_I], vs->valuators[WAC_YCOORD_I],
4788 screenArea.x(), screenArea.width(),
4789 screenArea.y(), screenArea.height());
4793 iClass = reinterpret_cast<XInputClass*>(reinterpret_cast<char*>(iClass) + iClass->length);
4795 XFreeDeviceState(s);
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;
4812 fetchWacomToolId(deviceType, uid);
4814 QRect screenArea = qApp->desktop()->rect();
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) {
4837 if (deviceType == QTabletEvent::Airbrush) {
4838 tangentialPressure = rotation;
4843 if (tablet->widgetToGetPress) {
4844 w = tablet->widgetToGetPress;
4846 QWidget *child = w->childAt(curr);
4850 curr = w->mapFromGlobal(global);
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;
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);
4865 QApplication::sendSpontaneousEvent(qApp, &e);
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);
4879 bool reinsertMouseEvent = false;
4880 XEvent mouseMotionEvent;
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;
4890 // Now discard any duplicate tablet events.
4891 tabletMotionData.error = false;
4893 while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) {
4894 // just discard the event
4898 if (reinsertMouseEvent) {
4899 XPutBackEvent(X11->display, &mouseMotionEvent);
4907 bool QETWidget::translatePropertyEvent(const XEvent *event)
4910 if (!isWindow()) return true;
4914 unsigned char *data = 0;
4915 unsigned long nitems, after;
4917 if (event->xproperty.atom == ATOM(_KDE_NET_WM_FRAME_STRUT)) {
4918 this->data->fstrut_dirty = 1;
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);
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;
4932 } else if (event->xproperty.atom == ATOM(_NET_WM_STATE)) {
4935 Qt::WindowStates oldState = Qt::WindowStates(this->data->window_state);
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);
4943 if (e == Success && ret == XA_ATOM && format == 32 && nitems > 0) {
4944 Atom *states = (Atom *) data;
4948 for (i = 0; i < nitems; i++) {
4949 if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_VERT))
4951 else if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))
4953 else if (states[i] == ATOM(_NET_WM_STATE_FULLSCREEN))
4956 if (maximized == 3) {
4957 // only set maximized if both horizontal and vertical properties are set
4963 bool send_event = false;
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;
4970 } else if (!max && isMaximized()) {
4971 this->data->window_state &= ~Qt::WindowMaximized;
4976 if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) {
4977 if (full && !isFullScreen()) {
4978 this->data->window_state = this->data->window_state | Qt::WindowFullScreen;
4980 } else if (!full && isFullScreen()) {
4981 this->data->window_state &= ~Qt::WindowFullScreen;
4987 QWindowStateChangeEvent e(oldState);
4988 QApplication::sendSpontaneousEvent(this, &e);
4990 } else if (event->xproperty.atom == ATOM(WM_STATE)) {
4991 // the widget frame strut should also be invalidated
4992 this->data->fstrut_dirty = 1;
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
5002 if (X11->deferred_map.removeAll(this)) {
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);
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);
5022 if (e == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) {
5023 long *state = (long *) data;
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));
5031 // set the parent id to zero, so that show() will
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)) {
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
5048 setAttribute(Qt::WA_WState_ExplicitShowHide, false);
5049 setAttribute(Qt::WA_WState_Visible, false);
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);
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);
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);
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);
5090 d->topData()->opacity = 255;
5101 // Paint event translation
5103 // When receiving many expose events, we compress them (union of all expose
5104 // rectangles) into one event which is sent to the widget.
5106 struct PaintEventInfo {
5110 #if defined(Q_C_CALLBACKS)
5114 static Bool isPaintOrScrollDoneEvent(Display *, XEvent *ev, XPointer a)
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)))
5120 if (ev->xexpose.window == info->window)
5126 #if defined(Q_C_CALLBACKS)
5133 bool translateBySips(QWidget* that, QRect& paintRect)
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) {
5148 paintRect.translate(dx, dy);
5154 void QETWidget::translatePaintEvent(const XEvent *event)
5156 if (!isWindow() && testAttribute(Qt::WA_NativeWindow))
5157 Q_ASSERT(internalWinId());
5160 QRect paintRect(event->xexpose.x, event->xexpose.y,
5161 event->xexpose.width, event->xexpose.height);
5163 PaintEventInfo info;
5164 info.window = internalWinId();
5165 translateBySips(this, paintRect);
5166 paintRect = d->mapFromWS(paintRect);
5168 QRegion paintRegion = paintRect;
5170 // WARNING: this is O(number_of_events * number_of_matching_events)
5171 while (XCheckIfEvent(X11->display,&xevent,isPaintOrScrollDoneEvent,
5173 !qt_x11EventFilter(&xevent) &&
5174 !x11Event(&xevent)) // send event through filter
5176 if (xevent.type == Expose || xevent.type == GraphicsExpose) {
5177 QRect exposure(xevent.xexpose.x,
5179 xevent.xexpose.width,
5180 xevent.xexpose.height);
5181 translateBySips(this, exposure);
5182 exposure = d->mapFromWS(exposure);
5183 paintRegion |= exposure;
5185 translateScrollDoneEvent(&xevent);
5189 if (!paintRegion.isEmpty() && !testAttribute(Qt::WA_WState_ConfigPending))
5190 d->syncBackingStore(paintRegion);
5194 // Scroll-done event translation.
5197 bool QETWidget::translateScrollDoneEvent(const XEvent *event)
5199 long id = event->xclient.data.l[0];
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);
5205 X11->sip_list.removeAt(i);
5214 // ConfigureNotify (window move and resize) event translation
5216 bool QETWidget::translateConfigEvent(const XEvent *event)
5218 Q_ASSERT((!isWindow() && !testAttribute(Qt::WA_NativeWindow)) ? internalWinId() : true);
5221 bool wasResize = testAttribute(Qt::WA_WState_ConfigPending); // set in QWidget::setGeometry_sys()
5222 setAttribute(Qt::WA_WState_ConfigPending, false);
5224 if (testAttribute(Qt::WA_OutsideWSRange)) {
5225 // discard events for windows that have a geometry X can't handle
5227 while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
5228 !qt_x11EventFilter(&xevent) &&
5229 !x11Event(&xevent)) // send event through filter
5234 const QSize oldSize = size();
5237 QPoint newCPos(geometry().topLeft());
5238 QSize newSize(event->xconfigure.width, event->xconfigure.height);
5240 bool trust = isVisible()
5241 && (d->topData()->parentWinId == XNone ||
5242 d->topData()->parentWinId == QX11Info::appRootWindow());
5243 bool isCPos = false;
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;
5253 QApplication::syncX();
5255 if (d->extra->compress_events) {
5256 // ConfigureNotify compression for faster opaque resizing
5258 while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify,
5260 if (qt_x11EventFilter(&otherEvent))
5263 if (x11Event(&otherEvent))
5266 if (otherEvent.xconfigure.event != otherEvent.xconfigure.window)
5269 newSize.setWidth(otherEvent.xconfigure.width);
5270 newSize.setHeight(otherEvent.xconfigure.height);
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;
5281 qt_sync_request_event_data sync_event;
5282 sync_event.window = internalWinId();
5284 if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
5287 #endif // QT_NO_XSYNC
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.
5296 XTranslateCoordinates(X11->display, internalWinId(),
5297 QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(),
5298 0, 0, &x, &y, &child);
5303 QRect cr (geometry());
5304 if (newCPos != cr.topLeft()) { // compare with cpos (exluding frame)
5305 QPoint oldPos = geometry().topLeft();
5306 cr.moveTopLeft(newCPos);
5309 QMoveEvent e(newCPos, oldPos); // pos (including frame), not cpos
5310 QApplication::sendSpontaneousEvent(this, &e);
5312 setAttribute(Qt::WA_PendingMoveEvent, true);
5315 if (newSize != cr.size()) { // size changed
5316 cr.setSize(newSize);
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;
5326 if (old_state != data->window_state) {
5327 QWindowStateChangeEvent e((Qt::WindowStates) old_state);
5328 QApplication::sendEvent(this, &e);
5332 setAttribute(Qt::WA_PendingResizeEvent, true);
5338 while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) &&
5339 !qt_x11EventFilter(&xevent) &&
5340 !x11Event(&xevent)) // send event through filter
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);
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);
5367 d->syncBackingStore();
5371 if (d->extra && d->extra->topextra)
5372 d->extra->topextra->inTopLevelResize = false;
5375 if (QTLWExtra *tlwExtra = d->maybeTopData()) {
5376 if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) {
5378 XSyncIntsToValue(&value,
5379 tlwExtra->newCounterValueLo,
5380 tlwExtra->newCounterValueHi);
5382 XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value);
5383 tlwExtra->newCounterValueHi = 0;
5384 tlwExtra->newCounterValueLo = 0;
5392 // Close window event translation.
5394 bool QETWidget::translateCloseEvent(const XEvent *)
5397 return d->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent);
5401 void QApplication::setCursorFlashTime(int msecs)
5403 QApplicationPrivate::cursor_flash_time = msecs;
5406 int QApplication::cursorFlashTime()
5408 return QApplicationPrivate::cursor_flash_time;
5411 void QApplication::setDoubleClickInterval(int ms)
5413 QApplicationPrivate::mouse_double_click_time = ms;
5416 int QApplication::doubleClickInterval()
5418 return QApplicationPrivate::mouse_double_click_time;
5421 void QApplication::setKeyboardInputInterval(int ms)
5423 QApplicationPrivate::keyboard_input_time = ms;
5426 int QApplication::keyboardInputInterval()
5428 return QApplicationPrivate::keyboard_input_time;
5431 #ifndef QT_NO_WHEELEVENT
5432 void QApplication::setWheelScrollLines(int n)
5434 QApplicationPrivate::wheel_scroll_lines = n;
5437 int QApplication::wheelScrollLines()
5439 return QApplicationPrivate::wheel_scroll_lines;
5443 void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
5446 case Qt::UI_AnimateMenu:
5447 if (enable) QApplicationPrivate::fade_menu = false;
5448 QApplicationPrivate::animate_menu = enable;
5450 case Qt::UI_FadeMenu:
5452 QApplicationPrivate::animate_menu = true;
5453 QApplicationPrivate::fade_menu = enable;
5455 case Qt::UI_AnimateCombo:
5456 QApplicationPrivate::animate_combo = enable;
5458 case Qt::UI_AnimateTooltip:
5459 if (enable) QApplicationPrivate::fade_tooltip = false;
5460 QApplicationPrivate::animate_tooltip = enable;
5462 case Qt::UI_FadeTooltip:
5464 QApplicationPrivate::animate_tooltip = true;
5465 QApplicationPrivate::fade_tooltip = enable;
5467 case Qt::UI_AnimateToolBox:
5468 QApplicationPrivate::animate_toolbox = enable;
5471 QApplicationPrivate::animate_ui = enable;
5476 bool QApplication::isEffectEnabled(Qt::UIEffect effect)
5478 if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui)
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;
5495 return QApplicationPrivate::animate_ui;
5499 /*****************************************************************************
5500 Session management support
5501 *****************************************************************************/
5503 #ifndef QT_NO_SESSIONMANAGER
5505 QT_BEGIN_INCLUDE_NAMESPACE
5506 #include <X11/SM/SMlib.h>
5507 QT_END_INCLUDE_NAMESPACE
5509 class QSessionManagerPrivate : public QObjectPrivate
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;
5519 QString& sessionKey;
5520 QSessionManager::RestartHint restartHint;
5521 QEventLoop *eventLoop;
5524 class QSmSocketReceiver : public QObject
5528 QSmSocketReceiver(int socket)
5530 QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this);
5531 connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int)));
5535 void socketActivated(int);
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;
5552 static QSmSocketReceiver* sm_receiver = 0;
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*);
5566 static void resetSmState()
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?!?
5577 sm_in_phase2 = false;
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)
5588 prop.name = (char*)name;
5589 prop.type = (char*)type;
5590 prop.num_vals = num_vals;
5595 SmcSetProperties(smcConnection, 1, props);
5599 names[0] = (char*) name;
5600 SmcDeleteProperties(smcConnection, 1, names);
5604 static void sm_setProperty(const QString& name, const QString& value)
5606 QByteArray v = value.toUtf8();
5608 prop.length = v.length();
5609 prop.value = (SmPointer) v.constData();
5610 sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop);
5613 static void sm_setProperty(const QString& name, const QStringList& value)
5615 SmPropValue *prop = new SmPropValue[value.count()];
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();
5624 sm_setProperty(name.toLatin1().data(), SmLISTofARRAY8, count, prop);
5629 // workaround for broken libsm, see below
5631 unsigned int save_yourself_in_progress : 1;
5632 unsigned int shutdown_in_progress : 1;
5635 static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData,
5636 int saveType, Bool shutdown , int interactStyle, Bool /*fast*/)
5638 if (smcConn != smcConnection)
5642 sm_isshutdown = shutdown;
5643 sm_saveType = saveType;
5644 sm_interactStyle = interactStyle;
5645 // sm_shouldbefast = fast; ### never used?!?
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;
5651 ((QT_smcConn*)smcConn)->shutdown_in_progress = true;
5653 sm_performSaveYourself((QSessionManagerPrivate*) clientData);
5654 if (!sm_isshutdown) // we cannot expect a confirmation message in that case
5658 static void sm_performSaveYourself(QSessionManagerPrivate* smd)
5661 qt_sm_blockUserInput = true;
5663 QSessionManager* sm = smd->sm;
5665 // generate a new session key
5667 gettimeofday(&tv, 0);
5668 smd->sessionKey = QString::number(qulonglong(tv.tv_sec)) + QLatin1Char('_') + QString::number(qulonglong(tv.tv_usec));
5670 QStringList arguments = qApp->arguments();
5671 QString argument0 = arguments.isEmpty() ? qApp->applicationFilePath() : arguments.at(0);
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[] = "";
5685 entry.pw_name = badusername;
5689 // retry with a bigger buffer
5690 buf.resize(buf.size() * 2);
5693 entryPtr = getpwuid(geteuid());
5696 sm_setProperty(QString::fromLatin1(SmUserID), QString::fromLatin1(entryPtr->pw_name));
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);
5708 switch (sm_saveType) {
5710 qApp->commitData(*sm);
5711 if (sm_isshutdown && sm_cancel)
5712 break; // we cancelled the shutdown, no need to save state
5715 qApp->saveState(*sm);
5718 qApp->commitData(*sm);
5724 if (sm_phase2 && !sm_in_phase2) {
5725 SmcRequestSaveYourselfPhase2(smcConnection, sm_saveYourselfPhase2Callback, (SmPointer*) smd);
5726 qt_sm_blockUserInput = false;
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;
5736 else if (sm_cancel && sm_isshutdown) {
5737 if (sm->allowsErrorInteraction()) {
5738 SmcInteractDone(smcConnection, True);
5739 sm_interactionActive = false;
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());
5747 // set the restart hint
5749 prop.length = sizeof(int);
5750 int value = sm->restartHint();
5751 prop.value = (SmPointer) &value;
5752 sm_setProperty(SmRestartStyleHint, SmCARD8, 1, &prop);
5755 SmcSaveYourselfDone(smcConnection, !sm_cancel);
5759 static void sm_dieCallback(SmcConn smcConn, SmPointer /* clientData */)
5761 if (smcConn != smcConnection)
5764 QEvent quitEvent(QEvent::Quit);
5765 QApplication::sendEvent(qApp, &quitEvent);
5768 static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData)
5770 if (smcConn != smcConnection)
5772 if (sm_waitingForInteraction)
5773 ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
5777 static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer /*clientData */)
5779 if (smcConn != smcConnection)
5784 static void sm_interactCallback(SmcConn smcConn, SmPointer clientData)
5786 if (smcConn != smcConnection)
5788 if (sm_waitingForInteraction)
5789 ((QSessionManagerPrivate *) clientData)->eventLoop->exit();
5792 static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData)
5794 if (smcConn != smcConnection)
5796 sm_in_phase2 = true;
5797 sm_performSaveYourself((QSessionManagerPrivate*) clientData);
5801 void QSmSocketReceiver::socketActivated(int)
5803 IceProcessMessages(SmcGetIceConnection(smcConnection), 0, 0);
5808 QT_BEGIN_INCLUDE_NAMESPACE
5809 #include "qapplication_x11.moc"
5810 QT_END_INCLUDE_NAMESPACE
5812 QSessionManager::QSessionManager(QApplication * app, QString &id, QString& key)
5813 : QObject(*new QSessionManagerPrivate(this, id, key), app)
5815 Q_D(QSessionManager);
5816 d->restartHint = RestartIfRunning;
5821 QByteArray b_id = id.toLatin1();
5822 char* prevId = b_id.data();
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;
5834 // avoid showing a warning message below
5835 if (qgetenv("SESSION_MANAGER").isEmpty())
5838 smcConnection = SmcOpenConnection(0, 0, 1, 0,
5839 SmcSaveYourselfProcMask |
5841 SmcSaveCompleteProcMask |
5842 SmcShutdownCancelledProcMask,
5848 id = QString::fromLatin1(myId);
5849 ::free(myId); // it was allocated by C
5851 QString error = QString::fromLocal8Bit(cerror);
5852 if (!smcConnection) {
5853 qWarning("Qt: Session management error: %s", qPrintable(error));
5856 sm_receiver = new QSmSocketReceiver(IceConnectionNumber(SmcGetIceConnection(smcConnection)));
5860 QSessionManager::~QSessionManager()
5863 SmcCloseConnection(smcConnection, 0, 0);
5868 QString QSessionManager::sessionId() const
5870 Q_D(const QSessionManager);
5871 return d->sessionId;
5874 QString QSessionManager::sessionKey() const
5876 Q_D(const QSessionManager);
5877 return d->sessionKey;
5881 void* QSessionManager::handle() const
5883 return (void*) smcConnection;
5887 bool QSessionManager::allowsInteraction()
5889 Q_D(QSessionManager);
5890 if (sm_interactionActive)
5893 if (sm_waitingForInteraction)
5896 if (sm_interactStyle == SmInteractStyleAny) {
5897 sm_waitingForInteraction = SmcInteractRequest(smcConnection, SmDialogNormal,
5898 sm_interactCallback, (SmPointer*) d);
5900 if (sm_waitingForInteraction) {
5901 QEventLoop eventLoop;
5902 d->eventLoop = &eventLoop;
5903 (void) eventLoop.exec();
5906 sm_waitingForInteraction = false;
5907 if (sm_smActive) { // not cancelled
5908 sm_interactionActive = true;
5909 qt_sm_blockUserInput = false;
5916 bool QSessionManager::allowsErrorInteraction()
5918 Q_D(QSessionManager);
5919 if (sm_interactionActive)
5922 if (sm_waitingForInteraction)
5925 if (sm_interactStyle == SmInteractStyleAny || sm_interactStyle == SmInteractStyleErrors) {
5926 sm_waitingForInteraction = SmcInteractRequest(smcConnection, SmDialogError,
5927 sm_interactCallback, (SmPointer*) d);
5929 if (sm_waitingForInteraction) {
5930 QEventLoop eventLoop;
5931 d->eventLoop = &eventLoop;
5932 (void) eventLoop.exec();
5935 sm_waitingForInteraction = false;
5936 if (sm_smActive) { // not cancelled
5937 sm_interactionActive = true;
5938 qt_sm_blockUserInput = false;
5945 void QSessionManager::release()
5947 if (sm_interactionActive) {
5948 SmcInteractDone(smcConnection, False);
5949 sm_interactionActive = false;
5950 if (sm_smActive && sm_isshutdown)
5951 qt_sm_blockUserInput = true;
5955 void QSessionManager::cancel()
5960 void QSessionManager::setRestartHint(QSessionManager::RestartHint hint)
5962 Q_D(QSessionManager);
5963 d->restartHint = hint;
5966 QSessionManager::RestartHint QSessionManager::restartHint() const
5968 Q_D(const QSessionManager);
5969 return d->restartHint;
5972 void QSessionManager::setRestartCommand(const QStringList& command)
5974 Q_D(QSessionManager);
5975 d->restartCommand = command;
5978 QStringList QSessionManager::restartCommand() const
5980 Q_D(const QSessionManager);
5981 return d->restartCommand;
5984 void QSessionManager::setDiscardCommand(const QStringList& command)
5986 Q_D(QSessionManager);
5987 d->discardCommand = command;
5990 QStringList QSessionManager::discardCommand() const
5992 Q_D(const QSessionManager);
5993 return d->discardCommand;
5996 void QSessionManager::setManagerProperty(const QString& name, const QString& value)
5998 sm_setProperty(name, value);
6001 void QSessionManager::setManagerProperty(const QString& name, const QStringList& value)
6003 sm_setProperty(name, value);
6006 bool QSessionManager::isPhase2() const
6008 return sm_in_phase2;
6011 void QSessionManager::requestPhase2()
6016 #endif // QT_NO_SESSIONMANAGER
6018 #if defined(QT_RX71_MULTITOUCH)
6020 static inline int testBit(const char *array, int bit)
6022 return (array[bit/8] & (1<<(bit%8)));
6025 static int openRX71Device(const QByteArray &deviceName)
6027 int fd = open(deviceName, O_RDONLY | O_NONBLOCK);
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) {
6040 if (!testBit(eventTypeMask, EV_ABS)) {
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) {
6052 if (!testBit(absMask, ABS_X) || !testBit(absMask, ABS_Y)) {
6060 void QApplicationPrivate::initializeMultitouch_sys()
6064 QByteArray deviceName = QByteArray("/dev/input/event");
6065 int currentDeviceNumber = 0;
6067 int fd = openRX71Device(QByteArray(deviceName + QByteArray::number(currentDeviceNumber++)));
6068 if (fd == -ENOENT) {
6073 // not a touch device
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);
6082 int deviceNumber = allRX71TouchPoints.count();
6084 QSocketNotifier *socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q);
6085 QObject::connect(socketNotifier, SIGNAL(activated(int)), q, SLOT(_q_readRX71MultiTouchEvents()));
6087 RX71TouchPointState touchPointState = {
6089 QTouchEvent::TouchPoint(deviceNumber),
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
6095 allRX71TouchPoints.append(touchPointState);
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;
6105 allRX71TouchPoints.clear();
6109 void QApplicationPrivate::cleanupMultitouch_sys()
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;
6117 allRX71TouchPoints.clear();
6120 bool QApplicationPrivate::readRX71MultiTouchEvents(int deviceNumber)
6122 RX71TouchPointState &touchPointState = allRX71TouchPoints[deviceNumber];
6123 QSocketNotifier *socketNotifier = touchPointState.socketNotifier;
6124 int fd = socketNotifier->socket();
6126 QTouchEvent::TouchPoint &touchPoint = touchPointState.touchPoint;
6128 bool down = touchPoint.state() != Qt::TouchPointReleased;
6130 touchPoint.setState(Qt::TouchPointStationary);
6132 bool changed = false;
6134 struct input_event inputEvent;
6135 int bytesRead = read(fd, &inputEvent, sizeof(inputEvent));
6138 if (bytesRead != sizeof(inputEvent)) {
6139 qWarning("Qt: INTERNAL ERROR: short read in readRX71MultiTouchEvents()");
6143 switch (inputEvent.type) {
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
6159 qWarning("Qt: WARNING: unknown event type %d on multitouch device", inputEvent.type);
6163 QPointF screenPos = touchPoint.screenPos();
6164 switch (inputEvent.code) {
6166 if (!down && inputEvent.value != 0)
6167 touchPoint.setState(Qt::TouchPointPressed);
6168 else if (down && inputEvent.value == 0)
6169 touchPoint.setState(Qt::TouchPointReleased);
6171 case ABS_TOOL_WIDTH:
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);
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);
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);
6203 qWarning("Qt: WARNING: unknown event code %d on multitouch device", inputEvent.code);
6208 if (down && touchPoint.state() != Qt::TouchPointReleased)
6209 touchPoint.setState(changed ? Qt::TouchPointMoved : Qt::TouchPointStationary);
6214 void QApplicationPrivate::_q_readRX71MultiTouchEvents()
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;
6223 QList<QTouchEvent::TouchPoint> touchPoints;
6224 for (int i = 0; i < allRX71TouchPoints.count(); ++i)
6225 touchPoints.append(allRX71TouchPoints.at(i).touchPoint);
6227 translateRawTouchEvent(0, QTouchEvent::TouchScreen, touchPoints);
6230 #else // !QT_RX71_MULTITOUCH
6232 void QApplicationPrivate::initializeMultitouch_sys()
6234 void QApplicationPrivate::cleanupMultitouch_sys()
6237 #endif // QT_RX71_MULTITOUCH