src/gui/kernel/qapplication_x11.cpp
changeset 30 5dc02b23752f
parent 19 fcece45ef507
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
   211     "_QT_INPUT_ENCODING\0"
   211     "_QT_INPUT_ENCODING\0"
   212 
   212 
   213     "_MOTIF_WM_HINTS\0"
   213     "_MOTIF_WM_HINTS\0"
   214 
   214 
   215     "DTWM_IS_RUNNING\0"
   215     "DTWM_IS_RUNNING\0"
   216     "KDE_FULL_SESSION\0"
       
   217     "KWIN_RUNNING\0"
       
   218     "KWM_RUNNING\0"
       
   219     "GNOME_BACKGROUND_PROPERTIES\0"
       
   220     "ENLIGHTENMENT_DESKTOP\0"
   216     "ENLIGHTENMENT_DESKTOP\0"
       
   217     "_DT_SAVE_MODE\0"
   221     "_SGI_DESKS_MANAGER\0"
   218     "_SGI_DESKS_MANAGER\0"
   222 
   219 
   223     // EWMH (aka NETWM)
   220     // EWMH (aka NETWM)
   224     "_NET_SUPPORTED\0"
   221     "_NET_SUPPORTED\0"
   225     "_NET_VIRTUAL_ROOTS\0"
   222     "_NET_VIRTUAL_ROOTS\0"
   276 
   273 
   277     "_NET_WM_CM_S0\0"
   274     "_NET_WM_CM_S0\0"
   278 
   275 
   279     "_NET_SYSTEM_TRAY_VISUAL\0"
   276     "_NET_SYSTEM_TRAY_VISUAL\0"
   280 
   277 
       
   278     "_NET_ACTIVE_WINDOW\0"
       
   279 
   281     // Property formats
   280     // Property formats
   282     "COMPOUND_TEXT\0"
   281     "COMPOUND_TEXT\0"
   283     "TEXT\0"
   282     "TEXT\0"
   284     "UTF8_STRING\0"
   283     "UTF8_STRING\0"
   285 
   284 
   622 static int (*original_x_errhandler)(Display *dpy, XErrorEvent *);
   621 static int (*original_x_errhandler)(Display *dpy, XErrorEvent *);
   623 static int (*original_xio_errhandler)(Display *dpy);
   622 static int (*original_xio_errhandler)(Display *dpy);
   624 
   623 
   625 static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
   624 static int qt_x_errhandler(Display *dpy, XErrorEvent *err)
   626 {
   625 {
       
   626     if (X11->display != dpy) {
       
   627         // only handle X errors for our display
       
   628         return 0;
       
   629     }
       
   630 
   627     switch (err->error_code) {
   631     switch (err->error_code) {
   628     case BadAtom:
   632     case BadAtom:
   629         if (err->request_code == 20 /* X_GetProperty */
   633         if (err->request_code == 20 /* X_GetProperty */
   630             && (err->resourceid == XA_RESOURCE_MANAGER
   634             && (err->resourceid == XA_RESOURCE_MANAGER
   631                 || err->resourceid == XA_RGB_DEFAULT_MAP
   635                 || err->resourceid == XA_RGB_DEFAULT_MAP
   632                 || err->resourceid == ATOM(_NET_SUPPORTED)
   636                 || err->resourceid == ATOM(_NET_SUPPORTED)
   633                 || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK)
   637                 || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK)
   634                 || err->resourceid == ATOM(KDE_FULL_SESSION)
       
   635                 || err->resourceid == ATOM(KWIN_RUNNING)
       
   636                 || err->resourceid == ATOM(XdndProxy)
   638                 || err->resourceid == ATOM(XdndProxy)
   637                 || err->resourceid == ATOM(XdndAware))) {
   639                 || err->resourceid == ATOM(XdndAware))) {
   638             // Perhaps we're running under SECURITY reduction? :/
   640             // Perhaps we're running under SECURITY reduction? :/
   639             return 0;
   641             return 0;
   640         }
   642         }
   662                 qDebug("xdndHandleBadwindow returned true");
   664                 qDebug("xdndHandleBadwindow returned true");
   663                 return 0;
   665                 return 0;
   664             }
   666             }
   665         }
   667         }
   666         if (X11->ignore_badwindow)
   668         if (X11->ignore_badwindow)
   667             return 0;
       
   668         break;
       
   669 
       
   670     case BadMatch:
       
   671         if (err->request_code == 42 /* X_SetInputFocus */)
       
   672             return 0;
   669             return 0;
   673         break;
   670         break;
   674 
   671 
   675     default:
   672     default:
   676 #if !defined(QT_NO_XINPUT)
   673 #if !defined(QT_NO_XINPUT)
   707             extensionName = "RANDR";
   704             extensionName = "RANDR";
   708         else if (err->request_code == X11->xinput_major)
   705         else if (err->request_code == X11->xinput_major)
   709             extensionName = "XInputExtension";
   706             extensionName = "XInputExtension";
   710         else if (err->request_code == X11->mitshm_major)
   707         else if (err->request_code == X11->mitshm_major)
   711             extensionName = "MIT-SHM";
   708             extensionName = "MIT-SHM";
       
   709 #ifndef QT_NO_XKB
       
   710         else if(err->request_code == X11->xkb_major)
       
   711             extensionName = "XKEYBOARD";
       
   712 #endif
   712 
   713 
   713         char minor_str[256];
   714         char minor_str[256];
   714         if (extensionName) {
   715         if (extensionName) {
   715             qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code);
   716             qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code);
   716             XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256);
   717             XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256);
  1632     // XInputExtension
  1633     // XInputExtension
  1633     X11->use_xinput = false;
  1634     X11->use_xinput = false;
  1634     X11->xinput_major = 0;
  1635     X11->xinput_major = 0;
  1635     X11->xinput_eventbase = 0;
  1636     X11->xinput_eventbase = 0;
  1636     X11->xinput_errorbase = 0;
  1637     X11->xinput_errorbase = 0;
       
  1638 
       
  1639     X11->use_xkb = false;
       
  1640     X11->xkb_major = 0;
       
  1641     X11->xkb_eventbase = 0;
       
  1642     X11->xkb_errorbase = 0;
  1637 
  1643 
  1638     // MIT-SHM
  1644     // MIT-SHM
  1639     X11->use_mitshm = false;
  1645     X11->use_mitshm = false;
  1640     X11->use_mitshm_pixmaps = false;
  1646     X11->use_mitshm_pixmaps = false;
  1641     X11->mitshm_major = 0;
  1647     X11->mitshm_major = 0;
  2106             X11->ptrXFreeDeviceList = XINPUT_LOAD(XFreeDeviceList);
  2112             X11->ptrXFreeDeviceList = XINPUT_LOAD(XFreeDeviceList);
  2107             X11->ptrXSelectExtensionEvent = XINPUT_LOAD(XSelectExtensionEvent);
  2113             X11->ptrXSelectExtensionEvent = XINPUT_LOAD(XSelectExtensionEvent);
  2108         }
  2114         }
  2109 #endif // QT_NO_XINPUT
  2115 #endif // QT_NO_XINPUT
  2110 
  2116 
       
  2117 #ifndef QT_NO_XKB
       
  2118         int xkblibMajor = XkbMajorVersion;
       
  2119         int xkblibMinor = XkbMinorVersion;
       
  2120         X11->use_xkb = XkbQueryExtension(X11->display,
       
  2121                                          &X11->xkb_major,
       
  2122                                          &X11->xkb_eventbase,
       
  2123                                          &X11->xkb_errorbase,
       
  2124                                          &xkblibMajor,
       
  2125                                          &xkblibMinor);
       
  2126         if (X11->use_xkb) {
       
  2127             // If XKB is detected, set the GrabsUseXKBState option so input method
       
  2128             // compositions continue to work (ie. deadkeys)
       
  2129             unsigned int state = XkbPCF_GrabsUseXKBStateMask;
       
  2130             (void) XkbSetPerClientControls(X11->display, state, &state);
       
  2131 
       
  2132             // select for group change events
       
  2133             XkbSelectEventDetails(X11->display,
       
  2134                                   XkbUseCoreKbd,
       
  2135                                   XkbStateNotify,
       
  2136                                   XkbAllStateComponentsMask,
       
  2137                                   XkbGroupStateMask);
       
  2138 
       
  2139             // current group state is queried when creating the keymapper, no need to do it here
       
  2140         }
       
  2141 #endif
       
  2142 
       
  2143 
  2111 #if !defined(QT_NO_FONTCONFIG)
  2144 #if !defined(QT_NO_FONTCONFIG)
  2112         int dpi = 0;
  2145         int dpi = 0;
  2113         getXDefault("Xft", FC_DPI, &dpi);
  2146         getXDefault("Xft", FC_DPI, &dpi);
  2114         if (dpi) {
  2147         if (dpi) {
  2115             for (int s = 0; s < ScreenCount(X11->display); ++s) {
  2148             for (int s = 0; s < ScreenCount(X11->display); ++s) {
  2184 #endif // QT_NO_XRENDER
  2217 #endif // QT_NO_XRENDER
  2185 
  2218 
  2186         // initialize key mapper
  2219         // initialize key mapper
  2187         QKeyMapper::changeKeyboard();
  2220         QKeyMapper::changeKeyboard();
  2188 
  2221 
  2189 #ifndef QT_NO_XKB
       
  2190         if (qt_keymapper_private()->useXKB) {
       
  2191             // If XKB is detected, set the GrabsUseXKBState option so input method
       
  2192             // compositions continue to work (ie. deadkeys)
       
  2193             unsigned int state = XkbPCF_GrabsUseXKBStateMask;
       
  2194             (void) XkbSetPerClientControls(X11->display, state, &state);
       
  2195         }
       
  2196 #endif // QT_NO_XKB
       
  2197 
       
  2198         // Misc. initialization
  2222         // Misc. initialization
  2199 #if 0 //disabled for now..
  2223 #if 0 //disabled for now..
  2200         QSegfaultHandler::initialize(priv->argv, priv->argc);
  2224         QSegfaultHandler::initialize(priv->argv, priv->argc);
  2201 #endif
  2225 #endif
  2202         QCursorData::initialize();
  2226         QCursorData::initialize();
  2225         X11->compositingManagerRunning = XGetSelectionOwner(X11->display,
  2249         X11->compositingManagerRunning = XGetSelectionOwner(X11->display,
  2226                                                             ATOM(_NET_WM_CM_S0));
  2250                                                             ATOM(_NET_WM_CM_S0));
  2227         X11->desktopEnvironment = DE_UNKNOWN;
  2251         X11->desktopEnvironment = DE_UNKNOWN;
  2228         X11->desktopVersion = 0;
  2252         X11->desktopVersion = 0;
  2229 
  2253 
  2230         // See if the current window manager is using the freedesktop.org spec to give its name
  2254         Atom type;
  2231         Window windowManagerWindow = XNone;
  2255         int format;
  2232         Atom typeReturned;
  2256         unsigned long length, after;
  2233         int formatReturned;
  2257         uchar *data = 0;
  2234         unsigned long nitemsReturned;
  2258         int rc;
  2235         unsigned long unused;
  2259 
  2236         unsigned char *data = 0;
  2260         do {
  2237         if (XGetWindowProperty(QX11Info::display(), QX11Info::appRootWindow(),
  2261             if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
  2238                            ATOM(_NET_SUPPORTING_WM_CHECK),
  2262                 X11->desktopEnvironment = DE_KDE;
  2239                            0, 1024, False, XA_WINDOW, &typeReturned,
  2263                 X11->desktopVersion = qgetenv("KDE_SESSION_VERSION").toInt();
  2240                            &formatReturned, &nitemsReturned, &unused, &data)
  2264                 break;
  2241               == Success) {
  2265             }
  2242             if (typeReturned == XA_WINDOW && formatReturned == 32)
  2266 
  2243                 windowManagerWindow = *((Window*) data);
  2267             if (qgetenv("DESKTOP_SESSION") == "gnome") {
  2244             if (data)
  2268                 X11->desktopEnvironment = DE_GNOME;
       
  2269                 break;
       
  2270             }
       
  2271 
       
  2272             // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it
       
  2273             if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
       
  2274                 X11->desktopEnvironment = DE_GNOME;
       
  2275                 break;
       
  2276             }
       
  2277 
       
  2278             rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_DT_SAVE_MODE),
       
  2279                                     0, 2, False, XA_STRING, &type, &format, &length,
       
  2280                                     &after, &data);
       
  2281             if (rc == Success && length) {
       
  2282                 if (!strcmp(reinterpret_cast<char *>(data), "xfce4")) {
       
  2283                     // Pretend that xfce4 is gnome, as it uses the same libraries.
       
  2284                     // The detection above is stolen from xdg-open.
       
  2285                     X11->desktopEnvironment = DE_GNOME;
       
  2286                     break;
       
  2287                 }
       
  2288 
       
  2289                 // We got the property but it wasn't xfce4. Free data before it gets overwritten.
  2245                 XFree(data);
  2290                 XFree(data);
  2246 
  2291                 data = 0;
  2247             if (windowManagerWindow != XNone) {
  2292             }
  2248                 QString wmName;
  2293 
  2249                 Atom utf8atom = ATOM(UTF8_STRING);
  2294             rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
  2250                 if (XGetWindowProperty(QX11Info::display(), windowManagerWindow, ATOM(_NET_WM_NAME),
  2295                                     0, 1, False, AnyPropertyType, &type, &format, &length,
  2251                                        0, 1024, False, utf8atom, &typeReturned,
  2296                                     &after, &data);
  2252                                        &formatReturned, &nitemsReturned, &unused, &data)
  2297             if (rc == Success && length) {
  2253                     == Success) {
       
  2254                     if (typeReturned == utf8atom && formatReturned == 8)
       
  2255                         wmName = QString::fromUtf8((const char*)data);
       
  2256                     if (data)
       
  2257                         XFree(data);
       
  2258                     if (wmName == QLatin1String("KWin"))
       
  2259                         X11->desktopEnvironment = DE_KDE;
       
  2260                     if (wmName == QLatin1String("Metacity"))
       
  2261                         X11->desktopEnvironment = DE_GNOME;
       
  2262                 }
       
  2263             }
       
  2264         }
       
  2265 
       
  2266         // Running a different/newer/older window manager?  Try some other things
       
  2267         if (X11->desktopEnvironment == DE_UNKNOWN){
       
  2268             Atom type;
       
  2269             int format;
       
  2270             unsigned long length, after;
       
  2271             uchar *data = 0;
       
  2272 
       
  2273             QString session = QString::fromLocal8Bit(qgetenv("DESKTOP_SESSION"));
       
  2274             if (session == QLatin1String("kde")) {
       
  2275                 X11->desktopEnvironment = DE_KDE;
       
  2276             } else if (session == QLatin1String("gnome") || session == QLatin1String("xfce")) {
       
  2277                 X11->desktopEnvironment = DE_GNOME;
       
  2278             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING),
       
  2279                                           0, 1, False, AnyPropertyType, &type, &format, &length,
       
  2280                                    &after, &data) == Success && length) {
       
  2281                 // DTWM is running, meaning most likely CDE is running...
  2298                 // DTWM is running, meaning most likely CDE is running...
  2282                 X11->desktopEnvironment = DE_CDE;
  2299                 X11->desktopEnvironment = DE_CDE;
  2283             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
  2300                 break;
  2284                                           ATOM(GNOME_BACKGROUND_PROPERTIES), 0, 1, False, AnyPropertyType,
  2301             }
  2285                                           &type, &format, &length, &after, &data) == Success && length) {
  2302 
  2286                 X11->desktopEnvironment = DE_GNOME;
  2303             rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(),
  2287             } else if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) {
  2304                                     ATOM(_SGI_DESKS_MANAGER), 0, 1, False, XA_WINDOW,
  2288                 X11->desktopEnvironment = DE_GNOME;
  2305                                     &type, &format, &length, &after, &data);
  2289             } else if ((XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KDE_FULL_SESSION),
  2306             if (rc == Success && length) {
  2290                                            0, 1, False, AnyPropertyType, &type, &format, &length, &after, &data) == Success
       
  2291                         && length)
       
  2292                        || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWIN_RUNNING),
       
  2293                                               0, 1, False, AnyPropertyType, &type, &format, &length,
       
  2294                                               &after, &data) == Success
       
  2295                            && length)
       
  2296                        || (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(KWM_RUNNING),
       
  2297                                               0, 1, False, AnyPropertyType, &type, &format, &length,
       
  2298                                               &after, &data) == Success && length)) {
       
  2299                 X11->desktopEnvironment = DE_KDE;
       
  2300             } else if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_SGI_DESKS_MANAGER),
       
  2301                                           0, 1, False, XA_WINDOW, &type, &format, &length, &after, &data) == Success
       
  2302                        && length) {
       
  2303                 X11->desktopEnvironment = DE_4DWM;
  2307                 X11->desktopEnvironment = DE_4DWM;
  2304             }
  2308                 break;
  2305             if (data)
  2309             }
  2306                 XFree((char *)data);
  2310         } while(0);
  2307         }
  2311 
  2308 
  2312         if (data)
  2309         if (X11->desktopEnvironment == DE_KDE)
  2313             XFree((char *)data);
  2310             X11->desktopVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
       
  2311 
  2314 
  2312 #if !defined(QT_NO_STYLE_GTK)
  2315 #if !defined(QT_NO_STYLE_GTK)
  2313         if (X11->desktopEnvironment == DE_GNOME) {
  2316         if (X11->desktopEnvironment == DE_GNOME) {
  2314             static bool menusHaveIcons = QGtkStyle::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true);
  2317             static bool menusHaveIcons = QGtkStyle::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true);
  2315             QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons);
  2318             QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons);
  3050             }
  3053             }
  3051             else if (a == ATOM(WM_TAKE_FOCUS)) {
  3054             else if (a == ATOM(WM_TAKE_FOCUS)) {
  3052                 if ((ulong) event->xclient.data.l[1] > X11->time)
  3055                 if ((ulong) event->xclient.data.l[1] > X11->time)
  3053                     X11->time = event->xclient.data.l[1];
  3056                     X11->time = event->xclient.data.l[1];
  3054                 QWidget *amw = activeModalWidget();
  3057                 QWidget *amw = activeModalWidget();
       
  3058                 if (amw && amw->testAttribute(Qt::WA_X11DoNotAcceptFocus))
       
  3059                     amw = 0;
  3055                 if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
  3060                 if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) {
  3056                     QWidget *p = amw->parentWidget();
  3061                     QWidget *p = amw->parentWidget();
  3057                     while (p && p != widget)
  3062                     while (p && p != widget)
  3058                         p = p->parentWidget();
  3063                         p = p->parentWidget();
  3059                     if (!p || !X11->net_supported_list)
  3064                     if (!p || !X11->net_supported_list)
  3248         XRefreshKeyboardMapping(&event->xmapping);
  3253         XRefreshKeyboardMapping(&event->xmapping);
  3249 
  3254 
  3250         QKeyMapper::changeKeyboard();
  3255         QKeyMapper::changeKeyboard();
  3251         return 0;
  3256         return 0;
  3252     }
  3257     }
       
  3258 #ifndef QT_NO_XKB
       
  3259     else if (X11->use_xkb && event->type == X11->xkb_eventbase) {
       
  3260         XkbAnyEvent *xkbevent = (XkbAnyEvent *) event;
       
  3261         switch (xkbevent->xkb_type) {
       
  3262         case XkbStateNotify:
       
  3263             {
       
  3264                 XkbStateNotifyEvent *xkbstateevent = (XkbStateNotifyEvent *) xkbevent;
       
  3265                 if ((xkbstateevent->changed & XkbGroupStateMask) != 0) {
       
  3266                     qt_keymapper_private()->xkb_currentGroup = xkbstateevent->group;
       
  3267                     QKeyMapper::changeKeyboard();
       
  3268                 }
       
  3269                 break;
       
  3270             }
       
  3271         default:
       
  3272             break;
       
  3273         }
       
  3274     }
       
  3275 #endif
  3253 
  3276 
  3254     if (!widget) {                                // don't know this windows
  3277     if (!widget) {                                // don't know this windows
  3255         QWidget* popup = QApplication::activePopupWidget();
  3278         QWidget* popup = QApplication::activePopupWidget();
  3256         if (popup) {
  3279         if (popup) {
  3257 
  3280