diff options
Diffstat (limited to 'src/widgets/platforms/x11')
33 files changed, 0 insertions, 32781 deletions
diff --git a/src/widgets/platforms/x11/qapplication_x11.cpp b/src/widgets/platforms/x11/qapplication_x11.cpp deleted file mode 100644 index 1827423f7d..0000000000 --- a/src/widgets/platforms/x11/qapplication_x11.cpp +++ /dev/null @@ -1,6223 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// ### 4.0: examine Q_EXPORT's below. The respective symbols had all -// been in use (e.g. in the KDE wm) before the introduction of a version -// map. One might want to turn some of them into proper public API and -// provide a proper alternative for others. See also the exports in -// qapplication_win.cpp, which suggest a unification. - -#include "qplatformdefs.h" - -#include "qcolormap.h" -#include "qdesktopwidget.h" -#include "qapplication.h" -#include "qapplication_p.h" -#include "qcursor.h" -#include "qwidget.h" -#include "qbitarray.h" -#include "qpainter.h" -#include "qfile.h" -#include "qpixmapcache.h" -#include "qdatetime.h" -#include "qtextcodec.h" -#include "qdatastream.h" -#include "qbuffer.h" -#include "qsocketnotifier.h" -#include "qsessionmanager.h" -#include "qclipboard.h" -#include "qwhatsthis.h" -#include "qsettings.h" -#include "qstylefactory.h" -#include "qfileinfo.h" -#include "qdir.h" -#include "qhash.h" -#include "qevent.h" -#include "qevent_p.h" -#include "qvarlengtharray.h" -#include "qdebug.h" -#include <private/qcrashhandler_p.h> -#include <private/qcolor_p.h> -#include <private/qcursor_p.h> -#include <private/qiconloader_p.h> -#include <qgtkstyle.h> -#include "qstyle.h" -#include "qmetaobject.h" -#include "qtimer.h" -#include "qlibrary.h" -#include <private/qgraphicssystemfactory_p.h> -#include "qguiplatformplugin_p.h" -#include "qkde_p.h" - -#if !defined (QT_NO_TABLET) -extern "C" { -# define class c_class //XIproto.h has a name member named 'class' which the c++ compiler doesn't like -# include <wacomcfg.h> -# undef class -} -#endif - -#ifndef QT_GUI_DOUBLE_CLICK_RADIUS -#define QT_GUI_DOUBLE_CLICK_RADIUS 5 -#endif - - -//#define ALIEN_DEBUG - -#if !defined(QT_NO_GLIB) -# include "qguieventdispatcher_glib_p.h" -#endif -#include "qeventdispatcher_x11_p.h" -#include <private/qpaintengine_x11_p.h> - -#include <private/qkeymapper_p.h> - -// Input method stuff -#ifndef QT_NO_IM -#include "qinputcontext.h" -#include "qinputcontextfactory.h" -#endif // QT_NO_IM - -#ifndef QT_NO_XFIXES -#include <X11/extensions/Xfixes.h> -#endif // QT_NO_XFIXES - -#include "qt_x11_p.h" -#include "qx11info_x11.h" - -#define XK_MISCELLANY -#include <X11/keysymdef.h> -#if !defined(QT_NO_XINPUT) -#include <X11/extensions/XI.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <locale.h> - -#include "qwidget_p.h" - -#include <private/qbackingstore_p.h> - -#ifdef QT_RX71_MULTITOUCH -# include <qsocketnotifier.h> -# include <linux/input.h> -# include <errno.h> -#endif - -#if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4) -# define QT_NO_UNSETENV -#endif - -QT_BEGIN_NAMESPACE - -//#define X_NOT_BROKEN -#ifdef X_NOT_BROKEN -// Some X libraries are built with setlocale #defined to _Xsetlocale, -// even though library users are then built WITHOUT such a definition. -// This creates a problem - Qt might setlocale() one value, but then -// X looks and doesn't see the value Qt set. The solution here is to -// implement _Xsetlocale just in case X calls it - redirecting it to -// the real libC version. -// -# ifndef setlocale -extern "C" char *_Xsetlocale(int category, const char *locale); -char *_Xsetlocale(int category, const char *locale) -{ - //qDebug("_Xsetlocale(%d,%s),category,locale"); - return setlocale(category,locale); -} -# endif // setlocale -#endif // X_NOT_BROKEN - -/* Warning: if you modify this string, modify the list of atoms in qt_x11_p.h as well! */ -static const char * x11_atomnames = { - // window-manager <-> client protocols - "WM_PROTOCOLS\0" - "WM_DELETE_WINDOW\0" - "WM_TAKE_FOCUS\0" - "_NET_WM_PING\0" - "_NET_WM_CONTEXT_HELP\0" - "_NET_WM_SYNC_REQUEST\0" - "_NET_WM_SYNC_REQUEST_COUNTER\0" - - // ICCCM window state - "WM_STATE\0" - "WM_CHANGE_STATE\0" - - // Session management - "WM_CLIENT_LEADER\0" - "WM_WINDOW_ROLE\0" - "SM_CLIENT_ID\0" - - // Clipboard - "CLIPBOARD\0" - "INCR\0" - "TARGETS\0" - "MULTIPLE\0" - "TIMESTAMP\0" - "SAVE_TARGETS\0" - "CLIP_TEMPORARY\0" - "_QT_SELECTION\0" - "_QT_CLIPBOARD_SENTINEL\0" - "_QT_SELECTION_SENTINEL\0" - "CLIPBOARD_MANAGER\0" - - "RESOURCE_MANAGER\0" - - "_XSETROOT_ID\0" - - "_QT_SCROLL_DONE\0" - "_QT_INPUT_ENCODING\0" - - "_MOTIF_WM_HINTS\0" - - "DTWM_IS_RUNNING\0" - "ENLIGHTENMENT_DESKTOP\0" - "_DT_SAVE_MODE\0" - "_SGI_DESKS_MANAGER\0" - - // EWMH (aka NETWM) - "_NET_SUPPORTED\0" - "_NET_VIRTUAL_ROOTS\0" - "_NET_WORKAREA\0" - - "_NET_MOVERESIZE_WINDOW\0" - "_NET_WM_MOVERESIZE\0" - - "_NET_WM_NAME\0" - "_NET_WM_ICON_NAME\0" - "_NET_WM_ICON\0" - - "_NET_WM_PID\0" - - "_NET_WM_WINDOW_OPACITY\0" - - "_NET_WM_STATE\0" - "_NET_WM_STATE_ABOVE\0" - "_NET_WM_STATE_BELOW\0" - "_NET_WM_STATE_FULLSCREEN\0" - "_NET_WM_STATE_MAXIMIZED_HORZ\0" - "_NET_WM_STATE_MAXIMIZED_VERT\0" - "_NET_WM_STATE_MODAL\0" - "_NET_WM_STATE_STAYS_ON_TOP\0" - "_NET_WM_STATE_DEMANDS_ATTENTION\0" - - "_NET_WM_USER_TIME\0" - "_NET_WM_USER_TIME_WINDOW\0" - "_NET_WM_FULL_PLACEMENT\0" - - "_NET_WM_WINDOW_TYPE\0" - "_NET_WM_WINDOW_TYPE_DESKTOP\0" - "_NET_WM_WINDOW_TYPE_DOCK\0" - "_NET_WM_WINDOW_TYPE_TOOLBAR\0" - "_NET_WM_WINDOW_TYPE_MENU\0" - "_NET_WM_WINDOW_TYPE_UTILITY\0" - "_NET_WM_WINDOW_TYPE_SPLASH\0" - "_NET_WM_WINDOW_TYPE_DIALOG\0" - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0" - "_NET_WM_WINDOW_TYPE_POPUP_MENU\0" - "_NET_WM_WINDOW_TYPE_TOOLTIP\0" - "_NET_WM_WINDOW_TYPE_NOTIFICATION\0" - "_NET_WM_WINDOW_TYPE_COMBO\0" - "_NET_WM_WINDOW_TYPE_DND\0" - "_NET_WM_WINDOW_TYPE_NORMAL\0" - "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0" - - "_KDE_NET_WM_FRAME_STRUT\0" - - "_NET_STARTUP_INFO\0" - "_NET_STARTUP_INFO_BEGIN\0" - - "_NET_SUPPORTING_WM_CHECK\0" - - "_NET_WM_CM_S0\0" - - "_NET_SYSTEM_TRAY_VISUAL\0" - - "_NET_ACTIVE_WINDOW\0" - - // Property formats - "COMPOUND_TEXT\0" - "TEXT\0" - "UTF8_STRING\0" - - // xdnd - "XdndEnter\0" - "XdndPosition\0" - "XdndStatus\0" - "XdndLeave\0" - "XdndDrop\0" - "XdndFinished\0" - "XdndTypeList\0" - "XdndActionList\0" - - "XdndSelection\0" - - "XdndAware\0" - "XdndProxy\0" - - "XdndActionCopy\0" - "XdndActionLink\0" - "XdndActionMove\0" - "XdndActionPrivate\0" - - // Motif DND - "_MOTIF_DRAG_AND_DROP_MESSAGE\0" - "_MOTIF_DRAG_INITIATOR_INFO\0" - "_MOTIF_DRAG_RECEIVER_INFO\0" - "_MOTIF_DRAG_WINDOW\0" - "_MOTIF_DRAG_TARGETS\0" - - "XmTRANSFER_SUCCESS\0" - "XmTRANSFER_FAILURE\0" - - // Xkb - "_XKB_RULES_NAMES\0" - - // XEMBED - "_XEMBED\0" - "_XEMBED_INFO\0" - - // Wacom old. (before version 0.10) - "Wacom Stylus\0" - "Wacom Cursor\0" - "Wacom Eraser\0" - - // Tablet - "STYLUS\0" - "ERASER\0" -}; - -Q_WIDGETS_EXPORT QX11Data *qt_x11Data = 0; - -/***************************************************************************** - Internal variables and functions - *****************************************************************************/ -static const char *appName = 0; // application name -static const char *appClass = 0; // application class -static const char *appFont = 0; // application font -static const char *appBGCol = 0; // application bg color -static const char *appFGCol = 0; // application fg color -static const char *appBTNCol = 0; // application btn color -static const char *mwGeometry = 0; // main widget geometry -static const char *mwTitle = 0; // main widget title -char *qt_ximServer = 0; // XIM Server will connect to -static bool appSync = false; // X11 synchronization -#if defined(QT_DEBUG) -static bool appNoGrab = false; // X11 grabbing enabled -static bool appDoGrab = false; // X11 grabbing override (gdb) -#endif -static bool app_save_rootinfo = false; // save root info -static bool app_do_modal = false; // modal mode -static Window curWin = 0; // current window - - -// function to update the workarea of the screen - in qdesktopwidget_x11.cpp -extern void qt_desktopwidget_update_workarea(); - -// Function to change the window manager state (from qwidget_x11.cpp) -extern void qt_change_net_wm_state(const QWidget *w, bool set, Atom one, Atom two = 0); - -// modifier masks for alt, meta, super, hyper, and mode_switch - detected when the application starts -// and/or keyboard layout changes -uchar qt_alt_mask = 0; -uchar qt_meta_mask = 0; -uchar qt_super_mask = 0; -uchar qt_hyper_mask = 0; -uchar qt_mode_switch_mask = 0; - -// flags for extensions for special Languages, currently only for RTL languages -bool qt_use_rtl_extensions = false; - -static Window mouseActWindow = 0; // window where mouse is -static Qt::MouseButton mouseButtonPressed = Qt::NoButton; // last mouse button pressed -static Qt::MouseButtons mouseButtonState = Qt::NoButton; // mouse button state -static Time mouseButtonPressTime = 0; // when was a button pressed -static short mouseXPos, mouseYPos; // mouse pres position in act window -static short mouseGlobalXPos, mouseGlobalYPos; // global mouse press position - -extern QWidgetList *qt_modal_stack; // stack of modal widgets - -// window where mouse buttons have been pressed -static Window pressed_window = XNone; - -// popup control -static bool replayPopupMouseEvent = false; -static bool popupGrabOk; - -bool qt_sm_blockUserInput = false; // session management - -Q_WIDGETS_EXPORT int qt_xfocusout_grab_counter = 0; - -#if !defined (QT_NO_TABLET) -Q_GLOBAL_STATIC(QTabletDeviceDataList, tablet_devices) -QTabletDeviceDataList *qt_tablet_devices() -{ - return tablet_devices(); -} - -extern bool qt_tabletChokeMouse; -#endif - -typedef bool(*QX11FilterFunction)(XEvent *event); - -Q_GLOBAL_STATIC(QList<QX11FilterFunction>, x11Filters) - -Q_WIDGETS_EXPORT void qt_installX11EventFilter(QX11FilterFunction func) -{ - Q_ASSERT(func); - - if (QList<QX11FilterFunction> *list = x11Filters()) - list->append(func); -} - -Q_WIDGETS_EXPORT void qt_removeX11EventFilter(QX11FilterFunction func) -{ - Q_ASSERT(func); - - if (QList<QX11FilterFunction> *list = x11Filters()) - list->removeOne(func); -} - - -static bool qt_x11EventFilter(XEvent* ev) -{ - long unused; - if (qApp->filterEvent(ev, &unused)) - return true; - if (const QList<QX11FilterFunction> *list = x11Filters()) { - for (QList<QX11FilterFunction>::const_iterator it = list->constBegin(); it != list->constEnd(); ++it) { - if ((*it)(ev)) - return true; - } - } - - return qApp->x11EventFilter(ev); -} - -#if !defined(QT_NO_XIM) -XIMStyle qt_xim_preferred_style = 0; -#endif -int qt_ximComposingKeycode=0; -QTextCodec * qt_input_mapper = 0; - -extern bool qt_check_clipboard_sentinel(); //def in qclipboard_x11.cpp -extern bool qt_check_selection_sentinel(); //def in qclipboard_x11.cpp -extern bool qt_xfixes_clipboard_changed(Window clipboardOwner, Time timestamp); //def in qclipboard_x11.cpp -extern bool qt_xfixes_selection_changed(Window selectionOwner, Time timestamp); //def in qclipboard_x11.cpp - -static void qt_save_rootinfo(); -Q_WIDGETS_EXPORT bool qt_try_modal(QWidget *, XEvent *); - -QWidget *qt_button_down = 0; // last widget to be pressed with the mouse -QPointer<QWidget> qt_last_mouse_receiver = 0; -static QWidget *qt_popup_down = 0; // popup that contains the pressed widget - -extern bool qt_xdnd_dragging; - -// gui or non-gui from qapplication.cpp -extern bool qt_is_gui_used; - -/*! - \internal - Try to resolve a \a symbol from \a library with the version specified - by \a vernum. - - Note that, in the case of the Xfixes library, \a vernum is not the same as - \c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes - version. -*/ -static void* qt_load_library_runtime(const char *library, int vernum, - int highestVernum, const char *symbol) -{ - QList<int> versions; - // we try to load in the following order: - // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) ) - if (vernum != -1) - versions << vernum; - versions << -1; - if (vernum != -1) { - for(int i = highestVernum; i > vernum; --i) - versions << i; - } - Q_FOREACH(int version, versions) { - QLatin1String libName(library); - QLibrary xfixesLib(libName, version); - void *ptr = xfixesLib.resolve(symbol); - if (ptr) - return ptr; - } - return 0; -} - -#ifndef QT_NO_XINPUT -# ifdef QT_RUNTIME_XINPUT -# define XINPUT_LOAD_RUNTIME(vernum, symbol, symbol_type) \ - (symbol_type)qt_load_library_runtime("libXi", vernum, 6, #symbol); -# define XINPUT_LOAD(symbol) \ - XINPUT_LOAD_RUNTIME(1, symbol, Ptr##symbol) -# else // not runtime XInput -# define XINPUT_LOAD(symbol) symbol -# endif // QT_RUNTIME_XINPUT -#else // not using Xinput at all -# define XINPUT_LOAD(symbol) 0 -#endif // QT_NO_XINPUT - -#ifndef QT_NO_XFIXES -# ifdef QT_RUNTIME_XFIXES -# define XFIXES_LOAD_RUNTIME(vernum, symbol, symbol_type) \ - (symbol_type)qt_load_library_runtime("libXfixes", vernum, 4, #symbol); -# define XFIXES_LOAD_V1(symbol) \ - XFIXES_LOAD_RUNTIME(1, symbol, Ptr##symbol) -# define XFIXES_LOAD_V2(symbol) \ - XFIXES_LOAD_RUNTIME(2, symbol, Ptr##symbol) - -# else // not runtime Xfixes - -# if XFIXES_MAJOR >= 2 -# define XFIXES_LOAD_V1(symbol) symbol -# define XFIXES_LOAD_V2(symbol) symbol -# elif XFIXES_MAJOR >= 1 -# define XFIXES_LOAD_V1(symbol) symbol -# define XFIXES_LOAD_V2(symbol) 0 -# else -# error Unsupported version of Xfixes -# endif -# endif // QT_RUNTIME_XFIXES -#else // not using Xfixes at all -# define XFIXES_LOAD_V1(symbol) 0 -# define XFIXES_LOAD_V2(symbol) 0 -#endif // QT_NO_XFIXES - -#ifndef QT_NO_XFIXES - -struct qt_xfixes_selection_event_data -{ - // which selection to filter out. - Atom selection; -}; - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg) -{ - qt_xfixes_selection_event_data *data = - reinterpret_cast<qt_xfixes_selection_event_data*>(arg); - if (event->type == X11->xfixes_eventbase + XFixesSelectionNotify) { - XFixesSelectionNotifyEvent *xfixes_event = reinterpret_cast<XFixesSelectionNotifyEvent*>(event); - if (xfixes_event->selection == data->selection) - return true; - } - return false; -} - -#if defined(Q_C_CALLBACKS) -} -#endif - -#endif // QT_NO_XFIXES - -class QETWidget : public QWidget // event translator widget -{ -public: - QWidgetPrivate* d_func() { return QWidget::d_func(); } - bool translateMouseEvent(const XEvent *); - void translatePaintEvent(const XEvent *); - bool translateConfigEvent(const XEvent *); - bool translateCloseEvent(const XEvent *); - bool translateScrollDoneEvent(const XEvent *); - bool translateWheelEvent(int global_x, int global_y, int delta, Qt::MouseButtons buttons, - Qt::KeyboardModifiers modifiers, Qt::Orientation orient); -#if !defined (QT_NO_TABLET) - bool translateXinputEvent(const XEvent*, QTabletDeviceData *tablet); -#endif - bool translatePropertyEvent(const XEvent *); - - void doDeferredMap() - { - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - if (!testAttribute(Qt::WA_Resized)) { - adjustSize(); - setAttribute(Qt::WA_Resized, false); - } - - /* - workaround for WM's that throw away ConfigureRequests from the following: - - window->hide(); - window->move(x, y); // could also be resize(), move()+resize(), or setGeometry() - window->show(); - */ - QRect r = geometry(); - - XMoveResizeWindow(X11->display, - internalWinId(), - r.x(), - r.y(), - r.width(), - r.height()); - - // static gravity! - XSizeHints sh; - long unused; - XGetWMNormalHints(X11->display, internalWinId(), &sh, &unused); - sh.flags |= USPosition | PPosition | USSize | PSize | PWinGravity; - sh.x = r.x(); - sh.y = r.y(); - sh.width = r.width(); - sh.height = r.height(); - sh.win_gravity = StaticGravity; - XSetWMNormalHints(X11->display, internalWinId(), &sh); - - setAttribute(Qt::WA_Mapped); - if (testAttribute(Qt::WA_DontShowOnScreen)) - return; - d_func()->topData()->waitingForMapNotify = 1; - XMapWindow(X11->display, internalWinId()); - } -}; - - -void QApplicationPrivate::createEventDispatcher() -{ - Q_Q(QApplication); -#if !defined(QT_NO_GLIB) - if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported()) - eventDispatcher = (q->type() != QApplication::Tty - ? new QGuiEventDispatcherGlib(q) - : new QEventDispatcherGlib(q)); - else -#endif - eventDispatcher = (q->type() != QApplication::Tty - ? new QEventDispatcherX11(q) - : new QEventDispatcherUNIX(q)); -} - -/***************************************************************************** - Default X error handlers - *****************************************************************************/ - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); -static int (*original_xio_errhandler)(Display *dpy); - -static int qt_x_errhandler(Display *dpy, XErrorEvent *err) -{ - if (X11->display != dpy) { - // only handle X errors for our display - return 0; - } - - switch (err->error_code) { - case BadAtom: - if (err->request_code == 20 /* X_GetProperty */ - && (err->resourceid == XA_RESOURCE_MANAGER - || err->resourceid == XA_RGB_DEFAULT_MAP - || err->resourceid == ATOM(_NET_SUPPORTED) - || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) - || err->resourceid == ATOM(XdndProxy) - || err->resourceid == ATOM(XdndAware))) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - break; - - case BadWindow: - if (err->request_code == 2 /* X_ChangeWindowAttributes */ - || err->request_code == 38 /* X_QueryPointer */) { - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (err->resourceid == RootWindow(dpy, i)) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - } - } - X11->seen_badwindow = true; - if (err->request_code == 25 /* X_SendEvent */) { - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (err->resourceid == RootWindow(dpy, i)) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - } - if (X11->xdndHandleBadwindow()) { - qDebug("xdndHandleBadwindow returned true"); - return 0; - } - } - if (X11->ignore_badwindow) - return 0; - break; - - default: -#if !defined(QT_NO_XINPUT) - if (err->request_code == X11->xinput_major - && err->error_code == (X11->xinput_errorbase + XI_BadDevice) - && err->minor_code == 3 /* X_OpenDevice */) { - return 0; - } -#endif - break; - } - - char errstr[256]; - XGetErrorText( dpy, err->error_code, errstr, 256 ); - char buffer[256]; - char request_str[256]; - qsnprintf(buffer, 256, "%d", err->request_code); - XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); - if (err->request_code < 128) { - // X error for a normal protocol request - qWarning( "X Error: %s %d\n" - " Major opcode: %d (%s)\n" - " Resource id: 0x%lx", - errstr, err->error_code, - err->request_code, - request_str, - err->resourceid ); - } else { - // X error for an extension request - const char *extensionName = 0; - if (err->request_code == X11->xrender_major) - extensionName = "RENDER"; - else if (err->request_code == X11->xrandr_major) - extensionName = "RANDR"; - else if (err->request_code == X11->xinput_major) - extensionName = "XInputExtension"; - else if (err->request_code == X11->mitshm_major) - extensionName = "MIT-SHM"; -#ifndef QT_NO_XKB - else if(err->request_code == X11->xkb_major) - extensionName = "XKEYBOARD"; -#endif - - char minor_str[256]; - if (extensionName) { - qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); - } else { - extensionName = "Uknown extension"; - qsnprintf(minor_str, 256, "Unknown request"); - } - qWarning( "X Error: %s %d\n" - " Extension: %d (%s)\n" - " Minor opcode: %d (%s)\n" - " Resource id: 0x%lx", - errstr, err->error_code, - err->request_code, - extensionName, - err->minor_code, - minor_str, - err->resourceid ); - } - - // ### we really should distinguish between severe, non-severe and - // ### application specific errors - - return 0; -} - - -static int qt_xio_errhandler(Display *) -{ - qWarning("%s: Fatal IO error: client killed", appName); - QApplicationPrivate::reset_instance_pointer(); - exit(1); - //### give the application a chance for a proper shutdown instead, - //### exit(1) doesn't help. - return 0; -} - -#if defined(Q_C_CALLBACKS) -} -#endif - -#ifndef QT_NO_XSYNC -struct qt_sync_request_event_data -{ - WId window; -}; - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg) -{ - qt_sync_request_event_data *data = - reinterpret_cast<qt_sync_request_event_data*>(arg); - if (event->type == ClientMessage && - event->xany.window == data->window && - event->xclient.message_type == ATOM(WM_PROTOCOLS) && - (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) { - QWidget *w = QWidget::find(event->xany.window); - if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) { - const ulong timestamp = (const ulong) event->xclient.data.l[1]; - if (timestamp > X11->time) - X11->time = timestamp; - if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) { - tlw->syncRequestTimestamp = timestamp; - tlw->newCounterValueLo = event->xclient.data.l[2]; - tlw->newCounterValueHi = event->xclient.data.l[3]; - } - } - return true; - } - return false; -} - -#if defined(Q_C_CALLBACKS) -} -#endif -#endif // QT_NO_XSYNC - -static void qt_x11_create_intern_atoms() -{ - const char *names[QX11Data::NAtoms]; - const char *ptr = x11_atomnames; - - int i = 0; - while (*ptr) { - names[i++] = ptr; - while (*ptr) - ++ptr; - ++ptr; - } - - Q_ASSERT(i == QX11Data::NPredefinedAtoms); - - QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); - settings_atom_name += XDisplayName(X11->displayName); - names[i++] = settings_atom_name; - - Q_ASSERT(i == QX11Data::NAtoms); -#if defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6) - XInternAtoms(X11->display, (char **)names, i, False, X11->atoms); -#else - for (i = 0; i < QX11Data::NAtoms; ++i) - X11->atoms[i] = XInternAtom(X11->display, (char *)names[i], False); -#endif -} - -Q_WIDGETS_EXPORT void qt_x11_apply_settings_in_all_apps() -{ - QByteArray stamp; - QDataStream s(&stamp, QIODevice::WriteOnly); - s << QDateTime::currentDateTime(); - - XChangeProperty(QX11Info::display(), QX11Info::appRootWindow(0), - ATOM(_QT_SETTINGS_TIMESTAMP), ATOM(_QT_SETTINGS_TIMESTAMP), 8, - PropModeReplace, (unsigned char *)stamp.data(), stamp.size()); -} - -/*! \internal - apply the settings to the application -*/ -bool QApplicationPrivate::x11_apply_settings() -{ - QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); - - settings.beginGroup(QLatin1String("Qt")); - - /* - Qt settings. This is now they are written into the datastream. - - Palette / * - QPalette - font - QFont - libraryPath - QStringList - style - QString - doubleClickInterval - int - keyboardInputInterval - int - cursorFlashTime - int - wheelScrollLines - int - colorSpec - QString - defaultCodec - QString - globalStrut/width - int - globalStrut/height - int - GUIEffects - QStringList - Font Substitutions/ * - QStringList - Font Substitutions/... - QStringList - */ - - QStringList strlist; - int i; - QPalette pal(Qt::black); - int groupCount = 0; - strlist = settings.value(QLatin1String("Palette/active")).toStringList(); - if (!strlist.isEmpty()) { - ++groupCount; - for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++) - pal.setColor(QPalette::Active, (QPalette::ColorRole) i, - QColor(strlist[i])); - } - strlist = settings.value(QLatin1String("Palette/inactive")).toStringList(); - if (!strlist.isEmpty()) { - ++groupCount; - for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++) - pal.setColor(QPalette::Inactive, (QPalette::ColorRole) i, - QColor(strlist[i])); - } - strlist = settings.value(QLatin1String("Palette/disabled")).toStringList(); - if (!strlist.isEmpty()) { - ++groupCount; - for (i = 0; i < qMin(strlist.count(), int(QPalette::NColorRoles)); i++) - pal.setColor(QPalette::Disabled, (QPalette::ColorRole) i, - QColor(strlist[i])); - } - - // ### Fix properly for 4.6 - bool usingGtkSettings = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"); - if (!usingGtkSettings) { - if (groupCount == QPalette::NColorGroups) - QApplicationPrivate::setSystemPalette(pal); - } - - if (!appFont) { - // ### Fix properly for 4.6 - if (!usingGtkSettings) { - QFont font(QApplication::font()); - QString fontDescription; - // Override Qt font if KDE4 settings can be used - if (X11->desktopVersion == 4) { - QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - fontDescription = kdeSettings.value(QLatin1String("font")).toString(); - if (fontDescription.isEmpty()) { - // KDE stores fonts without quotes - fontDescription = kdeSettings.value(QLatin1String("font")).toStringList().join(QLatin1String(",")); - } - } - if (fontDescription.isEmpty()) - fontDescription = settings.value(QLatin1String("font")).toString(); - if (!fontDescription .isEmpty()) { - font.fromString(fontDescription ); - QApplicationPrivate::setSystemFont(font); - } - } - } - - // read library (ie. plugin) path list - QString libpathkey = - QString::fromLatin1("%1.%2/libraryPath") - .arg(QT_VERSION >> 16) - .arg((QT_VERSION & 0xff00) >> 8); - QStringList pathlist = settings.value(libpathkey).toString().split(QLatin1Char(':')); - if (! pathlist.isEmpty()) { - QStringList::ConstIterator it = pathlist.constBegin(); - while (it != pathlist.constEnd()) - QApplication::addLibraryPath(*it++); - } - - // read new QStyle - QString stylename = settings.value(QLatin1String("style")).toString(); - - if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) { - stylename = qt_guiPlatformPlugin()->styleName(); - } - - static QString currentStyleName = stylename; - if (QCoreApplication::startingUp()) { - if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull()) - QApplicationPrivate::styleOverride = stylename; - } else { - if (currentStyleName != stylename) { - currentStyleName = stylename; - QApplication::setStyle(stylename); - } - } - - int num = - settings.value(QLatin1String("doubleClickInterval"), - QApplication::doubleClickInterval()).toInt(); - QApplication::setDoubleClickInterval(num); - - num = - settings.value(QLatin1String("cursorFlashTime"), - QApplication::cursorFlashTime()).toInt(); - QApplication::setCursorFlashTime(num); - -#ifndef QT_NO_WHEELEVENT - num = - settings.value(QLatin1String("wheelScrollLines"), - QApplication::wheelScrollLines()).toInt(); - QApplication::setWheelScrollLines(num); -#endif - - QString colorspec = settings.value(QLatin1String("colorSpec"), - QVariant(QLatin1String("default"))).toString(); - if (colorspec == QLatin1String("normal")) - QApplication::setColorSpec(QApplication::NormalColor); - else if (colorspec == QLatin1String("custom")) - QApplication::setColorSpec(QApplication::CustomColor); - else if (colorspec == QLatin1String("many")) - QApplication::setColorSpec(QApplication::ManyColor); - else if (colorspec != QLatin1String("default")) - colorspec = QLatin1String("default"); - - QString defaultcodec = settings.value(QLatin1String("defaultCodec"), - QVariant(QLatin1String("none"))).toString(); - if (defaultcodec != QLatin1String("none")) { - QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1()); - if (codec) - QTextCodec::setCodecForTr(codec); - } - - int w = settings.value(QLatin1String("globalStrut/width")).toInt(); - int h = settings.value(QLatin1String("globalStrut/height")).toInt(); - QSize strut(w, h); - if (strut.isValid()) - QApplication::setGlobalStrut(strut); - - QStringList effects = settings.value(QLatin1String("GUIEffects")).toStringList(); - QApplication::setEffectEnabled(Qt::UI_General, - effects.contains(QLatin1String("general"))); - QApplication::setEffectEnabled(Qt::UI_AnimateMenu, - effects.contains(QLatin1String("animatemenu"))); - QApplication::setEffectEnabled(Qt::UI_FadeMenu, - effects.contains(QLatin1String("fademenu"))); - QApplication::setEffectEnabled(Qt::UI_AnimateCombo, - effects.contains(QLatin1String("animatecombo"))); - QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, - effects.contains(QLatin1String("animatetooltip"))); - QApplication::setEffectEnabled(Qt::UI_FadeTooltip, - effects.contains(QLatin1String("fadetooltip"))); - QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, - effects.contains(QLatin1String("animatetoolbox"))); - - if (!X11->has_fontconfig) { - settings.beginGroup(QLatin1String("Font Substitutions")); - QStringList fontsubs = settings.childKeys(); - if (!fontsubs.isEmpty()) { - QStringList::Iterator it = fontsubs.begin(); - for (; it != fontsubs.end(); ++it) { - QString fam = *it; - QStringList subs = settings.value(fam).toStringList(); - QFont::insertSubstitutions(fam, subs); - } - } - settings.endGroup(); - } - - qt_use_rtl_extensions = - settings.value(QLatin1String("useRtlExtensions"), false).toBool(); - -#ifndef QT_NO_XIM - if (qt_xim_preferred_style == 0) { - QString ximInputStyle = settings.value(QLatin1String("XIMInputStyle"), - QVariant(QLatin1String("on the spot"))).toString().toLower(); - if (ximInputStyle == QLatin1String("on the spot")) - qt_xim_preferred_style = XIMPreeditCallbacks | XIMStatusNothing; - else if (ximInputStyle == QLatin1String("over the spot")) - qt_xim_preferred_style = XIMPreeditPosition | XIMStatusNothing; - else if (ximInputStyle == QLatin1String("off the spot")) - qt_xim_preferred_style = XIMPreeditArea | XIMStatusArea; - else if (ximInputStyle == QLatin1String("root")) - qt_xim_preferred_style = XIMPreeditNothing | XIMStatusNothing; - } -#endif - QStringList inputMethods = QInputContextFactory::keys(); - if (inputMethods.size() > 2 && inputMethods.contains(QLatin1String("imsw-multi"))) { - X11->default_im = QLatin1String("imsw-multi"); - } else { - X11->default_im = settings.value(QLatin1String("DefaultInputMethod"), - QLatin1String("xim")).toString(); - } - - settings.endGroup(); // Qt - - return true; -} - - -/*! \internal - Resets the QApplication::instance() pointer to zero -*/ -void QApplicationPrivate::reset_instance_pointer() -{ QApplication::self = 0; } - - -// read the _QT_INPUT_ENCODING property and apply the settings to -// the application -static void qt_set_input_encoding() -{ - Atom type; - int format; - ulong nitems, after = 1; - unsigned char *data = 0; - - int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_QT_INPUT_ENCODING), 0, 1024, - False, XA_STRING, &type, &format, &nitems, - &after, &data); - if (e != Success || !nitems || type == XNone) { - // Always use the locale codec, since we have no examples of non-local - // XIMs, and since we cannot get a sensible answer about the encoding - // from the XIM. - qt_input_mapper = QTextCodec::codecForLocale(); - - } else { - if (!qstricmp((char *)data, "locale")) - qt_input_mapper = QTextCodec::codecForLocale(); - else - qt_input_mapper = QTextCodec::codecForName((char *)data); - // make sure we have an input codec - if(!qt_input_mapper) - qt_input_mapper = QTextCodec::codecForName("ISO 8859-1"); - } - if (qt_input_mapper && qt_input_mapper->mibEnum() == 11) // 8859-8 - qt_input_mapper = QTextCodec::codecForName("ISO 8859-8-I"); - if(data) - XFree((char *)data); -} - -// set font, foreground and background from x11 resources. The -// arguments may override the resource settings. -static void qt_set_x11_resources(const char* font = 0, const char* fg = 0, - const char* bg = 0, const char* button = 0) -{ - - QString resFont, resFG, resBG, resButton, resEF, sysFont, selectBackground, selectForeground; - - QApplication::setEffectEnabled(Qt::UI_General, false); - QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false); - QApplication::setEffectEnabled(Qt::UI_FadeMenu, false); - QApplication::setEffectEnabled(Qt::UI_AnimateCombo, false); - QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, false); - QApplication::setEffectEnabled(Qt::UI_FadeTooltip, false); - QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, false); - - bool paletteAlreadySet = false; - if (QApplication::desktopSettingsAware()) { - // first, read from settings - QApplicationPrivate::x11_apply_settings(); - // the call to QApplication::style() below creates the system - // palette, which breaks the logic after the RESOURCE_MANAGER - // loop... so I have to save this value to be able to use it later - paletteAlreadySet = (QApplicationPrivate::sys_pal != 0); - - // second, parse the RESOURCE_MANAGER property - int format; - ulong nitems, after = 1; - QString res; - long offset = 0; - Atom type = XNone; - - while (after > 0) { - uchar *data = 0; - if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(0), - ATOM(RESOURCE_MANAGER), - offset, 8192, False, AnyPropertyType, - &type, &format, &nitems, &after, - &data) != Success) { - res = QString(); - break; - } - if (type == XA_STRING) - res += QString::fromLatin1((char*)data); - else - res += QString::fromLocal8Bit((char*)data); - offset += 2048; // offset is in 32bit quantities... 8192/4 == 2048 - if (data) - XFree((char *)data); - } - - QString key, value; - int l = 0, r; - QString apn = QString::fromLocal8Bit(appName); - QString apc = QString::fromLocal8Bit(appClass); - int apnl = apn.length(); - int apcl = apc.length(); - int resl = res.length(); - - while (l < resl) { - r = res.indexOf(QLatin1Char('\n'), l); - if (r < 0) - r = resl; - while (res.at(l).isSpace()) - l++; - bool mine = false; - QChar sc = res.at(l + 1); - if (res.at(l) == QLatin1Char('*') && - (sc == QLatin1Char('f') || sc == QLatin1Char('b') || sc == QLatin1Char('g') || - sc == QLatin1Char('F') || sc == QLatin1Char('B') || sc == QLatin1Char('G') || - sc == QLatin1Char('s') || sc == QLatin1Char('S') - // capital T only, since we're looking for "Text.selectSomething" - || sc == QLatin1Char('T'))) { - // OPTIMIZED, since we only want "*[fbgsT].." - QString item = res.mid(l, r - l).simplified(); - int i = item.indexOf(QLatin1Char(':')); - key = item.left(i).trimmed().mid(1).toLower(); - value = item.right(item.length() - i - 1).trimmed(); - mine = true; - } else if ((apnl && res.at(l) == apn.at(0)) || (appClass && apcl && res.at(l) == apc.at(0))) { - if (res.mid(l,apnl) == apn && (res.at(l+apnl) == QLatin1Char('.') - || res.at(l+apnl) == QLatin1Char('*'))) { - QString item = res.mid(l, r - l).simplified(); - int i = item.indexOf(QLatin1Char(':')); - key = item.left(i).trimmed().mid(apnl+1).toLower(); - value = item.right(item.length() - i - 1).trimmed(); - mine = true; - } else if (res.mid(l,apcl) == apc && (res.at(l+apcl) == QLatin1Char('.') - || res.at(l+apcl) == QLatin1Char('*'))) { - QString item = res.mid(l, r - l).simplified(); - int i = item.indexOf(QLatin1Char(':')); - key = item.left(i).trimmed().mid(apcl+1).toLower(); - value = item.right(item.length() - i - 1).trimmed(); - mine = true; - } - } - - if (mine) { - if (!font && key == QLatin1String("systemfont")) - sysFont = value.left(value.lastIndexOf(QLatin1Char(':'))); - if (!font && key == QLatin1String("font")) - resFont = value; - else if (!fg && !paletteAlreadySet) { - if (key == QLatin1String("foreground")) - resFG = value; - else if (!bg && key == QLatin1String("background")) - resBG = value; - else if (!bg && !button && key == QLatin1String("button.background")) - resButton = value; - else if (key == QLatin1String("text.selectbackground")) { - selectBackground = value; - } else if (key == QLatin1String("text.selectforeground")) { - selectForeground = value; - } - } else if (key == QLatin1String("guieffects")) - resEF = value; - // NOTE: if you add more, change the [fbg] stuff above - } - - l = r + 1; - } - } - if (!sysFont.isEmpty()) - resFont = sysFont; - if (resFont.isEmpty()) - resFont = QString::fromLocal8Bit(font); - if (resFG.isEmpty()) - resFG = QString::fromLocal8Bit(fg); - if (resBG.isEmpty()) - resBG = QString::fromLocal8Bit(bg); - if (resButton.isEmpty()) - resButton = QString::fromLocal8Bit(button); - if (!resFont.isEmpty() - && !X11->has_fontconfig - && !QApplicationPrivate::sys_font) { - // set application font - QFont fnt; - fnt.setRawName(resFont); - - // the font we get may actually be an alias for another font, - // so we reset the application font to the real font info. - if (! fnt.exactMatch()) { - QFontInfo fontinfo(fnt); - fnt.setFamily(fontinfo.family()); - fnt.setRawMode(fontinfo.rawMode()); - - if (! fnt.rawMode()) { - fnt.setItalic(fontinfo.italic()); - fnt.setWeight(fontinfo.weight()); - fnt.setUnderline(fontinfo.underline()); - fnt.setStrikeOut(fontinfo.strikeOut()); - fnt.setStyleHint(fontinfo.styleHint()); - - if (fnt.pointSize() <= 0 && fnt.pixelSize() <= 0) { - // size is all wrong... fix it - qreal pointSize = fontinfo.pixelSize() * 72. / (float) QX11Info::appDpiY(); - if (pointSize <= 0) - pointSize = 12; - fnt.setPointSize(qRound(pointSize)); - } - } - } - - QApplicationPrivate::setSystemFont(fnt); - } - // QGtkStyle sets it's own system palette - bool gtkStyle = QApplicationPrivate::app_style && QApplicationPrivate::app_style->inherits("QGtkStyle"); - bool kdeColors = (QApplication::desktopSettingsAware() && X11->desktopEnvironment == DE_KDE); - if (!gtkStyle && (kdeColors || (button || !resBG.isEmpty() || !resFG.isEmpty()))) {// set app colors - bool allowX11ColorNames = QColor::allowX11ColorNames(); - QColor::setAllowX11ColorNames(true); - - (void) QApplication::style(); // trigger creation of application style and system palettes - QColor btn; - QColor bg; - QColor fg; - QColor bfg; - QColor wfg; - if (!resBG.isEmpty()) - bg = QColor(resBG); - if (!bg.isValid()) - bg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Window); - - if (!resFG.isEmpty()) - fg = QColor(resFG); - if (!fg.isValid()) - fg = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::WindowText); - - if (!resButton.isEmpty()) - btn = QColor(resButton); - else if (!resBG.isEmpty()) - btn = bg; - if (!btn.isValid()) - btn = QApplicationPrivate::sys_pal->color(QPalette::Active, QPalette::Button); - - int h,s,v; - fg.getHsv(&h,&s,&v); - QColor base = Qt::white; - bool bright_mode = false; - if (v >= 255 - 50) { - base = btn.darker(150); - bright_mode = true; - } - - QPalette pal(fg, btn, btn.lighter(125), btn.darker(130), btn.darker(120), wfg.isValid() ? wfg : fg, Qt::white, base, bg); - QColor disabled((fg.red() + btn.red()) / 2, - (fg.green() + btn.green())/ 2, - (fg.blue() + btn.blue()) / 2); - pal.setColorGroup(QPalette::Disabled, disabled, btn, btn.lighter(125), - btn.darker(130), btn.darker(150), disabled, Qt::white, Qt::white, bg); - - QColor highlight, highlightText; - if (!selectBackground.isEmpty() && !selectForeground.isEmpty()) { - highlight = QColor(selectBackground); - highlightText = QColor(selectForeground); - } - - if (highlight.isValid() && highlightText.isValid()) { - pal.setColor(QPalette::Highlight, highlight); - pal.setColor(QPalette::HighlightedText, highlightText); - - // calculate disabled colors by removing saturation - highlight.setHsv(highlight.hue(), 0, highlight.value(), highlight.alpha()); - highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha()); - pal.setColor(QPalette::Disabled, QPalette::Highlight, highlight); - pal.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText); - } else if (bright_mode) { - pal.setColor(QPalette::HighlightedText, base); - pal.setColor(QPalette::Highlight, Qt::white); - pal.setColor(QPalette::Disabled, QPalette::HighlightedText, base); - pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::white); - } else { - pal.setColor(QPalette::HighlightedText, Qt::white); - pal.setColor(QPalette::Highlight, Qt::darkBlue); - pal.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::white); - pal.setColor(QPalette::Disabled, QPalette::Highlight, Qt::darkBlue); - } - - pal = qt_guiPlatformPlugin()->palette().resolve(pal); - QApplicationPrivate::setSystemPalette(pal); - QColor::setAllowX11ColorNames(allowX11ColorNames); - } - - if (!resEF.isEmpty()) { - QStringList effects = resEF.split(QLatin1Char(' ')); - QApplication::setEffectEnabled(Qt::UI_General, effects.contains(QLatin1String("general"))); - QApplication::setEffectEnabled(Qt::UI_AnimateMenu, - effects.contains(QLatin1String("animatemenu"))); - QApplication::setEffectEnabled(Qt::UI_FadeMenu, - effects.contains(QLatin1String("fademenu"))); - QApplication::setEffectEnabled(Qt::UI_AnimateCombo, - effects.contains(QLatin1String("animatecombo"))); - QApplication::setEffectEnabled(Qt::UI_AnimateTooltip, - effects.contains(QLatin1String("animatetooltip"))); - QApplication::setEffectEnabled(Qt::UI_FadeTooltip, - effects.contains(QLatin1String("fadetooltip"))); - QApplication::setEffectEnabled(Qt::UI_AnimateToolBox, - effects.contains(QLatin1String("animatetoolbox"))); - } - - QIconLoader::instance()->updateSystemTheme(); -} - - -// update the supported array -static void qt_get_net_supported() -{ - Atom type; - int format; - long offset = 0; - unsigned long nitems, after; - unsigned char *data = 0; - - int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_NET_SUPPORTED), 0, 0, - False, XA_ATOM, &type, &format, &nitems, &after, &data); - if (data) - XFree(data); - - if (X11->net_supported_list) - delete [] X11->net_supported_list; - X11->net_supported_list = 0; - - if (e == Success && type == XA_ATOM && format == 32) { - QBuffer ts; - ts.open(QIODevice::WriteOnly); - - while (after > 0) { - XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_NET_SUPPORTED), offset, 1024, - False, XA_ATOM, &type, &format, &nitems, &after, &data); - - if (type == XA_ATOM && format == 32) { - ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long)); - offset += nitems; - } else - after = 0; - if (data) - XFree(data); - } - - // compute nitems - QByteArray buffer(ts.buffer()); - nitems = buffer.size() / sizeof(Atom); - X11->net_supported_list = new Atom[nitems + 1]; - Atom *a = (Atom *) buffer.data(); - uint i; - for (i = 0; i < nitems; i++) - X11->net_supported_list[i] = a[i]; - X11->net_supported_list[nitems] = 0; - } -} - - -bool QX11Data::isSupportedByWM(Atom atom) -{ - if (!X11->net_supported_list) - return false; - - bool supported = false; - int i = 0; - while (X11->net_supported_list[i] != 0) { - if (X11->net_supported_list[i++] == atom) { - supported = true; - break; - } - } - - return supported; -} - - -// update the virtual roots array -static void qt_get_net_virtual_roots() -{ - if (X11->net_virtual_root_list) - delete [] X11->net_virtual_root_list; - X11->net_virtual_root_list = 0; - - if (!X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS))) - return; - - Atom type; - int format; - long offset = 0; - unsigned long nitems, after; - unsigned char *data; - - int e = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_NET_VIRTUAL_ROOTS), 0, 0, - False, XA_ATOM, &type, &format, &nitems, &after, &data); - if (data) - XFree(data); - - if (e == Success && type == XA_ATOM && format == 32) { - QBuffer ts; - ts.open(QIODevice::WriteOnly); - - while (after > 0) { - XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_NET_VIRTUAL_ROOTS), offset, 1024, - False, XA_ATOM, &type, &format, &nitems, &after, &data); - - if (type == XA_ATOM && format == 32) { - ts.write(reinterpret_cast<char *>(data), nitems * 4); - offset += nitems; - } else - after = 0; - if (data) - XFree(data); - } - - // compute nitems - QByteArray buffer(ts.buffer()); - nitems = buffer.size() / sizeof(Window); - X11->net_virtual_root_list = new Window[nitems + 1]; - Window *a = (Window *) buffer.data(); - uint i; - for (i = 0; i < nitems; i++) - X11->net_virtual_root_list[i] = a[i]; - X11->net_virtual_root_list[nitems] = 0; - } -} - -void qt_net_remove_user_time(QWidget *tlw) -{ - Q_ASSERT(tlw); - QTLWExtra *extra = tlw->d_func()->maybeTopData(); - if (extra && extra->userTimeWindow) { - Q_ASSERT(tlw->internalWinId()); - XDeleteProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME_WINDOW)); - XDestroyWindow(X11->display, extra->userTimeWindow); - extra->userTimeWindow = 0; - } -} - -void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp) -{ - Q_ASSERT(tlw); - Q_ASSERT(tlw->isWindow()); - Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created)); - QTLWExtra *extra = tlw->d_func()->topData(); - WId wid = tlw->internalWinId(); - const bool isSupportedByWM = X11->isSupportedByWM(ATOM(_NET_WM_USER_TIME_WINDOW)); - if (extra->userTimeWindow || isSupportedByWM) { - if (!extra->userTimeWindow) { - extra->userTimeWindow = XCreateSimpleWindow(X11->display, - tlw->internalWinId(), - -1, -1, 1, 1, 0, 0, 0); - wid = extra->userTimeWindow; - XChangeProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME_WINDOW), - XA_WINDOW, 32, PropModeReplace, - (unsigned char *)&wid, 1); - XDeleteProperty(X11->display, tlw->internalWinId(), ATOM(_NET_WM_USER_TIME)); - } else if (!isSupportedByWM) { - // WM no longer supports it, then we should remove the - // _NET_WM_USER_TIME_WINDOW atom. - qt_net_remove_user_time(tlw); - } else { - wid = extra->userTimeWindow; - } - } - XChangeProperty(X11->display, wid, ATOM(_NET_WM_USER_TIME), - XA_CARDINAL, 32, PropModeReplace, (unsigned char *) ×tamp, 1); -} - -static void qt_check_focus_model() -{ - Window fw = XNone; - int unused; - XGetInputFocus(X11->display, &fw, &unused); - if (fw == PointerRoot) - X11->focus_model = QX11Data::FM_PointerRoot; - else - X11->focus_model = QX11Data::FM_Other; -} - -#ifndef QT_NO_TABLET - -#if !defined (Q_OS_IRIX) -// from include/Xwacom.h -# define XWACOM_PARAM_TOOLID 322 -# define XWACOM_PARAM_TOOLSERIAL 323 - -typedef WACOMCONFIG * (*PtrWacomConfigInit) (Display*, WACOMERRORFUNC); -typedef WACOMDEVICE * (*PtrWacomConfigOpenDevice) (WACOMCONFIG*, const char*); -typedef int *(*PtrWacomConfigGetRawParam) (WACOMDEVICE*, int, int*, int, unsigned*); -typedef int (*PtrWacomConfigCloseDevice) (WACOMDEVICE *); -typedef void (*PtrWacomConfigTerm) (WACOMCONFIG *); - -static PtrWacomConfigInit ptrWacomConfigInit = 0; -static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0; -static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0; -static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0; -static PtrWacomConfigTerm ptrWacomConfigTerm = 0; -Q_GLOBAL_STATIC(QByteArray, wacomDeviceName) -#endif - -#endif - -/***************************************************************************** - qt_init() - initializes Qt for X11 - *****************************************************************************/ - -#if !defined(QT_NO_FONTCONFIG) -static void getXDefault(const char *group, const char *key, int *val) -{ - char *str = XGetDefault(X11->display, group, key); - if (str) { - char *end = 0; - int v = strtol(str, &end, 0); - if (str != end) - *val = v; - // otherwise use fontconfig to convert the string to integer - else - FcNameConstant((FcChar8 *) str, val); - } -} - -static void getXDefault(const char *group, const char *key, double *val) -{ - char *str = XGetDefault(X11->display, group, key); - if (str) { - bool ok; - double v = QByteArray(str).toDouble(&ok); - if (ok) - *val = v; - } -} - -static void getXDefault(const char *group, const char *key, bool *val) -{ - char *str = XGetDefault(X11->display, group, key); - if (str) { - char c = str[0]; - if (isupper((int)c)) - c = tolower(c); - if (c == 't' || c == 'y' || c == '1') - *val = true; - else if (c == 'f' || c == 'n' || c == '0') - *val = false; - if (c == 'o') { - c = str[1]; - if (isupper((int)c)) - c = tolower(c); - if (c == 'n') - *val = true; - if (c == 'f') - *val = false; - } - } -} -#endif - -// ### This should be static but it isn't because of the friend declaration -// ### in qpaintdevice.h which then should have a static too but can't have -// ### it because "storage class specifiers invalid in friend function -// ### declarations" :-) Ideas anyone? -void qt_init(QApplicationPrivate *priv, int, - Display *display, Qt::HANDLE visual, Qt::HANDLE colormap) -{ - X11 = new QX11Data; - X11->display = display; - X11->displayName = 0; - X11->foreignDisplay = (display != 0); - X11->focus_model = -1; - - // RANDR - X11->use_xrandr = false; - X11->xrandr_major = 0; - X11->xrandr_eventbase = 0; - X11->xrandr_errorbase = 0; - - // RENDER - X11->use_xrender = false; - X11->xrender_major = 0; - X11->xrender_version = 0; - - // XFIXES - X11->use_xfixes = false; - X11->xfixes_major = 0; - X11->xfixes_eventbase = 0; - X11->xfixes_errorbase = 0; - - // XInputExtension - X11->use_xinput = false; - X11->xinput_major = 0; - X11->xinput_eventbase = 0; - X11->xinput_errorbase = 0; - - X11->use_xkb = false; - X11->xkb_major = 0; - X11->xkb_eventbase = 0; - X11->xkb_errorbase = 0; - - // MIT-SHM - X11->use_mitshm = false; - X11->use_mitshm_pixmaps = false; - X11->mitshm_major = 0; - - X11->sip_serial = 0; - X11->net_supported_list = 0; - X11->net_virtual_root_list = 0; - X11->wm_client_leader = 0; - X11->screens = 0; - X11->argbVisuals = 0; - X11->argbColormaps = 0; - X11->screenCount = 0; - X11->time = CurrentTime; - X11->userTime = CurrentTime; - X11->ignore_badwindow = false; - X11->seen_badwindow = false; - - X11->motifdnd_active = false; - - X11->default_im = QLatin1String("imsw-multi"); - priv->inputContext = 0; - - // colormap control - X11->visual_class = -1; - X11->visual_id = -1; - X11->color_count = 0; - X11->custom_cmap = false; - - // outside visual/colormap - X11->visual = reinterpret_cast<Visual *>(visual); - X11->colormap = colormap; - - // Fontconfig - X11->has_fontconfig = false; -#if !defined(QT_NO_FONTCONFIG) - if (qgetenv("QT_X11_NO_FONTCONFIG").isNull()) - X11->has_fontconfig = FcInit(); - X11->fc_antialias = true; -#endif - -#ifndef QT_NO_XRENDER - memset(X11->solid_fills, 0, sizeof(X11->solid_fills)); - for (int i = 0; i < X11->solid_fill_count; ++i) - X11->solid_fills[i].screen = -1; - memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills)); - for (int i = 0; i < X11->pattern_fill_count; ++i) - X11->pattern_fills[i].screen = -1; -#endif - - X11->startupId = 0; - - int argc = priv->argc; - char **argv = priv->argv; - - if (X11->display) { - // Qt part of other application - - // Set application name and class - appName = qstrdup("Qt-subapplication"); - char *app_class = 0; - if (argv) { - const char* p = strrchr(argv[0], '/'); - app_class = qstrdup(p ? p + 1 : argv[0]); - if (app_class[0]) - app_class[0] = toupper(app_class[0]); - } - appClass = app_class; - } else { - // Qt controls everything (default) - - // With the threaded QML renderer, we always need this. - XInitThreads(); - - // Set application name and class - char *app_class = 0; - if (argv && argv[0]) { - const char *p = strrchr(argv[0], '/'); - appName = p ? p + 1 : argv[0]; - app_class = qstrdup(appName); - if (app_class[0]) - app_class[0] = toupper(app_class[0]); - } - appClass = app_class; - } - - // Install default error handlers - original_x_errhandler = XSetErrorHandler(qt_x_errhandler); - original_xio_errhandler = XSetIOErrorHandler(qt_xio_errhandler); - - // Get command line params - int j = argc ? 1 : 0; - for (int i=1; i<argc; i++) { - if (argv[i] && *argv[i] != '-') { - argv[j++] = argv[i]; - continue; - } - QByteArray arg(argv[i]); - if (arg == "-display") { - if (++i < argc && !X11->display) - X11->displayName = argv[i]; - } else if (arg == "-fn" || arg == "-font") { - if (++i < argc) - appFont = argv[i]; - } else if (arg == "-bg" || arg == "-background") { - if (++i < argc) - appBGCol = argv[i]; - } else if (arg == "-btn" || arg == "-button") { - if (++i < argc) - appBTNCol = argv[i]; - } else if (arg == "-fg" || arg == "-foreground") { - if (++i < argc) - appFGCol = argv[i]; - } else if (arg == "-name") { - if (++i < argc) - appName = argv[i]; - } else if (arg == "-title") { - if (++i < argc) - mwTitle = argv[i]; - } else if (arg == "-geometry") { - if (++i < argc) - mwGeometry = argv[i]; - } else if (arg == "-im") { - if (++i < argc) - qt_ximServer = argv[i]; - } else if (arg == "-ncols") { // xv and netscape use this name - if (++i < argc) - X11->color_count = qMax(0,atoi(argv[i])); - } else if (arg == "-visual") { // xv and netscape use this name - if (++i < argc && !X11->visual) { - QString s = QString::fromLocal8Bit(argv[i]).toLower(); - if (s == QLatin1String("staticgray")) - X11->visual_class = StaticGray; - else if (s == QLatin1String("grayscale")) - X11->visual_class = XGrayScale; - else if (s == QLatin1String("staticcolor")) - X11->visual_class = StaticColor; - else if (s == QLatin1String("pseudocolor")) - X11->visual_class = PseudoColor; - else if (s == QLatin1String("truecolor")) - X11->visual_class = TrueColor; - else if (s == QLatin1String("directcolor")) - X11->visual_class = DirectColor; - else - X11->visual_id = static_cast<int>(strtol(argv[i], 0, 0)); - } -#ifndef QT_NO_XIM - } else if (arg == "-inputstyle") { - if (++i < argc) { - QString s = QString::fromLocal8Bit(argv[i]).toLower(); - if (s == QLatin1String("onthespot")) - qt_xim_preferred_style = XIMPreeditCallbacks | - XIMStatusNothing; - else if (s == QLatin1String("overthespot")) - qt_xim_preferred_style = XIMPreeditPosition | - XIMStatusNothing; - else if (s == QLatin1String("offthespot")) - qt_xim_preferred_style = XIMPreeditArea | - XIMStatusArea; - else if (s == QLatin1String("root")) - qt_xim_preferred_style = XIMPreeditNothing | - XIMStatusNothing; - } -#endif - } else if (arg == "-cmap") { // xv uses this name - if (!X11->colormap) - X11->custom_cmap = true; - } - else if (arg == "-sync") - appSync = !appSync; -#if defined(QT_DEBUG) - else if (arg == "-nograb") - appNoGrab = !appNoGrab; - else if (arg == "-dograb") - appDoGrab = !appDoGrab; -#endif - else - argv[j++] = argv[i]; - } - - priv->argc = j; - -#if defined(QT_DEBUG) && defined(Q_OS_LINUX) - if (!appNoGrab && !appDoGrab) { - QString s; - s.sprintf("/proc/%d/cmdline", getppid()); - QFile f(s); - if (f.open(QIODevice::ReadOnly)) { - s.clear(); - char c; - while (f.getChar(&c) && c) { - if (c == '/') - s.clear(); - else - s += QLatin1Char(c); - } - if (s == QLatin1String("gdb")) { - appNoGrab = true; - qDebug("Qt: gdb: -nograb added to command-line options.\n" - "\t Use the -dograb option to enforce grabbing."); - } - f.close(); - } - } -#endif - - // Connect to X server - if (qt_is_gui_used && !X11->display) { - if ((X11->display = XOpenDisplay(X11->displayName)) == 0) { - qWarning("%s: cannot connect to X server %s", appName, - XDisplayName(X11->displayName)); - QApplicationPrivate::reset_instance_pointer(); - exit(1); - } - - if (appSync) // if "-sync" argument - XSynchronize(X11->display, true); - } - - // Common code, regardless of whether display is foreign. - - // Get X parameters - - if (qt_is_gui_used) { - X11->defaultScreen = DefaultScreen(X11->display); - X11->screenCount = ScreenCount(X11->display); - - X11->screens = new QX11InfoData[X11->screenCount]; - X11->argbVisuals = new Visual *[X11->screenCount]; - X11->argbColormaps = new Colormap[X11->screenCount]; - - for (int s = 0; s < X11->screenCount; s++) { - QX11InfoData *screen = X11->screens + s; - screen->ref = 1; // ensures it doesn't get deleted - screen->screen = s; - - int widthMM = DisplayWidthMM(X11->display, s); - if (widthMM != 0) { - screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10); - } else { - screen->dpiX = 72; - } - - int heightMM = DisplayHeightMM(X11->display, s); - if (heightMM != 0) { - screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10); - } else { - screen->dpiY = 72; - } - - X11->argbVisuals[s] = 0; - X11->argbColormaps[s] = 0; - } - - -#ifndef QT_NO_XRENDER - int xrender_eventbase, xrender_errorbase; - // See if XRender is supported on the connected display - if (XQueryExtension(X11->display, "RENDER", &X11->xrender_major, - &xrender_eventbase, &xrender_errorbase) - && XRenderQueryExtension(X11->display, &xrender_eventbase, - &xrender_errorbase)) { - // Check the version as well - we need v0.4 or higher - int major = 0; - int minor = 0; - XRenderQueryVersion(X11->display, &major, &minor); - if (qgetenv("QT_X11_NO_XRENDER").isNull()) { - X11->use_xrender = (major >= 0 && minor >= 5); - X11->xrender_version = major*100+minor; - // workaround for broken XServer on Ubuntu Breezy (6.8 compiled with 7.0 - // protocol headers) - if (X11->xrender_version == 10 - && VendorRelease(X11->display) < 60900000 - && QByteArray(ServerVendor(X11->display)).contains("X.Org")) - X11->xrender_version = 9; - } - } -#endif // QT_NO_XRENDER - -#ifndef QT_NO_MITSHM - int mitshm_minor; - int mitshm_major; - int mitshm_eventbase; - int mitshm_errorbase; - int mitshm_pixmaps; - if (XQueryExtension(X11->display, "MIT-SHM", &X11->mitshm_major, - &mitshm_eventbase, &mitshm_errorbase) - && XShmQueryVersion(X11->display, &mitshm_major, &mitshm_minor, - &mitshm_pixmaps)) - { - QString displayName = QLatin1String(XDisplayName(NULL)); - - // MITSHM only works for local displays, so do a quick check here - // to determine whether the display is local or not (not 100 % accurate). - // BGR server layouts are not supported either, since it requires the raster - // engine to work on a QImage with BGR layout. - bool local = displayName.isEmpty() || displayName.lastIndexOf(QLatin1Char(':')) == 0; - if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0)) { - Visual *defaultVisual = DefaultVisual(X11->display, DefaultScreen(X11->display)); - X11->use_mitshm = ((defaultVisual->red_mask == 0xff0000 - || defaultVisual->red_mask == 0xf800) - && (defaultVisual->green_mask == 0xff00 - || defaultVisual->green_mask == 0x7e0) - && (defaultVisual->blue_mask == 0xff - || defaultVisual->blue_mask == 0x1f)); - X11->use_mitshm_pixmaps = X11->use_mitshm && mitshm_pixmaps; - } - } -#endif // QT_NO_MITSHM - - // initialize the graphics system - order is imporant here - it must be done before - // the QColormap::initialize() call - QApplicationPrivate::graphics_system = QGraphicsSystemFactory::create(QApplicationPrivate::graphics_system_name); - QColormap::initialize(); - - // Support protocols - X11->xdndSetup(); - - // Finally create all atoms - qt_x11_create_intern_atoms(); - - // initialize NET lists - qt_get_net_supported(); - qt_get_net_virtual_roots(); - -#ifndef QT_NO_XRANDR - // See if XRandR is supported on the connected display - if (XQueryExtension(X11->display, "RANDR", &X11->xrandr_major, - &X11->xrandr_eventbase, &X11->xrandr_errorbase)) { - -# ifdef QT_RUNTIME_XRANDR - X11->ptrXRRSelectInput = 0; - X11->ptrXRRUpdateConfiguration = 0; - X11->ptrXRRRootToScreen = 0; - X11->ptrXRRQueryExtension = 0; - QLibrary xrandrLib(QLatin1String("Xrandr"), 2); - if (!xrandrLib.load()) { // try without the version number - xrandrLib.setFileName(QLatin1String("Xrandr")); - xrandrLib.load(); - } - if (xrandrLib.isLoaded()) { - X11->ptrXRRSelectInput = - (PtrXRRSelectInput) xrandrLib.resolve("XRRSelectInput"); - X11->ptrXRRUpdateConfiguration = - (PtrXRRUpdateConfiguration) xrandrLib.resolve("XRRUpdateConfiguration"); - X11->ptrXRRRootToScreen = - (PtrXRRRootToScreen) xrandrLib.resolve("XRRRootToScreen"); - X11->ptrXRRQueryExtension = - (PtrXRRQueryExtension) xrandrLib.resolve("XRRQueryExtension"); - X11->ptrXRRSizes = - (PtrXRRSizes) xrandrLib.resolve("XRRSizes"); - } -# else - X11->ptrXRRSelectInput = XRRSelectInput; - X11->ptrXRRUpdateConfiguration = XRRUpdateConfiguration; - X11->ptrXRRRootToScreen = XRRRootToScreen; - X11->ptrXRRQueryExtension = XRRQueryExtension; - X11->ptrXRRSizes = XRRSizes; -# endif - - if (X11->ptrXRRQueryExtension - && X11->ptrXRRQueryExtension(X11->display, &X11->xrandr_eventbase, &X11->xrandr_errorbase)) { - // XRandR is supported - X11->use_xrandr = true; - } - } -#endif // QT_NO_XRANDR - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - // XRender is supported, let's see if we have a PictFormat for the - // default visual - XRenderPictFormat *format = - XRenderFindVisualFormat(X11->display, - (Visual *) QX11Info::appVisual(X11->defaultScreen)); - - if (!format) { - X11->use_xrender = false; - } - } -#endif // QT_NO_XRENDER - -#ifndef QT_NO_XFIXES - // See if Xfixes is supported on the connected display - if (XQueryExtension(X11->display, "XFIXES", &X11->xfixes_major, - &X11->xfixes_eventbase, &X11->xfixes_errorbase)) { - X11->ptrXFixesQueryExtension = XFIXES_LOAD_V1(XFixesQueryExtension); - X11->ptrXFixesQueryVersion = XFIXES_LOAD_V1(XFixesQueryVersion); - X11->ptrXFixesSetCursorName = XFIXES_LOAD_V2(XFixesSetCursorName); - X11->ptrXFixesSelectSelectionInput = XFIXES_LOAD_V2(XFixesSelectSelectionInput); - - if(X11->ptrXFixesQueryExtension && X11->ptrXFixesQueryVersion - && X11->ptrXFixesQueryExtension(X11->display, &X11->xfixes_eventbase, - &X11->xfixes_errorbase)) { - // Xfixes is supported. - // Note: the XFixes protocol version is negotiated using QueryVersion. - // We supply the highest version we support, the X server replies with - // the highest version it supports, but no higher than the version we - // asked for. The version sent back is the protocol version the X server - // will use to talk us. If this call is removed, the behavior of the - // X server when it receives an XFixes request is undefined. - int major = 3; - int minor = 0; - X11->ptrXFixesQueryVersion(X11->display, &major, &minor); - X11->use_xfixes = (major >= 1); - X11->xfixes_major = major; - } - } -#endif // QT_NO_XFIXES - -#ifndef QT_NO_XCURSOR -#ifdef QT_RUNTIME_XCURSOR - X11->ptrXcursorLibraryLoadCursor = 0; - QLibrary xcursorLib(QLatin1String("Xcursor"), 1); - bool xcursorFound = xcursorLib.load(); - if (!xcursorFound) { //try without the version number - xcursorLib.setFileName(QLatin1String("Xcursor")); - xcursorFound = xcursorLib.load(); - } - if (xcursorFound) { - X11->ptrXcursorLibraryLoadCursor = - (PtrXcursorLibraryLoadCursor) xcursorLib.resolve("XcursorLibraryLoadCursor"); - } -#else - X11->ptrXcursorLibraryLoadCursor = XcursorLibraryLoadCursor; -#endif // QT_RUNTIME_XCURSOR -#endif // QT_NO_XCURSOR - -#ifndef QT_NO_XSYNC - int xsync_evbase, xsync_errbase; - int major, minor; - if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase)) - XSyncInitialize(X11->display, &major, &minor); -#endif // QT_NO_XSYNC - -#ifndef QT_NO_XINERAMA -#ifdef QT_RUNTIME_XINERAMA - X11->ptrXineramaQueryExtension = 0; - X11->ptrXineramaIsActive = 0; - X11->ptrXineramaQueryScreens = 0; - QLibrary xineramaLib(QLatin1String("Xinerama"), 1); - bool xineramaFound = xineramaLib.load(); - if (!xineramaFound) { //try without the version number - xineramaLib.setFileName(QLatin1String("Xinerama")); - xineramaFound = xineramaLib.load(); - } - if (xineramaFound) { - X11->ptrXineramaQueryExtension = - (PtrXineramaQueryExtension) xineramaLib.resolve("XineramaQueryExtension"); - X11->ptrXineramaIsActive = - (PtrXineramaIsActive) xineramaLib.resolve("XineramaIsActive"); - X11->ptrXineramaQueryScreens = - (PtrXineramaQueryScreens) xineramaLib.resolve("XineramaQueryScreens"); - } -#else - X11->ptrXineramaQueryScreens = XineramaQueryScreens; - X11->ptrXineramaIsActive = XineramaIsActive; - X11->ptrXineramaQueryExtension = XineramaQueryExtension; -#endif // QT_RUNTIME_XINERAMA -#endif // QT_NO_XINERAMA - -#ifndef QT_NO_XINPUT - // See if Xinput is supported on the connected display - X11->ptrXCloseDevice = 0; - X11->ptrXListInputDevices = 0; - X11->ptrXOpenDevice = 0; - X11->ptrXFreeDeviceList = 0; - X11->ptrXSelectExtensionEvent = 0; - X11->use_xinput = XQueryExtension(X11->display, "XInputExtension", &X11->xinput_major, - &X11->xinput_eventbase, &X11->xinput_errorbase); - if (X11->use_xinput) { - X11->ptrXCloseDevice = XINPUT_LOAD(XCloseDevice); - X11->ptrXListInputDevices = XINPUT_LOAD(XListInputDevices); - X11->ptrXOpenDevice = XINPUT_LOAD(XOpenDevice); - X11->ptrXFreeDeviceList = XINPUT_LOAD(XFreeDeviceList); - X11->ptrXSelectExtensionEvent = XINPUT_LOAD(XSelectExtensionEvent); - } -#endif // QT_NO_XINPUT - -#ifndef QT_NO_XKB - int xkblibMajor = XkbMajorVersion; - int xkblibMinor = XkbMinorVersion; - X11->use_xkb = XkbQueryExtension(X11->display, - &X11->xkb_major, - &X11->xkb_eventbase, - &X11->xkb_errorbase, - &xkblibMajor, - &xkblibMinor); - if (X11->use_xkb) { - // If XKB is detected, set the GrabsUseXKBState option so input method - // compositions continue to work (ie. deadkeys) - unsigned int state = XkbPCF_GrabsUseXKBStateMask; - (void) XkbSetPerClientControls(X11->display, state, &state); - - // select for group change events - XkbSelectEventDetails(X11->display, - XkbUseCoreKbd, - XkbStateNotify, - XkbAllStateComponentsMask, - XkbGroupStateMask); - - // current group state is queried when creating the keymapper, no need to do it here - } -#endif - - -#if !defined(QT_NO_FONTCONFIG) - int dpi = 0; - getXDefault("Xft", FC_DPI, &dpi); - if (dpi) { - for (int s = 0; s < ScreenCount(X11->display); ++s) { - QX11Info::setAppDpiX(s, dpi); - QX11Info::setAppDpiY(s, dpi); - } - } - double fc_scale = 1.; - getXDefault("Xft", FC_SCALE, &fc_scale); - X11->fc_scale = fc_scale; - for (int s = 0; s < ScreenCount(X11->display); ++s) { - int subpixel = FC_RGBA_UNKNOWN; -#if !defined(QT_NO_XRENDER) && (RENDER_MAJOR > 0 || RENDER_MINOR >= 6) - if (X11->use_xrender) { - int rsp = XRenderQuerySubpixelOrder(X11->display, s); - switch (rsp) { - default: - case SubPixelUnknown: - subpixel = FC_RGBA_UNKNOWN; - break; - case SubPixelHorizontalRGB: - subpixel = FC_RGBA_RGB; - break; - case SubPixelHorizontalBGR: - subpixel = FC_RGBA_BGR; - break; - case SubPixelVerticalRGB: - subpixel = FC_RGBA_VRGB; - break; - case SubPixelVerticalBGR: - subpixel = FC_RGBA_VBGR; - break; - case SubPixelNone: - subpixel = FC_RGBA_NONE; - break; - } - } -#endif - - char *rgba = XGetDefault(X11->display, "Xft", FC_RGBA); - if (rgba) { - char *end = 0; - int v = strtol(rgba, &end, 0); - if (rgba != end) { - subpixel = v; - } else if (qstrncmp(rgba, "unknown", 7) == 0) { - subpixel = FC_RGBA_UNKNOWN; - } else if (qstrncmp(rgba, "rgb", 3) == 0) { - subpixel = FC_RGBA_RGB; - } else if (qstrncmp(rgba, "bgr", 3) == 0) { - subpixel = FC_RGBA_BGR; - } else if (qstrncmp(rgba, "vrgb", 4) == 0) { - subpixel = FC_RGBA_VRGB; - } else if (qstrncmp(rgba, "vbgr", 4) == 0) { - subpixel = FC_RGBA_VBGR; - } else if (qstrncmp(rgba, "none", 4) == 0) { - subpixel = FC_RGBA_NONE; - } - } - X11->screens[s].subpixel = subpixel; - } - getXDefault("Xft", FC_ANTIALIAS, &X11->fc_antialias); -#ifdef FC_HINT_STYLE - X11->fc_hint_style = -1; - getXDefault("Xft", FC_HINT_STYLE, &X11->fc_hint_style); -#endif -#if 0 - // ###### these are implemented by Xft, not sure we need them - getXDefault("Xft", FC_AUTOHINT, &X11->fc_autohint); - getXDefault("Xft", FC_HINTING, &X11->fc_autohint); - getXDefault("Xft", FC_MINSPACE, &X11->fc_autohint); -#endif -#endif // QT_NO_XRENDER - - // initialize key mapper - QKeyMapper::changeKeyboard(); - - // Misc. initialization -#if 0 //disabled for now.. - QSegfaultHandler::initialize(priv->argv, priv->argc); -#endif - QCursorData::initialize(); - } - QFont::initialize(); - - if(qt_is_gui_used) { - qApp->setObjectName(QString::fromLocal8Bit(appName)); - - int screen; - for (screen = 0; screen < X11->screenCount; ++screen) { - XSelectInput(X11->display, QX11Info::appRootWindow(screen), - KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); - -#ifndef QT_NO_XRANDR - if (X11->use_xrandr) - X11->ptrXRRSelectInput(X11->display, QX11Info::appRootWindow(screen), True); -#endif // QT_NO_XRANDR - } - } - - if (qt_is_gui_used) { - // Attempt to determine the current running X11 Desktop Enviornment - // Use dbus if/when we can, but fall back to using windowManagerName() for now - -#ifndef QT_NO_XFIXES - if (X11->ptrXFixesSelectSelectionInput) - X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(), ATOM(_NET_WM_CM_S0), - XFixesSetSelectionOwnerNotifyMask - | XFixesSelectionWindowDestroyNotifyMask - | XFixesSelectionClientCloseNotifyMask); -#endif // QT_NO_XFIXES - X11->compositingManagerRunning = XGetSelectionOwner(X11->display, - ATOM(_NET_WM_CM_S0)); - X11->desktopEnvironment = DE_UNKNOWN; - X11->desktopVersion = 0; - - Atom type; - int format; - unsigned long length, after; - uchar *data = 0; - int rc; - - do { - if (!qgetenv("KDE_FULL_SESSION").isEmpty()) { - X11->desktopEnvironment = DE_KDE; - X11->desktopVersion = qgetenv("KDE_SESSION_VERSION").toInt(); - break; - } - - if (qgetenv("DESKTOP_SESSION") == "gnome") { - X11->desktopEnvironment = DE_GNOME; - break; - } - - // GNOME_DESKTOP_SESSION_ID is deprecated for some reason, but still check it - if (!qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty()) { - X11->desktopEnvironment = DE_GNOME; - break; - } - - rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(_DT_SAVE_MODE), - 0, 2, False, XA_STRING, &type, &format, &length, - &after, &data); - if (rc == Success && length) { - if (!strcmp(reinterpret_cast<char *>(data), "xfce4")) { - // Pretend that xfce4 is gnome, as it uses the same libraries. - // The detection above is stolen from xdg-open. - X11->desktopEnvironment = DE_GNOME; - break; - } - - // We got the property but it wasn't xfce4. Free data before it gets overwritten. - XFree(data); - data = 0; - } - - rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), ATOM(DTWM_IS_RUNNING), - 0, 1, False, AnyPropertyType, &type, &format, &length, - &after, &data); - if (rc == Success && length) { - // DTWM is running, meaning most likely CDE is running... - X11->desktopEnvironment = DE_CDE; - break; - } - - rc = XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_SGI_DESKS_MANAGER), 0, 1, False, XA_WINDOW, - &type, &format, &length, &after, &data); - if (rc == Success && length) { - X11->desktopEnvironment = DE_4DWM; - break; - } - - if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_NET_SUPPORTING_WM_CHECK), - 0, 1024, False, XA_WINDOW, &type, - &format, &length, &after, &data) == Success) { - if (type == XA_WINDOW && format == 32) { - Window windowManagerWindow = *((Window*) data); - XFree(data); - data = 0; - - if (windowManagerWindow != XNone) { - Atom utf8atom = ATOM(UTF8_STRING); - if (XGetWindowProperty(QX11Info::display(), windowManagerWindow, ATOM(_NET_WM_NAME), - 0, 1024, False, utf8atom, &type, - &format, &length, &after, &data) == Success) { - if (type == utf8atom && format == 8) { - if (qstrcmp((const char *)data, "MCompositor") == 0) - X11->desktopEnvironment = DE_MEEGO_COMPOSITOR; - } - } - } - } - } - - } while(0); - - if (data) - XFree((char *)data); - -#if !defined(QT_NO_STYLE_GTK) - if (X11->desktopEnvironment == DE_GNOME) { - static bool menusHaveIcons = QGtkStyle::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true); - QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons); - } -#endif - qt_set_input_encoding(); - - qt_set_x11_resources(appFont, appFGCol, appBGCol, appBTNCol); - - // be smart about the size of the default font. most X servers have helvetica - // 12 point available at 2 resolutions: - // 75dpi (12 pixels) and 100dpi (17 pixels). - // At 95 DPI, a 12 point font should be 16 pixels tall - in which case a 17 - // pixel font is a closer match than a 12 pixel font - int ptsz = (X11->use_xrender - ? 9 - : (int) (((QX11Info::appDpiY() >= 95 ? 17. : 12.) * - 72. / (float) QX11Info::appDpiY()) + 0.5)); - - if (!QApplicationPrivate::sys_font) { - // no font from settings or RESOURCE_MANAGER, provide a fallback - QFont f(X11->has_fontconfig ? QLatin1String("Sans Serif") : QLatin1String("Helvetica"), - ptsz); - QApplicationPrivate::setSystemFont(f); - } - -#if !defined (QT_NO_TABLET) - if (X11->use_xinput) { - int ndev, - i, - j; - bool gotStylus, - gotEraser; - XDeviceInfo *devices = 0, *devs; - XInputClassInfo *ip; - XAnyClassPtr any; - XValuatorInfoPtr v; - XAxisInfoPtr a; - XDevice *dev = 0; - - if (X11->ptrXListInputDevices) { - devices = X11->ptrXListInputDevices(X11->display, &ndev); - if (!devices) - qWarning("QApplication: Failed to get list of tablet devices"); - } - if (!devices) - ndev = -1; - QTabletEvent::TabletDevice deviceType; - for (devs = devices, i = 0; i < ndev && devs; i++, devs++) { - dev = 0; - deviceType = QTabletEvent::NoDevice; - gotStylus = false; - gotEraser = false; - -#if defined(Q_OS_IRIX) - QString devName = QString::fromLocal8Bit(devs->name).toLower(); - if (devName == QLatin1String(WACOM_NAME)) { - deviceType = QTabletEvent::Stylus; - gotStylus = true; - } -#else - if (devs->type == ATOM(XWacomStylus) || devs->type == ATOM(XTabletStylus)) { - deviceType = QTabletEvent::Stylus; - if (wacomDeviceName()->isEmpty()) - wacomDeviceName()->append(devs->name); - gotStylus = true; - } else if (devs->type == ATOM(XWacomEraser) || devs->type == ATOM(XTabletEraser)) { - deviceType = QTabletEvent::XFreeEraser; - gotEraser = true; - } -#endif - if (deviceType == QTabletEvent::NoDevice) - continue; - - if (gotStylus || gotEraser) { - if (X11->ptrXOpenDevice) - dev = X11->ptrXOpenDevice(X11->display, devs->id); - - if (!dev) - continue; - - QTabletDeviceData device_data; - device_data.deviceType = deviceType; - device_data.eventCount = 0; - device_data.device = dev; - device_data.xinput_motion = -1; - device_data.xinput_key_press = -1; - device_data.xinput_key_release = -1; - device_data.xinput_button_press = -1; - device_data.xinput_button_release = -1; - device_data.xinput_proximity_in = -1; - device_data.xinput_proximity_out = -1; - device_data.widgetToGetPress = 0; - - if (dev->num_classes > 0) { - for (ip = dev->classes, j = 0; j < dev->num_classes; - ip++, j++) { - switch (ip->input_class) { - case KeyClass: - DeviceKeyPress(dev, device_data.xinput_key_press, - device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - DeviceKeyRelease(dev, device_data.xinput_key_release, - device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - break; - case ButtonClass: - DeviceButtonPress(dev, device_data.xinput_button_press, - device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - DeviceButtonRelease(dev, device_data.xinput_button_release, - device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - break; - case ValuatorClass: - // I'm only going to be interested in motion when the - // stylus is already down anyway! - DeviceMotionNotify(dev, device_data.xinput_motion, - device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - ProximityIn(dev, device_data.xinput_proximity_in, device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - ProximityOut(dev, device_data.xinput_proximity_out, device_data.eventList[device_data.eventCount]); - if (device_data.eventList[device_data.eventCount]) - ++device_data.eventCount; - default: - break; - } - } - } - - // get the min/max value for pressure! - any = (XAnyClassPtr) (devs->inputclassinfo); - for (j = 0; j < devs->num_classes; j++) { - if (any->c_class == ValuatorClass) { - v = (XValuatorInfoPtr) any; - a = (XAxisInfoPtr) ((char *) v + - sizeof (XValuatorInfo)); -#if defined (Q_OS_IRIX) - // I'm not exaclty wild about this, but the - // dimensions of the tablet are more relevant here - // than the min and max values from the axis - // (actually it seems to be 2/3 or what is in the - // axis. So we'll try to parse it from this - // string. --tws - char returnString[SGIDeviceRtrnLen]; - int tmp; - if (XSGIMiscQueryExtension(X11->display, &tmp, &tmp) - && XSGIDeviceQuery(X11->display, devs->id, - "dimensions", returnString)) { - QString str = QLatin1String(returnString); - int comma = str.indexOf(','); - device_data.minX = 0; - device_data.minY = 0; - device_data.maxX = str.left(comma).toInt(); - device_data.maxY = str.mid(comma + 1).toInt(); - } else { - device_data.minX = a[WAC_XCOORD_I].min_value; - device_data.maxX = a[WAC_XCOORD_I].max_value; - device_data.minY = a[WAC_YCOORD_I].min_value; - device_data.maxY = a[WAC_YCOORD_I].max_value; - } - device_data.minPressure = a[WAC_PRESSURE_I].min_value; - device_data.maxPressure = a[WAC_PRESSURE_I].max_value; - device_data.minTanPressure = a[WAC_TAN_PRESSURE_I].min_value; - device_data.maxTanPressure = a[WAC_TAN_PRESSURE_I].max_value; - device_data.minZ = a[WAC_ZCOORD_I].min_value; - device_data.maxZ = a[WAC_ZCOORD_I].max_value; -#else - device_data.minX = a[0].min_value; - device_data.maxX = a[0].max_value; - device_data.minY = a[1].min_value; - device_data.maxY = a[1].max_value; - device_data.minPressure = a[2].min_value; - device_data.maxPressure = a[2].max_value; - device_data.minTanPressure = 0; - device_data.maxTanPressure = 0; - device_data.minZ = 0; - device_data.maxZ = 0; -#endif - - // got the max pressure no need to go further... - break; - } - any = (XAnyClassPtr) ((char *) any + any->length); - } // end of for loop - - tablet_devices()->append(device_data); - } // if (gotStylus || gotEraser) - } - if (X11->ptrXFreeDeviceList) - X11->ptrXFreeDeviceList(devices); - } -#endif // QT_NO_TABLET - - X11->startupId = getenv("DESKTOP_STARTUP_ID"); - if (X11->startupId) { -#ifndef QT_NO_UNSETENV - unsetenv("DESKTOP_STARTUP_ID"); -#else - // it's a small memory leak, however we won't crash if Qt is - // unloaded and someones tries to use the envoriment. - putenv(strdup("DESKTOP_STARTUP_ID=")); -#endif - } - } else { - // read some non-GUI settings when not using the X server... - - if (QApplication::desktopSettingsAware()) { - QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); - settings.beginGroup(QLatin1String("Qt")); - - // read library (ie. plugin) path list - QString libpathkey = QString::fromLatin1("%1.%2/libraryPath") - .arg(QT_VERSION >> 16) - .arg((QT_VERSION & 0xff00) >> 8); - QStringList pathlist = - settings.value(libpathkey).toString().split(QLatin1Char(':')); - if (! pathlist.isEmpty()) { - QStringList::ConstIterator it = pathlist.constBegin(); - while (it != pathlist.constEnd()) - QApplication::addLibraryPath(*it++); - } - - QString defaultcodec = settings.value(QLatin1String("defaultCodec"), - QVariant(QLatin1String("none"))).toString(); - if (defaultcodec != QLatin1String("none")) { - QTextCodec *codec = QTextCodec::codecForName(defaultcodec.toLatin1()); - if (codec) - QTextCodec::setCodecForTr(codec); - } - - settings.endGroup(); // Qt - } - } - -#if !defined (Q_OS_IRIX) && !defined (QT_NO_TABLET) - QLibrary wacom(QString::fromLatin1("wacomcfg"), 0); // version 0 is the latest release at time of writing this. - // NOTE: C casts instead of reinterpret_cast for GCC 3.3.x - ptrWacomConfigInit = (PtrWacomConfigInit)wacom.resolve("WacomConfigInit"); - ptrWacomConfigOpenDevice = (PtrWacomConfigOpenDevice)wacom.resolve("WacomConfigOpenDevice"); - ptrWacomConfigGetRawParam = (PtrWacomConfigGetRawParam)wacom.resolve("WacomConfigGetRawParam"); - ptrWacomConfigCloseDevice = (PtrWacomConfigCloseDevice)wacom.resolve("WacomConfigCloseDevice"); - ptrWacomConfigTerm = (PtrWacomConfigTerm)wacom.resolve("WacomConfigTerm"); - - if (ptrWacomConfigInit == 0 || ptrWacomConfigOpenDevice == 0 || ptrWacomConfigGetRawParam == 0 - || ptrWacomConfigCloseDevice == 0 || ptrWacomConfigTerm == 0) { // either we have all, or we have none. - ptrWacomConfigInit = 0; - ptrWacomConfigOpenDevice = 0; - ptrWacomConfigGetRawParam = 0; - ptrWacomConfigCloseDevice = 0; - ptrWacomConfigTerm = 0; - } -#endif -} - -void QApplicationPrivate::initializeWidgetPaletteHash() -{ -} - -/***************************************************************************** - qt_cleanup() - cleans up when the application is finished - *****************************************************************************/ - -void qt_cleanup() -{ - if (app_save_rootinfo) // root window must keep state - qt_save_rootinfo(); - - if (qt_is_gui_used) { - QPixmapCache::clear(); - QCursorData::cleanup(); - QFont::cleanup(); - QColormap::cleanup(); - -#if !defined (QT_NO_TABLET) - QTabletDeviceDataList *devices = qt_tablet_devices(); - if (X11->ptrXCloseDevice) - for (int i = 0; i < devices->size(); ++i) - X11->ptrXCloseDevice(X11->display, (XDevice*)devices->at(i).device); - devices->clear(); -#endif - } - -#ifndef QT_NO_XRENDER - for (int i = 0; i < X11->solid_fill_count; ++i) { - if (X11->solid_fills[i].picture) - XRenderFreePicture(X11->display, X11->solid_fills[i].picture); - } - for (int i = 0; i < X11->pattern_fill_count; ++i) { - if (X11->pattern_fills[i].picture) - XRenderFreePicture(X11->display, X11->pattern_fills[i].picture); - } -#endif - -#if !defined(QT_NO_IM) - delete QApplicationPrivate::inputContext; - QApplicationPrivate::inputContext = 0; -#endif - - // Reset the error handlers - if (qt_is_gui_used) - XSync(X11->display, False); // sync first to process all possible errors - XSetErrorHandler(original_x_errhandler); - XSetIOErrorHandler(original_xio_errhandler); - - if (X11->argbColormaps) { - for (int s = 0; s < X11->screenCount; s++) { - if (X11->argbColormaps[s]) - XFreeColormap(X11->display, X11->argbColormaps[s]); - } - } - - if (qt_is_gui_used && !X11->foreignDisplay) - XCloseDisplay(X11->display); // close X display - X11->display = 0; - - delete [] X11->screens; - delete [] X11->argbVisuals; - delete [] X11->argbColormaps; - - if (X11->foreignDisplay) { - delete [] (char *)appName; - appName = 0; - } - - delete [] (char *)appClass; - appClass = 0; - - if (X11->net_supported_list) - delete [] X11->net_supported_list; - X11->net_supported_list = 0; - - if (X11->net_virtual_root_list) - delete [] X11->net_virtual_root_list; - X11->net_virtual_root_list = 0; - - delete X11; - X11 = 0; -} - - -/***************************************************************************** - Platform specific global and internal functions - *****************************************************************************/ - -void qt_save_rootinfo() // save new root info -{ - Atom type; - int format; - unsigned long length, after; - uchar *data = 0; - - if (ATOM(_XSETROOT_ID)) { // kill old pixmap - if (XGetWindowProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_XSETROOT_ID), 0, 1, - True, AnyPropertyType, &type, &format, - &length, &after, &data) == Success) { - if (type == XA_PIXMAP && format == 32 && length == 1 && - after == 0 && data) { - XKillClient(X11->display, *((Pixmap*)data)); - } - Pixmap dummy = XCreatePixmap(X11->display, QX11Info::appRootWindow(), - 1, 1, 1); - XChangeProperty(X11->display, QX11Info::appRootWindow(), - ATOM(_XSETROOT_ID), XA_PIXMAP, 32, - PropModeReplace, (uchar *)&dummy, 1); - XSetCloseDownMode(X11->display, RetainPermanent); - } - } - if (data) - XFree((char *)data); -} - -void qt_updated_rootinfo() -{ - app_save_rootinfo = true; -} - -// ### Cleanup, this function is not in use! -bool qt_wstate_iconified(WId winid) -{ - Atom type; - int format; - unsigned long length, after; - uchar *data = 0; - int r = XGetWindowProperty(X11->display, winid, ATOM(WM_STATE), 0, 2, - False, AnyPropertyType, &type, &format, - &length, &after, &data); - bool iconic = false; - if (r == Success && data && format == 32) { - // quint32 *wstate = (quint32*)data; - unsigned long *wstate = (unsigned long *) data; - iconic = (*wstate == IconicState); - XFree((char *)data); - } - return iconic; -} - -QString QApplicationPrivate::appName() const -{ - return QString::fromLocal8Bit(QT_PREPEND_NAMESPACE(appName)); -} - -const char *QX11Info::appClass() // get application class -{ - return QT_PREPEND_NAMESPACE(appClass); -} - -bool qt_nograb() // application no-grab option -{ -#if defined(QT_DEBUG) - return appNoGrab; -#else - return false; -#endif -} - - -/***************************************************************************** - Platform specific QApplication members - *****************************************************************************/ - - -void QApplicationPrivate::applyX11SpecificCommandLineArguments(QWidget *main_widget) -{ - static bool beenHereDoneThat = false; - if (beenHereDoneThat) - return; - beenHereDoneThat = true; - Q_ASSERT(main_widget->testAttribute(Qt::WA_WState_Created)); - if (mwTitle) { - XStoreName(X11->display, main_widget->effectiveWinId(), (char*)mwTitle); - QByteArray net_wm_name = QString::fromLocal8Bit(mwTitle).toUtf8(); - XChangeProperty(X11->display, main_widget->effectiveWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8, - PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size()); - } - if (mwGeometry) { // parse geometry - int x, y; - int w, h; - int m = XParseGeometry((char*)mwGeometry, &x, &y, (uint*)&w, (uint*)&h); - QSize minSize = main_widget->minimumSize(); - QSize maxSize = main_widget->maximumSize(); - if ((m & XValue) == 0) - x = main_widget->geometry().x(); - if ((m & YValue) == 0) - y = main_widget->geometry().y(); - if ((m & WidthValue) == 0) - w = main_widget->width(); - if ((m & HeightValue) == 0) - h = main_widget->height(); - w = qMin(w,maxSize.width()); - h = qMin(h,maxSize.height()); - w = qMax(w,minSize.width()); - h = qMax(h,minSize.height()); - if ((m & XNegative)) { - x = QApplication::desktop()->width() + x - w; - } - if ((m & YNegative)) { - y = QApplication::desktop()->height() + y - h; - } - main_widget->setGeometry(x, y, w, h); - } -} - -#ifndef QT_NO_CURSOR - -/***************************************************************************** - QApplication cursor stack - *****************************************************************************/ - -void QApplication::setOverrideCursor(const QCursor &cursor) -{ - qApp->d_func()->cursor_list.prepend(cursor); - - QWidgetList all = allWidgets(); - for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) { - register QWidget *w = *it; - if ((w->testAttribute(Qt::WA_SetCursor) || w->isWindow()) && (w->windowType() != Qt::Desktop)) - qt_x11_enforce_cursor(w); - } - XFlush(X11->display); // make X execute it NOW -} - -void QApplication::restoreOverrideCursor() -{ - if (qApp->d_func()->cursor_list.isEmpty()) - return; - qApp->d_func()->cursor_list.removeFirst(); - - if (QWidgetPrivate::mapper != 0 && !closingDown()) { - QWidgetList all = allWidgets(); - for (QWidgetList::ConstIterator it = all.constBegin(); it != all.constEnd(); ++it) { - register QWidget *w = *it; - if ((w->testAttribute(Qt::WA_SetCursor) || w->isWindow()) && (w->windowType() != Qt::Desktop)) - qt_x11_enforce_cursor(w); - } - XFlush(X11->display); - } -} - -#endif - - -/***************************************************************************** - Routines to find a Qt widget from a screen position - *****************************************************************************/ - -Window QX11Data::findClientWindow(Window win, Atom property, bool leaf) -{ - Atom type = XNone; - int format, i; - ulong nitems, after; - uchar *data = 0; - Window root, parent, target=0, *children=0; - uint nchildren; - if (XGetWindowProperty(X11->display, win, property, 0, 0, false, AnyPropertyType, - &type, &format, &nitems, &after, &data) == Success) { - if (data) - XFree((char *)data); - if (type) - return win; - } - if (!XQueryTree(X11->display,win,&root,&parent,&children,&nchildren)) { - if (children) - XFree((char *)children); - return 0; - } - for (i=nchildren-1; !target && i >= 0; i--) - target = X11->findClientWindow(children[i], property, leaf); - if (children) - XFree((char *)children); - return target; -} - -QWidget *QApplication::topLevelAt(const QPoint &p) -{ -#ifdef QT_NO_CURSOR - Q_UNUSED(p); - return 0; -#else - int screen = QCursor::x11Screen(); - int unused; - - int x = p.x(); - int y = p.y(); - Window target; - if (!XTranslateCoordinates(X11->display, - QX11Info::appRootWindow(screen), - QX11Info::appRootWindow(screen), - x, y, &unused, &unused, &target)) { - return 0; - } - if (!target || target == QX11Info::appRootWindow(screen)) - return 0; - QWidget *w; - w = QWidget::find((WId)target); - - if (!w) { - X11->ignoreBadwindow(); - target = X11->findClientWindow(target, ATOM(WM_STATE), true); - if (X11->badwindow()) - return 0; - w = QWidget::find((WId)target); - if (!w) { - // Perhaps the widget at (x,y) is inside a foreign application? - // Search all toplevel widgets to see if one is within target - QWidgetList list = QApplication::topLevelWidgets(); - for (int i = 0; i < list.count(); ++i) { - QWidget *widget = list.at(i); - Window ctarget = target; - if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) { - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - Window wid = widget->internalWinId(); - while (ctarget && !w) { - X11->ignoreBadwindow(); - if (!XTranslateCoordinates(X11->display, - QX11Info::appRootWindow(screen), - ctarget, x, y, &unused, &unused, &ctarget) - || X11->badwindow()) - break; - if (ctarget == wid) { - // Found! - w = widget; - break; - } - } - } - if (w) - break; - } - } - } - return w ? w->window() : 0; -#endif -} - -void QApplication::syncX() -{ - if (X11->display) - XSync(X11->display, False); // don't discard events -} - - -void QApplication::beep() -{ - if (X11->display) - XBell(X11->display, 0); - else - printf("\7"); -} - -void QApplication::alert(QWidget *widget, int msec) -{ - if (!QApplicationPrivate::checkInstance("alert")) - return; - - QWidgetList windowsToMark; - if (!widget) { - windowsToMark += topLevelWidgets(); - } else { - windowsToMark.append(widget->window()); - } - - for (int i = 0; i < windowsToMark.size(); ++i) { - QWidget *window = windowsToMark.at(i); - if (!window->isActiveWindow()) { - qt_change_net_wm_state(window, true, ATOM(_NET_WM_STATE_DEMANDS_ATTENTION)); - if (msec != 0) { - QTimer *timer = new QTimer(qApp); - timer->setSingleShot(true); - connect(timer, SIGNAL(timeout()), qApp, SLOT(_q_alertTimeOut())); - if (QTimer *oldTimer = qApp->d_func()->alertTimerHash.value(window)) { - qApp->d_func()->alertTimerHash.remove(window); - delete oldTimer; - } - qApp->d_func()->alertTimerHash.insert(window, timer); - timer->start(msec); - } - } - } -} - -void QApplicationPrivate::_q_alertTimeOut() -{ - if (QTimer *timer = qobject_cast<QTimer *>(q_func()->sender())) { - QHash<QWidget *, QTimer *>::iterator it = alertTimerHash.begin(); - while (it != alertTimerHash.end()) { - if (it.value() == timer) { - QWidget *window = it.key(); - qt_change_net_wm_state(window, false, ATOM(_NET_WM_STATE_DEMANDS_ATTENTION)); - alertTimerHash.erase(it); - timer->deleteLater(); - break; - } - ++it; - } - } -} - -/***************************************************************************** - Special lookup functions for windows that have been reparented recently - *****************************************************************************/ - -static QWidgetMapper *wPRmapper = 0; // alternative widget mapper - -void qPRCreate(const QWidget *widget, Window oldwin) -{ // QWidget::reparent mechanism - if (!wPRmapper) - wPRmapper = new QWidgetMapper; - - QETWidget *w = static_cast<QETWidget *>(const_cast<QWidget *>(widget)); - wPRmapper->insert((int)oldwin, w); // add old window to mapper - w->setAttribute(Qt::WA_WState_Reparented); // set reparented flag -} - -void qPRCleanup(QWidget *widget) -{ - QETWidget *etw = static_cast<QETWidget *>(const_cast<QWidget *>(widget)); - if (!(wPRmapper && widget->testAttribute(Qt::WA_WState_Reparented))) - return; // not a reparented widget - QWidgetMapper::Iterator it = wPRmapper->begin(); - while (it != wPRmapper->constEnd()) { - QWidget *w = *it; - if (w == etw) { // found widget - etw->setAttribute(Qt::WA_WState_Reparented, false); // clear flag - it = wPRmapper->erase(it);// old window no longer needed - } else { - ++it; - } - } - if (wPRmapper->size() == 0) { // became empty - delete wPRmapper; // then reset alt mapper - wPRmapper = 0; - } -} - -static QETWidget *qPRFindWidget(Window oldwin) -{ - return wPRmapper ? (QETWidget*)wPRmapper->value((int)oldwin, 0) : 0; -} - -int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only) -{ - if (w && !w->internalWinId()) - return 0; - QETWidget *widget = (QETWidget*)w; - if (event->xclient.format == 32 && event->xclient.message_type) { - if (event->xclient.message_type == ATOM(WM_PROTOCOLS)) { - Atom a = event->xclient.data.l[0]; - if (a == ATOM(WM_DELETE_WINDOW)) { - if (passive_only) return 0; - widget->translateCloseEvent(event); - } - else if (a == ATOM(WM_TAKE_FOCUS)) { - if ((ulong) event->xclient.data.l[1] > X11->time) - X11->time = event->xclient.data.l[1]; - QWidget *amw = activeModalWidget(); - if (amw && amw->testAttribute(Qt::WA_X11DoNotAcceptFocus)) - amw = 0; - if (amw && !QApplicationPrivate::tryModalHelper(widget, 0)) { - QWidget *p = amw->parentWidget(); - while (p && p != widget) - p = p->parentWidget(); - if (!p || !X11->net_supported_list) - amw->raise(); // help broken window managers - amw->activateWindow(); - } -#ifndef QT_NO_WHATSTHIS - } else if (a == ATOM(_NET_WM_CONTEXT_HELP)) { - QWhatsThis::enterWhatsThisMode(); -#endif // QT_NO_WHATSTHIS - } else if (a == ATOM(_NET_WM_PING)) { - // avoid send/reply loops - Window root = RootWindow(X11->display, w->x11Info().screen()); - if (event->xclient.window != root) { - event->xclient.window = root; - XSendEvent(event->xclient.display, event->xclient.window, - False, SubstructureNotifyMask|SubstructureRedirectMask, event); - } -#ifndef QT_NO_XSYNC - } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) { - const ulong timestamp = (const ulong) event->xclient.data.l[1]; - if (timestamp > X11->time) - X11->time = timestamp; - if (QTLWExtra *tlw = w->d_func()->maybeTopData()) { - if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) { - tlw->syncRequestTimestamp = timestamp; - tlw->newCounterValueLo = event->xclient.data.l[2]; - tlw->newCounterValueHi = event->xclient.data.l[3]; - } - } -#endif - } - } else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) { - widget->translateScrollDoneEvent(event); - } else if (event->xclient.message_type == ATOM(XdndPosition)) { - X11->xdndHandlePosition(widget, event, passive_only); - } else if (event->xclient.message_type == ATOM(XdndEnter)) { - X11->xdndHandleEnter(widget, event, passive_only); - } else if (event->xclient.message_type == ATOM(XdndStatus)) { - X11->xdndHandleStatus(widget, event, passive_only); - } else if (event->xclient.message_type == ATOM(XdndLeave)) { - X11->xdndHandleLeave(widget, event, passive_only); - } else if (event->xclient.message_type == ATOM(XdndDrop)) { - X11->xdndHandleDrop(widget, event, passive_only); - } else if (event->xclient.message_type == ATOM(XdndFinished)) { - X11->xdndHandleFinished(widget, event, passive_only); - } else { - if (passive_only) return 0; - // All other are interactions - } - } else { - X11->motifdndHandle(widget, event, passive_only); - } - - return 0; -} - -int QApplication::x11ProcessEvent(XEvent* event) -{ - Q_D(QApplication); - QScopedLoopLevelCounter loopLevelCounter(d->threadData); - -#ifdef ALIEN_DEBUG - //qDebug() << "QApplication::x11ProcessEvent:" << event->type; -#endif - switch (event->type) { - case ButtonPress: - pressed_window = event->xbutton.window; - X11->userTime = event->xbutton.time; - // fallthrough intended - case ButtonRelease: - X11->time = event->xbutton.time; - break; - case MotionNotify: - X11->time = event->xmotion.time; - break; - case XKeyPress: - X11->userTime = event->xkey.time; - // fallthrough intended - case XKeyRelease: - X11->time = event->xkey.time; - break; - case PropertyNotify: - X11->time = event->xproperty.time; - break; - case EnterNotify: - case LeaveNotify: - X11->time = event->xcrossing.time; - break; - case SelectionClear: - X11->time = event->xselectionclear.time; - break; - default: - break; - } -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { - XFixesSelectionNotifyEvent *req = - reinterpret_cast<XFixesSelectionNotifyEvent *>(event); - X11->time = req->selection_timestamp; - if (req->selection == ATOM(_NET_WM_CM_S0)) - X11->compositingManagerRunning = req->owner; - } -#endif - - QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window); - - if (wPRmapper) { // just did a widget reparent? - if (widget == 0) { // not in std widget mapper - switch (event->type) { // only for mouse/key events - case ButtonPress: - case ButtonRelease: - case MotionNotify: - case XKeyPress: - case XKeyRelease: - widget = qPRFindWidget(event->xany.window); - break; - } - } - else if (widget->testAttribute(Qt::WA_WState_Reparented)) - qPRCleanup(widget); // remove from alt mapper - } - - QETWidget *keywidget=0; - bool grabbed=false; - if (event->type==XKeyPress || event->type==XKeyRelease) { - keywidget = (QETWidget*)QWidget::keyboardGrabber(); - if (keywidget) { - grabbed = true; - } else if (!keywidget) { - if (d->inPopupMode()) // no focus widget, see if we have a popup - keywidget = (QETWidget*) (activePopupWidget()->focusWidget() ? activePopupWidget()->focusWidget() : activePopupWidget()); - else if (QApplicationPrivate::focus_widget) - keywidget = (QETWidget*)QApplicationPrivate::focus_widget; - else if (widget) - keywidget = (QETWidget*)widget->window(); - } - } - -#ifndef QT_NO_IM - // Filtering input events by the input context. It has to be taken - // place before any other key event consumers such as eventfilters - // and accelerators because some input methods require quite - // various key combination and sequences. It often conflicts with - // accelerators and so on, so we must give the input context the - // filtering opportunity first to ensure all input methods work - // properly regardless of application design. - - if(keywidget && keywidget->isEnabled() && keywidget->testAttribute(Qt::WA_InputMethodEnabled)) { - // block user interaction during session management - if((event->type==XKeyPress || event->type==XKeyRelease) && qt_sm_blockUserInput) - return true; - - // for XIM handling - QInputContext *qic = keywidget->inputContext(); - if(qic && qic->x11FilterEvent(keywidget, event)) - return true; - - // filterEvent() accepts QEvent *event rather than preexpanded - // key event attribute values. This is intended to pass other - // QInputEvent in future. Other non IM-related events should - // not be forwarded to input contexts to prevent weird event - // handling. - if ((event->type == XKeyPress || event->type == XKeyRelease)) { - int code = -1; - int count = 0; - Qt::KeyboardModifiers modifiers; - QEvent::Type type; - QString text; - KeySym keySym; - - qt_keymapper_private()->translateKeyEventInternal(keywidget, event, keySym, count, - text, modifiers, code, type, false); - - // both key press/release is required for some complex - // input methods. don't eliminate anything. - QKeyEventEx keyevent(type, code, modifiers, text, false, qMax(qMax(count, 1), text.length()), - event->xkey.keycode, keySym, event->xkey.state); - if(qic && qic->filterEvent(&keyevent)) - return true; - } - } else -#endif // QT_NO_IM - { - if (XFilterEvent(event, XNone)) - return true; - } - - if (qt_x11EventFilter(event)) // send through app filter - return 1; - - if (event->type == MappingNotify) { - // keyboard mapping changed - XRefreshKeyboardMapping(&event->xmapping); - - QKeyMapper::changeKeyboard(); - return 0; - } -#ifndef QT_NO_XKB - else if (X11->use_xkb && event->type == X11->xkb_eventbase) { - XkbAnyEvent *xkbevent = (XkbAnyEvent *) event; - switch (xkbevent->xkb_type) { - case XkbStateNotify: - { - XkbStateNotifyEvent *xkbstateevent = (XkbStateNotifyEvent *) xkbevent; - if ((xkbstateevent->changed & XkbGroupStateMask) != 0) { - qt_keymapper_private()->xkb_currentGroup = xkbstateevent->group; - QKeyMapper::changeKeyboard(); - } - break; - } - default: - break; - } - } -#endif - - if (!widget) { // don't know this windows - QWidget* popup = QApplication::activePopupWidget(); - if (popup) { - - /* - That is more than suboptimal. The real solution should - do some keyevent and buttonevent translation, so that - the popup still continues to work as the user expects. - Unfortunately this translation is currently only - possible with a known widget. I'll change that soon - (Matthias). - */ - - // Danger - make sure we don't lock the server - switch (event->type) { - case ButtonPress: - case ButtonRelease: - case XKeyPress: - case XKeyRelease: - do { - popup->close(); - } while ((popup = qApp->activePopupWidget())); - return 1; - } - } - return -1; - } - - if (event->type == XKeyPress || event->type == XKeyRelease) - widget = keywidget; // send XKeyEvents through keywidget->x11Event() - - if (app_do_modal) // modal event handling - if (!qt_try_modal(widget, event)) { - if (event->type == ClientMessage && !widget->x11Event(event)) - x11ClientMessage(widget, event, true); - return 1; - } - - - if (widget->x11Event(event)) // send through widget filter - return 1; -#if !defined (QT_NO_TABLET) - if (!qt_xdnd_dragging) { - QTabletDeviceDataList *tablets = qt_tablet_devices(); - for (int i = 0; i < tablets->size(); ++i) { - QTabletDeviceData &tab = tablets->operator [](i); - if (event->type == tab.xinput_motion - || event->type == tab.xinput_button_release - || event->type == tab.xinput_button_press - || event->type == tab.xinput_proximity_in - || event->type == tab.xinput_proximity_out) { - widget->translateXinputEvent(event, &tab); - return 0; - } - } - } -#endif - -#ifndef QT_NO_XRANDR - if (X11->use_xrandr && event->type == (X11->xrandr_eventbase + RRScreenChangeNotify)) { - // update Xlib internals with the latest screen configuration - X11->ptrXRRUpdateConfiguration(event); - - // update the size for desktop widget - int scr = X11->ptrXRRRootToScreen(X11->display, event->xany.window); - QDesktopWidget *desktop = QApplication::desktop(); - QWidget *w = desktop->screen(scr); - QSize oldSize(w->size()); - w->data->crect.setWidth(DisplayWidth(X11->display, scr)); - w->data->crect.setHeight(DisplayHeight(X11->display, scr)); - QResizeEvent e(w->size(), oldSize); - QApplication::sendEvent(w, &e); - if (w != desktop) - QApplication::sendEvent(desktop, &e); - } -#endif // QT_NO_XRANDR - -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { - XFixesSelectionNotifyEvent *req = reinterpret_cast<XFixesSelectionNotifyEvent *>(event); - - // compress all XFixes events related to this selection - // we don't want to handle old SelectionNotify events. - qt_xfixes_selection_event_data xfixes_event; - xfixes_event.selection = req->selection; - for (XEvent ev;;) { - if (!XCheckIfEvent(X11->display, &ev, &qt_xfixes_scanner, (XPointer)&xfixes_event)) - break; - } - - if (req->selection == ATOM(CLIPBOARD)) { - if (qt_xfixes_clipboard_changed(req->owner, req->selection_timestamp)) { - emit clipboard()->changed(QClipboard::Clipboard); - emit clipboard()->dataChanged(); - } - } else if (req->selection == XA_PRIMARY) { - if (qt_xfixes_selection_changed(req->owner, req->selection_timestamp)) { - emit clipboard()->changed(QClipboard::Selection); - emit clipboard()->selectionChanged(); - } - } - } -#endif // QT_NO_XFIXES - - switch (event->type) { - - case ButtonRelease: // mouse event - if (!d->inPopupMode() && !QWidget::mouseGrabber() && pressed_window != widget->internalWinId() - && (widget = (QETWidget*) QWidget::find((WId)pressed_window)) == 0) - break; - // fall through intended - case ButtonPress: - if (event->xbutton.root != RootWindow(X11->display, widget->x11Info().screen()) - && ! qt_xdnd_dragging) { - while (activePopupWidget()) - activePopupWidget()->close(); - return 1; - } - if (event->type == ButtonPress) - qt_net_update_user_time(widget->window(), X11->userTime); - // fall through intended - case MotionNotify: -#if !defined(QT_NO_TABLET) - if (!qt_tabletChokeMouse) { -#endif - if (widget->testAttribute(Qt::WA_TransparentForMouseEvents)) { - QPoint pos(event->xbutton.x, event->xbutton.y); - pos = widget->d_func()->mapFromWS(pos); - QWidget *window = widget->window(); - pos = widget->mapTo(window, pos); - if (QWidget *child = window->childAt(pos)) { - widget = static_cast<QETWidget *>(child); - pos = child->mapFrom(window, pos); - event->xbutton.x = pos.x(); - event->xbutton.y = pos.y(); - } - } - widget->translateMouseEvent(event); -#if !defined(QT_NO_TABLET) - } else { - qt_tabletChokeMouse = false; - } -#endif - break; - - case XKeyPress: // keyboard event - qt_net_update_user_time(widget->window(), X11->userTime); - // fallthrough intended - case XKeyRelease: - { - if (keywidget && keywidget->isEnabled()) { // should always exist - // qDebug("sending key event"); - qt_keymapper_private()->translateKeyEvent(keywidget, event, grabbed); - } - break; - } - - case GraphicsExpose: - case Expose: // paint event - widget->translatePaintEvent(event); - break; - - case ConfigureNotify: // window move/resize event - if (event->xconfigure.event == event->xconfigure.window) - widget->translateConfigEvent(event); - break; - - case XFocusIn: { // got focus - if ((widget->windowType() == Qt::Desktop)) - break; - if (d->inPopupMode()) // some delayed focus event to ignore - break; - if (!widget->isWindow()) - break; - if (event->xfocus.detail != NotifyAncestor && - event->xfocus.detail != NotifyInferior && - event->xfocus.detail != NotifyNonlinear) - break; - setActiveWindow(widget); - if (X11->focus_model == QX11Data::FM_PointerRoot) { - // We got real input focus from somewhere, but we were in PointerRoot - // mode, so we don't trust this event. Check the focus model to make - // sure we know what focus mode we are using... - qt_check_focus_model(); - } - } - break; - - case XFocusOut: // lost focus - if ((widget->windowType() == Qt::Desktop)) - break; - if (!widget->isWindow()) - break; - if (event->xfocus.mode == NotifyGrab) { - qt_xfocusout_grab_counter++; - break; - } - if (event->xfocus.detail != NotifyAncestor && - event->xfocus.detail != NotifyNonlinearVirtual && - event->xfocus.detail != NotifyNonlinear) - break; - if (!d->inPopupMode() && widget == QApplicationPrivate::active_window) { - XEvent ev; - bool focus_will_change = false; - if (XCheckTypedEvent(X11->display, XFocusIn, &ev)) { - // we're about to get an XFocusIn, if we know we will - // get a new active window, we don't want to set the - // active window to 0 now - QWidget *w2 = QWidget::find(ev.xany.window); - if (w2 - && w2->windowType() != Qt::Desktop - && !d->inPopupMode() // some delayed focus event to ignore - && w2->isWindow() - && (ev.xfocus.detail == NotifyAncestor - || ev.xfocus.detail == NotifyInferior - || ev.xfocus.detail == NotifyNonlinear)) - focus_will_change = true; - - XPutBackEvent(X11->display, &ev); - } - if (!focus_will_change) - setActiveWindow(0); - } - break; - - case EnterNotify: { // enter window - if (QWidget::mouseGrabber() && (!d->inPopupMode() || widget->window() != activePopupWidget())) - break; - if ((event->xcrossing.mode != NotifyNormal - && event->xcrossing.mode != NotifyUngrab) - || event->xcrossing.detail == NotifyVirtual - || event->xcrossing.detail == NotifyNonlinearVirtual) - break; - if (event->xcrossing.focus && - !(widget->windowType() == Qt::Desktop) && !widget->isActiveWindow()) { - if (X11->focus_model == QX11Data::FM_Unknown) // check focus model - qt_check_focus_model(); - if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode - setActiveWindow(widget); - } - - if (qt_button_down && !d->inPopupMode()) - break; - - QWidget *alien = widget->childAt(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x, - event->xcrossing.y))); - QWidget *enter = alien ? alien : widget; - QWidget *leave = 0; - if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId()) - leave = qt_last_mouse_receiver; - else - leave = QWidget::find(curWin); - - // ### Alien: enter/leave might be wrong here with overlapping siblings - // if the enter widget is native and stacked under a non-native widget. - QApplicationPrivate::dispatchEnterLeave(enter, leave); - curWin = widget->internalWinId(); - qt_last_mouse_receiver = enter; - if (!d->inPopupMode() || widget->window() == activePopupWidget()) - widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it - } - break; - case LeaveNotify: { // leave window - QWidget *mouseGrabber = QWidget::mouseGrabber(); - if (mouseGrabber && !d->inPopupMode()) - break; - if (curWin && widget->internalWinId() != curWin) - break; - if ((event->xcrossing.mode != NotifyNormal - && event->xcrossing.mode != NotifyUngrab) - || event->xcrossing.detail == NotifyInferior) - break; - if (!(widget->windowType() == Qt::Desktop)) - widget->translateMouseEvent(event); //we don't get MotionNotify, emulate it - - QWidget* enter = 0; - QPoint enterPoint; - XEvent ev; - while (XCheckMaskEvent(X11->display, EnterWindowMask | LeaveWindowMask , &ev) - && !qt_x11EventFilter(&ev)) { - QWidget* event_widget = QWidget::find(ev.xcrossing.window); - if(event_widget && event_widget->x11Event(&ev)) - break; - if (ev.type == LeaveNotify - || (ev.xcrossing.mode != NotifyNormal - && ev.xcrossing.mode != NotifyUngrab) - || ev.xcrossing.detail == NotifyVirtual - || ev.xcrossing.detail == NotifyNonlinearVirtual) - continue; - enter = event_widget; - if (enter) - enterPoint = enter->d_func()->mapFromWS(QPoint(ev.xcrossing.x, ev.xcrossing.y)); - if (ev.xcrossing.focus && - enter && !(enter->windowType() == Qt::Desktop) && !enter->isActiveWindow()) { - if (X11->focus_model == QX11Data::FM_Unknown) // check focus model - qt_check_focus_model(); - if (X11->focus_model == QX11Data::FM_PointerRoot) // PointerRoot mode - setActiveWindow(enter); - } - break; - } - - if ((! enter || (enter->windowType() == Qt::Desktop)) && - event->xcrossing.focus && widget == QApplicationPrivate::active_window && - X11->focus_model == QX11Data::FM_PointerRoot // PointerRoot mode - ) { - setActiveWindow(0); - } - - if (qt_button_down && !d->inPopupMode()) - break; - - if (!curWin) - QApplicationPrivate::dispatchEnterLeave(widget, 0); - - if (enter) { - QWidget *alienEnter = enter->childAt(enterPoint); - if (alienEnter) - enter = alienEnter; - } - - QWidget *leave = qt_last_mouse_receiver ? qt_last_mouse_receiver : widget; - QWidget *activePopupWidget = qApp->activePopupWidget(); - - if (mouseGrabber && activePopupWidget && leave == activePopupWidget) - enter = mouseGrabber; - else if (enter != widget && mouseGrabber) { - if (!widget->rect().contains(widget->d_func()->mapFromWS(QPoint(event->xcrossing.x, - event->xcrossing.y)))) - break; - } - - QApplicationPrivate::dispatchEnterLeave(enter, leave); - qt_last_mouse_receiver = enter; - - if (enter && QApplicationPrivate::tryModalHelper(enter, 0)) { - QWidget *nativeEnter = enter->internalWinId() ? enter : enter->nativeParentWidget(); - curWin = nativeEnter->internalWinId(); - static_cast<QETWidget *>(nativeEnter)->translateMouseEvent(&ev); //we don't get MotionNotify, emulate it - } else { - curWin = 0; - qt_last_mouse_receiver = 0; - } - } - break; - - case UnmapNotify: // window hidden - if (widget->isWindow()) { - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - widget->d_func()->topData()->waitingForMapNotify = 0; - - if (widget->windowType() != Qt::Popup && !widget->testAttribute(Qt::WA_DontShowOnScreen)) { - widget->setAttribute(Qt::WA_Mapped, false); - if (widget->isVisible()) { - widget->d_func()->topData()->spont_unmapped = 1; - QHideEvent e; - QApplication::sendSpontaneousEvent(widget, &e); - widget->d_func()->hideChildren(true); - } - } - - if (!widget->d_func()->topData()->validWMState && X11->deferred_map.removeAll(widget)) - widget->doDeferredMap(); - } - break; - - case MapNotify: // window shown - if (widget->isWindow()) { - // if we got a MapNotify when we were not waiting for it, it most - // likely means the user has already asked to hide the window before - // it ever being shown, so we try to withdraw a window after sending - // the QShowEvent. - bool pendingHide = widget->testAttribute(Qt::WA_WState_ExplicitShowHide) && widget->testAttribute(Qt::WA_WState_Hidden); - widget->d_func()->topData()->waitingForMapNotify = 0; - - if (widget->windowType() != Qt::Popup) { - widget->setAttribute(Qt::WA_Mapped); - if (widget->d_func()->topData()->spont_unmapped) { - widget->d_func()->topData()->spont_unmapped = 0; - widget->d_func()->showChildren(true); - QShowEvent e; - QApplication::sendSpontaneousEvent(widget, &e); - - // show() must have been called on this widget in - // order to reach this point, but we could have - // cleared these 2 attributes in case something - // previously forced us into WithdrawnState - // (e.g. kdocker) - widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true); - widget->setAttribute(Qt::WA_WState_Visible, true); - } - } - if (pendingHide) // hide the window - XWithdrawWindow(X11->display, widget->internalWinId(), widget->x11Info().screen()); - } - break; - - case ClientMessage: // client message - return x11ClientMessage(widget,event,False); - - case ReparentNotify: { // window manager reparents - // compress old reparent events to self - XEvent ev; - while (XCheckTypedWindowEvent(X11->display, - widget->effectiveWinId(), - ReparentNotify, - &ev)) { - if (ev.xreparent.window != ev.xreparent.event) { - XPutBackEvent(X11->display, &ev); - break; - } - } - if (widget->isWindow()) { - QTLWExtra *topData = widget->d_func()->topData(); - - // store the parent. Useful for many things, embedding for instance. - topData->parentWinId = event->xreparent.parent; - - // the widget frame strut should also be invalidated - widget->data->fstrut_dirty = 1; - - // work around broken window managers... if we get a - // ReparentNotify before the MapNotify, we assume that - // we're being managed by a reparenting window - // manager. - // - // however, the WM_STATE property may not have been set - // yet, but we are going to assume that it will - // be... otherwise we could try to map again after getting - // an UnmapNotify... which could then, in turn, trigger a - // race in the window manager which causes the window to - // disappear when it really should be hidden. - if (topData->waitingForMapNotify && !topData->validWMState) { - topData->waitingForMapNotify = 0; - topData->validWMState = 1; - } - - if (X11->focus_model != QX11Data::FM_Unknown) { - // toplevel reparented... - QWidget *newparent = QWidget::find(event->xreparent.parent); - if (! newparent || (newparent->windowType() == Qt::Desktop)) { - // we don't know about the new parent (or we've been - // reparented to root), perhaps a window manager - // has been (re)started? reset the focus model to unknown - X11->focus_model = QX11Data::FM_Unknown; - } - } - } - break; - } - case SelectionRequest: { - XSelectionRequestEvent *req = &event->xselectionrequest; - if (! req) - break; - - if (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection)) { - X11->xdndHandleSelectionRequest(req); - - } else if (qt_clipboard) { - QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event)); - QApplication::sendSpontaneousEvent(qt_clipboard, &e); - } - break; - } - case SelectionClear: { - XSelectionClearEvent *req = &event->xselectionclear; - // don't deliver dnd events to the clipboard, it gets confused - if (! req || (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection))) - break; - - if (qt_clipboard && !X11->use_xfixes) { - QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event)); - QApplication::sendSpontaneousEvent(qt_clipboard, &e); - } - break; - } - - case SelectionNotify: { - XSelectionEvent *req = &event->xselection; - // don't deliver dnd events to the clipboard, it gets confused - if (! req || (ATOM(XdndSelection) && req->selection == ATOM(XdndSelection))) - break; - - if (qt_clipboard) { - QClipboardEvent e(reinterpret_cast<QEventPrivate*>(event)); - QApplication::sendSpontaneousEvent(qt_clipboard, &e); - } - break; - } - case PropertyNotify: - // some properties changed - if (event->xproperty.window == QX11Info::appRootWindow(0)) { - // root properties for the first screen - if (!X11->use_xfixes && event->xproperty.atom == ATOM(_QT_CLIPBOARD_SENTINEL)) { - if (qt_check_clipboard_sentinel()) { - emit clipboard()->changed(QClipboard::Clipboard); - emit clipboard()->dataChanged(); - } - } else if (!X11->use_xfixes && event->xproperty.atom == ATOM(_QT_SELECTION_SENTINEL)) { - if (qt_check_selection_sentinel()) { - emit clipboard()->changed(QClipboard::Selection); - emit clipboard()->selectionChanged(); - } - } else if (QApplicationPrivate::obey_desktop_settings) { - if (event->xproperty.atom == ATOM(RESOURCE_MANAGER)) - qt_set_x11_resources(); - else if (event->xproperty.atom == ATOM(_QT_SETTINGS_TIMESTAMP)) - qt_set_x11_resources(); - } - } - if (event->xproperty.window == QX11Info::appRootWindow()) { - // root properties for the default screen - if (event->xproperty.atom == ATOM(_QT_INPUT_ENCODING)) { - qt_set_input_encoding(); - } else if (event->xproperty.atom == ATOM(_NET_SUPPORTED)) { - qt_get_net_supported(); - } else if (event->xproperty.atom == ATOM(_NET_VIRTUAL_ROOTS)) { - qt_get_net_virtual_roots(); - } else if (event->xproperty.atom == ATOM(_NET_WORKAREA)) { - qt_desktopwidget_update_workarea(); - - // emit the workAreaResized() signal - QDesktopWidget *desktop = QApplication::desktop(); - int numScreens = desktop->numScreens(); - for (int i = 0; i < numScreens; ++i) - emit desktop->workAreaResized(i); - } - } else if (widget) { - widget->translatePropertyEvent(event); - } else { - return -1; // don't know this window - } - break; - - default: - break; - } - - return 0; -} - -bool QApplication::x11EventFilter(XEvent *) -{ - return false; -} - - - -/***************************************************************************** - Modal widgets; Since Xlib has little support for this we roll our own - modal widget mechanism. - A modal widget without a parent becomes application-modal. - A modal widget with a parent becomes modal to its parent and grandparents.. - - QApplicationPrivate::enterModal() - Enters modal state - Arguments: - QWidget *widget A modal widget - - QApplicationPrivate::leaveModal() - Leaves modal state for a widget - Arguments: - QWidget *widget A modal widget - *****************************************************************************/ - -bool QApplicationPrivate::modalState() -{ - return app_do_modal; -} - -void QApplicationPrivate::enterModal_sys(QWidget *widget) -{ - if (!qt_modal_stack) - qt_modal_stack = new QWidgetList; - - QWidget *leave = qt_last_mouse_receiver; - if (!leave) - leave = QWidget::find((WId)curWin); - QApplicationPrivate::dispatchEnterLeave(0, leave); - qt_modal_stack->insert(0, widget); - app_do_modal = true; - curWin = 0; - qt_last_mouse_receiver = 0; -} - -void QApplicationPrivate::leaveModal_sys(QWidget *widget) -{ - if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { - if (qt_modal_stack->isEmpty()) { - delete qt_modal_stack; - qt_modal_stack = 0; - QPoint p(QCursor::pos()); - QWidget* w = QApplication::widgetAt(p.x(), p.y()); - QWidget *leave = qt_last_mouse_receiver; - if (!leave) - leave = QWidget::find((WId)curWin); - if (QWidget *grabber = QWidget::mouseGrabber()) { - w = grabber; - if (leave == w) - leave = 0; - } - QApplicationPrivate::dispatchEnterLeave(w, leave); // send synthetic enter event - curWin = w ? w->effectiveWinId() : 0; - qt_last_mouse_receiver = w; - } - } - app_do_modal = qt_modal_stack != 0; -} - -bool qt_try_modal(QWidget *widget, XEvent *event) -{ - if (qt_xdnd_dragging) { - // allow mouse events while DnD is active - switch (event->type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: - return true; - default: - break; - } - } - - // allow mouse release events to be sent to widgets that have been pressed - if (event->type == ButtonRelease) { - QWidget *alienWidget = widget->childAt(widget->mapFromGlobal(QPoint(event->xbutton.x_root, - event->xbutton.y_root))); - if (widget == qt_button_down || (alienWidget && alienWidget == qt_button_down)) - return true; - } - - if (QApplicationPrivate::tryModalHelper(widget)) - return true; - - // disallow mouse/key events - switch (event->type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: - case XKeyPress: - case XKeyRelease: - case EnterNotify: - case LeaveNotify: - case ClientMessage: - return false; - default: - break; - } - - return true; -} - - -/***************************************************************************** - Popup widget mechanism - - openPopup() - Adds a widget to the list of popup widgets - Arguments: - QWidget *widget The popup widget to be added - - closePopup() - Removes a widget from the list of popup widgets - Arguments: - QWidget *widget The popup widget to be removed - *****************************************************************************/ - - -static int openPopupCount = 0; -void QApplicationPrivate::openPopup(QWidget *popup) -{ - Q_Q(QApplication); - openPopupCount++; - if (!QApplicationPrivate::popupWidgets) { // create list - QApplicationPrivate::popupWidgets = new QWidgetList; - } - QApplicationPrivate::popupWidgets->append(popup); // add to end of list - Display *dpy = X11->display; - if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard - Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); - int r = XGrabKeyboard(dpy, popup->effectiveWinId(), false, - GrabModeAsync, GrabModeAsync, X11->time); - if ((popupGrabOk = (r == GrabSuccess))) { - r = XGrabPointer(dpy, popup->effectiveWinId(), true, - (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask - | EnterWindowMask | LeaveWindowMask | PointerMotionMask), - GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time); - if (!(popupGrabOk = (r == GrabSuccess))) { - // transfer grab back to the keyboard grabber if any - if (QWidgetPrivate::keyboardGrabber != 0) - QWidgetPrivate::keyboardGrabber->grabKeyboard(); - else - XUngrabKeyboard(dpy, X11->time); - } - } - } - - // popups are not focus-handled by the window system (the first - // popup grabbed the keyboard), so we have to do that manually: A - // new popup gets the focus - if (popup->focusWidget()) { - popup->focusWidget()->setFocus(Qt::PopupFocusReason); - } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup - if (QWidget *fw = QApplication::focusWidget()) { - QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); - q->sendEvent(fw, &e); - } - } -} - -void QApplicationPrivate::closePopup(QWidget *popup) -{ - Q_Q(QApplication); - if (!QApplicationPrivate::popupWidgets) - return; - QApplicationPrivate::popupWidgets->removeAll(popup); - if (popup == qt_popup_down) { - qt_button_down = 0; - qt_popup_down = 0; - } - if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup - delete QApplicationPrivate::popupWidgets; - QApplicationPrivate::popupWidgets = 0; - if (!qt_nograb() && popupGrabOk) { // grabbing not disabled - Display *dpy = X11->display; - if (popup->geometry().contains(QPoint(mouseGlobalXPos, mouseGlobalYPos)) - || popup->testAttribute(Qt::WA_NoMouseReplay)) { - // mouse release event or inside - replayPopupMouseEvent = false; - } else { // mouse press event - mouseButtonPressTime -= 10000; // avoid double click - replayPopupMouseEvent = true; - } - // transfer grab back to mouse grabber if any, otherwise release the grab - if (QWidgetPrivate::mouseGrabber != 0) - QWidgetPrivate::mouseGrabber->grabMouse(); - else - XUngrabPointer(dpy, X11->time); - - // transfer grab back to keyboard grabber if any, otherwise release the grab - if (QWidgetPrivate::keyboardGrabber != 0) - QWidgetPrivate::keyboardGrabber->grabKeyboard(); - else - XUngrabKeyboard(dpy, X11->time); - - XFlush(dpy); - } - if (QApplicationPrivate::active_window) { - if (QWidget *fw = QApplicationPrivate::active_window->focusWidget()) { - if (fw != QApplication::focusWidget()) { - fw->setFocus(Qt::PopupFocusReason); - } else { - QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); - q->sendEvent(fw, &e); - } - } - } - } else { - // popups are not focus-handled by the window system (the - // first popup grabbed the keyboard), so we have to do that - // manually: A popup was closed, so the previous popup gets - // the focus. - QWidget* aw = QApplicationPrivate::popupWidgets->last(); - if (QWidget *fw = aw->focusWidget()) - fw->setFocus(Qt::PopupFocusReason); - - // regrab the keyboard and mouse in case 'popup' lost the grab - if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()){ // grab mouse/keyboard - Display *dpy = X11->display; - Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created)); - int r = XGrabKeyboard(dpy, aw->effectiveWinId(), false, - GrabModeAsync, GrabModeAsync, X11->time); - if ((popupGrabOk = (r == GrabSuccess))) { - r = XGrabPointer(dpy, aw->effectiveWinId(), true, - (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask - | EnterWindowMask | LeaveWindowMask | PointerMotionMask), - GrabModeAsync, GrabModeAsync, XNone, XNone, X11->time); - if (!(popupGrabOk = (r == GrabSuccess))) { - // transfer grab back to keyboard grabber - if (QWidgetPrivate::keyboardGrabber != 0) - QWidgetPrivate::keyboardGrabber->grabKeyboard(); - else - XUngrabKeyboard(dpy, X11->time); - } - } - } - } -} - -/***************************************************************************** - Event translation; translates X11 events to Qt events - *****************************************************************************/ - -// -// Mouse event translation -// -// Xlib doesn't give mouse double click events, so we generate them by -// comparing window, time and position between two mouse press events. -// - -static Qt::MouseButtons translateMouseButtons(int s) -{ - Qt::MouseButtons ret = 0; - if (s & Button1Mask) - ret |= Qt::LeftButton; - if (s & Button2Mask) - ret |= Qt::MidButton; - if (s & Button3Mask) - ret |= Qt::RightButton; - return ret; -} - -Qt::KeyboardModifiers QX11Data::translateModifiers(int s) -{ - Qt::KeyboardModifiers ret = 0; - if (s & ShiftMask) - ret |= Qt::ShiftModifier; - if (s & ControlMask) - ret |= Qt::ControlModifier; - if (s & qt_alt_mask) - ret |= Qt::AltModifier; - if (s & qt_meta_mask) - ret |= Qt::MetaModifier; - if (s & qt_mode_switch_mask) - ret |= Qt::GroupSwitchModifier; - return ret; -} - -bool QETWidget::translateMouseEvent(const XEvent *event) -{ - if (!isWindow() && testAttribute(Qt::WA_NativeWindow)) - Q_ASSERT(internalWinId()); - - Q_D(QWidget); - QEvent::Type type; // event parameters - QPoint pos; - QPoint globalPos; - Qt::MouseButton button = Qt::NoButton; - Qt::MouseButtons buttons; - Qt::KeyboardModifiers modifiers; - XEvent nextEvent; - - if (qt_sm_blockUserInput) // block user interaction during session management - return true; - - if (event->type == MotionNotify) { // mouse move - if (event->xmotion.root != RootWindow(X11->display, x11Info().screen()) && - ! qt_xdnd_dragging) - return false; - - XMotionEvent lastMotion = event->xmotion; - while(XPending(X11->display)) { // compress mouse moves - XNextEvent(X11->display, &nextEvent); - if (nextEvent.type == ConfigureNotify - || nextEvent.type == PropertyNotify - || nextEvent.type == Expose - || nextEvent.type == GraphicsExpose - || nextEvent.type == NoExpose - || nextEvent.type == KeymapNotify - || ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify) - && qt_button_down == this) - || (nextEvent.type == ClientMessage - && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) || - (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) && - (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) { - qApp->x11ProcessEvent(&nextEvent); - continue; - } else if (nextEvent.type != MotionNotify || - nextEvent.xmotion.window != event->xmotion.window || - nextEvent.xmotion.state != event->xmotion.state) { - XPutBackEvent(X11->display, &nextEvent); - break; - } - if (!qt_x11EventFilter(&nextEvent) - && !x11Event(&nextEvent)) // send event through filter - lastMotion = nextEvent.xmotion; - else - break; - } - type = QEvent::MouseMove; - pos.rx() = lastMotion.x; - pos.ry() = lastMotion.y; - pos = d->mapFromWS(pos); - globalPos.rx() = lastMotion.x_root; - globalPos.ry() = lastMotion.y_root; - buttons = translateMouseButtons(lastMotion.state); - modifiers = X11->translateModifiers(lastMotion.state); - if (qt_button_down && !buttons) - qt_button_down = 0; - } else if (event->type == EnterNotify || event->type == LeaveNotify) { - XEvent *xevent = (XEvent *)event; - //unsigned int xstate = event->xcrossing.state; - type = QEvent::MouseMove; - pos.rx() = xevent->xcrossing.x; - pos.ry() = xevent->xcrossing.y; - pos = d->mapFromWS(pos); - globalPos.rx() = xevent->xcrossing.x_root; - globalPos.ry() = xevent->xcrossing.y_root; - buttons = translateMouseButtons(xevent->xcrossing.state); - modifiers = X11->translateModifiers(xevent->xcrossing.state); - if (qt_button_down && !buttons) - qt_button_down = 0; - if (qt_button_down) - return true; - } else { // button press or release - pos.rx() = event->xbutton.x; - pos.ry() = event->xbutton.y; - pos = d->mapFromWS(pos); - globalPos.rx() = event->xbutton.x_root; - globalPos.ry() = event->xbutton.y_root; - buttons = translateMouseButtons(event->xbutton.state); - modifiers = X11->translateModifiers(event->xbutton.state); - switch (event->xbutton.button) { - case Button1: button = Qt::LeftButton; break; - case Button2: button = Qt::MidButton; break; - case Button3: button = Qt::RightButton; break; - case Button4: - case Button5: - case 6: - case 7: - // the fancy mouse wheel. - - // We are only interested in ButtonPress. - if (event->type == ButtonPress){ - // compress wheel events (the X Server will simply - // send a button press for each single notch, - // regardless whether the application can catch up - // or not) - int delta = 1; - XEvent xevent; - while (XCheckTypedWindowEvent(X11->display, effectiveWinId(), ButtonPress, &xevent)){ - if (xevent.xbutton.button != event->xbutton.button){ - XPutBackEvent(X11->display, &xevent); - break; - } - delta++; - } - - // the delta is defined as multiples of - // WHEEL_DELTA, which is set to 120. Future wheels - // may offer a finer-resolution. A positive delta - // indicates forward rotation, a negative one - // backward rotation respectively. - int btn = event->xbutton.button; - delta *= 120 * ((btn == Button4 || btn == 6) ? 1 : -1); - bool hor = (((btn == Button4 || btn == Button5) && (modifiers & Qt::AltModifier)) || - (btn == 6 || btn == 7)); - translateWheelEvent(globalPos.x(), globalPos.y(), delta, buttons, - modifiers, (hor) ? Qt::Horizontal: Qt::Vertical); - } - return true; - case 8: button = Qt::XButton1; break; - case 9: button = Qt::XButton2; break; - } - if (event->type == ButtonPress) { // mouse button pressed - buttons |= button; -#if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET) - QTabletDeviceDataList *tablets = qt_tablet_devices(); - for (int i = 0; i < tablets->size(); ++i) { - QTabletDeviceData &tab = tablets->operator[](i); - XEvent myEv; - if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) { - if (translateXinputEvent(&myEv, &tab)) { - //Spontaneous event sent. Check if we need to continue. - if (qt_tabletChokeMouse) { - qt_tabletChokeMouse = false; - return false; - } - } - } - } -#endif - if (!qt_button_down) { - qt_button_down = childAt(pos); //magic for masked widgets - if (!qt_button_down) - qt_button_down = this; - } - if (mouseActWindow == event->xbutton.window && - mouseButtonPressed == button && - (long)event->xbutton.time -(long)mouseButtonPressTime - < QApplication::doubleClickInterval() && - qAbs(event->xbutton.x - mouseXPos) < QT_GUI_DOUBLE_CLICK_RADIUS && - qAbs(event->xbutton.y - mouseYPos) < QT_GUI_DOUBLE_CLICK_RADIUS) { - type = QEvent::MouseButtonDblClick; - mouseButtonPressTime -= 2000; // no double-click next time - } else { - type = QEvent::MouseButtonPress; - mouseButtonPressTime = event->xbutton.time; - } - mouseButtonPressed = button; // save event params for - mouseXPos = event->xbutton.x; // future double click tests - mouseYPos = event->xbutton.y; - mouseGlobalXPos = globalPos.x(); - mouseGlobalYPos = globalPos.y(); - } else { // mouse button released - buttons &= ~button; -#if defined(Q_OS_IRIX) && !defined(QT_NO_TABLET) - QTabletDeviceDataList *tablets = qt_tablet_devices(); - for (int i = 0; i < tablets->size(); ++i) { - QTabletDeviceData &tab = tablets->operator[](i); - XEvent myEv; - if (XCheckTypedEvent(X11->display, tab.xinput_button_press, &myEv)) { - if (translateXinputEvent(&myEv, &tab)) { - //Spontaneous event sent. Check if we need to continue. - if (qt_tabletChokeMouse) { - qt_tabletChokeMouse = false; - return false; - } - } - } - } -#endif - type = QEvent::MouseButtonRelease; - } - } - mouseActWindow = effectiveWinId(); // save some event params - mouseButtonState = buttons; - if (type == 0) // don't send event - return false; - - if (qApp->d_func()->inPopupMode()) { // in popup mode - QWidget *activePopupWidget = qApp->activePopupWidget(); - QWidget *popup = qApp->activePopupWidget(); - if (popup != this) { - if (event->type == LeaveNotify) - return false; - if ((windowType() == Qt::Popup) && rect().contains(pos) && 0) - popup = this; - else // send to last popup - pos = popup->mapFromGlobal(globalPos); - } - bool releaseAfter = false; - QWidget *popupChild = popup->childAt(pos); - - if (popup != qt_popup_down){ - qt_button_down = 0; - qt_popup_down = 0; - } - - switch (type) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - qt_button_down = popupChild; - qt_popup_down = popup; - break; - case QEvent::MouseButtonRelease: - releaseAfter = true; - break; - default: - break; // nothing for mouse move - } - - int oldOpenPopupCount = openPopupCount; - - if (popup->isEnabled()) { - // deliver event - replayPopupMouseEvent = false; - QWidget *receiver = popup; - QPoint widgetPos = pos; - if (qt_button_down) - receiver = qt_button_down; - else if (popupChild) - receiver = popupChild; - if (receiver != popup) - widgetPos = receiver->mapFromGlobal(globalPos); - QWidget *alien = childAt(mapFromGlobal(globalPos)); - QMouseEvent e(type, widgetPos, globalPos, button, buttons, modifiers); - QApplicationPrivate::sendMouseEvent(receiver, &e, alien, this, &qt_button_down, qt_last_mouse_receiver); - } else { - // close disabled popups when a mouse button is pressed or released - switch (type) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonRelease: - popup->close(); - break; - default: - break; - } - } - - if (qApp->activePopupWidget() != activePopupWidget - && replayPopupMouseEvent) { - // the active popup was closed, replay the mouse event - if (!(windowType() == Qt::Popup)) { -#if 1 - qt_button_down = 0; -#else - if (buttons == button) - qt_button_down = this; - QMouseEvent e(type, mapFromGlobal(globalPos), globalPos, button, - buttons, modifiers); - QApplication::sendSpontaneousEvent(this, &e); - - if (type == QEvent::MouseButtonPress - && button == Qt::RightButton - && (openPopupCount == oldOpenPopupCount)) { - QContextMenuEvent e(QContextMenuEvent::Mouse, mapFromGlobal(globalPos), - globalPos, modifiers); - QApplication::sendSpontaneousEvent(this, &e); - } -#endif - } - replayPopupMouseEvent = false; - } else if (type == QEvent::MouseButtonPress - && button == Qt::RightButton - && (openPopupCount == oldOpenPopupCount)) { - QWidget *popupEvent = popup; - if (qt_button_down) - popupEvent = qt_button_down; - else if(popupChild) - popupEvent = popupChild; - QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers); - QApplication::sendSpontaneousEvent(popupEvent, &e); - } - - if (releaseAfter) { - qt_button_down = 0; - qt_popup_down = 0; - } - } else { - QWidget *alienWidget = childAt(pos); - QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type, buttons, - qt_button_down, alienWidget); - if (!widget) { - if (type == QEvent::MouseButtonRelease) - QApplicationPrivate::mouse_buttons &= ~button; - return false; // don't send event - } - - int oldOpenPopupCount = openPopupCount; - QMouseEvent e(type, pos, globalPos, button, buttons, modifiers); - QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, - qt_last_mouse_receiver); - if (type == QEvent::MouseButtonPress - && button == Qt::RightButton - && (openPopupCount == oldOpenPopupCount)) { - QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos, modifiers); - QApplication::sendSpontaneousEvent(widget, &e); - } - } - return true; -} - - -// -// Wheel event translation -// -bool QETWidget::translateWheelEvent(int global_x, int global_y, int delta, - Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, - Qt::Orientation orient) -{ - const QPoint globalPos = QPoint(global_x, global_y); - QPoint pos = mapFromGlobal(globalPos); - QWidget *widget = childAt(pos); - if (!widget) - widget = this; - else if (!widget->internalWinId()) - pos = widget->mapFromGlobal(globalPos); - -#ifdef ALIEN_DEBUG - qDebug() << "QETWidget::translateWheelEvent: receiver:" << widget << "pos:" << pos; -#endif - - // send the event to the widget or its ancestors - { - QWidget* popup = qApp->activePopupWidget(); - if (popup && window() != popup) - popup->close(); -#ifndef QT_NO_WHEELEVENT - QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient); - if (QApplication::sendSpontaneousEvent(widget, &e)) -#endif - return true; - } - - // send the event to the widget that has the focus or its ancestors, if different - if (widget != qApp->focusWidget() && (widget = qApp->focusWidget())) { - if (widget && !widget->internalWinId()) - pos = widget->mapFromGlobal(globalPos); - QWidget* popup = qApp->activePopupWidget(); - if (popup && widget != popup) - popup->hide(); -#ifndef QT_NO_WHEELEVENT - QWheelEvent e(pos, globalPos, delta, buttons, modifiers, orient); - if (QApplication::sendSpontaneousEvent(widget, &e)) -#endif - return true; - } - return false; -} - - -// -// XInput Translation Event -// -#if !defined (QT_NO_TABLET) - -#if !defined (Q_OS_IRIX) -void fetchWacomToolId(int &deviceType, qint64 &serialId) -{ - if (ptrWacomConfigInit == 0) // we actually have the lib - return; - WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0); - if (config == 0) - return; - WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData()); - if (device == 0) - return; - unsigned keys[1]; - int serialInt; - ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLSERIAL, &serialInt, 1, keys); - serialId = serialInt; - int toolId; - ptrWacomConfigGetRawParam (device, XWACOM_PARAM_TOOLID, &toolId, 1, keys); - switch(toolId) { - case 0x007: /* Mouse 4D and 2D */ - case 0x017: /* Intuos3 2D Mouse */ - case 0x094: - case 0x09c: - deviceType = QTabletEvent::FourDMouse; - break; - case 0x096: /* Lens cursor */ - case 0x097: /* Intuos3 Lens cursor */ - deviceType = QTabletEvent::Puck; - break; - case 0x0fa: - case 0x81b: /* Intuos3 Classic Pen Eraser */ - case 0x82a: /* Eraser */ - case 0x82b: /* Intuos3 Grip Pen Eraser */ - case 0x85a: - case 0x91a: - case 0x91b: /* Intuos3 Airbrush Eraser */ - case 0xd1a: - deviceType = QTabletEvent::XFreeEraser; - break; - case 0x112: - case 0x912: - case 0x913: /* Intuos3 Airbrush */ - case 0xd12: - deviceType = QTabletEvent::Airbrush; - break; - case 0x012: - case 0x022: - case 0x032: - case 0x801: /* Intuos3 Inking pen */ - case 0x812: /* Inking pen */ - case 0x813: /* Intuos3 Classic Pen */ - case 0x822: /* Pen */ - case 0x823: /* Intuos3 Grip Pen */ - case 0x832: /* Stroke pen */ - case 0x842: - case 0x852: - case 0x885: /* Intuos3 Marker Pen */ - default: /* Unknown tool */ - deviceType = QTabletEvent::Stylus; - } - - /* Close device and return */ - ptrWacomConfigCloseDevice (device); - ptrWacomConfigTerm(config); -} -#endif - -struct qt_tablet_motion_data -{ - bool filterByWidget; - const QWidget *widget; - const QWidget *etWidget; - int tabletMotionType; - bool error; // found a reason to stop searching -}; - -static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg) -{ - qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; - if (data->error) - return false; - - if (event->type == MotionNotify) - return true; - - data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between. - return false; -} - -static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg) -{ - qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; - if (data->error) - return false; - if (event->type == data->tabletMotionType) { - const XDeviceMotionEvent *const motion = reinterpret_cast<const XDeviceMotionEvent*>(event); - if (data->filterByWidget) { - const QPoint curr(motion->x, motion->y); - const QWidget *w = data->etWidget; - const QWidget *const child = w->childAt(curr); - if (child) { - w = child; - } - if (w == data->widget) - return true; - } else { - return true; - } - } - - data->error = event->type != MotionNotify; // we stop compression when another event gets in between. - return false; -} - -bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet) -{ -#if defined (Q_OS_IRIX) - // Wacom has put defines in their wacom.h file so it would be quite wise - // to use them, need to think of a decent way of not using - // it when it doesn't exist... - XDeviceState *s; - XInputClass *iClass; - XValuatorState *vs; - int j; -#endif - - Q_ASSERT(tablet != 0); - - QWidget *w = this; - QPoint global, - curr; - QPointF hiRes; - qreal pressure = 0; - int xTilt = 0, - yTilt = 0, - z = 0; - qreal tangentialPressure = 0; - qreal rotation = 0; - int deviceType = QTabletEvent::NoDevice; - int pointerType = QTabletEvent::UnknownPointer; - const XDeviceMotionEvent *motion = 0; - XDeviceButtonEvent *button = 0; - const XProximityNotifyEvent *proximity = 0; - QEvent::Type t; - Qt::KeyboardModifiers modifiers = 0; -#if !defined (Q_OS_IRIX) - XID device_id; -#endif - - if (ev->type == tablet->xinput_motion) { - motion = reinterpret_cast<const XDeviceMotionEvent*>(ev); - t = QEvent::TabletMove; - global = QPoint(motion->x_root, motion->y_root); - curr = QPoint(motion->x, motion->y); -#if !defined (Q_OS_IRIX) - device_id = motion->deviceid; -#endif - } else if (ev->type == tablet->xinput_button_press || ev->type == tablet->xinput_button_release) { - if (ev->type == tablet->xinput_button_press) { - t = QEvent::TabletPress; - } else { - t = QEvent::TabletRelease; - } - button = (XDeviceButtonEvent*)ev; - - global = QPoint(button->x_root, button->y_root); - curr = QPoint(button->x, button->y); -#if !defined (Q_OS_IRIX) - device_id = button->deviceid; -#endif - } else { // Proximity - if (ev->type == tablet->xinput_proximity_in) - t = QEvent::TabletEnterProximity; - else - t = QEvent::TabletLeaveProximity; - proximity = (const XProximityNotifyEvent*)ev; -#if !defined (Q_OS_IRIX) - device_id = proximity->deviceid; -#endif - } - - qint64 uid = 0; -#if defined (Q_OS_IRIX) - QRect screenArea = qApp->desktop()->screenGeometry(this); - s = XQueryDeviceState(X11->display, static_cast<XDevice *>(tablet->device)); - if (!s) - return false; - iClass = s->data; - for (j = 0; j < s->num_classes; j++) { - if (iClass->c_class == ValuatorClass) { - vs = reinterpret_cast<XValuatorState *>(iClass); - // figure out what device we have, based on bitmasking... - if (vs->valuators[WAC_TRANSDUCER_I] - & WAC_TRANSDUCER_PROX_MSK) { - switch (vs->valuators[WAC_TRANSDUCER_I] - & WAC_TRANSDUCER_MSK) { - case WAC_PUCK_ID: - pointerType = QTabletEvent::Puck; - break; - case WAC_STYLUS_ID: - pointerType = QTabletEvent::Pen; - break; - case WAC_ERASER_ID: - pointerType = QTabletEvent::Eraser; - break; - } - // Get a Unique Id for the device, Wacom gives us this ability - uid = vs->valuators[WAC_TRANSDUCER_I] & WAC_TRANSDUCER_ID_MSK; - uid = (uid << 24) | vs->valuators[WAC_SERIAL_NUM_I]; - switch (WAC_TRANSDUCER_I & 0x0F0600) { - case 0x080200: - deviceType = QTabletEvent::Stylus; - break; - case 0x090200: - deviceType = QTabletEvent::Airbrush; - break; - case 0x000400: - deviceType = QTabletEvent::FourDMouse; - break; - case 0x000600: - deviceType = QTabletEvent::Puck; - break; - case 0x080400: - deviceType = QTabletEvent::RotationStylus; - break; - } - } else { - pointerType = QTabletEvent::UnknownPointer; - deviceType = QTabletEvent::NoDevice; - uid = 0; - } - - if (!proximity) { - // apparently Wacom needs a cast for the +/- values to make sense - xTilt = short(vs->valuators[WAC_XTILT_I]); - yTilt = short(vs->valuators[WAC_YTILT_I]); - pressure = vs->valuators[WAC_PRESSURE_I]; - if (deviceType == QTabletEvent::FourDMouse - || deviceType == QTabletEvent::RotationStylus) { - rotation = vs->valuators[WAC_ROTATION_I] / 64.0; - if (deviceType == QTabletEvent::FourDMouse) - z = vs->valuators[WAC_ZCOORD_I]; - } else if (deviceType == QTabletEvent::Airbrush) { - tangentialPressure = vs->valuators[WAC_TAN_PRESSURE_I] - / qreal(tablet->maxTanPressure - tablet->minTanPressure); - } - - hiRes = tablet->scaleCoord(vs->valuators[WAC_XCOORD_I], vs->valuators[WAC_YCOORD_I], - screenArea.x(), screenArea.width(), - screenArea.y(), screenArea.height()); - } - break; - } - iClass = reinterpret_cast<XInputClass*>(reinterpret_cast<char*>(iClass) + iClass->length); - } - XFreeDeviceState(s); -#else - QTabletDeviceDataList *tablet_list = qt_tablet_devices(); - for (int i = 0; i < tablet_list->size(); ++i) { - const QTabletDeviceData &t = tablet_list->at(i); - if (device_id == static_cast<XDevice *>(t.device)->device_id) { - deviceType = t.deviceType; - if (t.deviceType == QTabletEvent::XFreeEraser) { - deviceType = QTabletEvent::Stylus; - pointerType = QTabletEvent::Eraser; - } else if (t.deviceType == QTabletEvent::Stylus) { - pointerType = QTabletEvent::Pen; - } - break; - } - } - - fetchWacomToolId(deviceType, uid); - - QRect screenArea = qApp->desktop()->rect(); - if (motion) { - xTilt = (short) motion->axis_data[3]; - yTilt = (short) motion->axis_data[4]; - rotation = ((short) motion->axis_data[5]) / 64.0; - pressure = (short) motion->axis_data[2]; - modifiers = X11->translateModifiers(motion->state); - hiRes = tablet->scaleCoord(motion->axis_data[0], motion->axis_data[1], - screenArea.x(), screenArea.width(), - screenArea.y(), screenArea.height()); - } else if (button) { - xTilt = (short) button->axis_data[3]; - yTilt = (short) button->axis_data[4]; - rotation = ((short) button->axis_data[5]) / 64.0; - pressure = (short) button->axis_data[2]; - modifiers = X11->translateModifiers(button->state); - hiRes = tablet->scaleCoord(button->axis_data[0], button->axis_data[1], - screenArea.x(), screenArea.width(), - screenArea.y(), screenArea.height()); - } else if (proximity) { - pressure = 0; - modifiers = 0; - } - if (deviceType == QTabletEvent::Airbrush) { - tangentialPressure = rotation; - rotation = 0.; - } -#endif - - if (tablet->widgetToGetPress) { - w = tablet->widgetToGetPress; - } else { - QWidget *child = w->childAt(curr); - if (child) - w = child; - } - curr = w->mapFromGlobal(global); - - if (t == QEvent::TabletPress) { - tablet->widgetToGetPress = w; - } else if (t == QEvent::TabletRelease && tablet->widgetToGetPress) { - w = tablet->widgetToGetPress; - curr = w->mapFromGlobal(global); - tablet->widgetToGetPress = 0; - } - - QTabletEvent e(t, curr, global, hiRes, - deviceType, pointerType, - qreal(pressure / qreal(tablet->maxPressure - tablet->minPressure)), - xTilt, yTilt, tangentialPressure, rotation, z, modifiers, uid); - if (proximity) { - QApplication::sendSpontaneousEvent(qApp, &e); - } else { - QApplication::sendSpontaneousEvent(w, &e); - const bool accepted = e.isAccepted(); - if (!accepted && ev->type == tablet->xinput_motion) { - // If the widget does not accept tablet events, we drop the next ones from the event queue - // for this widget so it is not overloaded with the numerous tablet events. - qt_tablet_motion_data tabletMotionData; - tabletMotionData.tabletMotionType = tablet->xinput_motion; - tabletMotionData.widget = w; - tabletMotionData.etWidget = this; - // if nothing is pressed, the events are filtered by position - tabletMotionData.filterByWidget = (tablet->widgetToGetPress == 0); - - bool reinsertMouseEvent = false; - XEvent mouseMotionEvent; - while (true) { - // Find first mouse event since we expect them in pairs inside Qt - tabletMotionData.error =false; - if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) { - reinsertMouseEvent = true; - } else { - break; - } - - // Now discard any duplicate tablet events. - tabletMotionData.error = false; - XEvent dummy; - while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { - // just discard the event - } - } - - if (reinsertMouseEvent) { - XPutBackEvent(X11->display, &mouseMotionEvent); - } - } - } - return true; -} -#endif - -bool QETWidget::translatePropertyEvent(const XEvent *event) -{ - Q_D(QWidget); - if (!isWindow()) return true; - - Atom ret; - int format, e; - unsigned char *data = 0; - unsigned long nitems, after; - - if (event->xproperty.atom == ATOM(_KDE_NET_WM_FRAME_STRUT)) { - this->data->fstrut_dirty = 1; - - if (event->xproperty.state == PropertyNewValue) { - e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_KDE_NET_WM_FRAME_STRUT), - 0, 4, // struts are 4 longs - False, XA_CARDINAL, &ret, &format, &nitems, &after, &data); - - if (e == Success && ret == XA_CARDINAL && - format == 32 && nitems == 4) { - long *strut = (long *) data; - d->topData()->frameStrut.setCoords(strut[0], strut[2], strut[1], strut[3]); - this->data->fstrut_dirty = 0; - } - } - } else if (event->xproperty.atom == ATOM(_NET_WM_STATE)) { - bool max = false; - bool full = false; - Qt::WindowStates oldState = Qt::WindowStates(this->data->window_state); - - if (event->xproperty.state == PropertyNewValue) { - // using length of 1024 should be safe for all current and - // possible NET states... - e = XGetWindowProperty(X11->display, event->xproperty.window, ATOM(_NET_WM_STATE), 0, 1024, - False, XA_ATOM, &ret, &format, &nitems, &after, &data); - - if (e == Success && ret == XA_ATOM && format == 32 && nitems > 0) { - Atom *states = (Atom *) data; - - unsigned long i; - uint maximized = 0; - for (i = 0; i < nitems; i++) { - if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_VERT)) - maximized |= 1; - else if (states[i] == ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)) - maximized |= 2; - else if (states[i] == ATOM(_NET_WM_STATE_FULLSCREEN)) - full = true; - } - if (maximized == 3) { - // only set maximized if both horizontal and vertical properties are set - max = true; - } - } - } - - bool send_event = false; - - if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)) - && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) { - if (max && !isMaximized()) { - this->data->window_state = this->data->window_state | Qt::WindowMaximized; - send_event = true; - } else if (!max && isMaximized()) { - this->data->window_state &= ~Qt::WindowMaximized; - send_event = true; - } - } - - if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) { - if (full && !isFullScreen()) { - this->data->window_state = this->data->window_state | Qt::WindowFullScreen; - send_event = true; - } else if (!full && isFullScreen()) { - this->data->window_state &= ~Qt::WindowFullScreen; - send_event = true; - } - } - - if (send_event) { - QWindowStateChangeEvent e(oldState); - QApplication::sendSpontaneousEvent(this, &e); - } - } else if (event->xproperty.atom == ATOM(WM_STATE)) { - // the widget frame strut should also be invalidated - this->data->fstrut_dirty = 1; - - if (event->xproperty.state == PropertyDelete) { - // the window manager has removed the WM State property, - // so it is now in the withdrawn state (ICCCM 4.1.3.1) and - // we are free to reuse this window - d->topData()->parentWinId = 0; - d->topData()->validWMState = 0; - // map the window if we were waiting for a transition to - // withdrawn - if (X11->deferred_map.removeAll(this)) { - doDeferredMap(); - } else if (isVisible() - && !testAttribute(Qt::WA_Mapped) - && !testAttribute(Qt::WA_OutsideWSRange)) { - // so that show() will work again. As stated in the - // ICCCM section 4.1.4: "Only the client can effect a - // transition into or out of the Withdrawn state.", - // but apparently this particular window manager - // doesn't seem to care - setAttribute(Qt::WA_WState_ExplicitShowHide, false); - setAttribute(Qt::WA_WState_Visible, false); - } - } else { - // the window manager has changed the WM State property... - // we are wanting to see if we are withdrawn so that we - // can reuse this window... - e = XGetWindowProperty(X11->display, internalWinId(), ATOM(WM_STATE), 0, 2, False, - ATOM(WM_STATE), &ret, &format, &nitems, &after, &data); - - if (e == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) { - long *state = (long *) data; - switch (state[0]) { - case WithdrawnState: - // if we are in the withdrawn state, we are free - // to reuse this window provided we remove the - // WM_STATE property (ICCCM 4.1.3.1) - XDeleteProperty(X11->display, internalWinId(), ATOM(WM_STATE)); - - // set the parent id to zero, so that show() will - // work again - d->topData()->parentWinId = 0; - d->topData()->validWMState = 0; - // map the window if we were waiting for a - // transition to withdrawn - if (X11->deferred_map.removeAll(this)) { - doDeferredMap(); - } else if (isVisible() - && !testAttribute(Qt::WA_Mapped) - && !testAttribute(Qt::WA_OutsideWSRange)) { - // so that show() will work again. As stated - // in the ICCCM section 4.1.4: "Only the - // client can effect a transition into or out - // of the Withdrawn state.", but apparently - // this particular window manager doesn't seem - // to care - setAttribute(Qt::WA_WState_ExplicitShowHide, false); - setAttribute(Qt::WA_WState_Visible, false); - } - break; - - case IconicState: - d->topData()->validWMState = 1; - if (!isMinimized()) { - // window was minimized - this->data->window_state = this->data->window_state | Qt::WindowMinimized; - QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state & ~Qt::WindowMinimized)); - QApplication::sendSpontaneousEvent(this, &e); - } - break; - - default: - d->topData()->validWMState = 1; - if (isMinimized()) { - // window was un-minimized - this->data->window_state &= ~Qt::WindowMinimized; - QWindowStateChangeEvent e(Qt::WindowStates(this->data->window_state | Qt::WindowMinimized)); - QApplication::sendSpontaneousEvent(this, &e); - } - break; - } - } - } - } else if (event->xproperty.atom == ATOM(_NET_WM_WINDOW_OPACITY)) { - // the window opacity was changed - if (event->xproperty.state == PropertyNewValue) { - e = XGetWindowProperty(event->xclient.display, - event->xclient.window, - ATOM(_NET_WM_WINDOW_OPACITY), - 0, 1, False, XA_CARDINAL, - &ret, &format, &nitems, &after, &data); - - if (e == Success && ret == XA_CARDINAL && format == 32 && nitems == 1 - && after == 0 && data) { - ulong value = *(ulong*)(data); - d->topData()->opacity = uint(value >> 24); - } - } else - d->topData()->opacity = 255; - } - - if (data) - XFree(data); - - return true; -} - - -// -// Paint event translation -// -// When receiving many expose events, we compress them (union of all expose -// rectangles) into one event which is sent to the widget. - -struct PaintEventInfo { - Window window; -}; - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static Bool isPaintOrScrollDoneEvent(Display *, XEvent *ev, XPointer a) -{ - PaintEventInfo *info = (PaintEventInfo *)a; - if (ev->type == Expose || ev->type == GraphicsExpose - || (ev->type == ClientMessage && ev->xclient.message_type == ATOM(_QT_SCROLL_DONE))) - { - if (ev->xexpose.window == info->window) - return True; - } - return False; -} - -#if defined(Q_C_CALLBACKS) -} -#endif - - - -static -bool translateBySips(QWidget* that, QRect& paintRect) -{ - int dx=0, dy=0; - int sips=0; - for (int i = 0; i < X11->sip_list.size(); ++i) { - const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i); - if (sip.scrolled_widget == that) { - if (sips) { - dx += sip.dx; - dy += sip.dy; - } - sips++; - } - } - if (sips > 1) { - paintRect.translate(dx, dy); - return true; - } - return false; -} - -void QETWidget::translatePaintEvent(const XEvent *event) -{ - if (!isWindow() && testAttribute(Qt::WA_NativeWindow)) - Q_ASSERT(internalWinId()); - - Q_D(QWidget); - QRect paintRect(event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); - XEvent xevent; - PaintEventInfo info; - info.window = internalWinId(); - translateBySips(this, paintRect); - paintRect = d->mapFromWS(paintRect); - - QRegion paintRegion = paintRect; - - // WARNING: this is O(number_of_events * number_of_matching_events) - while (XCheckIfEvent(X11->display,&xevent,isPaintOrScrollDoneEvent, - (XPointer)&info) && - !qt_x11EventFilter(&xevent) && - !x11Event(&xevent)) // send event through filter - { - if (xevent.type == Expose || xevent.type == GraphicsExpose) { - QRect exposure(xevent.xexpose.x, - xevent.xexpose.y, - xevent.xexpose.width, - xevent.xexpose.height); - translateBySips(this, exposure); - exposure = d->mapFromWS(exposure); - paintRegion |= exposure; - } else { - translateScrollDoneEvent(&xevent); - } - } - - if (!paintRegion.isEmpty() && !testAttribute(Qt::WA_WState_ConfigPending)) - d->syncBackingStore(paintRegion); -} - -// -// Scroll-done event translation. -// - -bool QETWidget::translateScrollDoneEvent(const XEvent *event) -{ - long id = event->xclient.data.l[0]; - - // Remove any scroll-in-progress record for the given id. - for (int i = 0; i < X11->sip_list.size(); ++i) { - const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i); - if (sip.id == id) { - X11->sip_list.removeAt(i); - return true; - } - } - - return false; -} - -// -// ConfigureNotify (window move and resize) event translation - -bool QETWidget::translateConfigEvent(const XEvent *event) -{ - Q_ASSERT((!isWindow() && !testAttribute(Qt::WA_NativeWindow)) ? internalWinId() : true); - - Q_D(QWidget); - bool wasResize = testAttribute(Qt::WA_WState_ConfigPending); // set in QWidget::setGeometry_sys() - setAttribute(Qt::WA_WState_ConfigPending, false); - - if (testAttribute(Qt::WA_OutsideWSRange)) { - // discard events for windows that have a geometry X can't handle - XEvent xevent; - while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) && - !qt_x11EventFilter(&xevent) && - !x11Event(&xevent)) // send event through filter - ; - return true; - } - - const QSize oldSize = size(); - - if (isWindow()) { - QPoint newCPos(geometry().topLeft()); - QSize newSize(event->xconfigure.width, event->xconfigure.height); - - bool trust = isVisible() - && (d->topData()->parentWinId == XNone || - d->topData()->parentWinId == QX11Info::appRootWindow()); - bool isCPos = false; - - if (event->xconfigure.send_event || trust) { - // if a ConfigureNotify comes from a real sendevent request, we can - // trust its values. - newCPos.rx() = event->xconfigure.x + event->xconfigure.border_width; - newCPos.ry() = event->xconfigure.y + event->xconfigure.border_width; - isCPos = true; - } - if (isVisible()) - QApplication::syncX(); - - if (d->extra->compress_events) { - // ConfigureNotify compression for faster opaque resizing - XEvent otherEvent; - while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify, - &otherEvent)) { - if (qt_x11EventFilter(&otherEvent)) - continue; - - if (x11Event(&otherEvent)) - continue; - - if (otherEvent.xconfigure.event != otherEvent.xconfigure.window) - continue; - - newSize.setWidth(otherEvent.xconfigure.width); - newSize.setHeight(otherEvent.xconfigure.height); - - if (otherEvent.xconfigure.send_event || trust) { - newCPos.rx() = otherEvent.xconfigure.x + - otherEvent.xconfigure.border_width; - newCPos.ry() = otherEvent.xconfigure.y + - otherEvent.xconfigure.border_width; - isCPos = true; - } - } -#ifndef QT_NO_XSYNC - qt_sync_request_event_data sync_event; - sync_event.window = internalWinId(); - for (XEvent ev;;) { - if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event)) - break; - } -#endif // QT_NO_XSYNC - } - - if (!isCPos) { - // we didn't get an updated position of the toplevel. - // either we haven't moved or there is a bug in the window manager. - // anyway, let's query the position to be certain. - int x, y; - Window child; - XTranslateCoordinates(X11->display, internalWinId(), - QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(), - 0, 0, &x, &y, &child); - newCPos.rx() = x; - newCPos.ry() = y; - } - - QRect cr (geometry()); - if (newCPos != cr.topLeft()) { // compare with cpos (exluding frame) - QPoint oldPos = geometry().topLeft(); - cr.moveTopLeft(newCPos); - data->crect = cr; - if (isVisible()) { - QMoveEvent e(newCPos, oldPos); // pos (including frame), not cpos - QApplication::sendSpontaneousEvent(this, &e); - } else { - setAttribute(Qt::WA_PendingMoveEvent, true); - } - } - if (newSize != cr.size()) { // size changed - cr.setSize(newSize); - data->crect = cr; - - uint old_state = data->window_state; - if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)) - && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) - data->window_state &= ~Qt::WindowMaximized; - if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) - data->window_state &= ~Qt::WindowFullScreen; - - if (old_state != data->window_state) { - QWindowStateChangeEvent e((Qt::WindowStates) old_state); - QApplication::sendEvent(this, &e); - } - - if (!isVisible()) - setAttribute(Qt::WA_PendingResizeEvent, true); - wasResize = true; - } - - } else { - XEvent xevent; - while (XCheckTypedWindowEvent(X11->display,internalWinId(), ConfigureNotify,&xevent) && - !qt_x11EventFilter(&xevent) && - !x11Event(&xevent)) // send event through filter - ; - } - - if (wasResize) { - if (isVisible() && data->crect.size() != oldSize) { - Q_ASSERT(d->extra->topextra); - QWidgetBackingStore *bs = d->extra->topextra->backingStore.data(); - const bool hasStaticContents = bs && bs->hasStaticContents(); - // If we have a backing store with static contents, we have to disable the top-level - // resize optimization in order to get invalidated regions for resized widgets. - // The optimization discards all invalidateBuffer() calls since we're going to - // repaint everything anyways, but that's not the case with static contents. - if (!hasStaticContents) - d->extra->topextra->inTopLevelResize = true; - QResizeEvent e(data->crect.size(), oldSize); - QApplication::sendSpontaneousEvent(this, &e); - } - - const bool waitingForMapNotify = d->extra->topextra && d->extra->topextra->waitingForMapNotify; - if (!waitingForMapNotify) { - if (d->paintOnScreen()) { - QRegion updateRegion(rect()); - if (testAttribute(Qt::WA_StaticContents)) - updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); - d->syncBackingStore(updateRegion); - } else { - d->syncBackingStore(); - } - } - - if (d->extra && d->extra->topextra) - d->extra->topextra->inTopLevelResize = false; - } -#ifndef QT_NO_XSYNC - if (QTLWExtra *tlwExtra = d->maybeTopData()) { - if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) { - XSyncValue value; - XSyncIntsToValue(&value, - tlwExtra->newCounterValueLo, - tlwExtra->newCounterValueHi); - - XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value); - tlwExtra->newCounterValueHi = 0; - tlwExtra->newCounterValueLo = 0; - } - } -#endif - return true; -} - -// -// Close window event translation. -// -bool QETWidget::translateCloseEvent(const XEvent *) -{ - Q_D(QWidget); - return d->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); -} - - -void QApplication::setCursorFlashTime(int msecs) -{ - QApplicationPrivate::cursor_flash_time = msecs; -} - -int QApplication::cursorFlashTime() -{ - return QApplicationPrivate::cursor_flash_time; -} - -void QApplication::setDoubleClickInterval(int ms) -{ - QApplicationPrivate::mouse_double_click_time = ms; -} - -int QApplication::doubleClickInterval() -{ - return QApplicationPrivate::mouse_double_click_time; -} - -void QApplication::setKeyboardInputInterval(int ms) -{ - QApplicationPrivate::keyboard_input_time = ms; -} - -int QApplication::keyboardInputInterval() -{ - return QApplicationPrivate::keyboard_input_time; -} - -#ifndef QT_NO_WHEELEVENT -void QApplication::setWheelScrollLines(int n) -{ - QApplicationPrivate::wheel_scroll_lines = n; -} - -int QApplication::wheelScrollLines() -{ - return QApplicationPrivate::wheel_scroll_lines; -} -#endif - -void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) -{ - switch (effect) { - case Qt::UI_AnimateMenu: - if (enable) QApplicationPrivate::fade_menu = false; - QApplicationPrivate::animate_menu = enable; - break; - case Qt::UI_FadeMenu: - if (enable) - QApplicationPrivate::animate_menu = true; - QApplicationPrivate::fade_menu = enable; - break; - case Qt::UI_AnimateCombo: - QApplicationPrivate::animate_combo = enable; - break; - case Qt::UI_AnimateTooltip: - if (enable) QApplicationPrivate::fade_tooltip = false; - QApplicationPrivate::animate_tooltip = enable; - break; - case Qt::UI_FadeTooltip: - if (enable) - QApplicationPrivate::animate_tooltip = true; - QApplicationPrivate::fade_tooltip = enable; - break; - case Qt::UI_AnimateToolBox: - QApplicationPrivate::animate_toolbox = enable; - break; - default: - QApplicationPrivate::animate_ui = enable; - break; - } -} - -bool QApplication::isEffectEnabled(Qt::UIEffect effect) -{ - if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui) - return false; - - switch(effect) { - case Qt::UI_AnimateMenu: - return QApplicationPrivate::animate_menu; - case Qt::UI_FadeMenu: - return QApplicationPrivate::fade_menu; - case Qt::UI_AnimateCombo: - return QApplicationPrivate::animate_combo; - case Qt::UI_AnimateTooltip: - return QApplicationPrivate::animate_tooltip; - case Qt::UI_FadeTooltip: - return QApplicationPrivate::fade_tooltip; - case Qt::UI_AnimateToolBox: - return QApplicationPrivate::animate_toolbox; - default: - return QApplicationPrivate::animate_ui; - } -} - -/***************************************************************************** - Session management support - *****************************************************************************/ - -#ifndef QT_NO_SESSIONMANAGER - -QT_BEGIN_INCLUDE_NAMESPACE -#include <X11/SM/SMlib.h> -QT_END_INCLUDE_NAMESPACE - -class QSessionManagerPrivate : public QObjectPrivate -{ -public: - QSessionManagerPrivate(QSessionManager* mgr, QString& id, QString& key) - : QObjectPrivate(), sm(mgr), sessionId(id), sessionKey(key), - restartHint(QSessionManager::RestartIfRunning), eventLoop(0) {} - QSessionManager* sm; - QStringList restartCommand; - QStringList discardCommand; - QString& sessionId; - QString& sessionKey; - QSessionManager::RestartHint restartHint; - QEventLoop *eventLoop; -}; - -class QSmSocketReceiver : public QObject -{ - Q_OBJECT -public: - QSmSocketReceiver(int socket) - { - QSocketNotifier* sn = new QSocketNotifier(socket, QSocketNotifier::Read, this); - connect(sn, SIGNAL(activated(int)), this, SLOT(socketActivated(int))); - } - -public slots: - void socketActivated(int); -}; - - -static SmcConn smcConnection = 0; -static bool sm_interactionActive; -static bool sm_smActive; -static int sm_interactStyle; -static int sm_saveType; -static bool sm_cancel; -// static bool sm_waitingForPhase2; ### never used?!? -static bool sm_waitingForInteraction; -static bool sm_isshutdown; -// static bool sm_shouldbefast; ### never used?!? -static bool sm_phase2; -static bool sm_in_phase2; - -static QSmSocketReceiver* sm_receiver = 0; - -static void resetSmState(); -static void sm_setProperty(const char* name, const char* type, - int num_vals, SmPropValue* vals); -static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData, - int saveType, Bool shutdown , int interactStyle, Bool fast); -static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData) ; -static void sm_dieCallback(SmcConn smcConn, SmPointer clientData) ; -static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData); -static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer clientData); -static void sm_interactCallback(SmcConn smcConn, SmPointer clientData); -static void sm_performSaveYourself(QSessionManagerPrivate*); - -static void resetSmState() -{ -// sm_waitingForPhase2 = false; ### never used?!? - sm_waitingForInteraction = false; - sm_interactionActive = false; - sm_interactStyle = SmInteractStyleNone; - sm_smActive = false; - qt_sm_blockUserInput = false; - sm_isshutdown = false; -// sm_shouldbefast = false; ### never used?!? - sm_phase2 = false; - sm_in_phase2 = false; -} - - -// theoretically it's possible to set several properties at once. For -// simplicity, however, we do just one property at a time -static void sm_setProperty(const char* name, const char* type, - int num_vals, SmPropValue* vals) -{ - if (num_vals) { - SmProp prop; - prop.name = (char*)name; - prop.type = (char*)type; - prop.num_vals = num_vals; - prop.vals = vals; - - SmProp* props[1]; - props[0] = ∝ - SmcSetProperties(smcConnection, 1, props); - } - else { - char* names[1]; - names[0] = (char*) name; - SmcDeleteProperties(smcConnection, 1, names); - } -} - -static void sm_setProperty(const QString& name, const QString& value) -{ - QByteArray v = value.toUtf8(); - SmPropValue prop; - prop.length = v.length(); - prop.value = (SmPointer) v.constData(); - sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop); -} - -static void sm_setProperty(const QString& name, const QStringList& value) -{ - SmPropValue *prop = new SmPropValue[value.count()]; - int count = 0; - QList<QByteArray> vl; - for (QStringList::ConstIterator it = value.begin(); it != value.end(); ++it) { - prop[count].length = (*it).length(); - vl.append((*it).toUtf8()); - prop[count].value = (char*)vl.last().data(); - ++count; - } - sm_setProperty(name.toLatin1().data(), SmLISTofARRAY8, count, prop); - delete [] prop; -} - - -// workaround for broken libsm, see below -struct QT_smcConn { - unsigned int save_yourself_in_progress : 1; - unsigned int shutdown_in_progress : 1; -}; - -static void sm_saveYourselfCallback(SmcConn smcConn, SmPointer clientData, - int saveType, Bool shutdown , int interactStyle, Bool /*fast*/) -{ - if (smcConn != smcConnection) - return; - sm_cancel = false; - sm_smActive = true; - sm_isshutdown = shutdown; - sm_saveType = saveType; - sm_interactStyle = interactStyle; -// sm_shouldbefast = fast; ### never used?!? - - // ugly workaround for broken libSM. libSM should do that _before_ - // actually invoking the callback in sm_process.c - ((QT_smcConn*)smcConn)->save_yourself_in_progress = true; - if (sm_isshutdown) - ((QT_smcConn*)smcConn)->shutdown_in_progress = true; - - sm_performSaveYourself((QSessionManagerPrivate*) clientData); - if (!sm_isshutdown) // we cannot expect a confirmation message in that case - resetSmState(); -} - -static void sm_performSaveYourself(QSessionManagerPrivate* smd) -{ - if (sm_isshutdown) - qt_sm_blockUserInput = true; - - QSessionManager* sm = smd->sm; - - // generate a new session key - timeval tv; - gettimeofday(&tv, 0); - smd->sessionKey = QString::number(qulonglong(tv.tv_sec)) + QLatin1Char('_') + QString::number(qulonglong(tv.tv_usec)); - - QStringList arguments = qApp->arguments(); - QString argument0 = arguments.isEmpty() ? qApp->applicationFilePath() : arguments.at(0); - - // tell the session manager about our program in best POSIX style - sm_setProperty(QString::fromLatin1(SmProgram), argument0); - // tell the session manager about our user as well. - struct passwd *entryPtr = 0; -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - QVarLengthArray<char, 1024> buf(qMax<long>(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); - struct passwd entry; - while (getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr) == ERANGE) { - if (buf.size() >= 32768) { - // too big already, fail - static char badusername[] = ""; - entryPtr = &entry; - entry.pw_name = badusername; - break; - } - - // retry with a bigger buffer - buf.resize(buf.size() * 2); - } -#else - entryPtr = getpwuid(geteuid()); -#endif - if (entryPtr) - sm_setProperty(QString::fromLatin1(SmUserID), QString::fromLatin1(entryPtr->pw_name)); - - // generate a restart and discard command that makes sense - QStringList restart; - restart << argument0 << QLatin1String("-session") - << smd->sessionId + QLatin1Char('_') + smd->sessionKey; - if (qstricmp(appName, QX11Info::appClass()) != 0) - restart << QLatin1String("-name") << qAppName(); - sm->setRestartCommand(restart); - QStringList discard; - sm->setDiscardCommand(discard); - - switch (sm_saveType) { - case SmSaveBoth: - qApp->commitData(*sm); - if (sm_isshutdown && sm_cancel) - break; // we cancelled the shutdown, no need to save state - // fall through - case SmSaveLocal: - qApp->saveState(*sm); - break; - case SmSaveGlobal: - qApp->commitData(*sm); - break; - default: - break; - } - - if (sm_phase2 && !sm_in_phase2) { - SmcRequestSaveYourselfPhase2(smcConnection, sm_saveYourselfPhase2Callback, (SmPointer*) smd); - qt_sm_blockUserInput = false; - } - else { - // close eventual interaction monitors and cancel the - // shutdown, if required. Note that we can only cancel when - // performing a shutdown, it does not work for checkpoints - if (sm_interactionActive) { - SmcInteractDone(smcConnection, sm_isshutdown && sm_cancel); - sm_interactionActive = false; - } - else if (sm_cancel && sm_isshutdown) { - if (sm->allowsErrorInteraction()) { - SmcInteractDone(smcConnection, True); - sm_interactionActive = false; - } - } - - // set restart and discard command in session manager - sm_setProperty(QString::fromLatin1(SmRestartCommand), sm->restartCommand()); - sm_setProperty(QString::fromLatin1(SmDiscardCommand), sm->discardCommand()); - - // set the restart hint - SmPropValue prop; - prop.length = sizeof(int); - int value = sm->restartHint(); - prop.value = (SmPointer) &value; - sm_setProperty(SmRestartStyleHint, SmCARD8, 1, &prop); - - // we are done - SmcSaveYourselfDone(smcConnection, !sm_cancel); - } -} - -static void sm_dieCallback(SmcConn smcConn, SmPointer /* clientData */) -{ - if (smcConn != smcConnection) - return; - resetSmState(); - QEvent quitEvent(QEvent::Quit); - QApplication::sendEvent(qApp, &quitEvent); -} - -static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData) -{ - if (smcConn != smcConnection) - return; - if (sm_waitingForInteraction) - ((QSessionManagerPrivate *) clientData)->eventLoop->exit(); - resetSmState(); -} - -static void sm_saveCompleteCallback(SmcConn smcConn, SmPointer /*clientData */) -{ - if (smcConn != smcConnection) - return; - resetSmState(); -} - -static void sm_interactCallback(SmcConn smcConn, SmPointer clientData) -{ - if (smcConn != smcConnection) - return; - if (sm_waitingForInteraction) - ((QSessionManagerPrivate *) clientData)->eventLoop->exit(); -} - -static void sm_saveYourselfPhase2Callback(SmcConn smcConn, SmPointer clientData) -{ - if (smcConn != smcConnection) - return; - sm_in_phase2 = true; - sm_performSaveYourself((QSessionManagerPrivate*) clientData); -} - - -void QSmSocketReceiver::socketActivated(int) -{ - IceProcessMessages(SmcGetIceConnection(smcConnection), 0, 0); -} - - -#undef Bool -QT_BEGIN_INCLUDE_NAMESPACE -#include "qapplication_x11.moc" -QT_END_INCLUDE_NAMESPACE - -QSessionManager::QSessionManager(QApplication * app, QString &id, QString& key) - : QObject(*new QSessionManagerPrivate(this, id, key), app) -{ - Q_D(QSessionManager); - d->restartHint = RestartIfRunning; - - resetSmState(); - char cerror[256]; - char* myId = 0; - QByteArray b_id = id.toLatin1(); - char* prevId = b_id.data(); - - SmcCallbacks cb; - cb.save_yourself.callback = sm_saveYourselfCallback; - cb.save_yourself.client_data = (SmPointer) d; - cb.die.callback = sm_dieCallback; - cb.die.client_data = (SmPointer) d; - cb.save_complete.callback = sm_saveCompleteCallback; - cb.save_complete.client_data = (SmPointer) d; - cb.shutdown_cancelled.callback = sm_shutdownCancelledCallback; - cb.shutdown_cancelled.client_data = (SmPointer) d; - - // avoid showing a warning message below - if (qgetenv("SESSION_MANAGER").isEmpty()) - return; - - smcConnection = SmcOpenConnection(0, 0, 1, 0, - SmcSaveYourselfProcMask | - SmcDieProcMask | - SmcSaveCompleteProcMask | - SmcShutdownCancelledProcMask, - &cb, - prevId, - &myId, - 256, cerror); - - id = QString::fromLatin1(myId); - ::free(myId); // it was allocated by C - - QString error = QString::fromLocal8Bit(cerror); - if (!smcConnection) { - qWarning("Qt: Session management error: %s", qPrintable(error)); - } - else { - sm_receiver = new QSmSocketReceiver(IceConnectionNumber(SmcGetIceConnection(smcConnection))); - } -} - -QSessionManager::~QSessionManager() -{ - if (smcConnection) - SmcCloseConnection(smcConnection, 0, 0); - smcConnection = 0; - delete sm_receiver; -} - -QString QSessionManager::sessionId() const -{ - Q_D(const QSessionManager); - return d->sessionId; -} - -QString QSessionManager::sessionKey() const -{ - Q_D(const QSessionManager); - return d->sessionKey; -} - - -void* QSessionManager::handle() const -{ - return (void*) smcConnection; -} - - -bool QSessionManager::allowsInteraction() -{ - Q_D(QSessionManager); - if (sm_interactionActive) - return true; - - if (sm_waitingForInteraction) - return false; - - if (sm_interactStyle == SmInteractStyleAny) { - sm_waitingForInteraction = SmcInteractRequest(smcConnection, SmDialogNormal, - sm_interactCallback, (SmPointer*) d); - } - if (sm_waitingForInteraction) { - QEventLoop eventLoop; - d->eventLoop = &eventLoop; - (void) eventLoop.exec(); - d->eventLoop = 0; - - sm_waitingForInteraction = false; - if (sm_smActive) { // not cancelled - sm_interactionActive = true; - qt_sm_blockUserInput = false; - return true; - } - } - return false; -} - -bool QSessionManager::allowsErrorInteraction() -{ - Q_D(QSessionManager); - if (sm_interactionActive) - return true; - - if (sm_waitingForInteraction) - return false; - - if (sm_interactStyle == SmInteractStyleAny || sm_interactStyle == SmInteractStyleErrors) { - sm_waitingForInteraction = SmcInteractRequest(smcConnection, SmDialogError, - sm_interactCallback, (SmPointer*) d); - } - if (sm_waitingForInteraction) { - QEventLoop eventLoop; - d->eventLoop = &eventLoop; - (void) eventLoop.exec(); - d->eventLoop = 0; - - sm_waitingForInteraction = false; - if (sm_smActive) { // not cancelled - sm_interactionActive = true; - qt_sm_blockUserInput = false; - return true; - } - } - return false; -} - -void QSessionManager::release() -{ - if (sm_interactionActive) { - SmcInteractDone(smcConnection, False); - sm_interactionActive = false; - if (sm_smActive && sm_isshutdown) - qt_sm_blockUserInput = true; - } -} - -void QSessionManager::cancel() -{ - sm_cancel = true; -} - -void QSessionManager::setRestartHint(QSessionManager::RestartHint hint) -{ - Q_D(QSessionManager); - d->restartHint = hint; -} - -QSessionManager::RestartHint QSessionManager::restartHint() const -{ - Q_D(const QSessionManager); - return d->restartHint; -} - -void QSessionManager::setRestartCommand(const QStringList& command) -{ - Q_D(QSessionManager); - d->restartCommand = command; -} - -QStringList QSessionManager::restartCommand() const -{ - Q_D(const QSessionManager); - return d->restartCommand; -} - -void QSessionManager::setDiscardCommand(const QStringList& command) -{ - Q_D(QSessionManager); - d->discardCommand = command; -} - -QStringList QSessionManager::discardCommand() const -{ - Q_D(const QSessionManager); - return d->discardCommand; -} - -void QSessionManager::setManagerProperty(const QString& name, const QString& value) -{ - sm_setProperty(name, value); -} - -void QSessionManager::setManagerProperty(const QString& name, const QStringList& value) -{ - sm_setProperty(name, value); -} - -bool QSessionManager::isPhase2() const -{ - return sm_in_phase2; -} - -void QSessionManager::requestPhase2() -{ - sm_phase2 = true; -} - -#endif // QT_NO_SESSIONMANAGER - -#if defined(QT_RX71_MULTITOUCH) - -static inline int testBit(const char *array, int bit) -{ - return (array[bit/8] & (1<<(bit%8))); -} - -static int openRX71Device(const QByteArray &deviceName) -{ - int fd = open(deviceName, O_RDONLY | O_NONBLOCK); - if (fd == -1) { - fd = -errno; - return fd; - } - - // fetch the event type mask and check that the device reports absolute coordinates - char eventTypeMask[(EV_MAX + sizeof(char) - 1) * sizeof(char) + 1]; - memset(eventTypeMask, 0, sizeof(eventTypeMask)); - if (ioctl(fd, EVIOCGBIT(0, sizeof(eventTypeMask)), eventTypeMask) < 0) { - close(fd); - return -1; - } - if (!testBit(eventTypeMask, EV_ABS)) { - close(fd); - return -1; - } - - // make sure that we can get the absolute X and Y positions from the device - char absMask[(ABS_MAX + sizeof(char) - 1) * sizeof(char) + 1]; - memset(absMask, 0, sizeof(absMask)); - if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absMask)), absMask) < 0) { - close(fd); - return -1; - } - if (!testBit(absMask, ABS_X) || !testBit(absMask, ABS_Y)) { - close(fd); - return -1; - } - - return fd; -} - -void QApplicationPrivate::initializeMultitouch_sys() -{ - Q_Q(QApplication); - - QByteArray deviceName = QByteArray("/dev/input/event"); - int currentDeviceNumber = 0; - for (;;) { - int fd = openRX71Device(QByteArray(deviceName + QByteArray::number(currentDeviceNumber++))); - if (fd == -ENOENT) { - // no more devices - break; - } - if (fd < 0) { - // not a touch device - continue; - } - - struct input_absinfo abs_x, abs_y, abs_z; - ioctl(fd, EVIOCGABS(ABS_X), &abs_x); - ioctl(fd, EVIOCGABS(ABS_Y), &abs_y); - ioctl(fd, EVIOCGABS(ABS_Z), &abs_z); - - int deviceNumber = allRX71TouchPoints.count(); - - QSocketNotifier *socketNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, q); - QObject::connect(socketNotifier, SIGNAL(activated(int)), q, SLOT(_q_readRX71MultiTouchEvents())); - - RX71TouchPointState touchPointState = { - socketNotifier, - QTouchEvent::TouchPoint(deviceNumber), - - abs_x.minimum, abs_x.maximum, q->desktop()->screenGeometry().width(), - abs_y.minimum, abs_y.maximum, q->desktop()->screenGeometry().height(), - abs_z.minimum, abs_z.maximum - }; - allRX71TouchPoints.append(touchPointState); - } - - hasRX71MultiTouch = allRX71TouchPoints.count() > 1; - if (!hasRX71MultiTouch) { - for (int i = 0; i < allRX71TouchPoints.count(); ++i) { - QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier; - close(socketNotifier->socket()); - delete socketNotifier; - } - allRX71TouchPoints.clear(); - } -} - -void QApplicationPrivate::cleanupMultitouch_sys() -{ - hasRX71MultiTouch = false; - for (int i = 0; i < allRX71TouchPoints.count(); ++i) { - QSocketNotifier *socketNotifier = allRX71TouchPoints.at(i).socketNotifier; - close(socketNotifier->socket()); - delete socketNotifier; - } - allRX71TouchPoints.clear(); -} - -bool QApplicationPrivate::readRX71MultiTouchEvents(int deviceNumber) -{ - RX71TouchPointState &touchPointState = allRX71TouchPoints[deviceNumber]; - QSocketNotifier *socketNotifier = touchPointState.socketNotifier; - int fd = socketNotifier->socket(); - - QTouchEvent::TouchPoint &touchPoint = touchPointState.touchPoint; - - bool down = touchPoint.state() != Qt::TouchPointReleased; - if (down) - touchPoint.setState(Qt::TouchPointStationary); - - bool changed = false; - for (;;) { - struct input_event inputEvent; - int bytesRead = read(fd, &inputEvent, sizeof(inputEvent)); - if (bytesRead <= 0) - break; - if (bytesRead != sizeof(inputEvent)) { - qWarning("Qt: INTERNAL ERROR: short read in readRX71MultiTouchEvents()"); - return false; - } - - switch (inputEvent.type) { - case EV_SYN: - changed = true; - switch (touchPoint.state()) { - case Qt::TouchPointPressed: - case Qt::TouchPointReleased: - // make sure we don't compress pressed and releases with any other events - return changed; - default: - break; - } - continue; - case EV_KEY: - case EV_ABS: - break; - default: - qWarning("Qt: WARNING: unknown event type %d on multitouch device", inputEvent.type); - continue; - } - - QPointF screenPos = touchPoint.screenPos(); - switch (inputEvent.code) { - case BTN_TOUCH: - if (!down && inputEvent.value != 0) - touchPoint.setState(Qt::TouchPointPressed); - else if (down && inputEvent.value == 0) - touchPoint.setState(Qt::TouchPointReleased); - break; - case ABS_TOOL_WIDTH: - case ABS_VOLUME: - case ABS_PRESSURE: - // ignore for now - break; - case ABS_X: - { - qreal newValue = ((qreal(inputEvent.value - touchPointState.minX) - / qreal(touchPointState.maxX - touchPointState.minX)) - * touchPointState.scaleX); - screenPos.rx() = newValue; - touchPoint.setScreenPos(screenPos); - break; - } - case ABS_Y: - { - qreal newValue = ((qreal(inputEvent.value - touchPointState.minY) - / qreal(touchPointState.maxY - touchPointState.minY)) - * touchPointState.scaleY); - screenPos.ry() = newValue; - touchPoint.setScreenPos(screenPos); - break; - } - case ABS_Z: - { - // map Z (signal strength) to pressure for now - qreal newValue = (qreal(inputEvent.value - touchPointState.minZ) - / qreal(touchPointState.maxZ - touchPointState.minZ)); - touchPoint.setPressure(newValue); - break; - } - default: - qWarning("Qt: WARNING: unknown event code %d on multitouch device", inputEvent.code); - continue; - } - } - - if (down && touchPoint.state() != Qt::TouchPointReleased) - touchPoint.setState(changed ? Qt::TouchPointMoved : Qt::TouchPointStationary); - - return changed; -} - -void QApplicationPrivate::_q_readRX71MultiTouchEvents() -{ - // read touch events from all devices - bool changed = false; - for (int i = 0; i < allRX71TouchPoints.count(); ++i) - changed = readRX71MultiTouchEvents(i) || changed; - if (!changed) - return; - - QList<QTouchEvent::TouchPoint> touchPoints; - for (int i = 0; i < allRX71TouchPoints.count(); ++i) - touchPoints.append(allRX71TouchPoints.at(i).touchPoint); - - translateRawTouchEvent(0, QTouchEvent::TouchScreen, touchPoints); -} - -#else // !QT_RX71_MULTITOUCH - -void QApplicationPrivate::initializeMultitouch_sys() -{ } -void QApplicationPrivate::cleanupMultitouch_sys() -{ } - -#endif // QT_RX71_MULTITOUCH - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qclipboard_x11.cpp b/src/widgets/platforms/x11/qclipboard_x11.cpp deleted file mode 100644 index 97e076cbc2..0000000000 --- a/src/widgets/platforms/x11/qclipboard_x11.cpp +++ /dev/null @@ -1,1539 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// #define QCLIPBOARD_DEBUG -// #define QCLIPBOARD_DEBUG_VERBOSE - -#ifdef QCLIPBOARD_DEBUG -# define DEBUG qDebug -#else -# define DEBUG if (false) qDebug -#endif - -#ifdef QCLIPBOARD_DEBUG_VERBOSE -# define VDEBUG qDebug -#else -# define VDEBUG if (false) qDebug -#endif - -#include "qplatformdefs.h" - -#include "qclipboard.h" -#include "qclipboard_p.h" - -#ifndef QT_NO_CLIPBOARD - -#include "qabstracteventdispatcher.h" -#include "qapplication.h" -#include "qdesktopwidget.h" -#include "qbitmap.h" -#include "qiodevice.h" -#include "qbuffer.h" -#include "qtextcodec.h" -#include "qlist.h" -#include "qmap.h" -#include "qapplication_p.h" -#include "qevent.h" -#include "qt_x11_p.h" -#include "qx11info_x11.h" -#include "qimagewriter.h" -#include "qelapsedtimer.h" -#include "qvariant.h" -#include "qdnd_p.h" -#include <private/qwidget_p.h> - -#ifndef QT_NO_XFIXES -#include <X11/extensions/Xfixes.h> -#endif // QT_NO_XFIXES - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - Internal QClipboard functions for X11. - *****************************************************************************/ - -static int clipboard_timeout = 5000; // 5s timeout on clipboard operations - -static QWidget * owner = 0; -static QWidget *requestor = 0; -static bool timer_event_clear = false; -static int timer_id = 0; - -static int pending_timer_id = 0; -static bool pending_clipboard_changed = false; -static bool pending_selection_changed = false; - - -// event capture mechanism for qt_xclb_wait_for_event -static bool waiting_for_data = false; -static bool has_captured_event = false; -static Window capture_event_win = XNone; -static int capture_event_type = -1; -static XEvent captured_event; - -class QClipboardWatcher; // forward decl -static QClipboardWatcher *selection_watcher = 0; -static QClipboardWatcher *clipboard_watcher = 0; - -static void cleanup() -{ - delete owner; - delete requestor; - owner = 0; - requestor = 0; -} - -static -void setupOwner() -{ - if (owner) - return; - owner = new QWidget(0); - owner->setObjectName(QLatin1String("internal clipboard owner")); - owner->createWinId(); - requestor = new QWidget(0); - requestor->createWinId(); - requestor->setObjectName(QLatin1String("internal clipboard requestor")); - // We don't need this internal widgets to appear in QApplication::topLevelWidgets() - if (QWidgetPrivate::allWidgets) { - QWidgetPrivate::allWidgets->remove(owner); - QWidgetPrivate::allWidgets->remove(requestor); - } - qAddPostRoutine(cleanup); -} - - -class QClipboardWatcher : public QInternalMimeData { -public: - QClipboardWatcher(QClipboard::Mode mode); - ~QClipboardWatcher(); - bool empty() const; - virtual bool hasFormat_sys(const QString &mimetype) const; - virtual QStringList formats_sys() const; - - QVariant retrieveData_sys(const QString &mimetype, QVariant::Type type) const; - QByteArray getDataInFormat(Atom fmtatom) const; - - Atom atom; - mutable QStringList formatList; - mutable QByteArray format_atoms; -}; - -class QClipboardData -{ -private: - QMimeData *&mimeDataRef() const - { - if(mode == QClipboard::Selection) - return selectionData; - return clipboardData; - } - -public: - QClipboardData(QClipboard::Mode mode); - ~QClipboardData(); - - void setSource(QMimeData* s) - { - if ((mode == QClipboard::Selection && selectionData == s) - || clipboardData == s) { - return; - } - - if (selectionData != clipboardData) { - delete mimeDataRef(); - } - - mimeDataRef() = s; - } - - QMimeData *source() const - { - return mimeDataRef(); - } - - void clear() - { - timestamp = CurrentTime; - if (selectionData == clipboardData) { - mimeDataRef() = 0; - } else { - QMimeData *&src = mimeDataRef(); - delete src; - src = 0; - } - } - - static QMimeData *selectionData; - static QMimeData *clipboardData; - Time timestamp; - QClipboard::Mode mode; -}; - -QMimeData *QClipboardData::selectionData = 0; -QMimeData *QClipboardData::clipboardData = 0; - -QClipboardData::QClipboardData(QClipboard::Mode clipboardMode) -{ - timestamp = CurrentTime; - mode = clipboardMode; -} - -QClipboardData::~QClipboardData() -{ clear(); } - - -static QClipboardData *internalCbData = 0; -static QClipboardData *internalSelData = 0; - -static void cleanupClipboardData() -{ - delete internalCbData; - internalCbData = 0; -} - -static QClipboardData *clipboardData() -{ - if (internalCbData == 0) { - internalCbData = new QClipboardData(QClipboard::Clipboard); - qAddPostRoutine(cleanupClipboardData); - } - return internalCbData; -} - -static void cleanupSelectionData() -{ - delete internalSelData; - internalSelData = 0; -} - -static QClipboardData *selectionData() -{ - if (internalSelData == 0) { - internalSelData = new QClipboardData(QClipboard::Selection); - qAddPostRoutine(cleanupSelectionData); - } - return internalSelData; -} - -class QClipboardINCRTransaction -{ -public: - QClipboardINCRTransaction(Window w, Atom p, Atom t, int f, QByteArray d, unsigned int i); - ~QClipboardINCRTransaction(void); - - int x11Event(XEvent *event); - - Window window; - Atom property, target; - int format; - QByteArray data; - unsigned int increment; - unsigned int offset; -}; - -typedef QMap<Window,QClipboardINCRTransaction*> TransactionMap; -static TransactionMap *transactions = 0; -static QApplication::EventFilter prev_event_filter = 0; -static int incr_timer_id = 0; - -static bool qt_x11_incr_event_filter(void *message, long *result) -{ - XEvent *event = reinterpret_cast<XEvent *>(message); - TransactionMap::Iterator it = transactions->find(event->xany.window); - if (it != transactions->end()) { - if ((*it)->x11Event(event) != 0) - return true; - } - if (prev_event_filter) - return prev_event_filter(event, result); - return false; -} - -/* - called when no INCR activity has happened for 'clipboard_timeout' - milliseconds... we assume that all unfinished transactions have - timed out and remove everything from the transaction map -*/ -static void qt_xclb_incr_timeout(void) -{ - qWarning("QClipboard: Timed out while sending data"); - - while (transactions) - delete *transactions->begin(); -} - -QClipboardINCRTransaction::QClipboardINCRTransaction(Window w, Atom p, Atom t, int f, - QByteArray d, unsigned int i) - : window(w), property(p), target(t), format(f), data(d), increment(i), offset(0u) -{ - DEBUG("QClipboard: sending %d bytes (INCR transaction %p)", d.size(), this); - - XSelectInput(X11->display, window, PropertyChangeMask); - - if (! transactions) { - VDEBUG("QClipboard: created INCR transaction map"); - transactions = new TransactionMap; - prev_event_filter = qApp->setEventFilter(qt_x11_incr_event_filter); - incr_timer_id = QApplication::clipboard()->startTimer(clipboard_timeout); - } - transactions->insert(window, this); -} - -QClipboardINCRTransaction::~QClipboardINCRTransaction(void) -{ - VDEBUG("QClipboard: destroyed INCR transacton %p", this); - - XSelectInput(X11->display, window, NoEventMask); - - transactions->remove(window); - if (transactions->isEmpty()) { - VDEBUG("QClipboard: no more INCR transactions"); - delete transactions; - transactions = 0; - - (void)qApp->setEventFilter(prev_event_filter); - - if (incr_timer_id != 0) { - QApplication::clipboard()->killTimer(incr_timer_id); - incr_timer_id = 0; - } - } -} - -int QClipboardINCRTransaction::x11Event(XEvent *event) -{ - if (event->type != PropertyNotify - || (event->xproperty.state != PropertyDelete - || event->xproperty.atom != property)) - return 0; - - // restart the INCR timer - if (incr_timer_id) QApplication::clipboard()->killTimer(incr_timer_id); - incr_timer_id = QApplication::clipboard()->startTimer(clipboard_timeout); - - unsigned int bytes_left = data.size() - offset; - if (bytes_left > 0) { - unsigned int xfer = qMin(increment, bytes_left); - VDEBUG("QClipboard: sending %d bytes, %d remaining (INCR transaction %p)", - xfer, bytes_left - xfer, this); - - XChangeProperty(X11->display, window, property, target, format, - PropModeReplace, (uchar *) data.data() + offset, xfer); - offset += xfer; - } else { - // INCR transaction finished... - XChangeProperty(X11->display, window, property, target, format, - PropModeReplace, (uchar *) data.data(), 0); - delete this; - } - - return 1; -} - - -/***************************************************************************** - QClipboard member functions for X11. - *****************************************************************************/ - -struct qt_init_timestamp_data -{ - Time timestamp; -}; - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static Bool qt_init_timestamp_scanner(Display*, XEvent *event, XPointer arg) -{ - qt_init_timestamp_data *data = - reinterpret_cast<qt_init_timestamp_data*>(arg); - switch(event->type) - { - case ButtonPress: - case ButtonRelease: - data->timestamp = event->xbutton.time; - break; - case MotionNotify: - data->timestamp = event->xmotion.time; - break; - case XKeyPress: - case XKeyRelease: - data->timestamp = event->xkey.time; - break; - case PropertyNotify: - data->timestamp = event->xproperty.time; - break; - case EnterNotify: - case LeaveNotify: - data->timestamp = event->xcrossing.time; - break; - case SelectionClear: - data->timestamp = event->xselectionclear.time; - break; - default: - break; - } -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { - XFixesSelectionNotifyEvent *req = - reinterpret_cast<XFixesSelectionNotifyEvent *>(event); - data->timestamp = req->selection_timestamp; - } -#endif - return false; -} - -#if defined(Q_C_CALLBACKS) -} -#endif - -QClipboard::QClipboard(QObject *parent) - : QObject(*new QClipboardPrivate, parent) -{ - // create desktop widget since we need it to get PropertyNotify or - // XFixesSelectionNotify events when someone changes the - // clipboard. - (void)QApplication::desktop(); - -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && X11->ptrXFixesSelectSelectionInput) { - const unsigned long eventMask = - XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask; - for (int i = 0; i < X11->screenCount; ++i) { - X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(i), - XA_PRIMARY, eventMask); - X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(i), - ATOM(CLIPBOARD), eventMask); - } - } -#endif // QT_NO_XFIXES - - if (X11->time == CurrentTime) { - // send a dummy event to myself to get the timestamp from X11. - qt_init_timestamp_data data; - data.timestamp = CurrentTime; - XEvent ev; - XCheckIfEvent(X11->display, &ev, &qt_init_timestamp_scanner, (XPointer)&data); - if (data.timestamp == CurrentTime) { - setupOwner(); - // We need this value just for completeness, we don't use it. - long dummy = 0; - Window ownerId = owner->internalWinId(); - XChangeProperty(X11->display, ownerId, - ATOM(CLIP_TEMPORARY), XA_INTEGER, 32, - PropModeReplace, (uchar*)&dummy, 1); - XWindowEvent(X11->display, ownerId, PropertyChangeMask, &ev); - data.timestamp = ev.xproperty.time; - XDeleteProperty(X11->display, ownerId, ATOM(CLIP_TEMPORARY)); - } - X11->time = data.timestamp; - } -} - -void QClipboard::clear(Mode mode) -{ - setMimeData(0, mode); -} - - -bool QClipboard::supportsMode(Mode mode) const -{ - return (mode == Clipboard || mode == Selection); -} - -bool QClipboard::ownsMode(Mode mode) const -{ - if (mode == Clipboard) - return clipboardData()->timestamp != CurrentTime; - else if(mode == Selection) - return selectionData()->timestamp != CurrentTime; - else - return false; -} - - -// event filter function... captures interesting events while -// qt_xclb_wait_for_event is running the event loop -static bool qt_x11_clipboard_event_filter(void *message, long *) -{ - XEvent *event = reinterpret_cast<XEvent *>(message); - if (event->xany.type == capture_event_type && - event->xany.window == capture_event_win) { - VDEBUG("QClipboard: event_filter(): caught event type %d", event->type); - has_captured_event = true; - captured_event = *event; - return true; - } - return false; -} - -static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer) -{ - return ((e->type == SelectionRequest && (e->xselectionrequest.selection == XA_PRIMARY - || e->xselectionrequest.selection == ATOM(CLIPBOARD))) - || (e->type == SelectionClear && (e->xselectionclear.selection == XA_PRIMARY - || e->xselectionclear.selection == ATOM(CLIPBOARD)))); -} - -bool QX11Data::clipboardWaitForEvent(Window win, int type, XEvent *event, int timeout) -{ - QElapsedTimer started; - started.start(); - QElapsedTimer now = started; - - if (QAbstractEventDispatcher::instance()->inherits("QtMotif") - || QApplication::clipboard()->property("useEventLoopWhenWaiting").toBool()) { - if (waiting_for_data) { - Q_ASSERT(!"QClipboard: internal error, qt_xclb_wait_for_event recursed"); - return false; - } - waiting_for_data = true; - - - has_captured_event = false; - capture_event_win = win; - capture_event_type = type; - - QApplication::EventFilter old_event_filter = - qApp->setEventFilter(qt_x11_clipboard_event_filter); - - do { - if (XCheckTypedWindowEvent(display, win, type, event)) { - waiting_for_data = false; - qApp->setEventFilter(old_event_filter); - return true; - } - - XSync(X11->display, false); - usleep(50000); - - now.start(); - - QEventLoop::ProcessEventsFlags flags(QEventLoop::ExcludeUserInputEvents - | QEventLoop::ExcludeSocketNotifiers - | QEventLoop::WaitForMoreEvents - | QEventLoop::X11ExcludeTimers); - QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(); - eventDispatcher->processEvents(flags); - - if (has_captured_event) { - waiting_for_data = false; - *event = captured_event; - qApp->setEventFilter(old_event_filter); - return true; - } - } while (started.msecsTo(now) < timeout); - - waiting_for_data = false; - qApp->setEventFilter(old_event_filter); - } else { - do { - if (XCheckTypedWindowEvent(X11->display,win,type,event)) - return true; - - // process other clipboard events, since someone is probably requesting data from us - XEvent e; - if (XCheckIfEvent(X11->display, &e, checkForClipboardEvents, 0)) - qApp->x11ProcessEvent(&e); - - now.start(); - - XFlush(X11->display); - - // sleep 50 ms, so we don't use up CPU cycles all the time. - struct timeval usleep_tv; - usleep_tv.tv_sec = 0; - usleep_tv.tv_usec = 50000; - select(0, 0, 0, 0, &usleep_tv); - } while (started.msecsTo(now) < timeout); - } - return false; -} - - -static inline int maxSelectionIncr(Display *dpy) -{ return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; } - -bool QX11Data::clipboardReadProperty(Window win, Atom property, bool deleteProperty, - QByteArray *buffer, int *size, Atom *type, int *format) -{ - int maxsize = maxSelectionIncr(display); - ulong bytes_left; // bytes_after - ulong length; // nitems - uchar *data; - Atom dummy_type; - int dummy_format; - int r; - - if (!type) // allow null args - type = &dummy_type; - if (!format) - format = &dummy_format; - - // Don't read anything, just get the size of the property data - r = XGetWindowProperty(display, win, property, 0, 0, False, - AnyPropertyType, type, format, - &length, &bytes_left, &data); - if (r != Success || (type && *type == XNone)) { - buffer->resize(0); - return false; - } - XFree((char*)data); - - int offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left; - - VDEBUG("QClipboard: read_property(): initial property length: %d", proplen); - - switch (*format) { - case 8: - default: - format_inc = sizeof(char) / 1; - break; - - case 16: - format_inc = sizeof(short) / 2; - proplen *= sizeof(short) / 2; - break; - - case 32: - format_inc = sizeof(long) / 4; - proplen *= sizeof(long) / 4; - break; - } - - int newSize = proplen; - buffer->resize(newSize); - - bool ok = (buffer->size() == newSize); - VDEBUG("QClipboard: read_property(): buffer resized to %d", buffer->size()); - - if (ok && newSize) { - // could allocate buffer - - while (bytes_left) { - // more to read... - - r = XGetWindowProperty(display, win, property, offset, maxsize/4, - False, AnyPropertyType, type, format, - &length, &bytes_left, &data); - if (r != Success || (type && *type == XNone)) - break; - - offset += length / (32 / *format); - length *= format_inc * (*format) / 8; - - // Here we check if we get a buffer overflow and tries to - // recover -- this shouldn't normally happen, but it doesn't - // hurt to be defensive - if ((int)(buffer_offset + length) > buffer->size()) { - length = buffer->size() - buffer_offset; - - // escape loop - bytes_left = 0; - } - - memcpy(buffer->data() + buffer_offset, data, length); - buffer_offset += length; - - XFree((char*)data); - } - - if (*format == 8 && *type == ATOM(COMPOUND_TEXT)) { - // convert COMPOUND_TEXT to a multibyte string - XTextProperty textprop; - textprop.encoding = *type; - textprop.format = *format; - textprop.nitems = buffer_offset; - textprop.value = (unsigned char *) buffer->data(); - - char **list_ret = 0; - int count; - if (XmbTextPropertyToTextList(display, &textprop, &list_ret, - &count) == Success && count && list_ret) { - offset = buffer_offset = strlen(list_ret[0]); - buffer->resize(offset); - memcpy(buffer->data(), list_ret[0], offset); - } - if (list_ret) XFreeStringList(list_ret); - } - } - - // correct size, not 0-term. - if (size) - *size = buffer_offset; - - VDEBUG("QClipboard: read_property(): buffer size %d, buffer offset %d, offset %d", - buffer->size(), buffer_offset, offset); - - if (deleteProperty) - XDeleteProperty(display, win, property); - - XFlush(display); - - return ok; -} - -QByteArray QX11Data::clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm) -{ - XEvent event; - - QByteArray buf; - QByteArray tmp_buf; - bool alloc_error = false; - int length; - int offset = 0; - - if (nbytes > 0) { - // Reserve buffer + zero-terminator (for text data) - // We want to complete the INCR transfer even if we cannot - // allocate more memory - buf.resize(nbytes+1); - alloc_error = buf.size() != nbytes+1; - } - - for (;;) { - XFlush(display); - if (!clipboardWaitForEvent(win,PropertyNotify,&event,clipboard_timeout)) - break; - if (event.xproperty.atom != property || - event.xproperty.state != PropertyNewValue) - continue; - if (X11->clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) { - if (length == 0) { // no more data, we're done - if (nullterm) { - buf.resize(offset+1); - buf[offset] = '\0'; - } else { - buf.resize(offset); - } - return buf; - } else if (!alloc_error) { - if (offset+length > (int)buf.size()) { - buf.resize(offset+length+65535); - if (buf.size() != offset+length+65535) { - alloc_error = true; - length = buf.size() - offset; - } - } - memcpy(buf.data()+offset, tmp_buf.constData(), length); - tmp_buf.resize(0); - offset += length; - } - } else { - break; - } - } - - // timed out ... create a new requestor window, otherwise the requestor - // could consider next request to be still part of this timed out request - delete requestor; - requestor = new QWidget(0); - requestor->setObjectName(QLatin1String("internal clipboard requestor")); - // We don't need this internal widget to appear in QApplication::topLevelWidgets() - if (QWidgetPrivate::allWidgets) - QWidgetPrivate::allWidgets->remove(requestor); - - return QByteArray(); -} - -static Atom send_targets_selection(QClipboardData *d, Window window, Atom property) -{ - QVector<Atom> types; - QStringList formats = QInternalMimeData::formatsHelper(d->source()); - for (int i = 0; i < formats.size(); ++i) { - QList<Atom> atoms = X11->xdndMimeAtomsForFormat(formats.at(i)); - for (int j = 0; j < atoms.size(); ++j) { - if (!types.contains(atoms.at(j))) - types.append(atoms.at(j)); - } - } - types.append(ATOM(TARGETS)); - types.append(ATOM(MULTIPLE)); - types.append(ATOM(TIMESTAMP)); - types.append(ATOM(SAVE_TARGETS)); - - XChangeProperty(X11->display, window, property, XA_ATOM, 32, - PropModeReplace, (uchar *) types.data(), types.size()); - return property; -} - -static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom property) -{ - Atom atomFormat = target; - int dataFormat = 0; - QByteArray data; - - QByteArray fmt = X11->xdndAtomToString(target); - if (fmt.isEmpty()) { // Not a MIME type we have - DEBUG("QClipboard: send_selection(): converting to type '%s' is not supported", fmt.data()); - return XNone; - } - DEBUG("QClipboard: send_selection(): converting to type '%s'", fmt.data()); - - if (X11->xdndMimeDataForAtom(target, d->source(), &data, &atomFormat, &dataFormat)) { - - VDEBUG("QClipboard: send_selection():\n" - " property type %lx\n" - " property name '%s'\n" - " format %d\n" - " %d bytes\n", - target, X11->xdndMimeAtomToString(atomFormat).toLatin1().data(), dataFormat, data.size()); - - // don't allow INCR transfers when using MULTIPLE or to - // Motif clients (since Motif doesn't support INCR) - static Atom motif_clip_temporary = ATOM(CLIP_TEMPORARY); - bool allow_incr = property != motif_clip_temporary; - - // X_ChangeProperty protocol request is 24 bytes - const int increment = (XMaxRequestSize(X11->display) * 4) - 24; - if (data.size() > increment && allow_incr) { - long bytes = data.size(); - XChangeProperty(X11->display, window, property, - ATOM(INCR), 32, PropModeReplace, (uchar *) &bytes, 1); - - (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment); - return property; - } - - // make sure we can perform the XChangeProperty in a single request - if (data.size() > increment) - return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend? - int dataSize = data.size() / (dataFormat / 8); - // use a single request to transfer data - XChangeProperty(X11->display, window, property, atomFormat, - dataFormat, PropModeReplace, (uchar *) data.data(), - dataSize); - } - return property; -} - -/*! \internal - Internal cleanup for Windows. -*/ -void QClipboard::ownerDestroyed() -{ } - - -/*! \internal - Internal optimization for Windows. -*/ -void QClipboard::connectNotify(const char *) -{ } - - -bool QClipboard::event(QEvent *e) -{ - if (e->type() == QEvent::Timer) { - QTimerEvent *te = (QTimerEvent *) e; - - if (waiting_for_data) // should never happen - return false; - - if (te->timerId() == timer_id) { - killTimer(timer_id); - timer_id = 0; - - timer_event_clear = true; - if (selection_watcher) // clear selection - selectionData()->clear(); - if (clipboard_watcher) // clear clipboard - clipboardData()->clear(); - timer_event_clear = false; - - return true; - } else if (te->timerId() == pending_timer_id) { - // I hate klipper - killTimer(pending_timer_id); - pending_timer_id = 0; - - if (pending_clipboard_changed) { - pending_clipboard_changed = false; - clipboardData()->clear(); - emitChanged(QClipboard::Clipboard); - } - if (pending_selection_changed) { - pending_selection_changed = false; - selectionData()->clear(); - emitChanged(QClipboard::Selection); - } - - return true; - } else if (te->timerId() == incr_timer_id) { - killTimer(incr_timer_id); - incr_timer_id = 0; - - qt_xclb_incr_timeout(); - - return true; - } else { - return QObject::event(e); - } - } else if (e->type() != QEvent::Clipboard) { - return QObject::event(e); - } - - XEvent *xevent = (XEvent *)(((QClipboardEvent *)e)->data()); - Display *dpy = X11->display; - - if (!xevent) { - // That means application exits and we need to give clipboard - // content to the clipboard manager. - // First we check if there is a clipboard manager. - if (XGetSelectionOwner(X11->display, ATOM(CLIPBOARD_MANAGER)) == XNone - || !owner) - return true; - - Window ownerId = owner->internalWinId(); - Q_ASSERT(ownerId); - // we delete the property so the manager saves all TARGETS. - XDeleteProperty(X11->display, ownerId, ATOM(_QT_SELECTION)); - XConvertSelection(X11->display, ATOM(CLIPBOARD_MANAGER), ATOM(SAVE_TARGETS), - ATOM(_QT_SELECTION), ownerId, X11->time); - XSync(dpy, false); - - XEvent event; - // waiting until the clipboard manager fetches the content. - if (!X11->clipboardWaitForEvent(ownerId, SelectionNotify, &event, 10000)) { - qWarning("QClipboard: Unable to receive an event from the " - "clipboard manager in a reasonable time"); - } - - return true; - } - - switch (xevent->type) { - - case SelectionClear: - // new selection owner - if (xevent->xselectionclear.selection == XA_PRIMARY) { - QClipboardData *d = selectionData(); - - // ignore the event if it was generated before we gained selection ownership - if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp) - break; - - DEBUG("QClipboard: new selection owner 0x%lx at time %lx (ours %lx)", - XGetSelectionOwner(dpy, XA_PRIMARY), - xevent->xselectionclear.time, d->timestamp); - - if (! waiting_for_data) { - d->clear(); - emitChanged(QClipboard::Selection); - } else { - pending_selection_changed = true; - if (! pending_timer_id) - pending_timer_id = QApplication::clipboard()->startTimer(0); - } - } else if (xevent->xselectionclear.selection == ATOM(CLIPBOARD)) { - QClipboardData *d = clipboardData(); - - // ignore the event if it was generated before we gained selection ownership - if (d->timestamp != CurrentTime && xevent->xselectionclear.time <= d->timestamp) - break; - - DEBUG("QClipboard: new clipboard owner 0x%lx at time %lx (%lx)", - XGetSelectionOwner(dpy, ATOM(CLIPBOARD)), - xevent->xselectionclear.time, d->timestamp); - - if (! waiting_for_data) { - d->clear(); - emitChanged(QClipboard::Clipboard); - } else { - pending_clipboard_changed = true; - if (! pending_timer_id) - pending_timer_id = QApplication::clipboard()->startTimer(0); - } - } else { - qWarning("QClipboard: Unknown SelectionClear event received"); - return false; - } - break; - - case SelectionNotify: - /* - Something has delivered data to us, but this was not caught - by QClipboardWatcher::getDataInFormat() - - Just skip the event to prevent Bad Things (tm) from - happening later on... - */ - break; - - case SelectionRequest: - { - // someone wants our data - XSelectionRequestEvent *req = &xevent->xselectionrequest; - - if (requestor && req->requestor == requestor->internalWinId()) - break; - - XEvent event; - event.xselection.type = SelectionNotify; - event.xselection.display = req->display; - event.xselection.requestor = req->requestor; - event.xselection.selection = req->selection; - event.xselection.target = req->target; - event.xselection.property = XNone; - event.xselection.time = req->time; - - DEBUG("QClipboard: SelectionRequest from %lx\n" - " selection 0x%lx (%s) target 0x%lx (%s)", - req->requestor, - req->selection, - X11->xdndAtomToString(req->selection).data(), - req->target, - X11->xdndAtomToString(req->target).data()); - - QClipboardData *d; - if (req->selection == XA_PRIMARY) { - d = selectionData(); - } else if (req->selection == ATOM(CLIPBOARD)) { - d = clipboardData(); - } else { - qWarning("QClipboard: Unknown selection '%lx'", req->selection); - XSendEvent(dpy, req->requestor, False, NoEventMask, &event); - break; - } - - if (! d->source()) { - qWarning("QClipboard: Cannot transfer data, no data available"); - XSendEvent(dpy, req->requestor, False, NoEventMask, &event); - break; - } - - DEBUG("QClipboard: SelectionRequest at time %lx (ours %lx)", - req->time, d->timestamp); - - if (d->timestamp == CurrentTime // we don't own the selection anymore - || (req->time != CurrentTime && req->time < d->timestamp)) { - DEBUG("QClipboard: SelectionRequest too old"); - XSendEvent(dpy, req->requestor, False, NoEventMask, &event); - break; - } - - Atom xa_targets = ATOM(TARGETS); - Atom xa_multiple = ATOM(MULTIPLE); - Atom xa_timestamp = ATOM(TIMESTAMP); - - struct AtomPair { Atom target; Atom property; } *multi = 0; - Atom multi_type = XNone; - int multi_format = 0; - int nmulti = 0; - int imulti = -1; - bool multi_writeback = false; - - if (req->target == xa_multiple) { - QByteArray multi_data; - if (req->property == XNone - || !X11->clipboardReadProperty(req->requestor, req->property, false, &multi_data, - 0, &multi_type, &multi_format) - || multi_format != 32) { - // MULTIPLE property not formatted correctly - XSendEvent(dpy, req->requestor, False, NoEventMask, &event); - break; - } - nmulti = multi_data.size()/sizeof(*multi); - multi = new AtomPair[nmulti]; - memcpy(multi,multi_data.data(),multi_data.size()); - imulti = 0; - } - - for (; imulti < nmulti; ++imulti) { - Atom target; - Atom property; - - if (multi) { - target = multi[imulti].target; - property = multi[imulti].property; - } else { - target = req->target; - property = req->property; - if (property == XNone) // obsolete client - property = target; - } - - Atom ret = XNone; - if (target == XNone || property == XNone) { - ; - } else if (target == xa_timestamp) { - if (d->timestamp != CurrentTime) { - XChangeProperty(dpy, req->requestor, property, XA_INTEGER, 32, - PropModeReplace, (uchar *) &d->timestamp, 1); - ret = property; - } else { - qWarning("QClipboard: Invalid data timestamp"); - } - } else if (target == xa_targets) { - ret = send_targets_selection(d, req->requestor, property); - } else { - ret = send_selection(d, target, req->requestor, property); - } - - if (nmulti > 0) { - if (ret == XNone) { - multi[imulti].property = XNone; - multi_writeback = true; - } - } else { - event.xselection.property = ret; - break; - } - } - - if (nmulti > 0) { - if (multi_writeback) { - // according to ICCCM 2.6.2 says to put None back - // into the original property on the requestor window - XChangeProperty(dpy, req->requestor, req->property, multi_type, 32, - PropModeReplace, (uchar *) multi, nmulti * 2); - } - - delete [] multi; - event.xselection.property = req->property; - } - - // send selection notify to requestor - XSendEvent(dpy, req->requestor, False, NoEventMask, &event); - - DEBUG("QClipboard: SelectionNotify to 0x%lx\n" - " property 0x%lx (%s)", - req->requestor, event.xselection.property, - X11->xdndAtomToString(event.xselection.property).data()); - } - break; - } - - return true; -} - - - - - - -QClipboardWatcher::QClipboardWatcher(QClipboard::Mode mode) - : QInternalMimeData() -{ - switch (mode) { - case QClipboard::Selection: - atom = XA_PRIMARY; - break; - - case QClipboard::Clipboard: - atom = ATOM(CLIPBOARD); - break; - - default: - qWarning("QClipboardWatcher: Internal error: Unsupported clipboard mode"); - break; - } - - setupOwner(); -} - -QClipboardWatcher::~QClipboardWatcher() -{ - if(selection_watcher == this) - selection_watcher = 0; - if(clipboard_watcher == this) - clipboard_watcher = 0; -} - -bool QClipboardWatcher::empty() const -{ - Display *dpy = X11->display; - Window win = XGetSelectionOwner(dpy, atom); - - if(win == requestor->internalWinId()) { - qWarning("QClipboardWatcher::empty: Internal error: Application owns the selection"); - return true; - } - - return win == XNone; -} - -QStringList QClipboardWatcher::formats_sys() const -{ - if (empty()) - return QStringList(); - - if (!formatList.count()) { - // get the list of targets from the current clipboard owner - we do this - // once so that multiple calls to this function don't require multiple - // server round trips... - - format_atoms = getDataInFormat(ATOM(TARGETS)); - - if (format_atoms.size() > 0) { - Atom *targets = (Atom *) format_atoms.data(); - int size = format_atoms.size() / sizeof(Atom); - - for (int i = 0; i < size; ++i) { - if (targets[i] == 0) - continue; - - QStringList formatsForAtom = X11->xdndMimeFormatsForAtom(targets[i]); - for (int j = 0; j < formatsForAtom.size(); ++j) { - if (!formatList.contains(formatsForAtom.at(j))) - formatList.append(formatsForAtom.at(j)); - } - VDEBUG(" format: %s", X11->xdndAtomToString(targets[i]).data()); - VDEBUG(" data:\n%s\n", getDataInFormat(targets[i]).data()); - } - DEBUG("QClipboardWatcher::format: %d formats available", formatList.count()); - } - } - - return formatList; -} - -bool QClipboardWatcher::hasFormat_sys(const QString &format) const -{ - QStringList list = formats(); - return list.contains(format); -} - -QVariant QClipboardWatcher::retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const -{ - if (fmt.isEmpty() || empty()) - return QByteArray(); - - (void)formats(); // trigger update of format list - DEBUG("QClipboardWatcher::data: fetching format '%s'", fmt.toLatin1().data()); - - QList<Atom> atoms; - Atom *targets = (Atom *) format_atoms.data(); - int size = format_atoms.size() / sizeof(Atom); - for (int i = 0; i < size; ++i) - atoms.append(targets[i]); - - QByteArray encoding; - Atom fmtatom = X11->xdndMimeAtomForFormat(fmt, requestedType, atoms, &encoding); - - if (fmtatom == 0) - return QVariant(); - - return X11->xdndMimeConvertToFormat(fmtatom, getDataInFormat(fmtatom), fmt, requestedType, encoding); -} - -QByteArray QClipboardWatcher::getDataInFormat(Atom fmtatom) const -{ - QByteArray buf; - - Display *dpy = X11->display; - requestor->createWinId(); - Window win = requestor->internalWinId(); - Q_ASSERT(requestor->testAttribute(Qt::WA_WState_Created)); - - DEBUG("QClipboardWatcher::getDataInFormat: selection '%s' format '%s'", - X11->xdndAtomToString(atom).data(), X11->xdndAtomToString(fmtatom).data()); - - XSelectInput(dpy, win, NoEventMask); // don't listen for any events - - XDeleteProperty(dpy, win, ATOM(_QT_SELECTION)); - XConvertSelection(dpy, atom, fmtatom, ATOM(_QT_SELECTION), win, X11->time); - XSync(dpy, false); - - VDEBUG("QClipboardWatcher::getDataInFormat: waiting for SelectionNotify event"); - - XEvent xevent; - if (!X11->clipboardWaitForEvent(win,SelectionNotify,&xevent,clipboard_timeout) || - xevent.xselection.property == XNone) { - DEBUG("QClipboardWatcher::getDataInFormat: format not available"); - return buf; - } - - VDEBUG("QClipboardWatcher::getDataInFormat: fetching data..."); - - Atom type; - XSelectInput(dpy, win, PropertyChangeMask); - - if (X11->clipboardReadProperty(win, ATOM(_QT_SELECTION), true, &buf, 0, &type, 0)) { - if (type == ATOM(INCR)) { - int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0; - buf = X11->clipboardReadIncrementalProperty(win, ATOM(_QT_SELECTION), nbytes, false); - } - } - - XSelectInput(dpy, win, NoEventMask); - - DEBUG("QClipboardWatcher::getDataInFormat: %d bytes received", buf.size()); - - return buf; -} - - -const QMimeData* QClipboard::mimeData(Mode mode) const -{ - QClipboardData *d = 0; - switch (mode) { - case Selection: - d = selectionData(); - break; - case Clipboard: - d = clipboardData(); - break; - default: - qWarning("QClipboard::mimeData: unsupported mode '%d'", mode); - return 0; - } - - if (! d->source() && ! timer_event_clear) { - if (mode == Selection) { - if (! selection_watcher) - selection_watcher = new QClipboardWatcher(mode); - d->setSource(selection_watcher); - } else { - if (! clipboard_watcher) - clipboard_watcher = new QClipboardWatcher(mode); - d->setSource(clipboard_watcher); - } - - if (! timer_id) { - // start a zero timer - we will clear cached data when the timer - // times out, which will be the next time we hit the event loop... - // that way, the data is cached long enough for calls within a single - // loop/function, but the data doesn't linger around in case the selection - // changes - QClipboard *that = ((QClipboard *) this); - timer_id = that->startTimer(0); - } - } - - return d->source(); -} - - -void QClipboard::setMimeData(QMimeData* src, Mode mode) -{ - Atom atom, sentinel_atom; - QClipboardData *d; - switch (mode) { - case Selection: - atom = XA_PRIMARY; - sentinel_atom = ATOM(_QT_SELECTION_SENTINEL); - d = selectionData(); - break; - - case Clipboard: - atom = ATOM(CLIPBOARD); - sentinel_atom = ATOM(_QT_CLIPBOARD_SENTINEL); - d = clipboardData(); - break; - - default: - qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode); - return; - } - - Display *dpy = X11->display; - Window newOwner; - - if (! src) { // no data, clear clipboard contents - newOwner = XNone; - d->clear(); - } else { - setupOwner(); - - newOwner = owner->internalWinId(); - - d->setSource(src); - d->timestamp = X11->time; - } - - Window prevOwner = XGetSelectionOwner(dpy, atom); - // use X11->time, since d->timestamp == CurrentTime when clearing - XSetSelectionOwner(dpy, atom, newOwner, X11->time); - - if (mode == Selection) - emitChanged(QClipboard::Selection); - else - emitChanged(QClipboard::Clipboard); - - if (XGetSelectionOwner(dpy, atom) != newOwner) { - qWarning("QClipboard::setData: Cannot set X11 selection owner for %s", - X11->xdndAtomToString(atom).data()); - d->clear(); - return; - } - - // Signal to other Qt processes that the selection has changed - Window owners[2]; - owners[0] = newOwner; - owners[1] = prevOwner; - XChangeProperty(dpy, QApplication::desktop()->screen(0)->internalWinId(), - sentinel_atom, XA_WINDOW, 32, PropModeReplace, - (unsigned char*)&owners, 2); -} - - -/* - Called by the main event loop in qapplication_x11.cpp when either - the _QT_SELECTION_SENTINEL property has been changed (i.e. when some - Qt process has performed QClipboard::setData()) or when Xfixes told - us that an other application changed the selection. If it returns - true, the QClipBoard dataChanged() signal should be emitted. -*/ - -bool qt_check_selection_sentinel() -{ - bool doIt = true; - if (owner && !X11->use_xfixes) { - /* - Since the X selection mechanism cannot give any signal when - the selection has changed, we emulate it (for Qt processes) here. - The notification should be ignored in case of either - a) This is the process that did setData (because setData() - then has already emitted dataChanged()) - b) This is the process that owned the selection when dataChanged() - was called (because we have then received a SelectionClear event, - and have already emitted dataChanged() as a result of that) - */ - - unsigned char *retval; - Atom actualType; - int actualFormat; - ulong nitems; - ulong bytesLeft; - - if (XGetWindowProperty(X11->display, - QApplication::desktop()->screen(0)->internalWinId(), - ATOM(_QT_SELECTION_SENTINEL), 0, 2, False, XA_WINDOW, - &actualType, &actualFormat, &nitems, - &bytesLeft, &retval) == Success) { - Window *owners = (Window *)retval; - if (actualType == XA_WINDOW && actualFormat == 32 && nitems == 2) { - Window win = owner->internalWinId(); - if (owners[0] == win || owners[1] == win) - doIt = false; - } - - XFree(owners); - } - } - - if (doIt) { - if (waiting_for_data) { - pending_selection_changed = true; - if (! pending_timer_id) - pending_timer_id = QApplication::clipboard()->startTimer(0); - doIt = false; - } else { - selectionData()->clear(); - } - } - - return doIt; -} - - -bool qt_check_clipboard_sentinel() -{ - bool doIt = true; - if (owner && !X11->use_xfixes) { - unsigned char *retval; - Atom actualType; - int actualFormat; - unsigned long nitems, bytesLeft; - - if (XGetWindowProperty(X11->display, - QApplication::desktop()->screen(0)->internalWinId(), - ATOM(_QT_CLIPBOARD_SENTINEL), 0, 2, False, XA_WINDOW, - &actualType, &actualFormat, &nitems, &bytesLeft, - &retval) == Success) { - Window *owners = (Window *)retval; - if (actualType == XA_WINDOW && actualFormat == 32 && nitems == 2) { - Window win = owner->internalWinId(); - if (owners[0] == win || owners[1] == win) - doIt = false; - } - - XFree(owners); - } - } - - if (doIt) { - if (waiting_for_data) { - pending_clipboard_changed = true; - if (! pending_timer_id) - pending_timer_id = QApplication::clipboard()->startTimer(0); - doIt = false; - } else { - clipboardData()->clear(); - } - } - - return doIt; -} - -bool qt_xfixes_selection_changed(Window selectionOwner, Time timestamp) -{ - QClipboardData *d = selectionData(); -#ifdef QCLIPBOARD_DEBUG - DEBUG("qt_xfixes_selection_changed: owner = %u; selectionOwner = %u; internal timestamp = %u; external timestamp = %u", - (unsigned int)(owner ? (int)owner->internalWinId() : 0), (unsigned int)selectionOwner, - (unsigned int)(d ? d->timestamp : 0), (unsigned int)timestamp); -#endif - if (!owner || (selectionOwner && selectionOwner != owner->internalWinId()) || - (!selectionOwner && (d->timestamp == CurrentTime || d->timestamp < timestamp))) - return qt_check_selection_sentinel(); - return false; -} - -bool qt_xfixes_clipboard_changed(Window clipboardOwner, Time timestamp) -{ - QClipboardData *d = clipboardData(); -#ifdef QCLIPBOARD_DEBUG - DEBUG("qt_xfixes_clipboard_changed: owner = %u; clipboardOwner = %u; internal timestamp = %u; external timestamp = %u", - (unsigned int)(owner ? (int)owner->internalWinId() : 0), (unsigned int)clipboardOwner, - (unsigned int)(d ? d->timestamp : 0), (unsigned int)timestamp); -#endif - if (!owner || (clipboardOwner && clipboardOwner != owner->internalWinId()) || - (!clipboardOwner && (d->timestamp == CurrentTime || d->timestamp < timestamp))) - return qt_check_clipboard_sentinel(); - return false; -} - -QT_END_NAMESPACE - -#endif // QT_NO_CLIPBOARD diff --git a/src/widgets/platforms/x11/qcolormap_x11.cpp b/src/widgets/platforms/x11/qcolormap_x11.cpp deleted file mode 100644 index 1d6d7b8adb..0000000000 --- a/src/widgets/platforms/x11/qcolormap_x11.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qcolormap.h" - -#include "qapplication.h" -#include "qdebug.h" -#include "qdesktopwidget.h" -#include "qvarlengtharray.h" - -#include "qx11info_x11.h" -#include <private/qt_x11_p.h> -#include <limits.h> - -QT_BEGIN_NAMESPACE - -class QColormapPrivate -{ -public: - QColormapPrivate() - : ref(1), mode(QColormap::Direct), depth(0), - colormap(0), defaultColormap(true), - visual(0), defaultVisual(true), - r_max(0), g_max(0), b_max(0), - r_shift(0), g_shift(0), b_shift(0) - {} - - QAtomicInt ref; - - QColormap::Mode mode; - int depth; - - Colormap colormap; - bool defaultColormap; - - Visual *visual; - bool defaultVisual; - - int r_max; - int g_max; - int b_max; - - uint r_shift; - uint g_shift; - uint b_shift; - - QVector<QColor> colors; - QVector<int> pixels; -}; - - -static uint right_align(uint v) -{ - while (!(v & 0x1)) - v >>= 1; - return v; -} - -static int lowest_bit(uint v) -{ - int i; - uint b = 1u; - for (i = 0; ((v & b) == 0u) && i < 32; ++i) - b <<= 1u; - return i == 32 ? -1 : i; -} - -static int cube_root(int v) -{ - if (v == 1) - return 1; - // brute force algorithm - int i = 1; - for (;;) { - const int b = i * i * i; - if (b <= v) { - ++i; - } else { - --i; - break; - } - } - return i; -} - -static Visual *find_visual(Display *display, - int screen, - int visual_class, - int visual_id, - int *depth, - bool *defaultVisual) -{ - XVisualInfo *vi, rvi; - int count; - - uint mask = VisualScreenMask; - rvi.screen = screen; - - if (visual_class != -1) { - rvi.c_class = visual_class; - mask |= VisualClassMask; - } - if (visual_id != -1) { - rvi.visualid = visual_id; - mask |= VisualIDMask; - } - - Visual *visual = DefaultVisual(display, screen); - *defaultVisual = true; - *depth = DefaultDepth(display, screen); - - vi = XGetVisualInfo(display, mask, &rvi, &count); - if (vi) { - int best = 0; - for (int x = 0; x < count; ++x) { - if (vi[x].depth > vi[best].depth) - best = x; - } - if (best >= 0 && best <= count && vi[best].visualid != XVisualIDFromVisual(visual)) { - visual = vi[best].visual; - *defaultVisual = (visual == DefaultVisual(display, screen)); - *depth = vi[best].depth; - } - } - if (vi) - XFree((char *)vi); - return visual; -} - -static void query_colormap(QColormapPrivate *d, int screen) -{ - Display *display = QX11Info::display(); - - // query existing colormap - int q_colors = (((1u << d->depth) > 256u) ? 256u : (1u << d->depth)); - XColor queried[256]; - memset(queried, 0, sizeof(queried)); - for (int x = 0; x < q_colors; ++x) - queried[x].pixel = x; - XQueryColors(display, d->colormap, queried, q_colors); - - d->colors.resize(q_colors); - for (int x = 0; x < q_colors; ++x) { - if (queried[x].red == 0 - && queried[x].green == 0 - && queried[x].blue == 0 - && queried[x].pixel != BlackPixel(display, screen)) { - // unallocated color cell, skip it - continue; - } - - d->colors[x] = QColor::fromRgbF(queried[x].red / float(USHRT_MAX), - queried[x].green / float(USHRT_MAX), - queried[x].blue / float(USHRT_MAX)); - } - - // for missing colors, find the closest color in the existing colormap - Q_ASSERT(d->pixels.size()); - for (int x = 0; x < d->pixels.size(); ++x) { - if (d->pixels.at(x) != -1) - continue; - - QRgb rgb; - if (d->mode == QColormap::Indexed) { - const int r = (x / (d->g_max * d->b_max)) % d->r_max; - const int g = (x / d->b_max) % d->g_max; - const int b = x % d->b_max; - rgb = qRgb((r * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1), - (g * 0xff + (d->g_max - 1) / 2) / (d->g_max - 1), - (b * 0xff + (d->b_max - 1) / 2) / (d->b_max - 1)); - } else { - rgb = qRgb(x, x, x); - } - - // find closest color - int mindist = INT_MAX, best = -1; - for (int y = 0; y < q_colors; ++y) { - int r = qRed(rgb) - (queried[y].red >> 8); - int g = qGreen(rgb) - (queried[y].green >> 8); - int b = qBlue(rgb) - (queried[y].blue >> 8); - int dist = (r * r) + (g * g) + (b * b); - if (dist < mindist) { - mindist = dist; - best = y; - } - } - - Q_ASSERT(best >= 0 && best < q_colors); - if (d->visual->c_class & 1) { - XColor xcolor; - xcolor.red = queried[best].red; - xcolor.green = queried[best].green; - xcolor.blue = queried[best].blue; - xcolor.pixel = queried[best].pixel; - - if (XAllocColor(display, d->colormap, &xcolor)) { - d->pixels[x] = xcolor.pixel; - } else { - // some weird stuff is going on... - d->pixels[x] = (qGray(rgb) < 127 - ? BlackPixel(display, screen) - : WhitePixel(display, screen)); - } - } else { - d->pixels[x] = best; - } - } -} - -static void init_gray(QColormapPrivate *d, int screen) -{ - d->pixels.resize(d->r_max); - - for (int g = 0; g < d->g_max; ++g) { - const int gray = (g * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1); - const QRgb rgb = qRgb(gray, gray, gray); - - d->pixels[g] = -1; - - if (d->visual->c_class & 1) { - XColor xcolor; - xcolor.red = qRed(rgb) * 0x101; - xcolor.green = qGreen(rgb) * 0x101; - xcolor.blue = qBlue(rgb) * 0x101; - xcolor.pixel = 0ul; - - if (XAllocColor(QX11Info::display(), d->colormap, &xcolor)) - d->pixels[g] = xcolor.pixel; - } - } - - query_colormap(d, screen); -} - -static void init_indexed(QColormapPrivate *d, int screen) -{ - d->pixels.resize(d->r_max * d->g_max * d->b_max); - - // create color cube - for (int x = 0, r = 0; r < d->r_max; ++r) { - for (int g = 0; g < d->g_max; ++g) { - for (int b = 0; b < d->b_max; ++b, ++x) { - const QRgb rgb = qRgb((r * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1), - (g * 0xff + (d->g_max - 1) / 2) / (d->g_max - 1), - (b * 0xff + (d->b_max - 1) / 2) / (d->b_max - 1)); - - d->pixels[x] = -1; - - if (d->visual->c_class & 1) { - XColor xcolor; - xcolor.red = qRed(rgb) * 0x101; - xcolor.green = qGreen(rgb) * 0x101; - xcolor.blue = qBlue(rgb) * 0x101; - xcolor.pixel = 0ul; - - if (XAllocColor(QX11Info::display(), d->colormap, &xcolor)) - d->pixels[x] = xcolor.pixel; - } - } - } - } - - query_colormap(d, screen); -} - -static void init_direct(QColormapPrivate *d, bool ownColormap) -{ - if (d->visual->c_class != DirectColor || !ownColormap) - return; - - // preallocate 768 on the stack, so that we don't have to malloc - // for the common case (<= 24 bpp) - QVarLengthArray<XColor, 768> colorTable(d->r_max + d->g_max + d->b_max); - int i = 0; - - for (int r = 0; r < d->r_max; ++r) { - colorTable[i].red = r << 8 | r; - colorTable[i].pixel = r << d->r_shift; - colorTable[i].flags = DoRed; - ++i; - } - - for (int g = 0; g < d->g_max; ++g) { - colorTable[i].green = g << 8 | g; - colorTable[i].pixel = g << d->g_shift; - colorTable[i].flags = DoGreen; - ++i; - } - - for (int b = 0; b < d->b_max; ++b) { - colorTable[i].blue = (b << 8 | b); - colorTable[i].pixel = b << d->b_shift; - colorTable[i].flags = DoBlue; - ++i; - } - - XStoreColors(X11->display, d->colormap, colorTable.data(), colorTable.count()); -} - -static QColormap **cmaps = 0; - -void QColormap::initialize() -{ - Display *display = QX11Info::display(); - const int screens = ScreenCount(display); - - cmaps = new QColormap*[screens]; - - for (int i = 0; i < screens; ++i) { - cmaps[i] = new QColormap; - QColormapPrivate * const d = cmaps[i]->d; - - bool use_stdcmap = false; - int color_count = X11->color_count; - - // defaults - d->depth = DefaultDepth(display, i); - d->colormap = DefaultColormap(display, i); - d->defaultColormap = true; - d->visual = DefaultVisual(display, i); - d->defaultVisual = true; - - Visual *argbVisual = 0; - - if (X11->visual && i == DefaultScreen(display)) { - // only use the outside colormap on the default screen - d->visual = find_visual(display, i, X11->visual->c_class, - XVisualIDFromVisual(X11->visual), - &d->depth, &d->defaultVisual); - } else if ((X11->visual_class != -1 && X11->visual_class >= 0 && X11->visual_class < 6) - || (X11->visual_id != -1)) { - // look for a specific visual or type of visual - d->visual = find_visual(display, i, X11->visual_class, X11->visual_id, - &d->depth, &d->defaultVisual); - } else if (QApplication::colorSpec() == QApplication::ManyColor) { - // look for a TrueColor w/ a depth higher than 8bpp - d->visual = find_visual(display, i, TrueColor, -1, &d->depth, &d->defaultVisual); - if (d->depth <= 8) { - d->visual = DefaultVisual(display, i); - d->defaultVisual = true; - color_count = 216; - } - } else if (!X11->custom_cmap) { - XStandardColormap *stdcmap = 0; - int ncmaps = 0; - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - int nvi; - XVisualInfo templ; - templ.screen = i; - templ.depth = 32; - templ.c_class = TrueColor; - XVisualInfo *xvi = XGetVisualInfo(X11->display, VisualScreenMask | - VisualDepthMask | - VisualClassMask, &templ, &nvi); - for (int idx = 0; idx < nvi; ++idx) { - XRenderPictFormat *format = XRenderFindVisualFormat(X11->display, - xvi[idx].visual); - if (format->type == PictTypeDirect && format->direct.alphaMask) { - argbVisual = xvi[idx].visual; - break; - } - } - XFree(xvi); - } -#endif - if (XGetRGBColormaps(display, RootWindow(display, i), - &stdcmap, &ncmaps, XA_RGB_DEFAULT_MAP)) { - if (stdcmap) { - for (int c = 0; c < ncmaps; ++c) { - if (!stdcmap[c].red_max || - !stdcmap[c].green_max || - !stdcmap[c].blue_max || - !stdcmap[c].red_mult || - !stdcmap[c].green_mult || - !stdcmap[c].blue_mult) - continue; // invalid stdcmap - - XVisualInfo proto; - proto.visualid = stdcmap[c].visualid; - proto.screen = i; - - int nvisuals = 0; - XVisualInfo *vi = XGetVisualInfo(display, VisualIDMask | VisualScreenMask, - &proto, &nvisuals); - if (vi) { - if (nvisuals > 0) { - use_stdcmap = true; - - d->mode = ((vi[0].visual->c_class < StaticColor) - ? Gray - : ((vi[0].visual->c_class < TrueColor) - ? Indexed - : Direct)); - - d->depth = vi[0].depth; - d->colormap = stdcmap[c].colormap; - d->defaultColormap = true; - d->visual = vi[0].visual; - d->defaultVisual = (d->visual == DefaultVisual(display, i)); - - d->r_max = stdcmap[c].red_max + 1; - d->g_max = stdcmap[c].green_max + 1; - d->b_max = stdcmap[c].blue_max + 1; - - if (d->mode == Direct) { - // calculate offsets - d->r_shift = lowest_bit(d->visual->red_mask); - d->g_shift = lowest_bit(d->visual->green_mask); - d->b_shift = lowest_bit(d->visual->blue_mask); - } else { - d->r_shift = 0; - d->g_shift = 0; - d->b_shift = 0; - } - } - XFree(vi); - } - break; - } - XFree(stdcmap); - } - } - } - if (!use_stdcmap) { - switch (d->visual->c_class) { - case StaticGray: - d->mode = Gray; - - d->r_max = d->g_max = d->b_max = d->visual->map_entries; - break; - - case XGrayScale: - d->mode = Gray; - - // follow precedent set in libXmu... - if (color_count != 0) - d->r_max = d->g_max = d->b_max = color_count; - else if (d->visual->map_entries > 65000) - d->r_max = d->g_max = d->b_max = 4096; - else if (d->visual->map_entries > 4000) - d->r_max = d->g_max = d->b_max = 512; - else if (d->visual->map_entries > 250) - d->r_max = d->g_max = d->b_max = 12; - else - d->r_max = d->g_max = d->b_max = 4; - break; - - case StaticColor: - d->mode = Indexed; - - d->r_max = right_align(d->visual->red_mask) + 1; - d->g_max = right_align(d->visual->green_mask) + 1; - d->b_max = right_align(d->visual->blue_mask) + 1; - break; - - case PseudoColor: - d->mode = Indexed; - - // follow precedent set in libXmu... - if (color_count != 0) - d->r_max = d->g_max = d->b_max = cube_root(color_count); - else if (d->visual->map_entries > 65000) - d->r_max = d->g_max = d->b_max = 27; - else if (d->visual->map_entries > 4000) - d->r_max = d->g_max = d->b_max = 12; - else if (d->visual->map_entries > 250) - d->r_max = d->g_max = d->b_max = cube_root(d->visual->map_entries - 125); - else - d->r_max = d->g_max = d->b_max = cube_root(d->visual->map_entries); - break; - - case TrueColor: - case DirectColor: - d->mode = Direct; - - d->r_max = right_align(d->visual->red_mask) + 1; - d->g_max = right_align(d->visual->green_mask) + 1; - d->b_max = right_align(d->visual->blue_mask) + 1; - - d->r_shift = lowest_bit(d->visual->red_mask); - d->g_shift = lowest_bit(d->visual->green_mask); - d->b_shift = lowest_bit(d->visual->blue_mask); - break; - } - } - - bool ownColormap = false; - if (X11->colormap && i == DefaultScreen(display)) { - // only use the outside colormap on the default screen - d->colormap = X11->colormap; - d->defaultColormap = (d->colormap == DefaultColormap(display, i)); - } else if ((!use_stdcmap - && (((d->visual->c_class & 1) && X11->custom_cmap) - || d->visual != DefaultVisual(display, i))) - || d->visual->c_class == DirectColor) { - // allocate custom colormap (we always do this when using DirectColor visuals) - d->colormap = - XCreateColormap(display, RootWindow(display, i), d->visual, - d->visual->c_class == DirectColor ? AllocAll : AllocNone); - d->defaultColormap = false; - ownColormap = true; - } - - switch (d->mode) { - case Gray: - init_gray(d, i); - break; - case Indexed: - init_indexed(d, i); - break; - case Direct: - init_direct(d, ownColormap); - break; - } - - QX11InfoData *screen = X11->screens + i; - screen->depth = d->depth; - screen->visual = d->visual; - screen->defaultVisual = d->defaultVisual; - screen->colormap = d->colormap; - screen->defaultColormap = d->defaultColormap; - screen->cells = screen->visual->map_entries; - - if (argbVisual) { - X11->argbVisuals[i] = argbVisual; - X11->argbColormaps[i] = XCreateColormap(display, RootWindow(display, i), argbVisual, AllocNone); - } - - // ### - // We assume that 8bpp == pseudocolor, but this is not - // always the case (according to the X server), so we need - // to make sure that our internal data is setup in a way - // that is compatible with our assumptions - if (screen->visual->c_class == TrueColor && screen->depth == 8 && screen->cells == 8) - screen->cells = 256; - } -} - -void QColormap::cleanup() -{ - Display *display = QX11Info::display(); - const int screens = ScreenCount(display); - - for (int i = 0; i < screens; ++i) - delete cmaps[i]; - - delete [] cmaps; - cmaps = 0; -} - - -QColormap QColormap::instance(int screen) -{ - if (screen == -1) - screen = QX11Info::appScreen(); - return *cmaps[screen]; -} - -/*! \internal - Constructs a new colormap. -*/ -QColormap::QColormap() - : d(new QColormapPrivate) -{} - -QColormap::QColormap(const QColormap &colormap) - :d (colormap.d) -{ d->ref.ref(); } - -QColormap::~QColormap() -{ - if (!d->ref.deref()) { - if (!d->defaultColormap) - XFreeColormap(QX11Info::display(), d->colormap); - delete d; - } -} - -QColormap::Mode QColormap::mode() const -{ return d->mode; } - -int QColormap::depth() const -{ return d->depth; } - -int QColormap::size() const -{ - return (d->mode == Gray - ? d->r_max - : (d->mode == Indexed - ? d->r_max * d->g_max * d->b_max - : -1)); -} - -uint QColormap::pixel(const QColor &color) const -{ - const QColor c = color.toRgb(); - const uint r = (c.ct.argb.red * d->r_max) >> 16; - const uint g = (c.ct.argb.green * d->g_max) >> 16; - const uint b = (c.ct.argb.blue * d->b_max) >> 16; - if (d->mode != Direct) { - if (d->mode == Gray) - return d->pixels.at((r * 30 + g * 59 + b * 11) / 100); - return d->pixels.at(r * d->g_max * d->b_max + g * d->b_max + b); - } - return (r << d->r_shift) + (g << d->g_shift) + (b << d->b_shift); -} - -const QColor QColormap::colorAt(uint pixel) const -{ - if (d->mode != Direct) { - Q_ASSERT(pixel <= (uint)d->colors.size()); - return d->colors.at(pixel); - } - - const int r = (((pixel & d->visual->red_mask) >> d->r_shift) << 8) / d->r_max; - const int g = (((pixel & d->visual->green_mask) >> d->g_shift) << 8) / d->g_max; - const int b = (((pixel & d->visual->blue_mask) >> d->b_shift) << 8) / d->b_max; - return QColor(r, g, b); -} - -const QVector<QColor> QColormap::colormap() const -{ return d->colors; } - -QColormap &QColormap::operator=(const QColormap &colormap) -{ - qAtomicAssign(d, colormap.d); - return *this; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qcursor_x11.cpp b/src/widgets/platforms/x11/qcursor_x11.cpp deleted file mode 100644 index 1132d3737d..0000000000 --- a/src/widgets/platforms/x11/qcursor_x11.cpp +++ /dev/null @@ -1,640 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qdebug.h> -#include <qdatastream.h> -#include <private/qcursor_p.h> -#include <private/qt_x11_p.h> -#include <private/qapplication_p.h> -#include <qbitmap.h> -#include <qcursor.h> -#include <X11/cursorfont.h> - -#include <qlibrary.h> - -#ifndef QT_NO_XCURSOR -# include <X11/Xcursor/Xcursor.h> -#endif // QT_NO_XCURSOR - -#ifndef QT_NO_XFIXES -#ifndef Status -#define Status int -#endif -# include <X11/extensions/Xfixes.h> -#endif // QT_NO_XFIXES - -#include "qx11info_x11.h" -#include <private/qpixmap_x11_p.h> - -QT_BEGIN_NAMESPACE - -// Define QT_USE_APPROXIMATE_CURSORS when compiling if you REALLY want to -// use the ugly X11 cursors. - -/***************************************************************************** - Internal QCursorData class - *****************************************************************************/ - -QCursorData::QCursorData(Qt::CursorShape s) - : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(0), pm(0), pmm(0) -{ - ref = 1; -} - -QCursorData::~QCursorData() -{ - Display *dpy = X11 ? X11->display : (Display*)0; - - // Add in checking for the display too as on HP-UX - // we seem to get a core dump as the cursor data is - // deleted again from main() on exit... - if (hcurs && dpy) - XFreeCursor(dpy, hcurs); - if (pm && dpy) - XFreePixmap(dpy, pm); - if (pmm && dpy) - XFreePixmap(dpy, pmm); - delete bm; - delete bmm; -} - -#ifndef QT_NO_CURSOR -QCursor::QCursor(Qt::HANDLE cursor) -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - d = new QCursorData(Qt::CustomCursor); - d->hcurs = cursor; -} - -#endif - -QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { - qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); - QCursorData *c = qt_cursorTable[0]; - c->ref.ref(); - return c; - } - QCursorData *d = new QCursorData; - d->ref = 1; - - extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp - d->bm = new QBitmap(qt_toX11Pixmap(bitmap)); - d->bmm = new QBitmap(qt_toX11Pixmap(mask)); - - d->hcurs = 0; - d->cshape = Qt::BitmapCursor; - d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; - d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; - d->fg.red = 0x0000; - d->fg.green = 0x0000; - d->fg.blue = 0x0000; - d->bg.red = 0xffff; - d->bg.green = 0xffff; - d->bg.blue = 0xffff; - return d; -} - - - -#ifndef QT_NO_CURSOR -Qt::HANDLE QCursor::handle() const -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (!d->hcurs) - d->update(); - return d->hcurs; -} -#endif - -QPoint QCursor::pos() -{ - Window root; - Window child; - int root_x, root_y, win_x, win_y; - uint buttons; - Display* dpy = X11->display; - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y, - &win_x, &win_y, &buttons)) - - return QPoint(root_x, root_y); - } - return QPoint(); -} - -/*! \internal -*/ -#ifndef QT_NO_CURSOR -int QCursor::x11Screen() -{ - Window root; - Window child; - int root_x, root_y, win_x, win_y; - uint buttons; - Display* dpy = X11->display; - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (XQueryPointer(dpy, QX11Info::appRootWindow(i), &root, &child, &root_x, &root_y, - &win_x, &win_y, &buttons)) - return i; - } - return -1; -} -#endif - -void QCursor::setPos(int x, int y) -{ - QPoint current, target(x, y); - - // this is copied from pos(), since we need the screen number for the correct - // root window in the XWarpPointer call - Window root; - Window child; - int root_x, root_y, win_x, win_y; - uint buttons; - Display* dpy = X11->display; - int screen; - for (screen = 0; screen < ScreenCount(dpy); ++screen) { - if (XQueryPointer(dpy, QX11Info::appRootWindow(screen), &root, &child, &root_x, &root_y, - &win_x, &win_y, &buttons)) { - current = QPoint(root_x, root_y); - break; - } - } - - if (screen >= ScreenCount(dpy)) - return; - - // Need to check, since some X servers generate null mouse move - // events, causing looping in applications which call setPos() on - // every mouse move event. - // - if (current == target) - return; - - XWarpPointer(X11->display, XNone, QX11Info::appRootWindow(screen), 0, 0, 0, 0, x, y); -} - - -/*! - \internal - - Creates the cursor. -*/ - -void QCursorData::update() -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (hcurs) - return; - - Display *dpy = X11->display; - Window rootwin = QX11Info::appRootWindow(); - - if (cshape == Qt::BitmapCursor) { - extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp -#ifndef QT_NO_XRENDER - if (!pixmap.isNull() && X11->use_xrender) { - pixmap = qt_toX11Pixmap(pixmap); - hcurs = XRenderCreateCursor (X11->display, pixmap.x11PictureHandle(), hx, hy); - } else -#endif - { - hcurs = XCreatePixmapCursor(dpy, bm->handle(), bmm->handle(), &fg, &bg, hx, hy); - } - return; - } - - static const char *cursorNames[] = { - "left_ptr", - "up_arrow", - "cross", - "wait", - "ibeam", - "size_ver", - "size_hor", - "size_bdiag", - "size_fdiag", - "size_all", - "blank", - "split_v", - "split_h", - "pointing_hand", - "forbidden", - "whats_this", - "left_ptr_watch", - "openhand", - "closedhand", - "copy", - "move", - "link" - }; - -#ifndef QT_NO_XCURSOR - if (X11->ptrXcursorLibraryLoadCursor) { - // special case for non-standard dnd-* cursors - switch (cshape) { - case Qt::DragCopyCursor: - hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-copy"); - break; - case Qt::DragMoveCursor: - hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-move"); - break; - case Qt::DragLinkCursor: - hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, "dnd-link"); - break; - default: - break; - } - if (!hcurs) - hcurs = X11->ptrXcursorLibraryLoadCursor(dpy, cursorNames[cshape]); - } - if (hcurs) - return; -#endif // QT_NO_XCURSOR - - static const uchar cur_blank_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - // Non-standard X11 cursors are created from bitmaps - -#ifndef QT_USE_APPROXIMATE_CURSORS - static const uchar cur_ver_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f, - 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 }; - static const uchar mcur_ver_bits[] = { - 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f, - 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f, - 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 }; - static const uchar cur_hor_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18, - 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar mcur_hor_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c, - 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c, - 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 }; - static const uchar cur_bdiag_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e, - 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00, - 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar mcur_bdiag_bits[] = { - 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f, - 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01, - 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 }; - static const uchar cur_fdiag_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, - 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c, - 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 }; - static const uchar mcur_fdiag_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, - 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e, - 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 }; - static const uchar *cursor_bits16[] = { - cur_ver_bits, mcur_ver_bits, cur_hor_bits, mcur_hor_bits, - cur_bdiag_bits, mcur_bdiag_bits, cur_fdiag_bits, mcur_fdiag_bits, - 0, 0, cur_blank_bits, cur_blank_bits }; - - static const uchar vsplit_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, - 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar vsplitm_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, - 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, - 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, - 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, - 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, - 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, - 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar hsplit_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, - 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, - 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03, - 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00, - 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, - 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar hsplitm_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, - 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00, - 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, - 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00, - 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, - 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const uchar whatsthis_bits[] = { - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00, - 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00, - 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00, - 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00, - 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00, - 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - static const uchar whatsthism_bits[] = { - 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00, - 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00, - 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00, - 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00, - 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00, - 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; - static const uchar busy_bits[] = { - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, - 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00, - 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00, - 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00, - 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00, - 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00, - 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - static const uchar busym_bits[] = { - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00, - 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00, - 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00, - 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00, - 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00, - 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - static const uchar * const cursor_bits32[] = { - vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits, - 0, 0, 0, 0, whatsthis_bits, whatsthism_bits, busy_bits, busym_bits - }; - - static const uchar forbidden_bits[] = { - 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01, - 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06, - 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03, - 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 }; - - static const uchar forbiddenm_bits[] = { - 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03, - 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f, - 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07, - 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00}; - - static const uchar openhand_bits[] = { - 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92, - 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20, - 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00}; - static const uchar openhandm_bits[] = { - 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff, - 0xf6,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f, - 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00}; - static const uchar closedhand_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50, - 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10, - 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00}; - static const uchar closedhandm_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f, - 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f, - 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00}; - - static const uchar * const cursor_bits20[] = { - forbidden_bits, forbiddenm_bits - }; - - if ((cshape >= Qt::SizeVerCursor && cshape < Qt::SizeAllCursor) - || cshape == Qt::BlankCursor) { - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - int i = (cshape - Qt::SizeVerCursor) * 2; - pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i]), 16, 16); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char*>(cursor_bits16[i + 1]), 16, 16); - hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8); - } else if ((cshape >= Qt::SplitVCursor && cshape <= Qt::SplitHCursor) - || cshape == Qt::WhatsThisCursor || cshape == Qt::BusyCursor) { - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - int i = (cshape - Qt::SplitVCursor) * 2; - pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i]), 32, 32); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits32[i + 1]), 32, 32); - int hs = (cshape == Qt::PointingHandCursor || cshape == Qt::WhatsThisCursor - || cshape == Qt::BusyCursor) ? 0 : 16; - hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, hs, hs); - } else if (cshape == Qt::ForbiddenCursor) { - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - int i = (cshape - Qt::ForbiddenCursor) * 2; - pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i]), 20, 20); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(cursor_bits20[i + 1]), 20, 20); - hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 10, 10); - } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) { - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - bool open = cshape == Qt::OpenHandCursor; - pm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhand_bits : closedhand_bits), 16, 16); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast<const char *>(open ? openhandm_bits : closedhandm_bits), 16, 16); - hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8); - } else if (cshape == Qt::DragCopyCursor || cshape == Qt::DragMoveCursor - || cshape == Qt::DragLinkCursor) { - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - QImage image = QApplicationPrivate::instance()->getPixmapCursor(cshape).toImage(); - pm = QX11PlatformPixmap::createBitmapFromImage(image); - pmm = QX11PlatformPixmap::createBitmapFromImage(image.createAlphaMask().convertToFormat(QImage::Format_MonoLSB)); - hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8); - } - - if (hcurs) - { -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && X11->ptrXFixesSetCursorName) - X11->ptrXFixesSetCursorName(dpy, hcurs, cursorNames[cshape]); -#endif /* ! QT_NO_XFIXES */ - return; - } - -#endif /* ! QT_USE_APPROXIMATE_CURSORS */ - - uint sh; - switch (cshape) { // map Q cursor to X cursor - case Qt::ArrowCursor: - sh = XC_left_ptr; - break; - case Qt::UpArrowCursor: - sh = XC_center_ptr; - break; - case Qt::CrossCursor: - sh = XC_crosshair; - break; - case Qt::WaitCursor: - sh = XC_watch; - break; - case Qt::IBeamCursor: - sh = XC_xterm; - break; - case Qt::SizeAllCursor: - sh = XC_fleur; - break; - case Qt::PointingHandCursor: - sh = XC_hand2; - break; -#ifdef QT_USE_APPROXIMATE_CURSORS - case Qt::SizeBDiagCursor: - sh = XC_top_right_corner; - break; - case Qt::SizeFDiagCursor: - sh = XC_bottom_right_corner; - break; - case Qt::BlankCursor: - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - pm = XCreateBitmapFromData(dpy, rootwin, cur_blank_bits, 16, 16); - pmm = XCreateBitmapFromData(dpy, rootwin, cur_blank_bits, 16, 16); - hcurs = XCreatePixmapCursor(dpy, pm, pmm, &fg, &bg, 8, 8); - return; - break; - case Qt::SizeVerCursor: - case Qt::SplitVCursor: - sh = XC_sb_v_double_arrow; - break; - case Qt::SizeHorCursor: - case Qt::SplitHCursor: - sh = XC_sb_h_double_arrow; - break; - case Qt::WhatsThisCursor: - sh = XC_question_arrow; - break; - case Qt::ForbiddenCursor: - sh = XC_circle; - break; - case Qt::BusyCursor: - sh = XC_watch; - break; - case Qt::DragCopyCursor: - sh = XC_tcross; - break; - case Qt::DragLinkCursor: - sh = XC_center_ptr; - break; - case Qt::DragMoveCursor: - sh = XC_top_left_arrow; - break; -#endif /* QT_USE_APPROXIMATE_CURSORS */ - default: - qWarning("QCursor::update: Invalid cursor shape %d", cshape); - return; - } - hcurs = XCreateFontCursor(dpy, sh); - -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && X11->ptrXFixesSetCursorName) - X11->ptrXFixesSetCursorName(dpy, hcurs, cursorNames[cshape]); -#endif /* ! QT_NO_XFIXES */ -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qdesktopwidget_x11.cpp b/src/widgets/platforms/x11/qdesktopwidget_x11.cpp deleted file mode 100644 index 52d3be18e9..0000000000 --- a/src/widgets/platforms/x11/qdesktopwidget_x11.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" -#include "qdesktopwidget.h" -#include "qlibrary.h" -#include "qt_x11_p.h" -#include "qvariant.h" -#include "qwidget_p.h" -#include "qx11info_x11.h" -#include <limits.h> - -QT_BEGIN_NAMESPACE - -// defined in qwidget_x11.cpp -extern int qt_x11_create_desktop_on_screen; - - -// function to update the workarea of the screen -static bool qt_desktopwidget_workarea_dirty = true; -void qt_desktopwidget_update_workarea() -{ - qt_desktopwidget_workarea_dirty = true; -} - - -class QSingleDesktopWidget : public QWidget -{ -public: - QSingleDesktopWidget(); - ~QSingleDesktopWidget(); -}; - -QSingleDesktopWidget::QSingleDesktopWidget() - : QWidget(0, Qt::Desktop) -{ -} - -QSingleDesktopWidget::~QSingleDesktopWidget() -{ - const QObjectList &childList = children(); - for (int i = childList.size(); i > 0 ;) { - --i; - childList.at(i)->setParent(0); - } -} - - -class QDesktopWidgetPrivate : public QWidgetPrivate -{ -public: - QDesktopWidgetPrivate(); - ~QDesktopWidgetPrivate(); - - void init(); - - bool use_xinerama; - int defaultScreen; - int screenCount; - - QWidget **screens; - QRect *rects; - QRect *workareas; -}; - -QDesktopWidgetPrivate::QDesktopWidgetPrivate() - : use_xinerama(false), defaultScreen(0), screenCount(1), - screens(0), rects(0), workareas(0) -{ -} - -QDesktopWidgetPrivate::~QDesktopWidgetPrivate() -{ - if (screens) { - for (int i = 0; i < screenCount; ++i) { - if (i == defaultScreen) continue; - delete screens[i]; - screens[i] = 0; - } - - free (screens); - } - - if (rects) delete [] rects; - if (workareas) delete [] workareas; -} - -void QDesktopWidgetPrivate::init() -{ - // get the screen count - int newScreenCount = ScreenCount(X11->display); -#ifndef QT_NO_XINERAMA - - XineramaScreenInfo *xinerama_screeninfo = 0; - - // we ignore the Xinerama extension when using the display is - // using traditional multi-screen (with multiple root windows) - if (newScreenCount == 1 - && X11->ptrXineramaQueryExtension - && X11->ptrXineramaIsActive - && X11->ptrXineramaQueryScreens) { - int unused; - use_xinerama = (X11->ptrXineramaQueryExtension(X11->display, &unused, &unused) - && X11->ptrXineramaIsActive(X11->display)); - } - - if (use_xinerama) { - xinerama_screeninfo = - X11->ptrXineramaQueryScreens(X11->display, &newScreenCount); - } - - if (xinerama_screeninfo) { - defaultScreen = 0; - } else -#endif // QT_NO_XINERAMA - { - defaultScreen = DefaultScreen(X11->display); - newScreenCount = ScreenCount(X11->display); - use_xinerama = false; - } - - delete [] rects; - rects = new QRect[newScreenCount]; - delete [] workareas; - workareas = new QRect[newScreenCount]; - - // get the geometry of each screen - int i, j, x, y, w, h; - for (i = 0, j = 0; i < newScreenCount; i++, j++) { - -#ifndef QT_NO_XINERAMA - if (use_xinerama) { - x = xinerama_screeninfo[i].x_org; - y = xinerama_screeninfo[i].y_org; - w = xinerama_screeninfo[i].width; - h = xinerama_screeninfo[i].height; - } else -#endif // QT_NO_XINERAMA - { - x = 0; - y = 0; - w = WidthOfScreen(ScreenOfDisplay(X11->display, i)); - h = HeightOfScreen(ScreenOfDisplay(X11->display, i)); - } - - rects[j].setRect(x, y, w, h); - - if (use_xinerama && j > 0 && rects[j-1].intersects(rects[j])) { - // merge a "cloned" screen with the previous, hiding all crtcs - // that are currently showing a sub-rect of the previous screen - if ((rects[j].width()*rects[j].height()) > - (rects[j-1].width()*rects[j-1].height())) - rects[j-1] = rects[j]; - j--; - } - - workareas[i] = QRect(); - } - - if (screens) { - // leaks QWidget* pointers on purpose, can't delete them as pointer escapes - screens = q_check_ptr((QWidget**) realloc(screens, j * sizeof(QWidget*))); - if (j > screenCount) - memset(&screens[screenCount], 0, (j-screenCount) * sizeof(QWidget*)); - } - - screenCount = j; - -#ifndef QT_NO_XINERAMA - if (use_xinerama && screenCount == 1) - use_xinerama = false; - - if (xinerama_screeninfo) - XFree(xinerama_screeninfo); -#endif // QT_NO_XINERAMA - -} - -// the QDesktopWidget itself will be created on the default screen -// as qt_x11_create_desktop_on_screen defaults to -1 -QDesktopWidget::QDesktopWidget() - : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) -{ - Q_D(QDesktopWidget); - d->init(); -} - -QDesktopWidget::~QDesktopWidget() -{ -} - -bool QDesktopWidget::isVirtualDesktop() const -{ - Q_D(const QDesktopWidget); - return d->use_xinerama; -} - -int QDesktopWidget::primaryScreen() const -{ - Q_D(const QDesktopWidget); - return d->defaultScreen; -} - -int QDesktopWidget::numScreens() const -{ - Q_D(const QDesktopWidget); - return d->screenCount; -} - -QWidget *QDesktopWidget::screen(int screen) -{ - Q_D(QDesktopWidget); - if (d->use_xinerama) - return this; - - if (screen < 0 || screen >= d->screenCount) - screen = d->defaultScreen; - - if (! d->screens) { - d->screens = (QWidget**) calloc( d->screenCount, sizeof(QWidget*)); - d->screens[d->defaultScreen] = this; - } - - if (! d->screens[screen] || // not created yet - ! (d->screens[screen]->windowType() == Qt::Desktop)) { // reparented away - qt_x11_create_desktop_on_screen = screen; - d->screens[screen] = new QSingleDesktopWidget; - qt_x11_create_desktop_on_screen = -1; - } - - return d->screens[screen]; -} - -const QRect QDesktopWidget::availableGeometry(int screen) const -{ - Q_D(const QDesktopWidget); - if (qt_desktopwidget_workarea_dirty) { - // the workareas are dirty, invalidate them - for (int i = 0; i < d->screenCount; ++i) - d->workareas[i] = QRect(); - qt_desktopwidget_workarea_dirty = false; - } - - if (screen < 0 || screen >= d->screenCount) - screen = d->defaultScreen; - - if (d->workareas[screen].isValid()) - return d->workareas[screen]; - - if (X11->isSupportedByWM(ATOM(_NET_WORKAREA))) { - int x11Screen = isVirtualDesktop() ? DefaultScreen(X11->display) : screen; - - Atom ret; - int format, e; - unsigned char *data = 0; - unsigned long nitems, after; - - e = XGetWindowProperty(X11->display, - QX11Info::appRootWindow(x11Screen), - ATOM(_NET_WORKAREA), 0, 4, False, XA_CARDINAL, - &ret, &format, &nitems, &after, &data); - - QRect workArea; - if (e == Success && ret == XA_CARDINAL && - format == 32 && nitems == 4) { - long *workarea = (long *) data; - workArea = QRect(workarea[0], workarea[1], workarea[2], workarea[3]); - } else { - workArea = screenGeometry(screen); - } - - if (isVirtualDesktop()) { - // intersect the workarea (which spawns all Xinerama screens) with the rect for the - // requested screen - workArea &= screenGeometry(screen); - } - - d->workareas[screen] = workArea; - - if (data) - XFree(data); - } else { - d->workareas[screen] = screenGeometry(screen); - } - - return d->workareas[screen]; -} - -const QRect QDesktopWidget::screenGeometry(int screen) const -{ - Q_D(const QDesktopWidget); - if (screen < 0 || screen >= d->screenCount) - screen = d->defaultScreen; - - return d->rects[screen]; -} - -int QDesktopWidget::screenNumber(const QWidget *widget) const -{ - Q_D(const QDesktopWidget); - if (!widget) - return d->defaultScreen; - -#ifndef QT_NO_XINERAMA - if (d->use_xinerama) { - // this is how we do it for xinerama - QRect frame = widget->frameGeometry(); - if (!widget->isWindow()) - frame.moveTopLeft(widget->mapToGlobal(QPoint(0, 0))); - - int maxSize = -1; - int maxScreen = -1; - - for (int i = 0; i < d->screenCount; ++i) { - QRect sect = d->rects[i].intersected(frame); - int size = sect.width() * sect.height(); - if (size > maxSize && sect.width() > 0 && sect.height() > 0) { - maxSize = size; - maxScreen = i; - } - } - return maxScreen; - } -#endif // QT_NO_XINERAMA - - return widget->x11Info().screen(); -} - -int QDesktopWidget::screenNumber(const QPoint &point) const -{ - Q_D(const QDesktopWidget); - int closestScreen = -1; - int shortestDistance = INT_MAX; - for (int i = 0; i < d->screenCount; ++i) { - int thisDistance = d->pointToRect(point, d->rects[i]); - if (thisDistance < shortestDistance) { - shortestDistance = thisDistance; - closestScreen = i; - } - } - return closestScreen; -} - -void QDesktopWidget::resizeEvent(QResizeEvent *event) -{ - Q_D(QDesktopWidget); - int oldScreenCount = d->screenCount; - QVector<QRect> oldRects(oldScreenCount); - for (int i = 0; i < oldScreenCount; ++i) { - oldRects[i] = d->rects[i]; - } - - d->init(); - - for (int i = 0; i < qMin(oldScreenCount, d->screenCount); ++i) { - if (oldRects.at(i) != d->rects[i]) - emit resized(i); - } - - if (oldScreenCount != d->screenCount) { - emit screenCountChanged(d->screenCount); - } - - qt_desktopwidget_workarea_dirty = true; - QWidget::resizeEvent(event); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qdnd_x11.cpp b/src/widgets/platforms/x11/qdnd_x11.cpp deleted file mode 100644 index 2718853920..0000000000 --- a/src/widgets/platforms/x11/qdnd_x11.cpp +++ /dev/null @@ -1,2072 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" - -#include "qapplication.h" - -#ifndef QT_NO_DRAGANDDROP - -#include "qwidget.h" -#include "qpainter.h" -#include "qpixmap.h" -#include "qbitmap.h" -#include "qdesktopwidget.h" -#include "qevent.h" -#include "qiodevice.h" -#include "qpointer.h" -#include "qcursor.h" -#include "qelapsedtimer.h" -#include "qvariant.h" -#include "qvector.h" -#include "qurl.h" -#include "qdebug.h" -#include "qimagewriter.h" -#include "qbuffer.h" -#include "qtextcodec.h" - -#include "qdnd_p.h" -#include "qapplication_p.h" -#include "qt_x11_p.h" -#include "qx11info_x11.h" - -#include "qwidget_p.h" -#include "qcursor_p.h" - -QT_BEGIN_NAMESPACE - -// #define DND_DEBUG -#ifdef DND_DEBUG -#define DEBUG qDebug -#else -#define DEBUG if(0) qDebug -#endif - -#ifdef DND_DEBUG -#define DNDDEBUG qDebug() -#else -#define DNDDEBUG if(0) qDebug() -#endif - -static int findXdndDropTransactionByWindow(Window window) -{ - int at = -1; - for (int i = 0; i < X11->dndDropTransactions.count(); ++i) { - const QXdndDropTransaction &t = X11->dndDropTransactions.at(i); - if (t.target == window || t.proxy_target == window) { - at = i; - break; - } - } - return at; -} - -static int findXdndDropTransactionByTime(Time timestamp) -{ - int at = -1; - for (int i = 0; i < X11->dndDropTransactions.count(); ++i) { - const QXdndDropTransaction &t = X11->dndDropTransactions.at(i); - if (t.timestamp == timestamp) { - at = i; - break; - } - } - return at; -} - -// timer used to discard old XdndDrop transactions -static int transaction_expiry_timer = -1; -enum { XdndDropTransactionTimeout = 5000 }; // 5 seconds - -static void restartXdndDropExpiryTimer() -{ - if (transaction_expiry_timer != -1) - QDragManager::self()->killTimer(transaction_expiry_timer); - transaction_expiry_timer = QDragManager::self()->startTimer(XdndDropTransactionTimeout); -} - - -// find an ancestor with XdndAware on it -static Window findXdndAwareParent(Window window) -{ - Window target = 0; - forever { - // check if window has XdndAware - Atom type = 0; - int f; - unsigned long n, a; - unsigned char *data = 0; - if (XGetWindowProperty(X11->display, window, ATOM(XdndAware), 0, 0, False, - AnyPropertyType, &type, &f,&n,&a,&data) == Success) { - if (data) - XFree(data); - if (type) { - target = window; - break; - } - } - - // try window's parent - Window root; - Window parent; - Window *children; - uint unused; - if (!XQueryTree(X11->display, window, &root, &parent, &children, &unused)) - break; - if (children) - XFree(children); - if (window == root) - break; - window = parent; - } - return target; -} - - - - -// and all this stuff is copied -into- qapp_x11.cpp - -static void handle_xdnd_position(QWidget *, const XEvent *, bool); -static void handle_xdnd_status(QWidget * w, const XEvent * xe, bool /*passive*/); - -const int xdnd_version = 5; - -static Qt::DropAction xdndaction_to_qtaction(Atom atom) -{ - if (atom == ATOM(XdndActionCopy) || atom == 0) - return Qt::CopyAction; - if (atom == ATOM(XdndActionLink)) - return Qt::LinkAction; - if (atom == ATOM(XdndActionMove)) - return Qt::MoveAction; - return Qt::CopyAction; -} - -static int qtaction_to_xdndaction(Qt::DropAction a) -{ - switch (a) { - case Qt::CopyAction: - return ATOM(XdndActionCopy); - case Qt::LinkAction: - return ATOM(XdndActionLink); - case Qt::MoveAction: - case Qt::TargetMoveAction: - return ATOM(XdndActionMove); - case Qt::IgnoreAction: - return XNone; - default: - return ATOM(XdndActionCopy); - } -} - -// clean up the stuff used. -static void qt_xdnd_cleanup(); - -static void qt_xdnd_send_leave(); - -// real variables: -// xid of current drag source -static Atom qt_xdnd_dragsource_xid = 0; - -// the types in this drop. 100 is no good, but at least it's big. -const int qt_xdnd_max_type = 100; -static Atom qt_xdnd_types[qt_xdnd_max_type + 1]; - -// timer used when target wants "continuous" move messages (eg. scroll) -static int heartbeat = -1; -// rectangle in which the answer will be the same -static QRect qt_xdnd_source_sameanswer; -// top-level window we sent position to last. -static Window qt_xdnd_current_target; -// window to send events to (always valid if qt_xdnd_current_target) -static Window qt_xdnd_current_proxy_target; -static Time qt_xdnd_source_current_time; - -// widget we forwarded position to last, and local position -static QPointer<QWidget> qt_xdnd_current_widget; -static QPoint qt_xdnd_current_position; -// timestamp from the XdndPosition and XdndDrop -static Time qt_xdnd_target_current_time; -// screen number containing the pointer... -1 means default -static int qt_xdnd_current_screen = -1; -// state of dragging... true if dragging, false if not -bool qt_xdnd_dragging = false; - -static bool waiting_for_status = false; - -// used to preset each new QDragMoveEvent -static Qt::DropAction last_target_accepted_action = Qt::IgnoreAction; - -// Shift/Ctrl handling, and final drop status -static Qt::DropAction global_accepted_action = Qt::CopyAction; -static Qt::DropActions possible_actions = Qt::IgnoreAction; - -// for embedding only -static QWidget* current_embedding_widget = 0; -static XEvent last_enter_event; - -// cursors -static QCursor *noDropCursor = 0; -static QCursor *moveCursor = 0; -static QCursor *copyCursor = 0; -static QCursor *linkCursor = 0; - -static QPixmap *defaultPm = 0; - -static const int default_pm_hotx = -2; -static const int default_pm_hoty = -16; -static const char* const default_pm[] = { -"13 9 3 1", -". c None", -" c #000000", -"X c #FFFFFF", -"X X X X X X X", -" X X X X X X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X X X X X X ", -"X X X X X X X" -}; - -class QShapedPixmapWidget : public QWidget -{ - Q_OBJECT -public: - QShapedPixmapWidget(QWidget* w) : - QWidget(w, - Qt::Tool | Qt::FramelessWindowHint - | Qt::X11BypassWindowManagerHint - | Qt::BypassGraphicsProxyWidget) - { - setAttribute(Qt::WA_X11NetWmWindowTypeDND); - } - - void setPixmap(const QPixmap &pm) - { - QBitmap mask = pm.mask(); - if (!mask.isNull()) { - setMask(mask); - } else { - clearMask(); - } - resize(pm.width(),pm.height()); - pixmap = pm; - update(); - } - QPoint pm_hot; - -protected: - QPixmap pixmap; - void paintEvent(QPaintEvent*) - { - QPainter p(this); - p.drawPixmap(0, 0, pixmap); - } -}; - -#include "qdnd_x11.moc" - -struct XdndData { - QShapedPixmapWidget *deco; - QWidget* desktop_proxy; -}; - -static XdndData xdnd_data = { 0, 0 }; - -class QExtraWidget : public QWidget -{ - Q_DECLARE_PRIVATE(QWidget) -public: - inline QWExtra* extraData(); - inline QTLWExtra* topData(); -}; - -inline QWExtra* QExtraWidget::extraData() { return d_func()->extraData(); } -inline QTLWExtra* QExtraWidget::topData() { return d_func()->topData(); } - - -static WId xdndProxy(WId w) -{ - Atom type = XNone; - int f; - unsigned long n, a; - unsigned char *retval = 0; - XGetWindowProperty(X11->display, w, ATOM(XdndProxy), 0, 1, False, - XA_WINDOW, &type, &f,&n,&a,&retval); - WId *proxy_id_ptr = (WId *)retval; - WId proxy_id = 0; - if (type == XA_WINDOW && proxy_id_ptr) { - proxy_id = *proxy_id_ptr; - XFree(proxy_id_ptr); - proxy_id_ptr = 0; - // Already exists. Real? - X11->ignoreBadwindow(); - XGetWindowProperty(X11->display, proxy_id, ATOM(XdndProxy), 0, 1, False, - XA_WINDOW, &type, &f,&n,&a,&retval); - proxy_id_ptr = (WId *)retval; - if (X11->badwindow() || type != XA_WINDOW || !proxy_id_ptr || *proxy_id_ptr != proxy_id) - // Bogus - we will overwrite. - proxy_id = 0; - } - if (proxy_id_ptr) - XFree(proxy_id_ptr); - return proxy_id; -} - -static bool xdndEnable(QWidget* w, bool on) -{ - DNDDEBUG << "xdndEnable" << w << on; - if (on) { - QWidget * xdnd_widget = 0; - if ((w->windowType() == Qt::Desktop)) { - if (xdnd_data.desktop_proxy) // *WE* already have one. - return false; - - // As per Xdnd4, use XdndProxy - XGrabServer(X11->display); - Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); - WId proxy_id = xdndProxy(w->effectiveWinId()); - - if (!proxy_id) { - xdnd_widget = xdnd_data.desktop_proxy = new QWidget; - proxy_id = xdnd_data.desktop_proxy->effectiveWinId(); - XChangeProperty (X11->display, w->effectiveWinId(), ATOM(XdndProxy), - XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1); - XChangeProperty (X11->display, proxy_id, ATOM(XdndProxy), - XA_WINDOW, 32, PropModeReplace, (unsigned char *)&proxy_id, 1); - } - - XUngrabServer(X11->display); - } else { - xdnd_widget = w->window(); - } - if (xdnd_widget) { - DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->effectiveWinId(); - Atom atm = (Atom)xdnd_version; - Q_ASSERT(xdnd_widget->testAttribute(Qt::WA_WState_Created)); - XChangeProperty(X11->display, xdnd_widget->effectiveWinId(), ATOM(XdndAware), - XA_ATOM, 32, PropModeReplace, (unsigned char *)&atm, 1); - return true; - } else { - return false; - } - } else { - if ((w->windowType() == Qt::Desktop)) { - XDeleteProperty(X11->display, w->internalWinId(), ATOM(XdndProxy)); - delete xdnd_data.desktop_proxy; - xdnd_data.desktop_proxy = 0; - } else { - DNDDEBUG << "not deleting XDndAware"; - } - return true; - } -} - -QByteArray QX11Data::xdndAtomToString(Atom a) -{ - if (!a) return 0; - - if (a == XA_STRING || a == ATOM(UTF8_STRING)) { - return "text/plain"; // some Xdnd clients are dumb - } - char *atom = XGetAtomName(display, a); - QByteArray result = atom; - XFree(atom); - return result; -} - -Atom QX11Data::xdndStringToAtom(const char *mimeType) -{ - if (!mimeType || !*mimeType) - return 0; - return XInternAtom(display, mimeType, False); -} - -//$$$ -QString QX11Data::xdndMimeAtomToString(Atom a) -{ - QString atomName; - if (a) { - char *atom = XGetAtomName(display, a); - atomName = QString::fromLatin1(atom); - XFree(atom); - } - return atomName; -} - -//$$$ -Atom QX11Data::xdndMimeStringToAtom(const QString &mimeType) -{ - if (mimeType.isEmpty()) - return 0; - return XInternAtom(display, mimeType.toLatin1().constData(), False); -} - -//$$$ replace ccxdndAtomToString() -QStringList QX11Data::xdndMimeFormatsForAtom(Atom a) -{ - QStringList formats; - if (a) { - QString atomName = xdndMimeAtomToString(a); - formats.append(atomName); - - // special cases for string type - if (a == ATOM(UTF8_STRING) || a == XA_STRING - || a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT)) - formats.append(QLatin1String("text/plain")); - - // special cases for uris - if (atomName == QLatin1String("text/x-moz-url")) - formats.append(QLatin1String("text/uri-list")); - - // special case for images - if (a == XA_PIXMAP) - formats.append(QLatin1String("image/ppm")); - } - return formats; -} - -//$$$ -bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat) -{ - bool ret = false; - *atomFormat = a; - *dataFormat = 8; - QString atomName = xdndMimeAtomToString(a); - if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) { - *data = QInternalMimeData::renderDataHelper(atomName, mimeData); - if (atomName == QLatin1String("application/x-color")) - *dataFormat = 16; - ret = true; - } else { - if ((a == ATOM(UTF8_STRING) || a == XA_STRING - || a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT)) - && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) { - if (a == ATOM(UTF8_STRING)){ - *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData); - ret = true; - } else if (a == XA_STRING) { - *data = QString::fromUtf8(QInternalMimeData::renderDataHelper( - QLatin1String("text/plain"), mimeData)).toLocal8Bit(); - ret = true; - } else if (a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT)) { - // the ICCCM states that TEXT and COMPOUND_TEXT are in the - // encoding of choice, so we choose the encoding of the locale - QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper( - QLatin1String("text/plain"), mimeData)).toLocal8Bit(); - char *list[] = { strData.data(), NULL }; - - XICCEncodingStyle style = (a == ATOM(COMPOUND_TEXT)) - ? XCompoundTextStyle : XStdICCTextStyle; - XTextProperty textprop; - if (list[0] != NULL - && XmbTextListToTextProperty(X11->display, list, 1, style, - &textprop) == Success) { - *atomFormat = textprop.encoding; - *dataFormat = textprop.format; - *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8); - ret = true; - - DEBUG(" textprop type %lx\n" - " textprop name '%s'\n" - " format %d\n" - " %ld items\n" - " %d bytes\n", - textprop.encoding, - X11->xdndMimeAtomToString(textprop.encoding).toLatin1().data(), - textprop.format, textprop.nitems, data->size()); - - XFree(textprop.value); - } - } - } else if (atomName == QLatin1String("text/x-moz-url") && - QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) { - QByteArray uri = QInternalMimeData::renderDataHelper( - QLatin1String("text/uri-list"), mimeData).split('\n').first(); - QString mozUri = QString::fromLatin1(uri, uri.size()); - mozUri += QLatin1Char('\n'); - *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2); - ret = true; - } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) { - QPixmap pm = qvariant_cast<QPixmap>(mimeData->imageData()); - if (a == XA_BITMAP && pm.depth() != 1) { - QImage img = pm.toImage(); - img = img.convertToFormat(QImage::Format_MonoLSB); - pm = QPixmap::fromImage(img); - } - QDragManager *dm = QDragManager::self(); - if (dm) { - Pixmap handle = pm.handle(); - *data = QByteArray((const char *) &handle, sizeof(Pixmap)); - dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm; - dm->xdndMimeTransferedPixmapIndex = - (dm->xdndMimeTransferedPixmapIndex + 1) % 2; - ret = true; - } - } else { - DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName)); - } - } - return ret && data != 0; -} - -//$$$ -QList<Atom> QX11Data::xdndMimeAtomsForFormat(const QString &format) -{ - QList<Atom> atoms; - atoms.append(xdndMimeStringToAtom(format)); - - // special cases for strings - if (format == QLatin1String("text/plain")) { - atoms.append(ATOM(UTF8_STRING)); - atoms.append(XA_STRING); - atoms.append(ATOM(TEXT)); - atoms.append(ATOM(COMPOUND_TEXT)); - } - - // special cases for uris - if (format == QLatin1String("text/uri-list")) { - atoms.append(xdndMimeStringToAtom(QLatin1String("text/x-moz-url"))); - } - - //special cases for images - if (format == QLatin1String("image/ppm")) - atoms.append(XA_PIXMAP); - if (format == QLatin1String("image/pbm")) - atoms.append(XA_BITMAP); - - return atoms; -} - -//$$$ -QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding) -{ - QString atomName = xdndMimeAtomToString(a); - if (atomName == format) - return data; - - if (!encoding.isEmpty() - && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) { - - if (requestedType == QVariant::String) { - QTextCodec *codec = QTextCodec::codecForName(encoding); - if (codec) - return codec->toUnicode(data); - } - - return data; - } - - // special cases for string types - if (format == QLatin1String("text/plain")) { - if (a == ATOM(UTF8_STRING)) - return QString::fromUtf8(data); - if (a == XA_STRING) - return QString::fromLatin1(data); - if (a == ATOM(TEXT) || a == ATOM(COMPOUND_TEXT)) - // #### might be wrong for COMPUND_TEXT - return QString::fromLocal8Bit(data, data.size()); - } - - // special case for uri types - if (format == QLatin1String("text/uri-list")) { - if (atomName == QLatin1String("text/x-moz-url")) { - // we expect this as utf16 <url><space><title> - // the first part is a url that should only contain ascci char - // so it should be safe to check that the second char is 0 - // to verify that it is utf16 - if (data.size() > 1 && data.at(1) == 0) - return QString::fromRawData((const QChar *)data.constData(), - data.size() / 2).split(QLatin1Char('\n')).first().toLatin1(); - } - } - - // special cas for images - if (format == QLatin1String("image/ppm")) { - if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { - Pixmap xpm = *((Pixmap*)data.data()); - if (!xpm) - return QByteArray(); - QPixmap qpm = QPixmap::fromX11Pixmap(xpm); - QImageWriter imageWriter; - imageWriter.setFormat("PPMRAW"); - QImage imageToWrite = qpm.toImage(); - QBuffer buf; - buf.open(QIODevice::WriteOnly); - imageWriter.setDevice(&buf); - imageWriter.write(imageToWrite); - return buf.buffer(); - } - } - return QVariant(); -} - -//$$$ middle of xdndObtainData -Atom QX11Data::xdndMimeAtomForFormat(const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *encoding) -{ - encoding->clear(); - - // find matches for string types - if (format == QLatin1String("text/plain")) { - if (atoms.contains(ATOM(UTF8_STRING))) - return ATOM(UTF8_STRING); - if (atoms.contains(ATOM(COMPOUND_TEXT))) - return ATOM(COMPOUND_TEXT); - if (atoms.contains(ATOM(TEXT))) - return ATOM(TEXT); - if (atoms.contains(XA_STRING)) - return XA_STRING; - } - - // find matches for uri types - if (format == QLatin1String("text/uri-list")) { - Atom a = xdndMimeStringToAtom(format); - if (a && atoms.contains(a)) - return a; - a = xdndMimeStringToAtom(QLatin1String("text/x-moz-url")); - if (a && atoms.contains(a)) - return a; - } - - // find match for image - if (format == QLatin1String("image/ppm")) { - if (atoms.contains(XA_PIXMAP)) - return XA_PIXMAP; - } - - // for string/text requests try to use a format with a well-defined charset - // first to avoid encoding problems - if (requestedType == QVariant::String - && format.startsWith(QLatin1String("text/")) - && !format.contains(QLatin1String("charset="))) { - - QString formatWithCharset = format; - formatWithCharset.append(QLatin1String(";charset=utf-8")); - - Atom a = xdndMimeStringToAtom(formatWithCharset); - if (a && atoms.contains(a)) { - *encoding = "utf-8"; - return a; - } - } - - Atom a = xdndMimeStringToAtom(format); - if (a && atoms.contains(a)) - return a; - - return 0; -} - -void QX11Data::xdndSetup() { - QCursorData::initialize(); - qAddPostRoutine(qt_xdnd_cleanup); -} - - -void qt_xdnd_cleanup() -{ - delete noDropCursor; - noDropCursor = 0; - delete copyCursor; - copyCursor = 0; - delete moveCursor; - moveCursor = 0; - delete linkCursor; - linkCursor = 0; - delete defaultPm; - defaultPm = 0; - delete xdnd_data.desktop_proxy; - xdnd_data.desktop_proxy = 0; - delete xdnd_data.deco; - xdnd_data.deco = 0; -} - - -static QWidget *find_child(QWidget *tlw, QPoint & p) -{ - QWidget *widget = tlw; - - p = widget->mapFromGlobal(p); - bool done = false; - while (!done) { - done = true; - if (((QExtraWidget*)widget)->extraData() && - ((QExtraWidget*)widget)->extraData()->xDndProxy != 0) - break; // stop searching for widgets under the mouse cursor if found widget is a proxy. - QObjectList children = widget->children(); - if (!children.isEmpty()) { - for(int i = children.size(); i > 0;) { - --i; - QWidget *w = qobject_cast<QWidget *>(children.at(i)); - if (!w) - continue; - if (w->testAttribute(Qt::WA_TransparentForMouseEvents)) - continue; - if (w->isVisible() && - w->geometry().contains(p) && - !w->isWindow()) { - widget = w; - done = false; - p = widget->mapFromParent(p); - break; - } - } - } - } - return widget; -} - - -static bool checkEmbedded(QWidget* w, const XEvent* xe) -{ - if (!w) - return false; - - if (current_embedding_widget != 0 && current_embedding_widget != w) { - qt_xdnd_current_target = ((QExtraWidget*)current_embedding_widget)->extraData()->xDndProxy; - qt_xdnd_current_proxy_target = qt_xdnd_current_target; - qt_xdnd_send_leave(); - qt_xdnd_current_target = 0; - qt_xdnd_current_proxy_target = 0; - current_embedding_widget = 0; - } - - QWExtra* extra = ((QExtraWidget*)w)->extraData(); - if (extra && extra->xDndProxy != 0) { - - if (current_embedding_widget != w) { - - last_enter_event.xany.window = extra->xDndProxy; - XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, &last_enter_event); - current_embedding_widget = w; - } - - ((XEvent*)xe)->xany.window = extra->xDndProxy; - XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, (XEvent*)xe); - if (qt_xdnd_current_widget != w) { - qt_xdnd_current_widget = w; - } - return true; - } - current_embedding_widget = 0; - return false; -} - -void QX11Data::xdndHandleEnter(QWidget *, const XEvent * xe, bool /*passive*/) -{ - motifdnd_active = false; - - last_enter_event.xclient = xe->xclient; - - const long *l = xe->xclient.data.l; - int version = (int)(((unsigned long)(l[1])) >> 24); - - if (version > xdnd_version) - return; - - qt_xdnd_dragsource_xid = l[0]; - - int j = 0; - if (l[1] & 1) { - // get the types from XdndTypeList - Atom type = XNone; - int f; - unsigned long n, a; - unsigned char *retval = 0; - XGetWindowProperty(X11->display, qt_xdnd_dragsource_xid, ATOM(XdndTypelist), 0, - qt_xdnd_max_type, False, XA_ATOM, &type, &f,&n,&a,&retval); - if (retval) { - Atom *data = (Atom *)retval; - for (; j<qt_xdnd_max_type && j < (int)n; j++) { - qt_xdnd_types[j] = data[j]; - } - XFree((uchar*)data); - } - } else { - // get the types from the message - int i; - for(i=2; i < 5; i++) { - qt_xdnd_types[j++] = l[i]; - } - } - qt_xdnd_types[j] = 0; -} - -static void handle_xdnd_position(QWidget *w, const XEvent * xe, bool passive) -{ - const unsigned long *l = (const unsigned long *)xe->xclient.data.l; - - QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff); - QWidget * c = find_child(w, p); // changes p to to c-local coordinates - - if (!passive && checkEmbedded(c, xe)) - return; - - if (!c || (!c->acceptDrops() && (c->windowType() == Qt::Desktop))) - return; - - if (l[0] != qt_xdnd_dragsource_xid) { - DEBUG("xdnd drag position from unexpected source (%08lx not %08lx)", l[0], qt_xdnd_dragsource_xid); - return; - } - - // timestamp from the source - if (l[3] != 0) { - // Some X server/client combination swallow the first 32 bit and - // interpret a set bit 31 as negative sign. - qt_xdnd_target_current_time = X11->userTime = - ((sizeof(Time) == 8 && xe->xclient.data.l[3] < 0) - ? uint(l[3]) - : l[3]); - } - - QDragManager *manager = QDragManager::self(); - QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData; - - XClientMessageEvent response; - response.type = ClientMessage; - response.window = qt_xdnd_dragsource_xid; - response.format = 32; - response.message_type = ATOM(XdndStatus); - response.data.l[0] = w->effectiveWinId(); - response.data.l[1] = 0; // flags - response.data.l[2] = 0; // x, y - response.data.l[3] = 0; // w, h - response.data.l[4] = 0; // action - - if (!passive) { // otherwise just reject - while (c && !c->acceptDrops() && !c->isWindow()) { - p = c->mapToParent(p); - c = c->parentWidget(); - } - QWidget *target_widget = c && c->acceptDrops() ? c : 0; - - QRect answerRect(c->mapToGlobal(p), QSize(1,1)); - - if (manager->object) { - possible_actions = manager->dragPrivate()->possible_actions; - } else { - possible_actions = Qt::DropActions(xdndaction_to_qtaction(l[4])); -// possible_actions |= Qt::CopyAction; - } - QDragMoveEvent me(p, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); - - Qt::DropAction accepted_action = Qt::IgnoreAction; - - - if (target_widget != qt_xdnd_current_widget) { - if (qt_xdnd_current_widget) { - QDragLeaveEvent e; - QApplication::sendEvent(qt_xdnd_current_widget, &e); - } - if (qt_xdnd_current_widget != target_widget) { - qt_xdnd_current_widget = target_widget; - } - if (target_widget) { - qt_xdnd_current_position = p; - - last_target_accepted_action = Qt::IgnoreAction; - QDragEnterEvent de(p, possible_actions, dropData, QApplication::mouseButtons(), QApplication::keyboardModifiers()); - QApplication::sendEvent(target_widget, &de); - if (de.isAccepted() && de.dropAction() != Qt::IgnoreAction) - last_target_accepted_action = de.dropAction(); - } - } - - DEBUG() << "qt_handle_xdnd_position action=" << X11->xdndAtomToString(l[4]); - if (!target_widget) { - answerRect = QRect(p, QSize(1, 1)); - } else { - qt_xdnd_current_widget = c; - qt_xdnd_current_position = p; - - if (last_target_accepted_action != Qt::IgnoreAction) { - me.setDropAction(last_target_accepted_action); - me.accept(); - } - QApplication::sendEvent(c, &me); - if (me.isAccepted()) { - response.data.l[1] = 1; // yes - accepted_action = me.dropAction(); - last_target_accepted_action = accepted_action; - } else { - response.data.l[0] = 0; - last_target_accepted_action = Qt::IgnoreAction; - } - answerRect = me.answerRect().intersected(c->rect()); - } - answerRect = QRect(c->mapToGlobal(answerRect.topLeft()), answerRect.size()); - - if (answerRect.left() < 0) - answerRect.setLeft(0); - if (answerRect.right() > 4096) - answerRect.setRight(4096); - if (answerRect.top() < 0) - answerRect.setTop(0); - if (answerRect.bottom() > 4096) - answerRect.setBottom(4096); - if (answerRect.width() < 0) - answerRect.setWidth(0); - if (answerRect.height() < 0) - answerRect.setHeight(0); - - response.data.l[2] = (answerRect.x() << 16) + answerRect.y(); - response.data.l[3] = (answerRect.width() << 16) + answerRect.height(); - response.data.l[4] = qtaction_to_xdndaction(accepted_action); - } - - // reset - qt_xdnd_target_current_time = CurrentTime; - - QWidget * source = QWidget::find(qt_xdnd_dragsource_xid); - if (source && (source->windowType() == Qt::Desktop) && !source->acceptDrops()) - source = 0; - - DEBUG() << "sending XdndStatus"; - if (source) - handle_xdnd_status(source, (const XEvent *)&response, passive); - else - XSendEvent(X11->display, qt_xdnd_dragsource_xid, False, NoEventMask, (XEvent*)&response); -} - -static Bool xdnd_position_scanner(Display *, XEvent *event, XPointer) -{ - if (event->type != ClientMessage) - return false; - XClientMessageEvent *ev = &event->xclient; - - if (ev->message_type == ATOM(XdndPosition)) - return true; - - return false; -} - -void QX11Data::xdndHandlePosition(QWidget * w, const XEvent * xe, bool passive) -{ - DEBUG("xdndHandlePosition"); - while (XCheckIfEvent(X11->display, (XEvent *)xe, xdnd_position_scanner, 0)) - ; - - handle_xdnd_position(w, xe, passive); -} - - -static void handle_xdnd_status(QWidget *, const XEvent * xe, bool) -{ - const unsigned long *l = (const unsigned long *)xe->xclient.data.l; - // ignore late status messages - if (l[0] && l[0] != qt_xdnd_current_proxy_target) - return; - Qt::DropAction newAction = (l[1] & 0x1) ? xdndaction_to_qtaction(l[4]) : Qt::IgnoreAction; - - if ((int)(l[1] & 2) == 0) { - QPoint p((l[2] & 0xffff0000) >> 16, l[2] & 0x0000ffff); - QSize s((l[3] & 0xffff0000) >> 16, l[3] & 0x0000ffff); - qt_xdnd_source_sameanswer = QRect(p, s); - } else { - qt_xdnd_source_sameanswer = QRect(); - } - QDragManager *manager = QDragManager::self(); - manager->willDrop = (l[1] & 0x1); - if (global_accepted_action != newAction) - manager->emitActionChanged(newAction); - global_accepted_action = newAction; - manager->updateCursor(); - waiting_for_status = false; -} - -static Bool xdnd_status_scanner(Display *, XEvent *event, XPointer) -{ - if (event->type != ClientMessage) - return false; - XClientMessageEvent *ev = &event->xclient; - - if (ev->message_type == ATOM(XdndStatus)) - return true; - - return false; -} - -void QX11Data::xdndHandleStatus(QWidget * w, const XEvent * xe, bool passive) -{ - DEBUG("xdndHandleStatus"); - while (XCheckIfEvent(X11->display, (XEvent *)xe, xdnd_status_scanner, 0)) - ; - - handle_xdnd_status(w, xe, passive); - DEBUG("xdndHandleStatus end"); -} - -void QX11Data::xdndHandleLeave(QWidget *w, const XEvent * xe, bool /*passive*/) -{ - DEBUG("xdnd leave"); - if (!qt_xdnd_current_widget || - w->window() != qt_xdnd_current_widget->window()) { - return; // sanity - } - - if (checkEmbedded(current_embedding_widget, xe)) { - current_embedding_widget = 0; - qt_xdnd_current_widget = 0; - return; - } - - const unsigned long *l = (const unsigned long *)xe->xclient.data.l; - - QDragLeaveEvent e; - QApplication::sendEvent(qt_xdnd_current_widget, &e); - - if (l[0] != qt_xdnd_dragsource_xid) { - // This often happens - leave other-process window quickly - DEBUG("xdnd drag leave from unexpected source (%08lx not %08lx", l[0], qt_xdnd_dragsource_xid); - qt_xdnd_current_widget = 0; - return; - } - - qt_xdnd_dragsource_xid = 0; - qt_xdnd_types[0] = 0; - qt_xdnd_current_widget = 0; -} - - -void qt_xdnd_send_leave() -{ - if (!qt_xdnd_current_target) - return; - - QDragManager *manager = QDragManager::self(); - - XClientMessageEvent leave; - leave.type = ClientMessage; - leave.window = qt_xdnd_current_target; - leave.format = 32; - leave.message_type = ATOM(XdndLeave); - leave.data.l[0] = manager->dragPrivate()->source->effectiveWinId(); - leave.data.l[1] = 0; // flags - leave.data.l[2] = 0; // x, y - leave.data.l[3] = 0; // w, h - leave.data.l[4] = 0; // just null - - QWidget * w = QWidget::find(qt_xdnd_current_proxy_target); - - if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops()) - w = 0; - - if (w) - X11->xdndHandleLeave(w, (const XEvent *)&leave, false); - else - XSendEvent(X11->display, qt_xdnd_current_proxy_target, False, - NoEventMask, (XEvent*)&leave); - - // reset the drag manager state - manager->willDrop = false; - if (global_accepted_action != Qt::IgnoreAction) - manager->emitActionChanged(Qt::IgnoreAction); - global_accepted_action = Qt::IgnoreAction; - manager->updateCursor(); - qt_xdnd_current_target = 0; - qt_xdnd_current_proxy_target = 0; - qt_xdnd_source_current_time = 0; - waiting_for_status = false; -} - -// TODO: remove and use QApplication::currentKeyboardModifiers() in Qt 4.8. -static Qt::KeyboardModifiers currentKeyboardModifiers() -{ - Window root; - Window child; - int root_x, root_y, win_x, win_y; - uint keybstate; - for (int i = 0; i < ScreenCount(X11->display); ++i) { - if (XQueryPointer(X11->display, QX11Info::appRootWindow(i), &root, &child, - &root_x, &root_y, &win_x, &win_y, &keybstate)) - return X11->translateModifiers(keybstate & 0x00ff); - } - return 0; -} - -void QX11Data::xdndHandleDrop(QWidget *, const XEvent * xe, bool passive) -{ - DEBUG("xdndHandleDrop"); - if (!qt_xdnd_current_widget) { - qt_xdnd_dragsource_xid = 0; - return; // sanity - } - - if (!passive && checkEmbedded(qt_xdnd_current_widget, xe)){ - current_embedding_widget = 0; - qt_xdnd_dragsource_xid = 0; - qt_xdnd_current_widget = 0; - return; - } - const unsigned long *l = (const unsigned long *)xe->xclient.data.l; - - QDragManager *manager = QDragManager::self(); - DEBUG("xdnd drop"); - - if (l[0] != qt_xdnd_dragsource_xid) { - DEBUG("xdnd drop from unexpected source (%08lx not %08lx", l[0], qt_xdnd_dragsource_xid); - return; - } - - // update the "user time" from the timestamp in the event. - if (l[2] != 0) { - // Some X server/client combination swallow the first 32 bit and - // interpret a set bit 31 as negative sign. - qt_xdnd_target_current_time = X11->userTime = - ((sizeof(Time) == 8 && xe->xclient.data.l[2] < 0) - ? uint(l[2]) - : l[2]); - } - - if (!passive) { - // this could be a same-application drop, just proxied due to - // some XEMBEDding, so try to find the real QMimeData used - // based on the timestamp for this drop. - QMimeData *dropData = 0; - int at = findXdndDropTransactionByTime(qt_xdnd_target_current_time); - if (at != -1) - dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data; - // if we can't find it, then use the data in the drag manager - if (!dropData) - dropData = (manager->object) ? manager->dragPrivate()->data : manager->dropData; - - // Drop coming from another app? Update keyboard modifiers. - if (!qt_xdnd_dragging) { - QApplicationPrivate::modifier_buttons = currentKeyboardModifiers(); - } - - QDropEvent de(qt_xdnd_current_position, possible_actions, dropData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - QApplication::sendEvent(qt_xdnd_current_widget, &de); - if (!de.isAccepted()) { - // Ignore a failed drag - global_accepted_action = Qt::IgnoreAction; - } else { - global_accepted_action = de.dropAction(); - } - XClientMessageEvent finished; - finished.type = ClientMessage; - finished.window = qt_xdnd_dragsource_xid; - finished.format = 32; - finished.message_type = ATOM(XdndFinished); - DNDDEBUG << "xdndHandleDrop" - << "qt_xdnd_current_widget" << qt_xdnd_current_widget - << (qt_xdnd_current_widget ? qt_xdnd_current_widget->effectiveWinId() : 0) - << "t_xdnd_current_widget->window()" - << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window() : 0) - << (qt_xdnd_current_widget ? qt_xdnd_current_widget->window()->internalWinId() : 0); - finished.data.l[0] = qt_xdnd_current_widget?qt_xdnd_current_widget->window()->internalWinId():0; - finished.data.l[1] = de.isAccepted() ? 1 : 0; // flags - finished.data.l[2] = qtaction_to_xdndaction(global_accepted_action); - XSendEvent(X11->display, qt_xdnd_dragsource_xid, False, - NoEventMask, (XEvent*)&finished); - } else { - QDragLeaveEvent e; - QApplication::sendEvent(qt_xdnd_current_widget, &e); - } - qt_xdnd_dragsource_xid = 0; - qt_xdnd_current_widget = 0; - waiting_for_status = false; - - // reset - qt_xdnd_target_current_time = CurrentTime; -} - - -void QX11Data::xdndHandleFinished(QWidget *, const XEvent * xe, bool passive) -{ - DEBUG("xdndHandleFinished"); - const unsigned long *l = (const unsigned long *)xe->xclient.data.l; - - DNDDEBUG << "xdndHandleFinished, l[0]" << l[0] - << "qt_xdnd_current_target" << qt_xdnd_current_target - << "qt_xdnd_current_proxy_targe" << qt_xdnd_current_proxy_target; - - if (l[0]) { - int at = findXdndDropTransactionByWindow(l[0]); - if (at != -1) { - restartXdndDropExpiryTimer(); - - QXdndDropTransaction t = X11->dndDropTransactions.takeAt(at); - QDragManager *manager = QDragManager::self(); - - Window target = qt_xdnd_current_target; - Window proxy_target = qt_xdnd_current_proxy_target; - QWidget *embedding_widget = current_embedding_widget; - QDrag *currentObject = manager->object; - - qt_xdnd_current_target = t.target; - qt_xdnd_current_proxy_target = t.proxy_target; - current_embedding_widget = t.embedding_widget; - manager->object = t.object; - - if (!passive) - (void) checkEmbedded(qt_xdnd_current_widget, xe); - - current_embedding_widget = 0; - qt_xdnd_current_target = 0; - qt_xdnd_current_proxy_target = 0; - - if (t.object) - t.object->deleteLater(); - - qt_xdnd_current_target = target; - qt_xdnd_current_proxy_target = proxy_target; - current_embedding_widget = embedding_widget; - manager->object = currentObject; - } - } - waiting_for_status = false; -} - - -void QDragManager::timerEvent(QTimerEvent* e) -{ - if (e->timerId() == heartbeat && qt_xdnd_source_sameanswer.isNull()) { - move(QCursor::pos()); - } else if (e->timerId() == transaction_expiry_timer) { - for (int i = 0; i < X11->dndDropTransactions.count(); ++i) { - const QXdndDropTransaction &t = X11->dndDropTransactions.at(i); - if (t.targetWidget) { - // dnd within the same process, don't delete these - continue; - } - t.object->deleteLater(); - X11->dndDropTransactions.removeAt(i--); - } - - killTimer(transaction_expiry_timer); - transaction_expiry_timer = -1; - } -} - -bool QDragManager::eventFilter(QObject * o, QEvent * e) -{ - if (beingCancelled) { - if (e->type() == QEvent::KeyRelease && ((QKeyEvent*)e)->key() == Qt::Key_Escape) { - qApp->removeEventFilter(this); - Q_ASSERT(object == 0); - beingCancelled = false; - eventLoop->exit(); - return true; // block the key release - } - return false; - } - - Q_ASSERT(object != 0); - - if (!o->isWidgetType()) - return false; - - if (e->type() == QEvent::MouseMove) { - QMouseEvent* me = (QMouseEvent *)e; - move(me->globalPos()); - return true; - } else if (e->type() == QEvent::MouseButtonRelease) { - DEBUG("pre drop"); - qApp->removeEventFilter(this); - if (willDrop) - drop(); - else - cancel(); - DEBUG("drop, resetting object"); - beingCancelled = false; - eventLoop->exit(); - return true; - } - - if (e->type() == QEvent::ShortcutOverride) { - // prevent accelerators from firing while dragging - e->accept(); - return true; - } - - if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) { - QKeyEvent *ke = ((QKeyEvent*)e); - if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - eventLoop->exit(); - } else { - qt_xdnd_source_sameanswer = QRect(); // force move - move(QCursor::pos()); - } - return true; // Eat all key events - } - - // ### We bind modality to widgets, so we have to do this - // ### "manually". - // DnD is modal - eat all other interactive events - switch (e->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::MouseMove: - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::Wheel: - case QEvent::ShortcutOverride: - return true; - default: - return false; - } -} - -void QDragManager::updateCursor() -{ - if (!noDropCursor) { -#ifndef QT_NO_CURSOR - noDropCursor = new QCursor(Qt::ForbiddenCursor); - moveCursor = new QCursor(Qt::DragMoveCursor); - copyCursor = new QCursor(Qt::DragCopyCursor); - linkCursor = new QCursor(Qt::DragLinkCursor); -#endif - } - - QCursor *c; - if (willDrop) { - if (global_accepted_action == Qt::CopyAction) { - c = copyCursor; - } else if (global_accepted_action == Qt::LinkAction) { - c = linkCursor; - } else { - c = moveCursor; - } - if (xdnd_data.deco) { - xdnd_data.deco->show(); - xdnd_data.deco->raise(); - } - } else { - c = noDropCursor; - //if (qt_xdnd_deco) - // qt_xdnd_deco->hide(); - } -#ifndef QT_NO_CURSOR - if (c) - qApp->changeOverrideCursor(*c); -#endif -} - - -void QDragManager::cancel(bool deleteSource) -{ - DEBUG("QDragManager::cancel"); - Q_ASSERT(heartbeat != -1); - killTimer(heartbeat); - heartbeat = -1; - beingCancelled = true; - qt_xdnd_dragging = false; - - if (qt_xdnd_current_target) - qt_xdnd_send_leave(); - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif - - if (deleteSource && object) - object->deleteLater(); - object = 0; - qDeleteInEventHandler(xdnd_data.deco); - xdnd_data.deco = 0; - - global_accepted_action = Qt::IgnoreAction; -} - -static -Window findRealWindow(const QPoint & pos, Window w, int md) -{ - if (xdnd_data.deco && w == xdnd_data.deco->effectiveWinId()) - return 0; - - if (md) { - X11->ignoreBadwindow(); - XWindowAttributes attr; - XGetWindowAttributes(X11->display, w, &attr); - if (X11->badwindow()) - return 0; - - if (attr.map_state == IsViewable - && QRect(attr.x,attr.y,attr.width,attr.height).contains(pos)) { - { - Atom type = XNone; - int f; - unsigned long n, a; - unsigned char *data; - - XGetWindowProperty(X11->display, w, ATOM(XdndAware), 0, 0, False, - AnyPropertyType, &type, &f,&n,&a,&data); - if (data) XFree(data); - if (type) - return w; - } - - Window r, p; - Window* c; - uint nc; - if (XQueryTree(X11->display, w, &r, &p, &c, &nc)) { - r=0; - for (uint i=nc; !r && i--;) { - r = findRealWindow(pos-QPoint(attr.x,attr.y), - c[i], md-1); - } - XFree(c); - if (r) - return r; - - // We didn't find a client window! Just use the - // innermost window. - } - - // No children! - return w; - } - } - return 0; -} - -void QDragManager::move(const QPoint & globalPos) -{ -#ifdef QT_NO_CURSOR - Q_UNUSED(globalPos); - return; -#else - DEBUG() << "QDragManager::move enter"; - if (!object) { - // perhaps the target crashed? - return; - } - - int screen = QCursor::x11Screen(); - if ((qt_xdnd_current_screen == -1 && screen != X11->defaultScreen) || (screen != qt_xdnd_current_screen)) { - // recreate the pixmap on the new screen... - delete xdnd_data.deco; - QWidget* parent = object->source()->window()->x11Info().screen() == screen - ? object->source()->window() : QApplication::desktop()->screen(screen); - xdnd_data.deco = new QShapedPixmapWidget(parent); - if (!QWidget::mouseGrabber()) { - updatePixmap(); - xdnd_data.deco->grabMouse(); - } - } - xdnd_data.deco->move(QCursor::pos() - xdnd_data.deco->pm_hot); - - if (qt_xdnd_source_sameanswer.contains(globalPos) && qt_xdnd_source_sameanswer.isValid()) - return; - - qt_xdnd_current_screen = screen; - Window rootwin = QX11Info::appRootWindow(qt_xdnd_current_screen); - Window target = 0; - int lx = 0, ly = 0; - if (!XTranslateCoordinates(X11->display, rootwin, rootwin, globalPos.x(), globalPos.y(), &lx, &ly, &target)) - // some weird error... - return; - - if (target == rootwin) { - // Ok. - } else if (target) { - //me - Window src = rootwin; - while (target != 0) { - DNDDEBUG << "checking target for XdndAware" << QWidget::find(target) << target; - int lx2, ly2; - Window t; - // translate coordinates - if (!XTranslateCoordinates(X11->display, src, target, lx, ly, &lx2, &ly2, &t)) { - target = 0; - break; - } - lx = lx2; - ly = ly2; - src = target; - - // check if it has XdndAware - Atom type = 0; - int f; - unsigned long n, a; - unsigned char *data = 0; - XGetWindowProperty(X11->display, target, ATOM(XdndAware), 0, 0, False, - AnyPropertyType, &type, &f,&n,&a,&data); - if (data) - XFree(data); - if (type) { - DNDDEBUG << "Found XdndAware on " << QWidget::find(target) << target; - break; - } - - // find child at the coordinates - if (!XTranslateCoordinates(X11->display, src, src, lx, ly, &lx2, &ly2, &target)) { - target = 0; - break; - } - } - if (xdnd_data.deco && (!target || target == xdnd_data.deco->effectiveWinId())) { - DNDDEBUG << "need to find real window"; - target = findRealWindow(globalPos, rootwin, 6); - DNDDEBUG << "real window found" << QWidget::find(target) << target; - } - } - - QWidget* w; - if (target) { - w = QWidget::find((WId)target); - if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops()) - w = 0; - } else { - w = 0; - target = rootwin; - } - - DNDDEBUG << "and the final target is " << QWidget::find(target) << target; - DNDDEBUG << "the widget w is" << w; - - WId proxy_target = xdndProxy(target); - if (!proxy_target) - proxy_target = target; - int target_version = 1; - - if (proxy_target) { - Atom type = XNone; - int r, f; - unsigned long n, a; - unsigned char *retval; - X11->ignoreBadwindow(); - r = XGetWindowProperty(X11->display, proxy_target, ATOM(XdndAware), 0, - 1, False, AnyPropertyType, &type, &f,&n,&a,&retval); - int *tv = (int *)retval; - if (r != Success || X11->badwindow()) { - target = 0; - } else { - target_version = qMin(xdnd_version,tv ? *tv : 1); - if (tv) - XFree(tv); -// if (!(!X11->badwindow() && type)) -// target = 0; - } - } - - if (target != qt_xdnd_current_target) { - if (qt_xdnd_current_target) - qt_xdnd_send_leave(); - - qt_xdnd_current_target = target; - qt_xdnd_current_proxy_target = proxy_target; - if (target) { - QVector<Atom> types; - int flags = target_version << 24; - QStringList fmts = QInternalMimeData::formatsHelper(dragPrivate()->data); - for (int i = 0; i < fmts.size(); ++i) { - QList<Atom> atoms = X11->xdndMimeAtomsForFormat(fmts.at(i)); - for (int j = 0; j < atoms.size(); ++j) { - if (!types.contains(atoms.at(j))) - types.append(atoms.at(j)); - } - } - if (types.size() > 3) { - XChangeProperty(X11->display, - dragPrivate()->source->effectiveWinId(), ATOM(XdndTypelist), - XA_ATOM, 32, PropModeReplace, - (unsigned char *)types.data(), - types.size()); - flags |= 0x0001; - } - XClientMessageEvent enter; - enter.type = ClientMessage; - enter.window = target; - enter.format = 32; - enter.message_type = ATOM(XdndEnter); - enter.data.l[0] = dragPrivate()->source->effectiveWinId(); - enter.data.l[1] = flags; - enter.data.l[2] = types.size()>0 ? types.at(0) : 0; - enter.data.l[3] = types.size()>1 ? types.at(1) : 0; - enter.data.l[4] = types.size()>2 ? types.at(2) : 0; - // provisionally set the rectangle to 5x5 pixels... - qt_xdnd_source_sameanswer = QRect(globalPos.x() - 2, - globalPos.y() -2 , 5, 5); - - DEBUG("sending Xdnd enter"); - if (w) - X11->xdndHandleEnter(w, (const XEvent *)&enter, false); - else if (target) - XSendEvent(X11->display, proxy_target, False, NoEventMask, (XEvent*)&enter); - waiting_for_status = false; - } - } - if (waiting_for_status) - return; - - if (target) { - waiting_for_status = true; - - XClientMessageEvent move; - move.type = ClientMessage; - move.window = target; - move.format = 32; - move.message_type = ATOM(XdndPosition); - move.window = target; - move.data.l[0] = dragPrivate()->source->effectiveWinId(); - move.data.l[1] = 0; // flags - move.data.l[2] = (globalPos.x() << 16) + globalPos.y(); - move.data.l[3] = X11->time; - move.data.l[4] = qtaction_to_xdndaction(defaultAction(dragPrivate()->possible_actions, QApplication::keyboardModifiers())); - DEBUG("sending Xdnd position"); - - qt_xdnd_source_current_time = X11->time; - - if (w) - handle_xdnd_position(w, (const XEvent *)&move, false); - else - XSendEvent(X11->display, proxy_target, False, NoEventMask, - (XEvent*)&move); - } else { - if (willDrop) { - willDrop = false; - updateCursor(); - } - } - DEBUG() << "QDragManager::move leave"; -#endif -} - - -void QDragManager::drop() -{ - Q_ASSERT(heartbeat != -1); - killTimer(heartbeat); - heartbeat = -1; - qt_xdnd_dragging = false; - - if (!qt_xdnd_current_target) - return; - - qDeleteInEventHandler(xdnd_data.deco); - xdnd_data.deco = 0; - - XClientMessageEvent drop; - drop.type = ClientMessage; - drop.window = qt_xdnd_current_target; - drop.format = 32; - drop.message_type = ATOM(XdndDrop); - drop.data.l[0] = dragPrivate()->source->effectiveWinId(); - drop.data.l[1] = 0; // flags - drop.data.l[2] = X11->time; - - drop.data.l[3] = 0; - drop.data.l[4] = 0; - - QWidget * w = QWidget::find(qt_xdnd_current_proxy_target); - - if (w && (w->windowType() == Qt::Desktop) && !w->acceptDrops()) - w = 0; - - QXdndDropTransaction t = { - X11->time, - qt_xdnd_current_target, - qt_xdnd_current_proxy_target, - w, - current_embedding_widget, - object - }; - X11->dndDropTransactions.append(t); - restartXdndDropExpiryTimer(); - - if (w) - X11->xdndHandleDrop(w, (const XEvent *)&drop, false); - else - XSendEvent(X11->display, qt_xdnd_current_proxy_target, False, - NoEventMask, (XEvent*)&drop); - - qt_xdnd_current_target = 0; - qt_xdnd_current_proxy_target = 0; - qt_xdnd_source_current_time = 0; - current_embedding_widget = 0; - object = 0; - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif -} - - - -bool QX11Data::xdndHandleBadwindow() -{ - if (qt_xdnd_current_target) { - QDragManager *manager = QDragManager::self(); - if (manager->object) { - qt_xdnd_current_target = 0; - qt_xdnd_current_proxy_target = 0; - manager->object->deleteLater(); - manager->object = 0; - delete xdnd_data.deco; - xdnd_data.deco = 0; - return true; - } - } - if (qt_xdnd_dragsource_xid) { - qt_xdnd_dragsource_xid = 0; - if (qt_xdnd_current_widget) { - QApplication::postEvent(qt_xdnd_current_widget, new QDragLeaveEvent); - qt_xdnd_current_widget = 0; - } - return true; - } - return false; -} - -void QX11Data::xdndHandleSelectionRequest(const XSelectionRequestEvent * req) -{ - if (!req) - return; - XEvent evt; - evt.xselection.type = SelectionNotify; - evt.xselection.display = req->display; - evt.xselection.requestor = req->requestor; - evt.xselection.selection = req->selection; - evt.xselection.target = XNone; - evt.xselection.property = XNone; - evt.xselection.time = req->time; - - QDragManager *manager = QDragManager::self(); - QDrag *currentObject = manager->object; - - // which transaction do we use? (note: -2 means use current manager->object) - int at = -1; - - // figure out which data the requestor is really interested in - if (manager->object && req->time == qt_xdnd_source_current_time) { - // requestor wants the current drag data - at = -2; - } else { - // if someone has requested data in response to XdndDrop, find the corresponding transaction. the - // spec says to call XConvertSelection() using the timestamp from the XdndDrop - at = findXdndDropTransactionByTime(req->time); - if (at == -1) { - // no dice, perhaps the client was nice enough to use the same window id in XConvertSelection() - // that we sent the XdndDrop event to. - at = findXdndDropTransactionByWindow(req->requestor); - } - if (at == -1 && req->time == CurrentTime) { - // previous Qt versions always requested the data on a child of the target window - // using CurrentTime... but it could be asking for either drop data or the current drag's data - Window target = findXdndAwareParent(req->requestor); - if (target) { - if (qt_xdnd_current_target && qt_xdnd_current_target == target) - at = -2; - else - at = findXdndDropTransactionByWindow(target); - } - } - } - if (at >= 0) { - restartXdndDropExpiryTimer(); - - // use the drag object from an XdndDrop tansaction - manager->object = X11->dndDropTransactions.at(at).object; - } else if (at != -2) { - // no transaction found, we'll have to reject the request - manager->object = 0; - } - if (manager->object) { - Atom atomFormat = req->target; - int dataFormat = 0; - QByteArray data; - if (X11->xdndMimeDataForAtom(req->target, manager->dragPrivate()->data, - &data, &atomFormat, &dataFormat)) { - int dataSize = data.size() / (dataFormat / 8); - XChangeProperty (X11->display, req->requestor, req->property, - atomFormat, dataFormat, PropModeReplace, - (unsigned char *)data.data(), dataSize); - evt.xselection.property = req->property; - evt.xselection.target = atomFormat; - } - } - - // reset manager->object in case we modified it above - manager->object = currentObject; - - // ### this can die if req->requestor crashes at the wrong - // ### moment - XSendEvent(X11->display, req->requestor, False, 0, &evt); -} - -static QVariant xdndObtainData(const char *format, QVariant::Type requestedType) -{ - QByteArray result; - - QWidget* w; - QDragManager *manager = QDragManager::self(); - if (qt_xdnd_dragsource_xid && manager->object && - (w=QWidget::find(qt_xdnd_dragsource_xid)) - && (!(w->windowType() == Qt::Desktop) || w->acceptDrops())) - { - QDragPrivate * o = QDragManager::self()->dragPrivate(); - if (o->data->hasFormat(QLatin1String(format))) - result = o->data->data(QLatin1String(format)); - return result; - } - - QList<Atom> atoms; - int i = 0; - while ((qt_xdnd_types[i])) { - atoms.append(qt_xdnd_types[i]); - ++i; - } - QByteArray encoding; - Atom a = X11->xdndMimeAtomForFormat(QLatin1String(format), requestedType, atoms, &encoding); - if (!a) - return result; - - if (XGetSelectionOwner(X11->display, ATOM(XdndSelection)) == XNone) - return result; // should never happen? - - QWidget* tw = qt_xdnd_current_widget; - if (!qt_xdnd_current_widget || (qt_xdnd_current_widget->windowType() == Qt::Desktop)) - tw = new QWidget; - - XConvertSelection(X11->display, ATOM(XdndSelection), a, ATOM(XdndSelection), tw->effectiveWinId(), - qt_xdnd_target_current_time); - XFlush(X11->display); - - XEvent xevent; - bool got=X11->clipboardWaitForEvent(tw->effectiveWinId(), SelectionNotify, &xevent, 5000); - if (got) { - Atom type; - - if (X11->clipboardReadProperty(tw->effectiveWinId(), ATOM(XdndSelection), true, &result, 0, &type, 0)) { - if (type == ATOM(INCR)) { - int nbytes = result.size() >= 4 ? *((int*)result.data()) : 0; - result = X11->clipboardReadIncrementalProperty(tw->effectiveWinId(), ATOM(XdndSelection), nbytes, false); - } else if (type != a && type != XNone) { - DEBUG("Qt clipboard: unknown atom %ld", type); - } - } - } - if (!qt_xdnd_current_widget || (qt_xdnd_current_widget->windowType() == Qt::Desktop)) - delete tw; - - return X11->xdndMimeConvertToFormat(a, result, QLatin1String(format), requestedType, encoding); -} - - -/* - Enable drag and drop for widget w by installing the proper - properties on w's toplevel widget. -*/ -bool QX11Data::dndEnable(QWidget* w, bool on) -{ - w = w->window(); - - if (bool(((QExtraWidget*)w)->topData()->dnd) == on) - return true; // been there, done that - ((QExtraWidget*)w)->topData()->dnd = on ? 1 : 0; - - motifdndEnable(w, on); - return xdndEnable(w, on); -} - -Qt::DropAction QDragManager::drag(QDrag * o) -{ - if (object == o || !o || !o->d_func()->source) - return Qt::IgnoreAction; - - if (object) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - } - - if (object) { - // the last drag and drop operation hasn't finished, so we are going to wait - // for one second to see if it does... if the finish message comes after this, - // then we could still have problems, but this is highly unlikely - QApplication::flush(); - - QElapsedTimer timer; - timer.start(); - do { - XEvent event; - if (XCheckTypedEvent(X11->display, ClientMessage, &event)) - qApp->x11ProcessEvent(&event); - - // sleep 50 ms, so we don't use up CPU cycles all the time. - struct timeval usleep_tv; - usleep_tv.tv_sec = 0; - usleep_tv.tv_usec = 50000; - select(0, 0, 0, 0, &usleep_tv); - } while (object && timer.hasExpired(1000)); - } - - object = o; - object->d_func()->target = 0; - xdnd_data.deco = new QShapedPixmapWidget(object->source()->window()); - - willDrop = false; - - updatePixmap(); - - qApp->installEventFilter(this); - XSetSelectionOwner(X11->display, ATOM(XdndSelection), dragPrivate()->source->window()->internalWinId(), X11->time); - global_accepted_action = Qt::CopyAction; - qt_xdnd_source_sameanswer = QRect(); -#ifndef QT_NO_CURSOR - // set the override cursor (must be done here, since it is updated - // in the call to move() below) - qApp->setOverrideCursor(Qt::ArrowCursor); - restoreCursor = true; -#endif - move(QCursor::pos()); - heartbeat = startTimer(200); - - qt_xdnd_dragging = true; - - if (!QWidget::mouseGrabber()) - xdnd_data.deco->grabMouse(); - - eventLoop = new QEventLoop; - (void) eventLoop->exec(); - delete eventLoop; - eventLoop = 0; - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - qApp->restoreOverrideCursor(); - restoreCursor = false; - } -#endif - - // delete cursors as they may be different next drag. - delete noDropCursor; - noDropCursor = 0; - delete copyCursor; - copyCursor = 0; - delete moveCursor; - moveCursor = 0; - delete linkCursor; - linkCursor = 0; - - delete xdnd_data.deco; - xdnd_data.deco = 0; - if (heartbeat != -1) - killTimer(heartbeat); - heartbeat = -1; - qt_xdnd_current_screen = -1; - qt_xdnd_dragging = false; - - return global_accepted_action; - // object persists until we get an xdnd_finish message -} - -void QDragManager::updatePixmap() -{ - if (xdnd_data.deco) { - QPixmap pm; - QPoint pm_hot(default_pm_hotx,default_pm_hoty); - if (object) { - pm = dragPrivate()->pixmap; - if (!pm.isNull()) - pm_hot = dragPrivate()->hotspot; - } - if (pm.isNull()) { - if (!defaultPm) - defaultPm = new QPixmap(default_pm); - pm = *defaultPm; - } - xdnd_data.deco->pm_hot = pm_hot; - xdnd_data.deco->setPixmap(pm); - xdnd_data.deco->move(QCursor::pos()-pm_hot); - xdnd_data.deco->show(); - } -} - -QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const -{ - QByteArray mime = mimetype.toLatin1(); - QVariant data = X11->motifdnd_active - ? X11->motifdndObtainData(mime) - : xdndObtainData(mime, requestedType); - return data; -} - -bool QDropData::hasFormat_sys(const QString &format) const -{ - return formats().contains(format); -} - -QStringList QDropData::formats_sys() const -{ - QStringList formats; - if (X11->motifdnd_active) { - int i = 0; - QByteArray fmt; - while (!(fmt = X11->motifdndFormat(i)).isEmpty()) { - formats.append(QLatin1String(fmt)); - ++i; - } - } else { - int i = 0; - while ((qt_xdnd_types[i])) { - QStringList formatsForAtom = X11->xdndMimeFormatsForAtom(qt_xdnd_types[i]); - for (int j = 0; j < formatsForAtom.size(); ++j) { - if (!formats.contains(formatsForAtom.at(j))) - formats.append(formatsForAtom.at(j)); - } - ++i; - } - } - return formats; -} - -QT_END_NAMESPACE - -#endif // QT_NO_DRAGANDDROP diff --git a/src/widgets/platforms/x11/qeventdispatcher_x11.cpp b/src/widgets/platforms/x11/qeventdispatcher_x11.cpp deleted file mode 100644 index e31d8ed301..0000000000 --- a/src/widgets/platforms/x11/qeventdispatcher_x11.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qeventdispatcher_x11_p.h" - -#include "qapplication.h" -#include "qx11info_x11.h" - -#include "qt_x11_p.h" -#include <private/qeventdispatcher_unix_p.h> - -QT_BEGIN_NAMESPACE - -class QEventDispatcherX11Private : public QEventDispatcherUNIXPrivate -{ - Q_DECLARE_PUBLIC(QEventDispatcherX11) -public: - inline QEventDispatcherX11Private() - : xfd(-1) - { } - int xfd; - QList<XEvent> queuedUserInputEvents; -}; - -QEventDispatcherX11::QEventDispatcherX11(QObject *parent) - : QEventDispatcherUNIX(*new QEventDispatcherX11Private, parent) -{ } - -QEventDispatcherX11::~QEventDispatcherX11() -{ } - -bool QEventDispatcherX11::processEvents(QEventLoop::ProcessEventsFlags flags) -{ - Q_D(QEventDispatcherX11); - - d->interrupt = false; - QApplication::sendPostedEvents(); - - ulong marker = XNextRequest(X11->display); - int nevents = 0; - do { - while (!d->interrupt) { - XEvent event; - if (!(flags & QEventLoop::ExcludeUserInputEvents) - && !d->queuedUserInputEvents.isEmpty()) { - // process a pending user input event - event = d->queuedUserInputEvents.takeFirst(); - } else if (XEventsQueued(X11->display, QueuedAlready)) { - // process events from the X server - XNextEvent(X11->display, &event); - - if (flags & QEventLoop::ExcludeUserInputEvents) { - // queue user input events - switch (event.type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: - case XKeyPress: - case XKeyRelease: - case EnterNotify: - case LeaveNotify: - d->queuedUserInputEvents.append(event); - continue; - - case ClientMessage: - // only keep the wm_take_focus and - // _qt_scrolldone protocols, queue all other - // client messages - if (event.xclient.format == 32) { - if (event.xclient.message_type == ATOM(WM_PROTOCOLS) && - (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) { - break; - } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) { - break; - } - } - d->queuedUserInputEvents.append(event); - continue; - - default: - break; - } - } - } else { - // no event to process - break; - } - - // send through event filter - if (filterEvent(&event)) - continue; - - nevents++; - if (qApp->x11ProcessEvent(&event) == 1) - return true; - - if (event.xany.serial >= marker) { - if (XEventsQueued(X11->display, QueuedAfterFlush)) - flags &= ~QEventLoop::WaitForMoreEvents; - goto out; - } - } - } while (!d->interrupt && XEventsQueued(X11->display, QueuedAfterFlush)); - - out: - if (!d->interrupt) { - const uint exclude_all = - QEventLoop::ExcludeSocketNotifiers | QEventLoop::X11ExcludeTimers | QEventLoop::WaitForMoreEvents; - if (nevents > 0 && ((uint)flags & exclude_all) == exclude_all) { - QApplication::sendPostedEvents(); - return nevents > 0; - } - // return true if we handled events, false otherwise - return QEventDispatcherUNIX::processEvents(flags) || (nevents > 0); - } - return nevents > 0; -} - -bool QEventDispatcherX11::hasPendingEvents() -{ - extern uint qGlobalPostedEventsCount(); // from qapplication.cpp - return (qGlobalPostedEventsCount() || XPending(X11->display)); -} - -void QEventDispatcherX11::flush() -{ - XFlush(X11->display); -} - -void QEventDispatcherX11::startingUp() -{ - Q_D(QEventDispatcherX11); - d->xfd = XConnectionNumber(X11->display); -} - -void QEventDispatcherX11::closingDown() -{ - Q_D(QEventDispatcherX11); - d->xfd = -1; -} - -int QEventDispatcherX11::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - timeval *timeout) -{ - Q_D(QEventDispatcherX11); - if (d->xfd > 0) { - nfds = qMax(nfds - 1, d->xfd) + 1; - FD_SET(d->xfd, readfds); - } - return QEventDispatcherUNIX::select(nfds, readfds, writefds, exceptfds, timeout); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qeventdispatcher_x11_p.h b/src/widgets/platforms/x11/qeventdispatcher_x11_p.h deleted file mode 100644 index 1b6620d90f..0000000000 --- a/src/widgets/platforms/x11/qeventdispatcher_x11_p.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QEVENTDISPATCHER_X11_P_H -#define QEVENTDISPATCHER_X11_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "private/qeventdispatcher_unix_p.h" - -QT_BEGIN_NAMESPACE - -class QEventDispatcherX11Private; - -class QEventDispatcherX11 : public QEventDispatcherUNIX -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QEventDispatcherX11) - -public: - explicit QEventDispatcherX11(QObject *parent = 0); - ~QEventDispatcherX11(); - - bool processEvents(QEventLoop::ProcessEventsFlags flags); - bool hasPendingEvents(); - - void flush(); - - void startingUp(); - void closingDown(); - -protected: - int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - timeval *timeout); -}; - -QT_END_NAMESPACE - -#endif // QEVENTDISPATCHER_X11_P_H diff --git a/src/widgets/platforms/x11/qfont_x11.cpp b/src/widgets/platforms/x11/qfont_x11.cpp deleted file mode 100644 index ba69871855..0000000000 --- a/src/widgets/platforms/x11/qfont_x11.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#define QT_FATAL_ASSERT - -#include "qplatformdefs.h" - -#include "qfont.h" -#include "qapplication.h" -#include "qfontinfo.h" -#include "qfontdatabase.h" -#include "qfontmetrics.h" -#include "qpaintdevice.h" -#include "qtextcodec.h" -#include "qiodevice.h" -#include "qhash.h" - -#include <private/qunicodetables_p.h> -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qfontengine_x11_p.h" -#include "qtextengine_p.h" - -#include <private/qt_x11_p.h> -#include "qx11info_x11.h" - -#include <time.h> -#include <stdlib.h> -#include <ctype.h> - -#define QFONTLOADER_DEBUG -#define QFONTLOADER_DEBUG_VERBOSE - -QT_BEGIN_NAMESPACE - -double qt_pixelSize(double pointSize, int dpi) -{ - if (pointSize < 0) - return -1.; - if (dpi == 75) // the stupid 75 dpi setting on X11 - dpi = 72; - return (pointSize * dpi) /72.; -} - -double qt_pointSize(double pixelSize, int dpi) -{ - if (pixelSize < 0) - return -1.; - if (dpi == 75) // the stupid 75 dpi setting on X11 - dpi = 72; - return pixelSize * 72. / ((double) dpi); -} - -/* - Removes wildcards from an XLFD. - - Returns \a xlfd with all wildcards removed if a match for \a xlfd is - found, otherwise it returns \a xlfd. -*/ -static QByteArray qt_fixXLFD(const QByteArray &xlfd) -{ - QByteArray ret = xlfd; - int count = 0; - char **fontNames = - XListFonts(QX11Info::display(), xlfd, 32768, &count); - if (count > 0) - ret = fontNames[0]; - XFreeFontNames(fontNames); - return ret ; -} - -typedef QHash<int, QString> FallBackHash; -Q_GLOBAL_STATIC(FallBackHash, fallBackHash) - -// Returns the user-configured fallback family for the specified script. -QString qt_fallback_font_family(int script) -{ - FallBackHash *hash = fallBackHash(); - return hash->value(script); -} - -// Sets the fallback family for the specified script. -Q_WIDGETS_EXPORT void qt_x11_set_fallback_font_family(int script, const QString &family) -{ - FallBackHash *hash = fallBackHash(); - if (!family.isEmpty()) - hash->insert(script, family); - else - hash->remove(script); -} - -int QFontPrivate::defaultEncodingID = -1; - -void QFont::initialize() -{ - extern int qt_encoding_id_for_mib(int mib); // from qfontdatabase_x11.cpp - QTextCodec *codec = QTextCodec::codecForLocale(); - // determine the default encoding id using the locale, otherwise - // fallback to latin1 (mib == 4) - int mib = codec ? codec->mibEnum() : 4; - - // for asian locales, use the mib for the font codec instead of the locale codec - switch (mib) { - case 38: // eucKR - mib = 36; - break; - - case 2025: // GB2312 - mib = 57; - break; - - case 113: // GBK - mib = -113; - break; - - case 114: // GB18030 - mib = -114; - break; - - case 2026: // Big5 - mib = -2026; - break; - - case 2101: // Big5-HKSCS - mib = -2101; - break; - - case 16: // JIS7 - mib = 15; - break; - - case 17: // SJIS - case 18: // eucJP - mib = 63; - break; - } - - // get the default encoding id for the locale encoding... - QFontPrivate::defaultEncodingID = qt_encoding_id_for_mib(mib); -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - -/*! - \internal - X11 Only: Returns the screen with which this font is associated. -*/ -int QFont::x11Screen() const -{ - return d->screen; -} - -/*! \internal - X11 Only: Associate the font with the specified \a screen. -*/ -void QFont::x11SetScreen(int screen) -{ - if (screen < 0) // assume default - screen = QX11Info::appScreen(); - - if (screen == d->screen) - return; // nothing to do - - detach(); - d->screen = screen; -} - -Qt::HANDLE QFont::handle() const -{ - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - Q_ASSERT(engine != 0); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); - if (engine->type() == QFontEngine::XLFD) - return static_cast<QFontEngineXLFD *>(engine)->fontStruct()->fid; - return 0; -} - - -FT_Face QFont::freetypeFace() const -{ -#ifndef QT_NO_FREETYPE - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); -#ifndef QT_NO_FONTCONFIG - if (engine->type() == QFontEngine::Freetype) { - const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine); - return ft->non_locked_face(); - } else -#endif - if (engine->type() == QFontEngine::XLFD) { - const QFontEngineXLFD *xlfd = static_cast<const QFontEngineXLFD *>(engine); - return xlfd->non_locked_face(); - } -#endif - return 0; -} - -QString QFont::rawName() const -{ - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - Q_ASSERT(engine != 0); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); - if (engine->type() == QFontEngine::XLFD) - return QString::fromLatin1(engine->name()); - return QString(); -} -struct QtFontDesc; - -void QFont::setRawName(const QString &name) -{ - detach(); - - // from qfontdatabase_x11.cpp - extern bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *desc); - - if (!qt_fillFontDef(qt_fixXLFD(name.toLatin1()), &d->request, d->dpi, 0)) { - qWarning("QFont::setRawName: Invalid XLFD: \"%s\"", name.toLatin1().constData()); - - setFamily(name); - setRawMode(true); - } else { - resolve_mask = QFont::AllPropertiesResolved; - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("Helvetica"); -} - -QString QFont::defaultFamily() const -{ - switch (d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("Times"); - - case QFont::Courier: - return QString::fromLatin1("Courier"); - - case QFont::Monospace: - return QString::fromLatin1("Courier New"); - - case QFont::Cursive: - return QString::fromLatin1("Comic Sans MS"); - - case QFont::Fantasy: - return QString::fromLatin1("Impact"); - - case QFont::Decorative: - return QString::fromLatin1("Old English"); - - case QFont::Helvetica: - case QFont::System: - default: - return QString::fromLatin1("Helvetica"); - } -} - -/* - Returns a last resort raw font name for the font matching algorithm. - This is used if even the last resort family is not available. It - returns \e something, almost no matter what. The current - implementation tries a wide variety of common fonts, returning the - first one it finds. The implementation may change at any time. -*/ -static const char * const tryFonts[] = { - "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-courier-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-times-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-lucida-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-helvetica-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-courier-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-times-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-lucida-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-helvetica-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-courier-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-times-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-lucida-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-fixed-*-*-*-*-*-*-*-*-*-*-*-*", - "6x13", - "7x13", - "8x13", - "9x15", - "fixed", - 0 -}; - -// Returns true if the font exists, false otherwise -static bool fontExists(const QString &fontName) -{ - int count; - char **fontNames = XListFonts(QX11Info::display(), (char*)fontName.toLatin1().constData(), 32768, &count); - if (fontNames) XFreeFontNames(fontNames); - - return count != 0; -} - -QString QFont::lastResortFont() const -{ - static QString last; - - // already found - if (! last.isNull()) - return last; - - int i = 0; - const char* f; - - while ((f = tryFonts[i])) { - last = QString::fromLatin1(f); - - if (fontExists(last)) - return last; - - i++; - } - -#if defined(CHECK_NULL) - qFatal("QFontPrivate::lastResortFont: Cannot find any reasonable font"); -#endif - return last; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qfontdatabase_x11.cpp b/src/widgets/platforms/x11/qfontdatabase_x11.cpp deleted file mode 100644 index 922a97f3aa..0000000000 --- a/src/widgets/platforms/x11/qfontdatabase_x11.cpp +++ /dev/null @@ -1,2154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qplatformdefs.h> - -#include <qdebug.h> -#include <qpaintdevice.h> -#include <qelapsedtimer.h> - -#include <private/qt_x11_p.h> -#include "qx11info_x11.h" -#include <qdebug.h> -#include <qfile.h> -#include <qtemporaryfile.h> -#include <qabstractfileengine.h> -#include <qmath.h> - -#include <ctype.h> -#include <stdlib.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/mman.h> - -#include <private/qfontengine_x11_p.h> - -#ifndef QT_NO_FONTCONFIG -#include <ft2build.h> -#include FT_FREETYPE_H - -#if FC_VERSION >= 20402 -#include <fontconfig/fcfreetype.h> -#endif -#endif - -QT_BEGIN_NAMESPACE - -// from qfont_x11.cpp -extern double qt_pointSize(double pixelSize, int dpi); -extern double qt_pixelSize(double pointSize, int dpi); - -// from qapplication.cpp -extern bool qt_is_gui_used; - -static inline void capitalize (char *s) -{ - bool space = true; - while(*s) { - if (space) - *s = toupper(*s); - space = (*s == ' '); - ++s; - } -} - - -/* - To regenerate the writingSystems_for_xlfd_encoding table, run - 'util/unicode/x11/makeencodings' and paste the generated - 'encodings.c' here. -*/ -// ----- begin of generated code ----- - -#define make_tag( c1, c2, c3, c4 ) \ - ((((unsigned int)c1)<<24) | (((unsigned int)c2)<<16) | \ - (((unsigned int)c3)<<8) | ((unsigned int)c4)) - -struct XlfdEncoding { - const char *name; - int id; - int mib; - unsigned int hash1; - unsigned int hash2; -}; - -static const XlfdEncoding xlfd_encoding[] = { - { "iso8859-1", 0, 4, make_tag('i','s','o','8'), make_tag('5','9','-','1') }, - { "iso8859-2", 1, 5, make_tag('i','s','o','8'), make_tag('5','9','-','2') }, - { "iso8859-3", 2, 6, make_tag('i','s','o','8'), make_tag('5','9','-','3') }, - { "iso8859-4", 3, 7, make_tag('i','s','o','8'), make_tag('5','9','-','4') }, - { "iso8859-9", 4, 12, make_tag('i','s','o','8'), make_tag('5','9','-','9') }, - { "iso8859-10", 5, 13, make_tag('i','s','o','8'), make_tag('9','-','1','0') }, - { "iso8859-13", 6, 109, make_tag('i','s','o','8'), make_tag('9','-','1','3') }, - { "iso8859-14", 7, 110, make_tag('i','s','o','8'), make_tag('9','-','1','4') }, - { "iso8859-15", 8, 111, make_tag('i','s','o','8'), make_tag('9','-','1','5') }, - { "hp-roman8", 9, 2004, make_tag('h','p','-','r'), make_tag('m','a','n','8') }, - { "iso8859-5", 10, 8, make_tag('i','s','o','8'), make_tag('5','9','-','5') }, - { "*-cp1251", 11, 2251, 0, make_tag('1','2','5','1') }, - { "koi8-ru", 12, 2084, make_tag('k','o','i','8'), make_tag('8','-','r','u') }, - { "koi8-u", 13, 2088, make_tag('k','o','i','8'), make_tag('i','8','-','u') }, - { "koi8-r", 14, 2084, make_tag('k','o','i','8'), make_tag('i','8','-','r') }, - { "iso8859-7", 15, 10, make_tag('i','s','o','8'), make_tag('5','9','-','7') }, - { "iso8859-8", 16, 85, make_tag('i','s','o','8'), make_tag('5','9','-','8') }, - { "gb18030-0", 17, -114, make_tag('g','b','1','8'), make_tag('3','0','-','0') }, - { "gb18030.2000-0", 18, -113, make_tag('g','b','1','8'), make_tag('0','0','-','0') }, - { "gbk-0", 19, -113, make_tag('g','b','k','-'), make_tag('b','k','-','0') }, - { "gb2312.*-0", 20, 57, make_tag('g','b','2','3'), 0 }, - { "jisx0201*-0", 21, 15, make_tag('j','i','s','x'), 0 }, - { "jisx0208*-0", 22, 63, make_tag('j','i','s','x'), 0 }, - { "ksc5601*-*", 23, 36, make_tag('k','s','c','5'), 0 }, - { "big5hkscs-0", 24, -2101, make_tag('b','i','g','5'), make_tag('c','s','-','0') }, - { "hkscs-1", 25, -2101, make_tag('h','k','s','c'), make_tag('c','s','-','1') }, - { "big5*-*", 26, -2026, make_tag('b','i','g','5'), 0 }, - { "tscii-*", 27, 2028, make_tag('t','s','c','i'), 0 }, - { "tis620*-*", 28, 2259, make_tag('t','i','s','6'), 0 }, - { "iso8859-11", 29, 2259, make_tag('i','s','o','8'), make_tag('9','-','1','1') }, - { "mulelao-1", 30, -4242, make_tag('m','u','l','e'), make_tag('a','o','-','1') }, - { "ethiopic-unicode", 31, 0, make_tag('e','t','h','i'), make_tag('c','o','d','e') }, - { "iso10646-1", 32, 0, make_tag('i','s','o','1'), make_tag('4','6','-','1') }, - { "unicode-*", 33, 0, make_tag('u','n','i','c'), 0 }, - { "*-symbol", 34, 0, 0, make_tag('m','b','o','l') }, - { "*-fontspecific", 35, 0, 0, make_tag('i','f','i','c') }, - { "fontspecific-*", 36, 0, make_tag('f','o','n','t'), 0 }, - { 0, 0, 0, 0, 0 } -}; - -static const char writingSystems_for_xlfd_encoding[sizeof(xlfd_encoding)][QFontDatabase::WritingSystemsCount] = { - // iso8859-1 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-2 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-3 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-4 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-9 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-10 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-13 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-14 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-15 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // hp-roman8 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-5 - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // *-cp1251 - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // koi8-ru - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // koi8-u - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // koi8-r - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-7 - { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-8 - { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // gb18030-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // gb18030.2000-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // gbk-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // gb2312.*-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // jisx0201*-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0 }, - // jisx0208*-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0 }, - // ksc5601*-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0 }, - // big5hkscs-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0 }, - // hkscs-1 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0 }, - // big5*-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0 }, - // tscii-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // tis620*-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-11 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // mulelao-1 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // ethiopic-unicode - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso10646-1 - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0, 0 }, - // unicode-* - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0, 0 }, - // *-symbol - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0 }, - // *-fontspecific - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0 }, - // fontspecific-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0 } - -}; - -// ----- end of generated code ----- - - -const int numEncodings = sizeof(xlfd_encoding) / sizeof(XlfdEncoding) - 1; - -int qt_xlfd_encoding_id(const char *encoding) -{ - // qDebug("looking for encoding id for '%s'", encoding); - int len = strlen(encoding); - if (len < 4) - return -1; - unsigned int hash1 = make_tag(encoding[0], encoding[1], encoding[2], encoding[3]); - const char *ch = encoding + len - 4; - unsigned int hash2 = make_tag(ch[0], ch[1], ch[2], ch[3]); - - const XlfdEncoding *enc = xlfd_encoding; - for (; enc->name; ++enc) { - if ((enc->hash1 && enc->hash1 != hash1) || - (enc->hash2 && enc->hash2 != hash2)) - continue; - // hashes match, do a compare if strings match - // the enc->name can contain '*'s we have to interpret correctly - const char *n = enc->name; - const char *e = encoding; - while (1) { - // qDebug("bol: *e='%c', *n='%c'", *e, *n); - if (*e == '\0') { - if (*n) - break; - // qDebug("found encoding id %d", enc->id); - return enc->id; - } - if (*e == *n) { - ++e; - ++n; - continue; - } - if (*n != '*') - break; - ++n; - // qDebug("skip: *e='%c', *n='%c'", *e, *n); - while (*e && *e != *n) - ++e; - } - } - // qDebug("couldn't find encoding %s", encoding); - return -1; -} - -int qt_mib_for_xlfd_encoding(const char *encoding) -{ - int id = qt_xlfd_encoding_id(encoding); - if (id != -1) return xlfd_encoding[id].mib; - return 0; -} - -int qt_encoding_id_for_mib(int mib) -{ - const XlfdEncoding *enc = xlfd_encoding; - for (; enc->name; ++enc) { - if (enc->mib == mib) - return enc->id; - } - return -1; -} - -static const char * xlfd_for_id(int id) -{ - // special case: -1 returns the "*-*" encoding, allowing us to do full - // database population in a single X server round trip. - if (id < 0 || id > numEncodings) - return "*-*"; - return xlfd_encoding[id].name; -} - -enum XLFDFieldNames { - Foundry, - Family, - Weight, - Slant, - Width, - AddStyle, - PixelSize, - PointSize, - ResolutionX, - ResolutionY, - Spacing, - AverageWidth, - CharsetRegistry, - CharsetEncoding, - NFontFields -}; - -// Splits an X font name into fields separated by '-' -static bool parseXFontName(char *fontName, char **tokens) -{ - if (! fontName || fontName[0] == '0' || fontName[0] != '-') { - tokens[0] = 0; - return false; - } - - int i; - ++fontName; - for (i = 0; i < NFontFields && fontName && fontName[0]; ++i) { - tokens[i] = fontName; - for (;; ++fontName) { - if (*fontName == '-') - break; - if (! *fontName) { - fontName = 0; - break; - } - } - - if (fontName) *fontName++ = '\0'; - } - - if (i < NFontFields) { - for (int j = i ; j < NFontFields; ++j) - tokens[j] = 0; - return false; - } - - return true; -} - -static inline bool isZero(char *x) -{ - return (x[0] == '0' && x[1] == 0); -} - -static inline bool isScalable(char **tokens) -{ - return (isZero(tokens[PixelSize]) && - isZero(tokens[PointSize]) && - isZero(tokens[AverageWidth])); -} - -static inline bool isSmoothlyScalable(char **tokens) -{ - return (isZero(tokens[ResolutionX]) && - isZero(tokens[ResolutionY])); -} - -static inline bool isFixedPitch(char **tokens) -{ - return (tokens[Spacing][0] == 'm' || - tokens[Spacing][0] == 'c' || - tokens[Spacing][0] == 'M' || - tokens[Spacing][0] == 'C'); -} - -/* - Fills in a font definition (QFontDef) from an XLFD (X Logical Font - Description). - - Returns true if the given xlfd is valid. -*/ -bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *desc) -{ - char *tokens[NFontFields]; - QByteArray buffer = xlfd; - if (! parseXFontName(buffer.data(), tokens)) - return false; - - capitalize(tokens[Family]); - capitalize(tokens[Foundry]); - - fd->styleStrategy |= QFont::NoAntialias; - fd->family = QString::fromLatin1(tokens[Family]); - QString foundry = QString::fromLatin1(tokens[Foundry]); - if (! foundry.isEmpty() && foundry != QLatin1String("*") && (!desc || desc->family->count > 1)) - fd->family += - QLatin1String(" [") + foundry + QLatin1Char(']'); - - if (qstrlen(tokens[AddStyle]) > 0) - fd->addStyle = QString::fromLatin1(tokens[AddStyle]); - else - fd->addStyle.clear(); - - fd->pointSize = atoi(tokens[PointSize])/10.; - fd->styleHint = QFont::AnyStyle; // ### any until we match families - - char slant = tolower((uchar) tokens[Slant][0]); - fd->style = (slant == 'o' ? QFont::StyleOblique : (slant == 'i' ? QFont::StyleItalic : QFont::StyleNormal)); - char fixed = tolower((uchar) tokens[Spacing][0]); - fd->fixedPitch = (fixed == 'm' || fixed == 'c'); - fd->weight = getFontWeight(QLatin1String(tokens[Weight])); - - int r = atoi(tokens[ResolutionY]); - fd->pixelSize = atoi(tokens[PixelSize]); - // not "0" or "*", or required DPI - if (r && fd->pixelSize && r != dpi) { - // calculate actual pointsize for display DPI - fd->pointSize = qt_pointSize(fd->pixelSize, dpi); - } else if (fd->pixelSize == 0 && fd->pointSize) { - // calculate pixel size from pointsize/dpi - fd->pixelSize = qRound(qt_pixelSize(fd->pointSize, dpi)); - } - - return true; -} - -/* - Fills in a font definition (QFontDef) from the font properties in an - XFontStruct. - - Returns true if the QFontDef could be filled with properties from - the XFontStruct. -*/ -static bool qt_fillFontDef(XFontStruct *fs, QFontDef *fd, int dpi, QtFontDesc *desc) -{ - unsigned long value; - if (!fs || !XGetFontProperty(fs, XA_FONT, &value)) - return false; - - char *n = XGetAtomName(QX11Info::display(), value); - QByteArray xlfd(n); - if (n) - XFree(n); - return qt_fillFontDef(xlfd.toLower(), fd, dpi, desc); -} - - -static QtFontStyle::Key getStyle(char ** tokens) -{ - QtFontStyle::Key key; - - char slant0 = tolower((uchar) tokens[Slant][0]); - - if (slant0 == 'r') { - if (tokens[Slant][1]) { - char slant1 = tolower((uchar) tokens[Slant][1]); - - if (slant1 == 'o') - key.style = QFont::StyleOblique; - else if (slant1 == 'i') - key.style = QFont::StyleItalic; - } - } else if (slant0 == 'o') - key.style = QFont::StyleOblique; - else if (slant0 == 'i') - key.style = QFont::StyleItalic; - - key.weight = getFontWeight(QLatin1String(tokens[Weight])); - - if (qstrcmp(tokens[Width], "normal") == 0) { - key.stretch = 100; - } else if (qstrcmp(tokens[Width], "semi condensed") == 0 || - qstrcmp(tokens[Width], "semicondensed") == 0) { - key.stretch = 90; - } else if (qstrcmp(tokens[Width], "condensed") == 0) { - key.stretch = 80; - } else if (qstrcmp(tokens[Width], "narrow") == 0) { - key.stretch = 60; - } - - return key; -} - - -static bool xlfdsFullyLoaded = false; -static unsigned char encodingLoaded[numEncodings]; - -static void loadXlfds(const char *reqFamily, int encoding_id) -{ - QFontDatabasePrivate *db = privateDb(); - QtFontFamily *fontFamily = reqFamily ? db->family(QLatin1String(reqFamily)) : 0; - - // make sure we don't load twice - if ((encoding_id == -1 && xlfdsFullyLoaded) - || (encoding_id != -1 && encodingLoaded[encoding_id])) - return; - if (fontFamily && fontFamily->xlfdLoaded) - return; - - int fontCount; - // force the X server to give us XLFDs - QByteArray xlfd_pattern("-*-"); - xlfd_pattern += (reqFamily && reqFamily[0] != '\0') ? reqFamily : "*"; - xlfd_pattern += "-*-*-*-*-*-*-*-*-*-*-"; - xlfd_pattern += xlfd_for_id(encoding_id); - - char **fontList = XListFonts(QX11Info::display(), - xlfd_pattern, - 0xffff, &fontCount); - // qDebug("requesting xlfd='%s', got %d fonts", xlfd_pattern.data(), fontCount); - - - char *tokens[NFontFields]; - - for(int i = 0 ; i < fontCount ; i++) { - if (! parseXFontName(fontList[i], tokens)) - continue; - - // get the encoding_id for this xlfd. we need to do this - // here, since we can pass -1 to this function to do full - // database population - *(tokens[CharsetEncoding] - 1) = '-'; - int encoding_id = qt_xlfd_encoding_id(tokens[CharsetRegistry]); - if (encoding_id == -1) - continue; - - char *familyName = tokens[Family]; - capitalize(familyName); - char *foundryName = tokens[Foundry]; - capitalize(foundryName); - QtFontStyle::Key styleKey = getStyle(tokens); - - bool smooth_scalable = false; - bool bitmap_scalable = false; - if (isScalable(tokens)) { - if (isSmoothlyScalable(tokens)) - smooth_scalable = true; - else - bitmap_scalable = true; - } - uint pixelSize = atoi(tokens[PixelSize]); - uint xpointSize = atoi(tokens[PointSize]); - uint xres = atoi(tokens[ResolutionX]); - uint yres = atoi(tokens[ResolutionY]); - uint avgwidth = atoi(tokens[AverageWidth]); - bool fixedPitch = isFixedPitch(tokens); - - if (avgwidth == 0 && pixelSize != 0) { - /* - Ignore bitmap scalable fonts that are automatically - generated by some X servers. We know they are bitmap - scalable because even though they have a specified pixel - size, the average width is zero. - */ - continue; - } - - QtFontFamily *family = fontFamily ? fontFamily : db->family(QLatin1String(familyName), true); - family->fontFileIndex = -1; - family->symbol_checked = true; - QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true); - QtFontStyle *style = foundry->style(styleKey, QString(), true); - - delete [] style->weightName; - style->weightName = qstrdup(tokens[Weight]); - delete [] style->setwidthName; - style->setwidthName = qstrdup(tokens[Width]); - - if (smooth_scalable) { - style->smoothScalable = true; - style->bitmapScalable = false; - pixelSize = SMOOTH_SCALABLE; - } - if (!style->smoothScalable && bitmap_scalable) - style->bitmapScalable = true; - if (!fixedPitch) - family->fixedPitch = false; - - QtFontSize *size = style->pixelSize(pixelSize, true); - QtFontEncoding *enc = - size->encodingID(encoding_id, xpointSize, xres, yres, avgwidth, true); - enc->pitch = *tokens[Spacing]; - if (!enc->pitch) enc->pitch = '*'; - - for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { - if (writingSystems_for_xlfd_encoding[encoding_id][i]) - family->writingSystems[i] = QtFontFamily::Supported; - } - } - if (!reqFamily) { - // mark encoding as loaded - if (encoding_id == -1) - xlfdsFullyLoaded = true; - else - encodingLoaded[encoding_id] = true; - } - - XFreeFontNames(fontList); -} - - -#ifndef QT_NO_FONTCONFIG - -#ifndef FC_WIDTH -#define FC_WIDTH "width" -#endif - -static int getFCWeight(int fc_weight) -{ - int qtweight = QFont::Black; - if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2) - qtweight = QFont::Light; - else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2) - qtweight = QFont::Normal; - else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2) - qtweight = QFont::DemiBold; - else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) - qtweight = QFont::Bold; - - return qtweight; -} - -QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request) -{ - QFontDef fontDef; - fontDef.styleStrategy = request.styleStrategy; - - fontDef.hintingPreference = request.hintingPreference; - FcChar8 *value = 0; - if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) { - fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value)); - } - - double dpi; - if (FcPatternGetDouble(pattern, FC_DPI, 0, &dpi) != FcResultMatch) { - if (X11->display) - dpi = QX11Info::appDpiY(); - else - dpi = qt_defaultDpiY(); - } - - double size; - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) - fontDef.pixelSize = size; - else - fontDef.pixelSize = 12; - - fontDef.pointSize = qt_pointSize(fontDef.pixelSize, qRound(dpi)); - - /* ### - fontDef.styleHint - */ - - int weight; - if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch) - weight = FC_WEIGHT_MEDIUM; - fontDef.weight = getFCWeight(weight); - - int slant; - if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch) - slant = FC_SLANT_ROMAN; - fontDef.style = (slant == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - - - FcBool scalable; - if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = false; - if (scalable) { - fontDef.stretch = request.stretch; - fontDef.style = request.style; - } else { - int width; - if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width) == FcResultMatch) - fontDef.stretch = width; - else - fontDef.stretch = 100; - } - - int spacing; - if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch) { - fontDef.fixedPitch = (spacing >= FC_MONO); - fontDef.ignorePitch = false; - } else { - fontDef.ignorePitch = true; - } - - return fontDef; -} - -static const char *specialLanguages[] = { - "en", // Common - "el", // Greek - "ru", // Cyrillic - "hy", // Armenian - "he", // Hebrew - "ar", // Arabic - "syr", // Syriac - "div", // Thaana - "hi", // Devanagari - "bn", // Bengali - "pa", // Gurmukhi - "gu", // Gujarati - "or", // Oriya - "ta", // Tamil - "te", // Telugu - "kn", // Kannada - "ml", // Malayalam - "si", // Sinhala - "th", // Thai - "lo", // Lao - "bo", // Tibetan - "my", // Myanmar - "ka", // Georgian - "ko", // Hangul - "", // Ogham - "", // Runic - "km", // Khmer - "" // N'Ko -}; -enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; - -static const ushort specialChars[] = { - 0, // English - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - 0, // Syriac - 0, // Thaana - 0, // Devanagari - 0, // Bengali - 0, // Gurmukhi - 0, // Gujarati - 0, // Oriya - 0, // Tamil - 0xc15, // Telugu - 0xc95, // Kannada - 0xd15, // Malayalam - 0xd9a, // Sinhala - 0, // Thai - 0, // Lao - 0, // Tibetan - 0x1000, // Myanmar - 0, // Georgian - 0, // Hangul - 0x1681, // Ogham - 0x16a0, // Runic - 0, // Khmer - 0x7ca // N'Ko -}; -enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; - -// this could become a list of all languages used for each writing -// system, instead of using the single most common language. -static const char *languageForWritingSystem[] = { - 0, // Any - "en", // Latin - "el", // Greek - "ru", // Cyrillic - "hy", // Armenian - "he", // Hebrew - "ar", // Arabic - "syr", // Syriac - "div", // Thaana - "hi", // Devanagari - "bn", // Bengali - "pa", // Gurmukhi - "gu", // Gujarati - "or", // Oriya - "ta", // Tamil - "te", // Telugu - "kn", // Kannada - "ml", // Malayalam - "si", // Sinhala - "th", // Thai - "lo", // Lao - "bo", // Tibetan - "my", // Myanmar - "ka", // Georgian - "km", // Khmer - "zh-cn", // SimplifiedChinese - "zh-tw", // TraditionalChinese - "ja", // Japanese - "ko", // Korean - "vi", // Vietnamese - 0, // Symbol - 0, // Ogham - 0, // Runic - 0 // N'Ko -}; -enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; - -// Unfortunately FontConfig doesn't know about some languages. We have to test these through the -// charset. The lists below contain the systems where we need to do this. -static const ushort sampleCharForWritingSystem[] = { - 0, // Any - 0, // Latin - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - 0, // Syriac - 0, // Thaana - 0, // Devanagari - 0, // Bengali - 0, // Gurmukhi - 0, // Gujarati - 0, // Oriya - 0, // Tamil - 0xc15, // Telugu - 0xc95, // Kannada - 0xd15, // Malayalam - 0xd9a, // Sinhala - 0, // Thai - 0, // Lao - 0, // Tibetan - 0x1000, // Myanmar - 0, // Georgian - 0, // Khmer - 0, // SimplifiedChinese - 0, // TraditionalChinese - 0, // Japanese - 0, // Korean - 0, // Vietnamese - 0, // Symbol - 0x1681, // Ogham - 0x16a0, // Runic - 0x7ca // N'Ko -}; -enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) }; - -// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no -// open type tables for is directly. Do this so we don't pick some strange -// pseudo unicode font -static const char *openType[] = { - 0, // Any - 0, // Latin - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - "syrc", // Syriac - "thaa", // Thaana - "deva", // Devanagari - "beng", // Bengali - "guru", // Gurmukhi - "gurj", // Gujarati - "orya", // Oriya - "taml", // Tamil - "telu", // Telugu - "knda", // Kannada - "mlym", // Malayalam - "sinh", // Sinhala - 0, // Thai - 0, // Lao - "tibt", // Tibetan - "mymr", // Myanmar - 0, // Georgian - "khmr", // Khmer - 0, // SimplifiedChinese - 0, // TraditionalChinese - 0, // Japanese - 0, // Korean - 0, // Vietnamese - 0, // Symbol - 0, // Ogham - 0, // Runic - "nko " // N'Ko -}; -enum { OpenTypeCount = sizeof(openType) / sizeof(const char *) }; - - -static void loadFontConfig() -{ - Q_ASSERT_X(X11, "QFontDatabase", - "A QApplication object needs to be constructed before FontConfig is used."); - if (!X11->has_fontconfig) - return; - - Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialLanguageCount, - "QFontDatabase", "New scripts have been added."); - Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialCharCount, - "QFontDatabase", "New scripts have been added."); - Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == LanguageCount, - "QFontDatabase", "New writing systems have been added."); - Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == SampleCharCount, - "QFontDatabase", "New writing systems have been added."); - Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == OpenTypeCount, - "QFontDatabase", "New writing systems have been added."); - - QFontDatabasePrivate *db = privateDb(); - FcFontSet *fonts; - - FcPattern *pattern = FcPatternCreate(); - FcDefaultSubstitute(pattern); - FcChar8 *lang = 0; - if (FcPatternGetString(pattern, FC_LANG, 0, &lang) == FcResultMatch) - db->systemLang = QString::fromUtf8((const char *) lang); - FcPatternDestroy(pattern); - - QString familyName; - FcChar8 *value = 0; - int weight_value; - int slant_value; - int spacing_value; - FcChar8 *file_value; - int index_value; - FcChar8 *foundry_value; - FcChar8 *style_value; - FcBool scalable; - - { - FcObjectSet *os = FcObjectSetCreate(); - FcPattern *pattern = FcPatternCreate(); - const char *properties [] = { - FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, - FC_SPACING, FC_FILE, FC_INDEX, - FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, - FC_WIDTH, -#if FC_VERSION >= 20297 - FC_CAPABILITY, -#endif - (const char *)0 - }; - const char **p = properties; - while (*p) { - FcObjectSetAdd(os, *p); - ++p; - } - fonts = FcFontList(0, pattern, os); - FcObjectSetDestroy(os); - FcPatternDestroy(pattern); - } - - for (int i = 0; i < fonts->nfont; i++) { - if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) - continue; - // capitalize(value); - familyName = QString::fromUtf8((const char *)value); - slant_value = FC_SLANT_ROMAN; - weight_value = FC_WEIGHT_MEDIUM; - spacing_value = FC_PROPORTIONAL; - file_value = 0; - index_value = 0; - scalable = FcTrue; - - if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) - slant_value = FC_SLANT_ROMAN; - if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) - weight_value = FC_WEIGHT_MEDIUM; - if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) - spacing_value = FC_PROPORTIONAL; - if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) - file_value = 0; - if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &index_value) != FcResultMatch) - index_value = 0; - if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = FcTrue; - if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) - foundry_value = 0; - if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch) - style_value = 0; - QtFontFamily *family = db->family(familyName, true); - - FcLangSet *langset = 0; - FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); - if (res == FcResultMatch) { - for (int i = 1; i < LanguageCount; ++i) { - const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; - if (!lang) { - family->writingSystems[i] |= QtFontFamily::UnsupportedFT; - } else { - FcLangResult langRes = FcLangSetHasLang(langset, lang); - if (langRes != FcLangDifferentLang) - family->writingSystems[i] = QtFontFamily::Supported; - else - family->writingSystems[i] |= QtFontFamily::UnsupportedFT; - } - } - family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT; - family->ftWritingSystemCheck = true; - } else { - // we set Other to supported for symbol fonts. It makes no - // sense to merge these with other ones, as they are - // special in a way. - for (int i = 1; i < LanguageCount; ++i) - family->writingSystems[i] |= QtFontFamily::UnsupportedFT; - family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported; - } - - FcCharSet *cs = 0; - res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); - if (res == FcResultMatch) { - // some languages are not supported by FontConfig, we rather check the - // charset to detect these - for (int i = 1; i < SampleCharCount; ++i) { - if (!sampleCharForWritingSystem[i]) - continue; - if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) - family->writingSystems[i] = QtFontFamily::Supported; - } - } - -#if FC_VERSION >= 20297 - for (int j = 1; j < LanguageCount; ++j) { - if (family->writingSystems[j] == QtFontFamily::Supported && requiresOpenType(j) && openType[j]) { - FcChar8 *cap; - res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); - if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) - family->writingSystems[j] = QtFontFamily::UnsupportedFT; - } - } -#endif - - QByteArray file((const char *)file_value); - family->fontFilename = file; - family->fontFileIndex = index_value; - - QtFontStyle::Key styleKey; - QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); - styleKey.style = (slant_value == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant_value == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - styleKey.weight = getFCWeight(weight_value); - if (!scalable) { - int width = 100; - FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); - styleKey.stretch = width; - } - - QtFontFoundry *foundry - = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true); - QtFontStyle *style = foundry->style(styleKey, styleName, true); - - if (spacing_value < FC_MONO) - family->fixedPitch = false; - - QtFontSize *size; - if (scalable) { - style->smoothScalable = true; - size = style->pixelSize(SMOOTH_SCALABLE, true); - } else { - double pixel_size = 0; - FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); - size = style->pixelSize((int)pixel_size, true); - } - QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); - enc->pitch = (spacing_value >= FC_CHARCELL ? 'c' : - (spacing_value >= FC_MONO ? 'm' : 'p')); - } - - FcFontSetDestroy (fonts); - - struct FcDefaultFont { - const char *qtname; - const char *rawname; - bool fixed; - }; - const FcDefaultFont defaults[] = { - { "Serif", "serif", false }, - { "Sans Serif", "sans-serif", false }, - { "Monospace", "monospace", true }, - { 0, 0, false } - }; - const FcDefaultFont *f = defaults; - while (f->qtname) { - QtFontFamily *family = db->family(QLatin1String(f->qtname), true); - family->fixedPitch = f->fixed; - family->synthetic = true; - QtFontFoundry *foundry = family->foundry(QString(), true); - - // aliases only make sense for 'common', not for any of the specials - for (int i = 1; i < LanguageCount; ++i) { - if (requiresOpenType(i)) - family->writingSystems[i] = QtFontFamily::UnsupportedFT; - else - family->writingSystems[i] = QtFontFamily::Supported; - } - family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT; - - QtFontStyle::Key styleKey; - for (int i = 0; i < 4; ++i) { - styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic; - styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal; - QtFontStyle *style = foundry->style(styleKey, QString(), true); - style->smoothScalable = true; - QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true); - QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); - enc->pitch = (f->fixed ? 'm' : 'p'); - } - ++f; - } -} -#endif // QT_NO_FONTCONFIG - -static void initializeDb(); - -static void load(const QString &family = QString(), int script = -1, bool forceXLFD = false) -{ - if (X11->has_fontconfig && !forceXLFD) { - initializeDb(); - return; - } - -#ifdef QFONTDATABASE_DEBUG - QElapsedTimer t; - t.start(); -#endif - - if (family.isNull() && script == -1) { - loadXlfds(0, -1); - } else { - if (family.isNull()) { - // load all families in all writing systems that match \a script - for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { - if (scriptForWritingSystem[ws] != script) - continue; - for (int i = 0; i < numEncodings; ++i) { - if (writingSystems_for_xlfd_encoding[i][ws]) - loadXlfds(0, i); - } - } - } else { - QtFontFamily *f = privateDb()->family(family); - // could reduce this further with some more magic: - // would need to remember the encodings loaded for the family. - if (!f || !f->xlfdLoaded) - loadXlfds(family.toLatin1(), -1); - } - } - -#ifdef QFONTDATABASE_DEBUG - FD_DEBUG("QFontDatabase: load(%s, %d) took %d ms", - family.toLatin1().constData(), script, t.elapsed()); -#endif -} - -static void checkSymbolFont(QtFontFamily *family) -{ - if (!family || family->symbol_checked || family->fontFilename.isEmpty()) - return; -// qDebug() << "checking " << family->rawName; - family->symbol_checked = true; - - QFontEngine::FaceId id; - id.filename = family->fontFilename; - id.index = family->fontFileIndex; - QFreetypeFace *f = QFreetypeFace::getFace(id); - if (!f) { - qWarning("checkSymbolFonts: Couldn't open face %s (%s/%d)", - qPrintable(family->name), family->fontFilename.data(), family->fontFileIndex); - return; - } - for (int i = 0; i < f->face->num_charmaps; ++i) { - FT_CharMap cm = f->face->charmaps[i]; - if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM - || cm->encoding == FT_ENCODING_MS_SYMBOL) { - for (int x = QFontDatabase::Latin; x < QFontDatabase::Other; ++x) - family->writingSystems[x] = QtFontFamily::Unsupported; - family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported; - break; - } - } - f->release(id); -} - -static void checkSymbolFonts(const QString &family = QString()) -{ -#ifndef QT_NO_FONTCONFIG - QFontDatabasePrivate *d = privateDb(); - - if (family.isEmpty()) { - for (int i = 0; i < d->count; ++i) - checkSymbolFont(d->families[i]); - } else { - checkSymbolFont(d->family(family)); - } -#endif -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt); - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db || db->count) - return; - - QElapsedTimer t; - t.start(); - -#ifndef QT_NO_FONTCONFIG - if (db->reregisterAppFonts) { - db->reregisterAppFonts = false; - for (int i = 0; i < db->applicationFonts.count(); ++i) - if (!db->applicationFonts.at(i).families.isEmpty()) { - registerFont(&db->applicationFonts[i]); - } - } - - loadFontConfig(); - FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(t.elapsed())); -#endif - - t.start(); - -#ifndef QT_NO_FONTCONFIG - for (int i = 0; i < db->count; i++) { - for (int j = 0; j < db->families[i]->count; ++j) { // each foundry - QtFontFoundry *foundry = db->families[i]->foundries[j]; - for (int k = 0; k < foundry->count; ++k) { - QtFontStyle *style = foundry->styles[k]; - if (style->key.style != QFont::StyleNormal) continue; - - QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE); - if (! size) continue; // should not happen - QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); - if (! enc) continue; // should not happen either - - QtFontStyle::Key key = style->key; - - // does this style have an italic equivalent? - key.style = QFont::StyleItalic; - QtFontStyle *equiv = foundry->style(key); - if (equiv) continue; - - // does this style have an oblique equivalent? - key.style = QFont::StyleOblique; - equiv = foundry->style(key); - if (equiv) continue; - - // let's fake one... - equiv = foundry->style(key, QString(), true); - equiv->smoothScalable = true; - - QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true); - QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true); - - // keep the same pitch - equiv_enc->pitch = enc->pitch; - } - } - } -#endif - - -#ifdef QFONTDATABASE_DEBUG -#ifndef QT_NO_FONTCONFIG - if (!X11->has_fontconfig) -#endif - // load everything at startup in debug mode. - loadXlfds(0, -1); - - // print the database - for (int f = 0; f < db->count; f++) { - QtFontFamily *family = db->families[f]; - FD_DEBUG("'%s' %s fixed=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""), - (family->fixedPitch ? "yes" : "no")); - for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { - QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i); - FD_DEBUG("\t%s: %s", QFontDatabase::writingSystemName(ws).toLatin1().constData(), - ((family->writingSystems[i] & QtFontFamily::Supported) ? "Supported" : - (family->writingSystems[i] & QtFontFamily::Unsupported) == QtFontFamily::Unsupported ? - "Unsupported" : "Unknown")); - } - - for (int fd = 0; fd < family->count; fd++) { - QtFontFoundry *foundry = family->foundries[fd]; - FD_DEBUG("\t\t'%s'", foundry->name.latin1()); - for (int s = 0; s < foundry->count; s++) { - QtFontStyle *style = foundry->styles[s]; - FD_DEBUG("\t\t\tstyle: style=%d weight=%d (%s)\n" - "\t\t\tstretch=%d (%s)", - style->key.style, style->key.weight, - style->weightName, style->key.stretch, - style->setwidthName ? style->setwidthName : "nil"); - if (style->smoothScalable) - FD_DEBUG("\t\t\t\tsmooth scalable"); - else if (style->bitmapScalable) - FD_DEBUG("\t\t\t\tbitmap scalable"); - if (style->pixelSizes) { - qDebug("\t\t\t\t%d pixel sizes", style->count); - for (int z = 0; z < style->count; ++z) { - QtFontSize *size = style->pixelSizes + z; - for (int e = 0; e < size->count; ++e) { - FD_DEBUG("\t\t\t\t size %5d pitch %c encoding %s", - size->pixelSize, - size->encodings[e].pitch, - xlfd_for_id(size->encodings[e].encoding)); - } - } - } - } - } - } -#endif // QFONTDATABASE_DEBUG -} - - -// -------------------------------------------------------------------------------------- -// font loader -// -------------------------------------------------------------------------------------- - -static const char *styleHint(const QFontDef &request) -{ - const char *stylehint = 0; - switch (request.styleHint) { - case QFont::SansSerif: - stylehint = "sans-serif"; - break; - case QFont::Serif: - stylehint = "serif"; - break; - case QFont::TypeWriter: - stylehint = "monospace"; - break; - default: - if (request.fixedPitch) - stylehint = "monospace"; - break; - } - return stylehint; -} - -#ifndef QT_NO_FONTCONFIG - -void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontDef &request) -{ - double size_value = qMax(qreal(1.), request.pixelSize); - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value); - - if (X11->display && QX11Info::appDepth(screen) <= 8) { - FcPatternDel(pattern, FC_ANTIALIAS); - // can't do antialiasing on 8bpp - FcPatternAddBool(pattern, FC_ANTIALIAS, false); - } else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) { - FcPatternDel(pattern, FC_ANTIALIAS); - FcPatternAddBool(pattern, FC_ANTIALIAS, - !(request.styleStrategy & QFont::NoAntialias)); - } - - if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { - Q_ASSERT(script < QUnicodeTables::ScriptCount); - FcLangSet *ls = FcLangSetCreate(); - FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); - FcPatternDel(pattern, FC_LANG); - FcPatternAddLangSet(pattern, FC_LANG, ls); - FcLangSetDestroy(ls); - } - - if (!request.styleName.isEmpty()) { - QByteArray cs = request.styleName.toUtf8(); - FcPatternAddString(pattern, FC_STYLE, (const FcChar8 *) cs.constData()); - return; - } - - int weight_value = FC_WEIGHT_BLACK; - if (request.weight == 0) - weight_value = FC_WEIGHT_MEDIUM; - else if (request.weight < (QFont::Light + QFont::Normal) / 2) - weight_value = FC_WEIGHT_LIGHT; - else if (request.weight < (QFont::Normal + QFont::DemiBold) / 2) - weight_value = FC_WEIGHT_MEDIUM; - else if (request.weight < (QFont::DemiBold + QFont::Bold) / 2) - weight_value = FC_WEIGHT_DEMIBOLD; - else if (request.weight < (QFont::Bold + QFont::Black) / 2) - weight_value = FC_WEIGHT_BOLD; - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, weight_value); - - int slant_value = FC_SLANT_ROMAN; - if (request.style == QFont::StyleItalic) - slant_value = FC_SLANT_ITALIC; - else if (request.style == QFont::StyleOblique) - slant_value = FC_SLANT_OBLIQUE; - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, slant_value); - - int stretch = request.stretch; - if (!stretch) - stretch = 100; - FcPatternDel(pattern, FC_WIDTH); - FcPatternAddInteger(pattern, FC_WIDTH, stretch); -} - -static bool preferScalable(const QFontDef &request) -{ - return request.styleStrategy & (QFont::PreferOutline|QFont::ForceOutline|QFont::PreferQuality|QFont::PreferAntialias); -} - - -static FcPattern *getFcPattern(const QFontPrivate *fp, int script, const QFontDef &request) -{ - if (!X11->has_fontconfig) - return 0; - - FcPattern *pattern = FcPatternCreate(); - if (!pattern) - return 0; - - FcValue value; - value.type = FcTypeString; - - QtFontDesc desc; - QStringList families_and_foundries = familyList(request); - for (int i = 0; i < families_and_foundries.size(); ++i) { - QString family, foundry; - parseFontName(families_and_foundries.at(i), foundry, family); - if (!family.isEmpty()) { - QByteArray cs = family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern, FC_FAMILY, value, FcTrue); - } - if (i == 0) { - QT_PREPEND_NAMESPACE(match)(script, request, family, foundry, -1, &desc); - if (!foundry.isEmpty()) { - QByteArray cs = foundry.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FOUNDRY, value, FcTrue); - } - } - } - - const char *stylehint = styleHint(request); - if (stylehint) { - value.u.s = (const FcChar8 *)stylehint; - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - } - - if (!request.ignorePitch) { - char pitch_value = FC_PROPORTIONAL; - if (request.fixedPitch || (desc.family && desc.family->fixedPitch)) - pitch_value = FC_MONO; - FcPatternAddInteger(pattern, FC_SPACING, pitch_value); - } - FcPatternAddBool(pattern, FC_OUTLINE, !(request.styleStrategy & QFont::PreferBitmap)); - if (preferScalable(request) || (desc.style && desc.style->smoothScalable)) - FcPatternAddBool(pattern, FC_SCALABLE, true); - - qt_addPatternProps(pattern, fp->screen, script, request); - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - // these should only get added to the pattern _after_ substitution - // append the default fallback font for the specified script - extern QString qt_fallback_font_family(int); - QString fallback = qt_fallback_font_family(script); - if (!fallback.isEmpty()) { - QByteArray cs = fallback.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - } - - // add the default family - QString defaultFamily = QApplication::font().family(); - QByteArray cs = defaultFamily.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - defaultFamily = QApplication::font().defaultFamily(); - cs = defaultFamily.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - - return pattern; -} - - -static void FcFontSetRemove(FcFontSet *fs, int at) -{ - Q_ASSERT(at < fs->nfont); - FcPatternDestroy(fs->fonts[at]); - int len = (--fs->nfont - at) * sizeof(FcPattern *);; - if (len > 0) - memmove(fs->fonts + at, fs->fonts + at + 1, len); -} - -static QFontEngine *tryPatternLoad(FcPattern *match, int screen, - const QFontDef &request, int script) -{ -#ifdef FONT_MATCH_DEBUG - FcChar8 *fam; - FcPatternGetString(match, FC_FAMILY, 0, &fam); - FM_DEBUG("==== trying %s\n", fam); -#endif - FM_DEBUG("passes charset test\n"); - - QFontEngineX11FT *engine = 0; - if (!match) // probably no fonts available. - goto done; - - if (script != QUnicodeTables::Common) { - // skip font if it doesn't support the language we want - if (specialChars[script]) { - // need to check the charset, as the langset doesn't work for these scripts - FcCharSet *cs; - if (FcPatternGetCharSet(match, FC_CHARSET, 0, &cs) != FcResultMatch) - goto done; - if (!FcCharSetHasChar(cs, specialChars[script])) - goto done; - } else if (*specialLanguages[script] != '\0'){ - FcLangSet *langSet = 0; - if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch) - goto done; - if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual) - goto done; - } - } - - // enforce non-antialiasing if requested. the ft font engine looks at this property. - if (request.styleStrategy & QFont::NoAntialias) { - FcPatternDel(match, FC_ANTIALIAS); - FcPatternAddBool(match, FC_ANTIALIAS, false); - } - - engine = new QFontEngineX11FT(match, qt_FcPatternToQFontDef(match, request), screen); - if (engine->invalid()) { - FM_DEBUG(" --> invalid!\n"); - delete engine; - engine = 0; - } else if (scriptRequiresOpenType(script)) { - HB_Face hbFace = engine->harfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { - FM_DEBUG(" OpenType support missing for script\n"); - delete engine; - engine = 0; - } - } -done: - return engine; -} - -FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request) -{ - FcResult result; - FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result); -#ifdef FONT_MATCH_DEBUG - FM_DEBUG("first font in fontset:\n"); - FcPatternPrint(fs->fonts[0]); -#endif - - FcBool forceScalable = request.styleStrategy & QFont::ForceOutline; - - // remove fonts if they are not scalable (and should be) - if (forceScalable && fs) { - for (int i = 0; i < fs->nfont; ++i) { - FcPattern *font = fs->fonts[i]; - FcResult res; - FcBool scalable; - res = FcPatternGetBool(font, FC_SCALABLE, 0, &scalable); - if (res != FcResultMatch || !scalable) { - FcFontSetRemove(fs, i); -#ifdef FONT_MATCH_DEBUG - FM_DEBUG("removing pattern:"); - FcPatternPrint(font); -#endif - --i; // go back one - } - } - } - - FM_DEBUG("final pattern contains %d fonts\n", fs->nfont); - - return fs; -} - -static QFontEngine *loadFc(const QFontPrivate *fp, int script, const QFontDef &request) -{ - FM_DEBUG("===================== loadFc: script=%d family='%s'\n", script, request.family.toLatin1().data()); - FcPattern *pattern = getFcPattern(fp, script, request); - -#ifdef FONT_MATCH_DEBUG - FM_DEBUG("\n\nfinal FcPattern contains:\n"); - FcPatternPrint(pattern); -#endif - - QFontEngine *fe = 0; - FcResult res; - FcPattern *match = FcFontMatch(0, pattern, &res); - fe = tryPatternLoad(match, fp->screen, request, script); - if (!fe) { - FcFontSet *fs = qt_fontSetForPattern(pattern, request); - - if (match) { - FcPatternDestroy(match); - match = 0; - } - - if (fs) { - for (int i = 0; !fe && i < fs->nfont; ++i) { - match = FcFontRenderPrepare(NULL, pattern, fs->fonts[i]); - fe = tryPatternLoad(match, fp->screen, request, script); - if (fe) - break; - FcPatternDestroy(match); - match = 0; - } - FcFontSetDestroy(fs); - } - FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)"); - } - if (fe - && script == QUnicodeTables::Common - && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) { - fe = new QFontEngineMultiFT(fe, match, pattern, fp->screen, request); - } else { - FcPatternDestroy(pattern); - if (match) - FcPatternDestroy(match); - } - return fe; -} - -static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count) -{ -#if FC_VERSION < 20402 - Q_UNUSED(data) - return FcFreeTypeQuery(file, id, blanks, count); -#else - if (data.isEmpty()) - return FcFreeTypeQuery(file, id, blanks, count); - - extern FT_Library qt_getFreetype(); - FT_Library lib = qt_getFreetype(); - - FcPattern *pattern = 0; - - FT_Face face; - if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { - *count = face->num_faces; - - pattern = FcFreeTypeQueryFace(face, file, id, blanks); - - FT_Done_Face(face); - } - - return pattern; -#endif -} -#endif // QT_NO_FONTCONFIG - -static QFontEngine *loadRaw(const QFontPrivate *fp, const QFontDef &request) -{ - Q_ASSERT(fp && fp->rawMode); - - QByteArray xlfd = request.family.toLatin1(); - FM_DEBUG("Loading XLFD (rawmode) '%s'", xlfd.data()); - - QFontEngine *fe; - XFontStruct *xfs; - if (!(xfs = XLoadQueryFont(QX11Info::display(), xlfd.data()))) - if (!(xfs = XLoadQueryFont(QX11Info::display(), "fixed"))) - return 0; - - fe = new QFontEngineXLFD(xfs, xlfd, 0); - if (! qt_fillFontDef(xfs, &fe->fontDef, fp->dpi, 0) && - ! qt_fillFontDef(xlfd, &fe->fontDef, fp->dpi, 0)) - fe->fontDef = QFontDef(); - return fe; -} - -QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &request, int force_encoding_id) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QtFontDesc desc; - FM_DEBUG() << "---> loadXlfd: request is" << request.family; - QStringList families_and_foundries = familyList(request); - const char *stylehint = styleHint(request); - if (stylehint) - families_and_foundries << QString::fromLatin1(stylehint); - families_and_foundries << QString(); - FM_DEBUG() << "loadXlfd: list is" << families_and_foundries; - for (int i = 0; i < families_and_foundries.size(); ++i) { - QString family, foundry; - QT_PREPEND_NAMESPACE(parseFontName)(families_and_foundries.at(i), foundry, family); - FM_DEBUG("loadXlfd: >>>>>>>>>>>>>>trying to match '%s' encoding=%d", family.toLatin1().data(), force_encoding_id); - QT_PREPEND_NAMESPACE(match)(script, request, family, foundry, force_encoding_id, &desc, QList<int>(), true); - if (desc.family) - break; - } - - QFontEngine *fe = 0; - if (force_encoding_id != -1 - || (request.styleStrategy & QFont::NoFontMerging) - || (desc.family && desc.family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) { - if (desc.family) { - int px = desc.size->pixelSize; - if (desc.style->smoothScalable && px == SMOOTH_SCALABLE) - px = request.pixelSize; - else if (desc.style->bitmapScalable && px == 0) - px = request.pixelSize; - - QByteArray xlfd("-"); - xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1(); - xlfd += '-'; - xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1(); - xlfd += '-'; - xlfd += desc.style->weightName ? desc.style->weightName : "*"; - xlfd += '-'; - xlfd += (desc.style->key.style == QFont::StyleItalic - ? 'i' - : (desc.style->key.style == QFont::StyleOblique ? 'o' : 'r')); - xlfd += '-'; - xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*"; - // ### handle add-style - xlfd += "-*-"; - xlfd += QByteArray::number(px); - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->xpoint); - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->xres); - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->yres); - xlfd += '-'; - xlfd += desc.encoding->pitch; - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->avgwidth); - xlfd += '-'; - xlfd += xlfd_for_id(desc.encoding->encoding); - - FM_DEBUG(" using XLFD: %s\n", xlfd.data()); - - const int mib = xlfd_encoding[desc.encoding->encoding].mib; - XFontStruct *xfs; - if ((xfs = XLoadQueryFont(QX11Info::display(), xlfd))) { - fe = new QFontEngineXLFD(xfs, xlfd, mib); - const int dpi = QX11Info::appDpiY(); - if (!qt_fillFontDef(xfs, &fe->fontDef, dpi, &desc) - && !qt_fillFontDef(xlfd, &fe->fontDef, dpi, &desc)) { - initFontDef(desc, request, &fe->fontDef); - } - } - } - if (!fe) { - fe = new QFontEngineBox(request.pixelSize); - fe->fontDef = QFontDef(); - } - } else { - QList<int> encodings; - if (desc.encoding) { - if (desc.encoding->encoding >= 0) - encodings.append(int(desc.encoding->encoding)); - } - - if (desc.size) { - // append all other encodings for the matched font - for (int i = 0; i < desc.size->count; ++i) { - QtFontEncoding *e = desc.size->encodings + i; - if (e == desc.encoding || e->encoding < 0) - continue; - encodings.append(int(e->encoding)); - } - } - // fill in the missing encodings - const XlfdEncoding *enc = xlfd_encoding; - for (; enc->name; ++enc) { - if (!encodings.contains(enc->id) && enc->id >= 0) { - encodings.append(enc->id); - } - } - -#if defined(FONT_MATCH_DEBUG) - FM_DEBUG(" using MultiXLFD, encodings:"); - for (int i = 0; i < encodings.size(); ++i) { - const int id = encodings.at(i); - FM_DEBUG(" %2d: %s", xlfd_encoding[id].id, xlfd_encoding[id].name); - } -#endif - - fe = new QFontEngineMultiXLFD(request, encodings, screen); - } - return fe; -} - -#if (defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6)) && defined(Q_CC_GNU) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) -#define NEEDS_GCC_BUG_WORKAROUND -#endif - -#ifdef NEEDS_GCC_BUG_WORKAROUND -static inline void gccBugWorkaround(const QFontDef &req) -{ - char buffer[8]; - snprintf(buffer, 8, "%f", req.pixelSize); -} -#endif - -/*! \internal - Loads a QFontEngine for the specified \a script that matches the - QFontDef \e request member variable. -*/ -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); - - // normalize the request to get better caching - QFontDef req = d->request; - if (req.pixelSize <= 0) - req.pixelSize = qFloor(qt_pixelSize(req.pointSize, d->dpi) * 100.0 + 0.5) * 0.01; - if (req.pixelSize < 1) - req.pixelSize = 1; - -#ifdef NEEDS_GCC_BUG_WORKAROUND - // req.pixelSize ends up with a bogus value unless this workaround is called - gccBugWorkaround(req); -#endif - - if (req.weight == 0) - req.weight = QFont::Normal; - if (req.stretch == 0) - req.stretch = 100; - - QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen); - if (!d->engineData) - getEngineData(d, key); - - // the cached engineData could have already loaded the engine we want - if (d->engineData->engines[script]) - return; - - // set it to the actual pointsize, so QFontInfo will do the right thing - if (req.pointSize < 0) - req.pointSize = qt_pointSize(req.pixelSize, d->dpi); - - - QFontEngine *fe = QFontCache::instance()->findEngine(key); - - if (!fe) { - QMutexLocker locker(fontDatabaseMutex()); - if (!privateDb()->count) - initializeDb(); - - const bool mainThread = (qApp->thread() == QThread::currentThread()); - if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - fe = new QTestFontEngine(req.pixelSize); - fe->fontDef = req; - } else if (d->rawMode) { - if (mainThread) - fe = loadRaw(d, req); -#ifndef QT_NO_FONTCONFIG - } else if (X11->has_fontconfig) { - fe = loadFc(d, script, req); -#endif - } else if (mainThread && qt_is_gui_used) { - fe = loadXlfd(d->screen, script, req); - } - if (!fe) { - fe = new QFontEngineBox(req.pixelSize); - fe->fontDef = QFontDef(); - } - } - if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) { - for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { - if (!d->engineData->engines[i]) { - d->engineData->engines[i] = fe; - fe->ref.ref(); - } - } - } else { - d->engineData->engines[script] = fe; - fe->ref.ref(); - } - QFontCache::instance()->insertEngine(key, fe); -} - -// Needed for fontconfig version < 2.2.97 -#ifndef FC_FAMILYLANG -#define FC_FAMILYLANG "familylang" -#endif - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ -#if defined(QT_NO_FONTCONFIG) - return; -#else - if (!X11->has_fontconfig) - return; - - FcConfig *config = FcConfigGetCurrent(); - if (!config) - return; - - FcFontSet *set = FcConfigGetFonts(config, FcSetApplication); - if (!set) { - FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-existent"); - set = FcConfigGetFonts(config, FcSetApplication); // try again - if (!set) - return; - } - - QString fileNameForQuery = fnt->fileName; -#if FC_VERSION < 20402 - QTemporaryFile tmp; - - if (!fnt->data.isEmpty()) { - if (!tmp.open()) - return; - tmp.write(fnt->data); - tmp.flush(); - fileNameForQuery = tmp.fileName(); - } -#endif - - int id = 0; - FcBlanks *blanks = FcConfigGetBlanks(0); - int count = 0; - - QStringList families; - QFontDatabasePrivate *db = privateDb(); - - FcPattern *pattern = 0; - do { - pattern = queryFont((const FcChar8 *)QFile::encodeName(fileNameForQuery).constData(), - fnt->data, id, blanks, &count); - if (!pattern) - return; - - FcPatternDel(pattern, FC_FILE); - QByteArray cs = fnt->fileName.toUtf8(); - FcPatternAddString(pattern, FC_FILE, (const FcChar8 *) cs.constData()); - - FcChar8 *fam = 0, *familylang = 0; - int i, n = 0; - for (i = 0; ; i++) { - if (FcPatternGetString(pattern, FC_FAMILYLANG, i, &familylang) != FcResultMatch) - break; - QString familyLang = QString::fromUtf8((const char *) familylang); - if (familyLang.compare(db->systemLang, Qt::CaseInsensitive) == 0) { - n = i; - break; - } - } - - if (FcPatternGetString(pattern, FC_FAMILY, n, &fam) == FcResultMatch) { - QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); - families << family; - } - - if (!FcFontSetAdd(set, pattern)) - return; - - ++id; - } while (pattern && id < count); - - fnt->families = families; -#endif -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ -#if defined(QT_NO_FONTCONFIG) - return false; -#else - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (handle < 0 || handle >= db->applicationFonts.count()) - return false; - - FcConfigAppFontClear(0); - - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - - db->reregisterAppFonts = true; - db->invalidate(); - return true; -#endif -} - -bool QFontDatabase::removeAllApplicationFonts() -{ -#if defined(QT_NO_FONTCONFIG) - return false; -#else - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (db->applicationFonts.isEmpty()) - return false; - - FcConfigAppFontClear(0); - db->applicationFonts.clear(); - db->invalidate(); - return true; -#endif -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ -#if defined(QT_NO_FONTCONFIG) - return false; -#else - return X11->has_fontconfig; -#endif -} - -QString QFontDatabase::resolveFontFamilyAlias(const QString &family) -{ -#if defined(QT_NO_FONTCONFIG) - return family; -#else - FcPattern *pattern = FcPatternCreate(); - if (!pattern) - return family; - - QByteArray cs = family.toUtf8(); - FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData()); - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcChar8 *familyAfterSubstitution; - FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); - QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution); - FcPatternDestroy(pattern); - - return resolved; -#endif -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qfontengine_x11.cpp b/src/widgets/platforms/x11/qfontengine_x11.cpp deleted file mode 100644 index be421976fa..0000000000 --- a/src/widgets/platforms/x11/qfontengine_x11.cpp +++ /dev/null @@ -1,1205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbitmap.h" - -// #define FONTENGINE_DEBUG - -#include <qapplication.h> -#include <qbytearray.h> -#include <qdebug.h> -#include <qtextcodec.h> -#include <qthread.h> - -#include "qfontdatabase.h" -#include "qpaintdevice.h" -#include "qpainter.h" -#include "qvarlengtharray.h" -#include "qwidget.h" -#include "qsettings.h" -#include "qfile.h" - -#include <private/qpaintengine_x11_p.h> -#include "qfont.h" -#include "qfont_p.h" -#include "qfontengine_p.h" -#include <qhash.h> - -#include <private/qpainter_p.h> -#include <private/qunicodetables_p.h> - -#include <private/qt_x11_p.h> -#include <private/qpixmap_x11_p.h> -#include "qx11info_x11.h" -#include "qfontengine_x11_p.h" - -#include <limits.h> - -#include <ft2build.h> -#if defined(FT_LCD_FILTER_H) -#include FT_LCD_FILTER_H -#endif - -#if defined(FC_LCD_FILTER) - -#ifndef FC_LCD_FILTER_NONE -#define FC_LCD_FILTER_NONE FC_LCD_NONE -#endif - -#ifndef FC_LCD_FILTER_DEFAULT -#define FC_LCD_FILTER_DEFAULT FC_LCD_DEFAULT -#endif - -#ifndef FC_LCD_FILTER_LIGHT -#define FC_LCD_FILTER_LIGHT FC_LCD_LIGHT -#endif - -#ifndef FC_LCD_FILTER_LEGACY -#define FC_LCD_FILTER_LEGACY FC_LCD_LEGACY -#endif - -#endif - -QT_BEGIN_NAMESPACE - - -// ------------------------------------------------------------------ -// Multi XLFD engine -// ------------------------------------------------------------------ - -QFontEngineMultiXLFD::QFontEngineMultiXLFD(const QFontDef &r, const QList<int> &l, int s) - : QFontEngineMulti(l.size()), encodings(l), screen(s), request(r) -{ - loadEngine(0); - fontDef = engines[0]->fontDef; -} - -QFontEngineMultiXLFD::~QFontEngineMultiXLFD() -{ } - -void QFontEngineMultiXLFD::loadEngine(int at) -{ - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - const int encoding = encodings.at(at); - QFontEngine *fontEngine = QFontDatabase::loadXlfd(0, QUnicodeTables::Common, request, encoding); - Q_ASSERT(fontEngine != 0); - fontEngine->ref.ref(); - engines[at] = fontEngine; -} - -// ------------------------------------------------------------------ -// Xlfd font engine -// ------------------------------------------------------------------ - -#ifndef QT_NO_FREETYPE - -static QStringList *qt_fontpath = 0; - -static QStringList fontPath() -{ - if (qt_fontpath) - return *qt_fontpath; - - // append qsettings fontpath - QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); - settings.beginGroup(QLatin1String("Qt")); - - QStringList fontpath; - - int npaths; - char** font_path; - font_path = XGetFontPath(X11->display, &npaths); - bool xfsconfig_read = false; - for (int i=0; i<npaths; i++) { - // If we're using xfs, append font paths from /etc/X11/fs/config - // can't hurt, and chances are we'll get all fonts that way. - if (((font_path[i])[0] != '/') && !xfsconfig_read) { - // We're using xfs -> read its config - bool finished = false; - QFile f(QLatin1String("/etc/X11/fs/config")); - if (!f.exists()) - f.setFileName(QLatin1String("/usr/X11R6/lib/X11/fs/config")); - if (!f.exists()) - f.setFileName(QLatin1String("/usr/X11/lib/X11/fs/config")); - if (f.exists()) { - f.open(QIODevice::ReadOnly); - while (f.error()==QFile::NoError && !finished) { - QString fs = QString::fromLocal8Bit(f.readLine(1024)); - fs=fs.trimmed(); - if (fs.left(9)==QLatin1String("catalogue") && fs.contains(QLatin1Char('='))) { - fs = fs.mid(fs.indexOf(QLatin1Char('=')) + 1).trimmed(); - bool end = false; - while (f.error()==QFile::NoError && !end) { - if (fs[int(fs.length())-1] == QLatin1Char(',')) - fs = fs.left(fs.length()-1); - else - end = true; - - fs = fs.left(fs.indexOf(QLatin1String(":unscaled"))); - if (fs[0] != QLatin1Char('#')) - fontpath += fs; - fs = QLatin1String(f.readLine(1024)); - fs = fs.trimmed(); - if (fs.isEmpty()) - end = true; - } - finished = true; - } - } - f.close(); - } - xfsconfig_read = true; - } else { - QString fs = QString::fromLocal8Bit(font_path[i]); - fontpath += fs.left(fs.indexOf(QLatin1String(":unscaled"))); - } - } - XFreeFontPath(font_path); - - // append qsettings fontpath - QStringList fp = settings.value(QLatin1String("fontPath")).toStringList(); - if (!fp.isEmpty()) - fontpath += fp; - - qt_fontpath = new QStringList(fontpath); - return fontpath; -} - -static QFontEngine::FaceId fontFile(const QByteArray &_xname, QFreetypeFace **freetype, int *synth) -{ - *freetype = 0; - *synth = 0; - - QByteArray xname = _xname.toLower(); - - int pos = 0; - int minus = 0; - while (minus < 5 && (pos = xname.indexOf('-', pos + 1))) - ++minus; - QByteArray searchname = xname.left(pos); - while (minus < 12 && (pos = xname.indexOf('-', pos + 1))) - ++minus; - QByteArray encoding = xname.mid(pos + 1); - //qDebug("xname='%s', searchname='%s', encoding='%s'", xname.data(), searchname.data(), encoding.data()); - QStringList fontpath = fontPath(); - QFontEngine::FaceId face_id; - face_id.index = 0; - - QByteArray best_mapping; - - for (QStringList::ConstIterator it = fontpath.constBegin(); it != fontpath.constEnd(); ++it) { - if (!(*it).startsWith(QLatin1Char('/'))) - continue; // not a path name, a font server - QString fontmapname; - int num = 0; - // search font.dir and font.scale for the right file - while (num < 2) { - if (num == 0) - fontmapname = (*it) + QLatin1String("/fonts.scale"); - else - fontmapname = (*it) + QLatin1String("/fonts.dir"); - ++num; - //qWarning(fontmapname); - QFile fontmap(fontmapname); - if (!fontmap.open(QIODevice::ReadOnly)) - continue; - while (!fontmap.atEnd()) { - QByteArray mapping = fontmap.readLine(); - QByteArray lmapping = mapping.toLower(); - - //qWarning(xfontname); - //qWarning(mapping); - if (!lmapping.contains(searchname)) - continue; - int index = mapping.indexOf(' '); - QByteArray ffn = mapping.mid(0,index); - // remove bitmap formats freetype can't handle - if (ffn.contains(".spd") || ffn.contains(".phont")) - continue; - bool best_match = false; - if (!best_mapping.isEmpty()) { - if (lmapping.contains("-0-0-0-0-")) { // scalable font - best_match = true; - goto found; - } - if (lmapping.contains(encoding) && !best_mapping.toLower().contains(encoding)) - goto found; - continue; - } - - found: - int colon = ffn.lastIndexOf(':'); - if (colon != -1) { - QByteArray s = ffn.left(colon); - ffn = ffn.mid(colon + 1); - if (s.contains("ds=")) - *synth |= QFontEngine::SynthesizedBold; - if (s.contains("ai=")) - *synth |= QFontEngine::SynthesizedItalic; - } - face_id.filename = (*it).toLocal8Bit() + '/' + ffn; - best_mapping = mapping; - if (best_match) - goto end; - } - } - } -end: -// qDebug("fontfile for %s is from '%s'\n got %s synth=%d", xname.data(), -// best_mapping.data(), face_id.filename.data(), *synth); - *freetype = QFreetypeFace::getFace(face_id); - if (!*freetype) { - face_id.index = 0; - face_id.filename = QByteArray(); - } - return face_id; -} - -#endif // QT_NO_FREETYPE - -// defined in qfontdatabase_x11.cpp -extern int qt_mib_for_xlfd_encoding(const char *encoding); -extern int qt_xlfd_encoding_id(const char *encoding); - -static inline XCharStruct *charStruct(XFontStruct *xfs, uint ch) -{ - XCharStruct *xcs = 0; - unsigned char r = ch>>8; - unsigned char c = ch&0xff; - if (xfs->per_char && - r >= xfs->min_byte1 && - r <= xfs->max_byte1 && - c >= xfs->min_char_or_byte2 && - c <= xfs->max_char_or_byte2) { - xcs = xfs->per_char + ((r - xfs->min_byte1) * - (xfs->max_char_or_byte2 - - xfs->min_char_or_byte2 + 1)) + - (c - xfs->min_char_or_byte2); - if (xcs->width == 0 && xcs->ascent == 0 && xcs->descent == 0) - xcs = 0; - } - return xcs; -} - -QFontEngineXLFD::QFontEngineXLFD(XFontStruct *fs, const QByteArray &name, int mib) - : _fs(fs), _name(name), _codec(0), _cmap(mib) -{ - if (_cmap) _codec = QTextCodec::codecForMib(_cmap); - - cache_cost = (((fs->max_byte1 - fs->min_byte1) * - (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1)) + - fs->max_char_or_byte2 - fs->min_char_or_byte2); - cache_cost = ((fs->max_bounds.ascent + fs->max_bounds.descent) * - (fs->max_bounds.width * cache_cost / 8)); - lbearing = SHRT_MIN; - rbearing = SHRT_MIN; - face_id.index = -1; - freetype = 0; - synth = 0; -} - -QFontEngineXLFD::~QFontEngineXLFD() -{ - XFreeFont(QX11Info::display(), _fs); - _fs = 0; -#ifndef QT_NO_FREETYPE - if (freetype) - freetype->release(face_id); -#endif -} - -bool QFontEngineXLFD::stringToCMap(const QChar *s, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - // filter out surrogates, we can't handle them anyway with XLFD fonts - QVarLengthArray<ushort> _s(len); - QChar *str = (QChar *)_s.data(); - for (int i = 0; i < len; ++i) { - if (i < len - 1 - && s[i].unicode() >= 0xd800 && s[i].unicode() < 0xdc00 - && s[i+1].unicode() >= 0xdc00 && s[i].unicode() < 0xe000) { - *str = QChar(); - ++i; - } else { - *str = s[i]; - } - ++str; - } - - len = str - (QChar *)_s.data(); - str = (QChar *)_s.data(); - - bool mirrored = flags & QTextEngine::RightToLeft; - if (_codec) { - bool haveNbsp = false; - for (int i = 0; i < len; i++) - if (str[i].unicode() == 0xa0) { - haveNbsp = true; - break; - } - - QVarLengthArray<unsigned short> ch(len); - QChar *chars = (QChar *)ch.data(); - if (haveNbsp || mirrored) { - for (int i = 0; i < len; i++) - chars[i] = (str[i].unicode() == 0xa0 ? 0x20 : - (mirrored ? QChar::mirroredChar(str[i].unicode()) : str[i].unicode())); - } else { - for (int i = 0; i < len; i++) - chars[i] = str[i].unicode(); - } - QTextCodec::ConverterState state; - state.flags = QTextCodec::ConvertInvalidToNull; - QByteArray ba = _codec->fromUnicode(chars, len, &state); - if (ba.length() == 2*len) { - // double byte encoding - const uchar *data = (const uchar *)ba.constData(); - for (int i = 0; i < len; i++) { - glyphs->glyphs[i] = ((ushort)data[0] << 8) + data[1]; - data += 2; - } - } else { - const uchar *data = (const uchar *)ba.constData(); - for (int i = 0; i < len; i++) - glyphs->glyphs[i] = (ushort)data[i]; - } - } else { - int i = len; - const QChar *c = str + len; - if (mirrored) { - while (c != str) - glyphs->glyphs[--i] = (--c)->unicode() == 0xa0 ? 0x20 : QChar::mirroredChar(c->unicode()); - } else { - while (c != str) - glyphs->glyphs[--i] = (--c)->unicode() == 0xa0 ? 0x20 : c->unicode(); - } - } - *nglyphs = len; - glyphs->numGlyphs = len; - - if (!(flags & QTextEngine::GlyphIndicesOnly)) - recalcAdvances(glyphs, flags); - return true; -} - -void QFontEngineXLFD::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags /*flags*/) const -{ - int i = glyphs->numGlyphs; - XCharStruct *xcs; - // inlined for better performance - if (!_fs->per_char) { - xcs = &_fs->min_bounds; - while (i != 0) { - --i; - const unsigned char r = glyphs->glyphs[i] >> 8; - const unsigned char c = glyphs->glyphs[i] & 0xff; - if (r >= _fs->min_byte1 && - r <= _fs->max_byte1 && - c >= _fs->min_char_or_byte2 && - c <= _fs->max_char_or_byte2) { - glyphs->advances_x[i] = xcs->width; - } else { - glyphs->glyphs[i] = 0; - } - } - } - else if (!_fs->max_byte1) { - XCharStruct *base = _fs->per_char - _fs->min_char_or_byte2; - while (i != 0) { - unsigned int gl = glyphs->glyphs[--i]; - xcs = (gl >= _fs->min_char_or_byte2 && gl <= _fs->max_char_or_byte2) ? - base + gl : 0; - if (!xcs || (!xcs->width && !xcs->ascent && !xcs->descent)) { - glyphs->glyphs[i] = 0; - } else { - glyphs->advances_x[i] = xcs->width; - } - } - } - else { - while (i != 0) { - xcs = charStruct(_fs, glyphs->glyphs[--i]); - if (!xcs) { - glyphs->glyphs[i] = 0; - } else { - glyphs->advances_x[i] = xcs->width; - } - } - } -} - -glyph_metrics_t QFontEngineXLFD::boundingBox(const QGlyphLayout &glyphs) -{ - int i; - - glyph_metrics_t overall; - // initialize with line height, we get the same behaviour on all platforms - overall.y = -ascent(); - overall.height = ascent() + descent() + 1; - QFixed ymax; - QFixed xmax; - for (i = 0; i < glyphs.numGlyphs; i++) { - XCharStruct *xcs = charStruct(_fs, glyphs.glyphs[i]); - if (xcs) { - QFixed x = overall.xoff + glyphs.offsets[i].x + xcs->lbearing; - QFixed y = overall.yoff + glyphs.offsets[i].y - xcs->ascent; - overall.x = qMin(overall.x, x); - overall.y = qMin(overall.y, y); - // XCharStruct::rbearing is defined as distance from left edge to rightmost pixel - xmax = qMax(xmax, overall.xoff + glyphs.offsets[i].x + xcs->rbearing); - ymax = qMax(ymax, y + xcs->ascent + xcs->descent); - overall.xoff += glyphs.advances_x[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6); - } else { - QFixed size = _fs->ascent; - overall.x = qMin(overall.x, overall.xoff); - overall.y = qMin(overall.y, overall.yoff - size); - ymax = qMax(ymax, overall.yoff); - overall.xoff += size; - xmax = qMax(xmax, overall.xoff); - } - } - overall.height = qMax(overall.height, ymax - overall.y); - overall.width = xmax - overall.x; - - return overall; -} - -glyph_metrics_t QFontEngineXLFD::boundingBox(glyph_t glyph) -{ - glyph_metrics_t gm; - XCharStruct *xcs = charStruct(_fs, glyph); - if (xcs) { - // XCharStruct::rbearing is defined as distance from left edge to rightmost pixel - // XCharStruct::width is defined as the advance - gm = glyph_metrics_t(xcs->lbearing, -xcs->ascent, xcs->rbearing- xcs->lbearing, xcs->ascent + xcs->descent, - xcs->width, 0); - } else { - QFixed size = ascent(); - gm = glyph_metrics_t(0, size, size, size, size, 0); - } - return gm; -} - -QFixed QFontEngineXLFD::ascent() const -{ - return _fs->ascent; -} - -QFixed QFontEngineXLFD::descent() const -{ - return (_fs->descent-1); -} - -QFixed QFontEngineXLFD::leading() const -{ - QFixed l = QFixed(qMin<int>(_fs->ascent, _fs->max_bounds.ascent) - + qMin<int>(_fs->descent, _fs->max_bounds.descent)) * QFixed::fromReal(0.15); - return l.ceil(); -} - -qreal QFontEngineXLFD::maxCharWidth() const -{ - return _fs->max_bounds.width; -} - - -// Loads the font for the specified script -static inline int maxIndex(XFontStruct *f) { - return (((f->max_byte1 - f->min_byte1) * - (f->max_char_or_byte2 - f->min_char_or_byte2 + 1)) + - f->max_char_or_byte2 - f->min_char_or_byte2); -} - -qreal QFontEngineXLFD::minLeftBearing() const -{ - if (lbearing == SHRT_MIN) { - if (_fs->per_char) { - XCharStruct *cs = _fs->per_char; - int nc = maxIndex(_fs) + 1; - int mx = cs->lbearing; - - for (int c = 1; c < nc; c++) { - // ignore the bearings for characters whose ink is - // completely outside the normal bounding box - if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) || - (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width)) - continue; - - int nmx = cs[c].lbearing; - - if (nmx < mx) - mx = nmx; - } - - ((QFontEngineXLFD *)this)->lbearing = mx; - } else - ((QFontEngineXLFD *)this)->lbearing = _fs->min_bounds.lbearing; - } - return lbearing; -} - -qreal QFontEngineXLFD::minRightBearing() const -{ - if (rbearing == SHRT_MIN) { - if (_fs->per_char) { - XCharStruct *cs = _fs->per_char; - int nc = maxIndex(_fs) + 1; - int mx = cs->rbearing; - - for (int c = 1; c < nc; c++) { - // ignore the bearings for characters whose ink is - // completely outside the normal bounding box - if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) || - (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width)) - continue; - - int nmx = cs[c].rbearing; - - if (nmx < mx) - mx = nmx; - } - - ((QFontEngineXLFD *)this)->rbearing = mx; - } else - ((QFontEngineXLFD *)this)->rbearing = _fs->min_bounds.rbearing; - } - return rbearing; -} - -const char *QFontEngineXLFD::name() const -{ - return _name; -} - -bool QFontEngineXLFD::canRender(const QChar *string, int len) -{ - QVarLengthGlyphLayoutArray glyphs(len); - int nglyphs = len; - if (stringToCMap(string, len, &glyphs, &nglyphs, 0) == false) { - glyphs.resize(nglyphs); - stringToCMap(string, len, &glyphs, &nglyphs, 0); - } - - bool allExist = true; - for (int i = 0; i < nglyphs; i++) { - if (!glyphs.glyphs[i] || !charStruct(_fs, glyphs.glyphs[i])) { - allExist = false; - break; - } - } - - return allExist; -} - -QBitmap QFontEngineXLFD::bitmapForGlyphs(const QGlyphLayout &glyphs, const glyph_metrics_t &metrics, QTextItem::RenderFlags flags) -{ - int w = metrics.width.toInt(); - int h = metrics.height.toInt(); - if (w <= 0 || h <= 0) - return QBitmap(); - - QPlatformPixmap *data = new QX11PlatformPixmap(QPlatformPixmap::BitmapType); - data->resize(w, h); - QPixmap bm(data); - QPainter p(&bm); - p.fillRect(0, 0, w, h, Qt::color0); - p.setPen(Qt::color1); - - QTextItemInt item; - item.flags = flags; - item.ascent = -metrics.y; - item.descent = metrics.height - item.ascent; - item.width = metrics.width; - item.chars = 0; - item.num_chars = 0; - item.logClusters = 0; - item.glyphs = glyphs; - item.fontEngine = this; - item.f = 0; - - p.drawTextItem(QPointF(-metrics.x.toReal(), item.ascent.toReal()), item); - p.end(); - - return QBitmap(bm); -} - -void QFontEngineXLFD::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) -{ - // cannot use QFontEngine::addBitmapFontToPath(), since we don't - // have direct access to the glyph bitmaps, so we have to draw - // onto a QBitmap, then convert to QImage, then to path - glyph_metrics_t metrics = boundingBox(glyphs); - - QImage image = bitmapForGlyphs(glyphs, metrics, flags).toImage(); - if (image.isNull()) - return; - - image = image.convertToFormat(QImage::Format_Mono); - const uchar *image_data = image.bits(); - uint bpl = image.bytesPerLine(); - // from qfontengine.cpp - extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, - int bpl, int w, int h, QPainterPath *path); - qt_addBitmapToPath(x, y + metrics.y.toReal(), image_data, bpl, image.width(), image.height(), path); -} - -QFontEngine::FaceId QFontEngineXLFD::faceId() const -{ -#ifndef QT_NO_FREETYPE - if (face_id.index == -1) { - face_id = fontFile(_name, &freetype, &synth); - if (_codec) - face_id.encoding = _codec->mibEnum(); - if (freetype) { - const_cast<QFontEngineXLFD *>(this)->fsType = freetype->fsType(); - } else { - face_id.index = 0; - face_id.filename = '-' + QFontEngine::properties().postscriptName; - } - } -#endif - - return face_id; -} - -QFontEngine::Properties QFontEngineXLFD::properties() const -{ - if (face_id.index == -1) - (void)faceId(); - -#ifndef QT_NO_FREETYPE - if (freetype) - return freetype->properties(); -#endif - return QFontEngine::properties(); -} - -void QFontEngineXLFD::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - if (face_id.index == -1) - (void)faceId(); -#ifndef QT_NO_FREETYPE - if (!freetype) -#endif - { - QFontEngine::getUnscaledGlyph(glyph, path, metrics); - return; - } - -#ifndef QT_NO_FREETYPE - freetype->lock(); - - FT_Face face = freetype->face; - FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0); - freetype->xsize = face->units_per_EM << 6; - freetype->ysize = face->units_per_EM << 6; - FT_Set_Transform(face, 0, 0); - glyph = glyphIndexToFreetypeGlyphIndex(glyph); - FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); - - int left = face->glyph->metrics.horiBearingX; - int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width; - int top = face->glyph->metrics.horiBearingY; - int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height; - - QFixedPoint p; - p.x = 0; - p.y = 0; - metrics->width = QFixed::fromFixed(right-left); - metrics->height = QFixed::fromFixed(top-bottom); - metrics->x = QFixed::fromFixed(left); - metrics->y = QFixed::fromFixed(-top); - metrics->xoff = QFixed::fromFixed(face->glyph->advance.x); - - if (!FT_IS_SCALABLE(freetype->face)) - QFreetypeFace::addBitmapToPath(face->glyph, p, path); - else - QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6); - - FT_Set_Transform(face, &freetype->matrix, 0); - freetype->unlock(); -#endif // QT_NO_FREETYPE -} - - -bool QFontEngineXLFD::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ -#ifndef QT_NO_FREETYPE - if (face_id.index == -1) - (void)faceId(); - if (!freetype) - return false; - return freetype->getSfntTable(tag, buffer, length); -#else - Q_UNUSED(tag); - Q_UNUSED(buffer); - Q_UNUSED(length); - return false; -#endif -} - -int QFontEngineXLFD::synthesized() const -{ - return synth; -} - -QImage QFontEngineXLFD::alphaMapForGlyph(glyph_t glyph) -{ - glyph_metrics_t metrics = boundingBox(glyph); - -/* - printf("a) w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n", - metrics.width.toReal(), - metrics.height.toReal(), - metrics.xoff.toReal(), - metrics.yoff.toReal(), - metrics.x.toReal(), - metrics.y.toReal()); -*/ - - QGlyphLayoutArray<1> glyphs; - glyphs.glyphs[0] = glyph; - - QImage image = bitmapForGlyphs(glyphs, metrics).toImage(); -//image.save(QString::fromLatin1("x11cache-%1.png").arg((int)glyph)); - - image = image.convertToFormat(QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i = 0; i < 256; ++i) - colors[i] = qRgba(0, 0, 0, i); - image.setColorTable(colors); - - int width = image.width(); - int height = image.height(); - for (int y = 0; y < height; ++y) { - uchar *bits = image.scanLine(y); - for (int x = 0; x < width; ++x) - bits[x] = ~(bits[x]-1); - } - - return image; -} - -#ifndef QT_NO_FREETYPE - -FT_Face QFontEngineXLFD::non_locked_face() const -{ - return freetype ? freetype->face : 0; -} - -uint QFontEngineXLFD::toUnicode(glyph_t g) const -{ - if (_codec) { - QTextCodec::ConverterState state; - state.flags = QTextCodec::ConvertInvalidToNull; - uchar data[2]; - int l = 1; - if (g > 255) { - data[0] = (g >> 8); - data[1] = (g & 255); - l = 2; - } else { - data[0] = g; - } - QString s = _codec->toUnicode((char *)data, l, &state); - Q_ASSERT(s.length() == 1); - g = s.at(0).unicode(); - } - return g; -} - -glyph_t QFontEngineXLFD::glyphIndexToFreetypeGlyphIndex(glyph_t g) const -{ - return FT_Get_Char_Index(freetype->face, toUnicode(g)); -} -#endif - -#ifndef QT_NO_FONTCONFIG - -// ------------------------------------------------------------------ -// Multi FT engine -// ------------------------------------------------------------------ - -static QFontEngine *engineForPattern(FcPattern *match, const QFontDef &request, int screen) -{ - QFontEngineX11FT *engine = new QFontEngineX11FT(match, request, screen); - if (!engine->invalid()) - return engine; - - delete engine; - QFontEngine *fe = new QFontEngineBox(request.pixelSize); - fe->fontDef = request; - return fe; -} - -QFontEngineMultiFT::QFontEngineMultiFT(QFontEngine *fe, FcPattern *matchedPattern, FcPattern *p, int s, const QFontDef &req) - : QFontEngineMulti(2), request(req), pattern(p), fontSet(0), screen(s) -{ - firstEnginePattern = FcPatternDuplicate(matchedPattern); - engines[0] = fe; - engines.at(0)->ref.ref(); - fontDef = engines[0]->fontDef; - cache_cost = 100; - firstFontIndex = 1; -} - -QFontEngineMultiFT::~QFontEngineMultiFT() -{ - extern QMutex *qt_fontdatabase_mutex(); - QMutexLocker locker(qt_fontdatabase_mutex()); - - FcPatternDestroy(pattern); - if (firstEnginePattern) - FcPatternDestroy(firstEnginePattern); - if (fontSet) - FcFontSetDestroy(fontSet); -} - - -void QFontEngineMultiFT::loadEngine(int at) -{ - extern QMutex *qt_fontdatabase_mutex(); - QMutexLocker locker(qt_fontdatabase_mutex()); - - extern QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &); - extern FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request); - - Q_ASSERT(at > 0); - if (!fontSet) { - fontSet = qt_fontSetForPattern(pattern, request); - - // it may happen that the fontset of fallbacks consists of only one font. In this case we - // have to fall back to the box fontengine as we cannot render the glyph. - if (fontSet->nfont == 1 && at == 1 && engines.size() == 2) { - Q_ASSERT(engines.at(at) == 0); - QFontEngine *fe = new QFontEngineBox(request.pixelSize); - fe->fontDef = request; - engines[at] = fe; - return; - } - - if (firstEnginePattern) { - - if (!FcPatternEqual(firstEnginePattern, fontSet->fonts[0])) - firstFontIndex = 0; - - FcPatternDestroy(firstEnginePattern); - firstEnginePattern = 0; - } - - engines.resize(fontSet->nfont + 1 - firstFontIndex); - } - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - FcPattern *match = FcFontRenderPrepare(NULL, pattern, fontSet->fonts[at + firstFontIndex - 1]); - QFontDef fontDef = qt_FcPatternToQFontDef(match, this->request); - - // note: we use -1 for the script to make sure that we keep real - // FT engines separate from Multi engines in the font cache - QFontCache::Key key(fontDef, -1, screen); - QFontEngine *fontEngine = QFontCache::instance()->findEngine(key); - if (!fontEngine) { - fontEngine = engineForPattern(match, request, screen); - QFontCache::instance()->insertEngine(key, fontEngine); - } - FcPatternDestroy(match); - fontEngine->ref.ref(); - engines[at] = fontEngine; -} - -// ------------------------------------------------------------------ -// X11 FT engine -// ------------------------------------------------------------------ - - - -Q_WIDGETS_EXPORT void qt_x11ft_convert_pattern(FcPattern *pattern, QByteArray *file_name, int *index, bool *antialias) -{ - FcChar8 *fileName; - FcPatternGetString(pattern, FC_FILE, 0, &fileName); - *file_name = (const char *)fileName; - if (!FcPatternGetInteger(pattern, FC_INDEX, 0, index)) - index = 0; - FcBool b; - if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &b) == FcResultMatch) - *antialias = b; -} - - -QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int screen) - : QFontEngineFT(fd) -{ -// FcPatternPrint(pattern); - - bool antialias = X11->fc_antialias; - QByteArray file_name; - int face_index; - qt_x11ft_convert_pattern(pattern, &file_name, &face_index, &antialias); - QFontEngine::FaceId face_id; - face_id.filename = file_name; - face_id.index = face_index; - - canUploadGlyphsToServer = QApplication::testAttribute(Qt::AA_X11InitThreads) || (qApp->thread() == QThread::currentThread()); - - subpixelType = Subpixel_None; - if (antialias) { - int subpixel = X11->display ? X11->screens[screen].subpixel : FC_RGBA_UNKNOWN; - if (subpixel == FC_RGBA_UNKNOWN) - (void) FcPatternGetInteger(pattern, FC_RGBA, 0, &subpixel); - if (!antialias || subpixel == FC_RGBA_UNKNOWN) - subpixel = FC_RGBA_NONE; - - switch (subpixel) { - case FC_RGBA_NONE: subpixelType = Subpixel_None; break; - case FC_RGBA_RGB: subpixelType = Subpixel_RGB; break; - case FC_RGBA_BGR: subpixelType = Subpixel_BGR; break; - case FC_RGBA_VRGB: subpixelType = Subpixel_VRGB; break; - case FC_RGBA_VBGR: subpixelType = Subpixel_VBGR; break; - default: break; - } - } - - if (fd.hintingPreference != QFont::PreferDefaultHinting) { - switch (fd.hintingPreference) { - case QFont::PreferNoHinting: - default_hint_style = HintNone; - break; - case QFont::PreferVerticalHinting: - default_hint_style = HintLight; - break; - case QFont::PreferFullHinting: - default: - default_hint_style = HintFull; - break; - } - } -#ifdef FC_HINT_STYLE - else { - int hint_style = 0; - // Try to use Xft.hintstyle from XDefaults first if running in GNOME, to match - // the behavior of cairo - if (X11->fc_hint_style > -1 && X11->desktopEnvironment == DE_GNOME) - hint_style = X11->fc_hint_style; - else if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch - && X11->fc_hint_style > -1) - hint_style = X11->fc_hint_style; - - switch (hint_style) { - case FC_HINT_NONE: - default_hint_style = HintNone; - break; - case FC_HINT_SLIGHT: - default_hint_style = HintLight; - break; - case FC_HINT_MEDIUM: - default_hint_style = HintMedium; - break; - default: - default_hint_style = HintFull; - break; - } - } -#endif - -#if defined(FC_AUTOHINT) && defined(FT_LOAD_FORCE_AUTOHINT) - { - bool autohint = false; - - FcBool b; - if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &b) == FcResultMatch) - autohint = b; - - if (autohint) - default_load_flags |= FT_LOAD_FORCE_AUTOHINT; - } -#endif - -#if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H) - { - int filter = FC_LCD_FILTER_NONE; - if (FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter) == FcResultMatch) { - switch (filter) { - case FC_LCD_FILTER_NONE: - lcdFilterType = FT_LCD_FILTER_NONE; - break; - case FC_LCD_FILTER_DEFAULT: - lcdFilterType = FT_LCD_FILTER_DEFAULT; - break; - case FC_LCD_FILTER_LIGHT: - lcdFilterType = FT_LCD_FILTER_LIGHT; - break; - case FC_LCD_FILTER_LEGACY: - lcdFilterType = FT_LCD_FILTER_LEGACY; - break; - default: - // new unknown lcd filter type?! - break; - } - } - } -#endif - -#ifdef FC_EMBEDDED_BITMAP - { - FcBool b; - if (FcPatternGetBool(pattern, FC_EMBEDDED_BITMAP, 0, &b) == FcResultMatch) - embeddedbitmap = b; - } -#endif - - GlyphFormat defaultFormat = Format_None; - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - int format = PictStandardA8; - if (!antialias) - format = PictStandardA1; - else if (subpixelType == Subpixel_RGB - || subpixelType == Subpixel_BGR - || subpixelType == Subpixel_VRGB - || subpixelType == Subpixel_VBGR) - format = PictStandardARGB32; - xglyph_format = format; - - if (subpixelType != QFontEngineFT::Subpixel_None) - defaultFormat = Format_A32; - else if (antialias) - defaultFormat = Format_A8; - else - defaultFormat = Format_Mono; - } -#endif - - if (!init(face_id, antialias, defaultFormat)) - return; - - if (!freetype->charset) { - FcCharSet *cs; - FcPatternGetCharSet (pattern, FC_CHARSET, 0, &cs); - freetype->charset = FcCharSetCopy(cs); - } -} - -QFontEngineX11FT::~QFontEngineX11FT() -{ - freeGlyphSets(); -} - -unsigned long QFontEngineX11FT::allocateServerGlyphSet() -{ -#ifndef QT_NO_XRENDER - if (!canUploadGlyphsToServer || !X11->use_xrender) - return 0; - return XRenderCreateGlyphSet(X11->display, XRenderFindStandardFormat(X11->display, xglyph_format)); -#else - return 0; -#endif -} - -void QFontEngineX11FT::freeServerGlyphSet(unsigned long id) -{ -#ifndef QT_NO_XRENDER - if (!id) - return; - XRenderFreeGlyphSet(X11->display, id); -#endif -} - -bool QFontEngineX11FT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const -{ -#ifndef QT_NO_XRENDER - if (!canUploadGlyphsToServer) - return false; - if (g->format == Format_Mono) { - /* - * swap bit order around; FreeType is always MSBFirst - */ - if (BitmapBitOrder(X11->display) != MSBFirst) { - unsigned char *line = g->data; - int i = glyphDataSize; - while (i--) { - unsigned char c; - c = *line; - c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55); - c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33); - c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f); - *line++ = c; - } - } - } - - ::Glyph xglyph = glyphid; - XRenderAddGlyphs (X11->display, set->id, &xglyph, info, 1, (const char *)g->data, glyphDataSize); - delete [] g->data; - g->data = 0; - g->format = Format_None; - g->uploadedToServer = true; - return true; -#else - return false; -#endif -} - -QFontEngine *QFontEngineX11FT::cloneWithSize(qreal pixelSize) const -{ - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - QFontEngineX11FT *fe = new QFontEngineX11FT(fontDef); - if (!fe->initFromFontEngine(this)) { - delete fe; - return 0; - } else { -#ifndef QT_NO_XRENDER - fe->xglyph_format = xglyph_format; -#endif - return fe; - } -} - -#endif // QT_NO_FONTCONFIG - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qfontengine_x11_p.h b/src/widgets/platforms/x11/qfontengine_x11_p.h deleted file mode 100644 index b12fbc28d4..0000000000 --- a/src/widgets/platforms/x11/qfontengine_x11_p.h +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_X11_P_H -#define QFONTENGINE_X11_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// -#include <private/qt_x11_p.h> - -#include <private/qfontengine_ft_p.h> - -QT_BEGIN_NAMESPACE - -class QFreetypeFace; - -// -------------------------------------------------------------------------- - -class QFontEngineMultiXLFD : public QFontEngineMulti -{ -public: - QFontEngineMultiXLFD(const QFontDef &r, const QList<int> &l, int s); - ~QFontEngineMultiXLFD(); - - void loadEngine(int at); - -private: - QList<int> encodings; - int screen; - QFontDef request; -}; - -/** - * \internal The font engine for X Logical Font Description (XLFD) fonts, which is for X11 systems without freetype. - */ -class QFontEngineXLFD : public QFontEngine -{ -public: - QFontEngineXLFD(XFontStruct *f, const QByteArray &name, int mib); - ~QFontEngineXLFD(); - - virtual QFontEngine::FaceId faceId() const; - QFontEngine::Properties properties() const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - virtual int synthesized() const; - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t glyph); - - virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags); - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual qreal maxCharWidth() const; - virtual qreal minLeftBearing() const; - virtual qreal minRightBearing() const; - virtual QImage alphaMapForGlyph(glyph_t); - - virtual inline Type type() const - { return QFontEngine::XLFD; } - - virtual bool canRender(const QChar *string, int len); - virtual const char *name() const; - - inline XFontStruct *fontStruct() const - { return _fs; } - -#ifndef QT_NO_FREETYPE - FT_Face non_locked_face() const; - glyph_t glyphIndexToFreetypeGlyphIndex(glyph_t g) const; -#endif - uint toUnicode(glyph_t g) const; - -private: - QBitmap bitmapForGlyphs(const QGlyphLayout &glyphs, const glyph_metrics_t &metrics, QTextItem::RenderFlags flags = 0); - - XFontStruct *_fs; - QByteArray _name; - QTextCodec *_codec; - int _cmap; - int lbearing, rbearing; - mutable QFontEngine::FaceId face_id; - mutable QFreetypeFace *freetype; - mutable int synth; -}; - -#ifndef QT_NO_FONTCONFIG - -class Q_WIDGETS_EXPORT QFontEngineMultiFT : public QFontEngineMulti -{ -public: - QFontEngineMultiFT(QFontEngine *fe, FcPattern *firstEnginePattern, FcPattern *p, int s, const QFontDef &request); - ~QFontEngineMultiFT(); - - void loadEngine(int at); - -private: - QFontDef request; - FcPattern *pattern; - FcPattern *firstEnginePattern; - FcFontSet *fontSet; - int screen; - int firstFontIndex; // first font in fontset -}; - -class Q_WIDGETS_EXPORT QFontEngineX11FT : public QFontEngineFT -{ -public: - explicit QFontEngineX11FT(const QFontDef &fontDef) : QFontEngineFT(fontDef) {} - explicit QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int screen); - ~QFontEngineX11FT(); - - QFontEngine *cloneWithSize(qreal pixelSize) const; - -#ifndef QT_NO_XRENDER - int xglyph_format; -#endif - -protected: - virtual bool uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const; - virtual unsigned long allocateServerGlyphSet(); - virtual void freeServerGlyphSet(unsigned long id); -}; - -#endif // QT_NO_FONTCONFIG - -QT_END_NAMESPACE - -#endif // QFONTENGINE_X11_P_H diff --git a/src/widgets/platforms/x11/qkde.cpp b/src/widgets/platforms/x11/qkde.cpp deleted file mode 100644 index b89951b5cd..0000000000 --- a/src/widgets/platforms/x11/qkde.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qkde_p.h" -#include <QtCore/QLibrary> -#include <QtCore/QDir> -#include <QtCore/qdebug.h> -#include <QtCore/QSettings> -#include "QtGui/qstylefactory.h" -#include "qt_x11_p.h" - -#if defined(Q_WS_X11) - -QT_BEGIN_NAMESPACE - -/*! \internal -Gets the current KDE home path -like "/home/troll/.kde" -*/ -QString QKde::kdeHome() -{ - static QString kdeHomePath; - if (kdeHomePath.isEmpty()) { - kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME")); - if (kdeHomePath.isEmpty()) { - QDir homeDir(QDir::homePath()); - QString kdeConfDir(QLatin1String("/.kde")); - if (4 == X11->desktopVersion && homeDir.exists(QLatin1String(".kde4"))) - kdeConfDir = QLatin1String("/.kde4"); - kdeHomePath = QDir::homePath() + kdeConfDir; - } - } - return kdeHomePath; -} - -/*!\internal - Reads the color from the config, and store it in the palette with the given color role if found - */ -static bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QSettings &kdeSettings, const QString &kde4Key, const QString &kde3Key = QString()) -{ - QVariant variant = kdeSettings.value(kde4Key); - if (!variant.isValid()) - QVariant variant = kdeSettings.value(kde3Key); - if (variant.isValid()) { - QStringList values = variant.toStringList(); - if (values.size() == 3) { - int r = values[0].toInt(); - int g = values[1].toInt(); - int b = values[2].toInt(); - pal->setBrush(role, QColor(r, g, b)); - return true; - } - } - return false; -} - - -/*!\internal - Returns the KDE palette -*/ -QPalette QKde::kdePalette() -{ - const QSettings theKdeSettings(QKde::kdeHome() + - QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - QPalette pal; - - // Setup KDE palette - kdeColor(&pal, QPalette::Button, theKdeSettings, QLatin1String("Colors:Button/BackgroundNormal"), QLatin1String("buttonBackground")); - kdeColor(&pal, QPalette::Window, theKdeSettings, QLatin1String("Colors:Window/BackgroundNormal"), QLatin1String("background")); - kdeColor(&pal, QPalette::Text, theKdeSettings, QLatin1String("Colors:View/ForegroundNormal"), QLatin1String("foreground")); - kdeColor(&pal, QPalette::WindowText, theKdeSettings, QLatin1String("Colors:Window/ForegroundNormal"), QLatin1String("windowForeground")); - kdeColor(&pal, QPalette::Base, theKdeSettings, QLatin1String("Colors:View/BackgroundNormal"), QLatin1String("windowBackground")); - kdeColor(&pal, QPalette::Highlight, theKdeSettings, QLatin1String("Colors:Selection/BackgroundNormal"), QLatin1String("selectBackground")); - kdeColor(&pal, QPalette::HighlightedText, theKdeSettings, QLatin1String("Colors:Selection/ForegroundNormal"), QLatin1String("selectForeground")); - kdeColor(&pal, QPalette::AlternateBase, theKdeSettings, QLatin1String("Colors:View/BackgroundAlternate"), QLatin1String("alternateBackground")); - kdeColor(&pal, QPalette::ButtonText, theKdeSettings, QLatin1String("Colors:Button/ForegroundNormal"), QLatin1String("buttonForeground")); - kdeColor(&pal, QPalette::Link, theKdeSettings, QLatin1String("Colors:View/ForegroundLink"), QLatin1String("linkColor")); - kdeColor(&pal, QPalette::LinkVisited, theKdeSettings, QLatin1String("Colors:View/ForegroundVisited"), QLatin1String("visitedLinkColor")); - //## TODO tooltip color - - return pal; -} - -/*!\internal - Returns the name of the QStyle to use. - (read from the kde config if needed) -*/ -QString QKde::kdeStyle() -{ - if (X11->desktopVersion >= 4) { - QSettings kdeSettings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat); - QString style = kdeSettings.value(QLatin1String("widgetStyle"), QLatin1String("Oxygen")).toString(); - - QStringList availableStyles = QStyleFactory::keys(); - if(availableStyles.contains(style, Qt::CaseInsensitive)) - return style; - } - - if (X11->use_xrender) - return QLatin1String("plastique"); - else - return QLatin1String("windows"); -} - - -int QKde::kdeToolButtonStyle() -{ - QSettings settings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), - QSettings::IniFormat); - settings.beginGroup(QLatin1String("Toolbar style")); - QString toolbarStyle = settings.value(QLatin1String("ToolButtonStyle"), QLatin1String("TextBesideIcon")).toString(); - if (toolbarStyle == QLatin1String("TextBesideIcon")) - return Qt::ToolButtonTextBesideIcon; - else if (toolbarStyle == QLatin1String("TextOnly")) - return Qt::ToolButtonTextOnly; - else if (toolbarStyle == QLatin1String("TextUnderIcon")) - return Qt::ToolButtonTextUnderIcon; - - return Qt::ToolButtonTextBesideIcon; -} - -int QKde::kdeToolBarIconSize() -{ - static int iconSize = -1; - if (iconSize == -1) { - QSettings settings(QKde::kdeHome() + QLatin1String("/share/config/kdeglobals"), - QSettings::IniFormat); - settings.beginGroup(QLatin1String("ToolbarIcons")); - iconSize = settings.value(QLatin1String("Size")).toInt(); - } - return iconSize; -} - -QT_END_NAMESPACE - -#endif //Q_WS_X11 - diff --git a/src/widgets/platforms/x11/qkde_p.h b/src/widgets/platforms/x11/qkde_p.h deleted file mode 100644 index 5abe824a72..0000000000 --- a/src/widgets/platforms/x11/qkde_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QKDE_H -#define QKDE_H - -#include <QtCore/qglobal.h> -#include <QtGui/QPalette> -#include <QtWidgets/QIcon> - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// -#if defined(Q_WS_X11) - - -QT_BEGIN_NAMESPACE - -/*!\internal - This namespace contains helper function to help KDE integration - They are only used if we detect the use of KDE and the KDE platform plugin is not found (old KDE version) - Or if the detected KDE version is KDE3 -*/ -namespace QKde { - QString kdeHome(); - QString kdeStyle(); - QPalette kdePalette(); - int kdeToolButtonStyle(); - int kdeToolBarIconSize(); -} - - -QT_END_NAMESPACE - -#endif // Q_WS_X11 -#endif // QKDE_H diff --git a/src/widgets/platforms/x11/qkeymapper_x11.cpp b/src/widgets/platforms/x11/qkeymapper_x11.cpp deleted file mode 100644 index 7e348b3385..0000000000 --- a/src/widgets/platforms/x11/qkeymapper_x11.cpp +++ /dev/null @@ -1,1857 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qkeymapper_p.h" - -#include "qdebug.h" -#include "qtextcodec.h" -#include "qwidget.h" - -#include "qapplication_p.h" -#include "qevent_p.h" -#include "qt_x11_p.h" - -#ifndef QT_NO_XKB -# include <X11/XKBlib.h> -#endif - -#define XK_MISCELLANY -#define XK_LATIN1 -#define XK_KOREAN -#define XK_XKB_KEYS -#include <X11/keysymdef.h> - -#include <ctype.h> - -#ifdef QT_LINUXBASE -// LSB's IsKeypadKey define is wrong - see -// http://bugs.linuxbase.org/show_bug.cgi?id=2521 -#undef IsKeypadKey -#define IsKeypadKey(keysym) \ - (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal)) - -#undef IsPrivateKeypadKey -#define IsPrivateKeypadKey(keysym) \ - (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF)) -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_XKB - -// bring in the auto-generated xkbLayoutData -#include "qkeymapper_x11_p.cpp" - -QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName) -{ - int i = 0; - while (xkbLayoutData[i].layout != 0) { - if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant) - return QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country); - ++i; - } - return QLocale::c(); -} -#endif // QT_NO_XKB - -// from qapplication_x11.cpp -extern uchar qt_alt_mask; -extern uchar qt_meta_mask; -extern uchar qt_super_mask; -extern uchar qt_hyper_mask; -extern uchar qt_mode_switch_mask; -uchar qt_num_lock_mask = 0; -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); - -// ### we should really resolve conflicts with other masks by -// ### decomposing the Qt::KeyboardModifers in possibleKeys() -#define SETMASK(sym, mask) \ - do { \ - if (qt_alt_mask == 0 \ - && qt_meta_mask != mask \ - && qt_super_mask != mask \ - && qt_hyper_mask != mask \ - && (sym == XK_Alt_L || sym == XK_Alt_R)) { \ - qt_alt_mask = mask; \ - } \ - if (qt_meta_mask == 0 \ - && qt_alt_mask != mask \ - && qt_super_mask != mask \ - && qt_hyper_mask != mask \ - && (sym == XK_Meta_L || sym == XK_Meta_R)) { \ - qt_meta_mask = mask; \ - } \ - if (qt_super_mask == 0 \ - && qt_alt_mask != mask \ - && qt_meta_mask != mask \ - && qt_hyper_mask != mask \ - && (sym == XK_Super_L || sym == XK_Super_R)) { \ - qt_super_mask = mask; \ - } \ - if (qt_hyper_mask == 0 \ - && qt_alt_mask != mask \ - && qt_meta_mask != mask \ - && qt_super_mask != mask \ - && (sym == XK_Hyper_L || sym == XK_Hyper_R)) { \ - qt_hyper_mask = mask; \ - } \ - if (qt_mode_switch_mask == 0 \ - && qt_alt_mask != mask \ - && qt_meta_mask != mask \ - && qt_super_mask != mask \ - && qt_hyper_mask != mask \ - && sym == XK_Mode_switch) { \ - qt_mode_switch_mask = mask; \ - } \ - if (qt_num_lock_mask == 0 \ - && sym == XK_Num_Lock) { \ - qt_num_lock_mask = mask; \ - } \ - } while(false) - -// qt_XTranslateKey() is based on _XTranslateKey() taken from: - -/* $Xorg: KeyBind.c,v 1.4 2001/02/09 02:03:34 xorgcvs Exp $ */ - -/* - -Copyright 1985, 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -*/ -static int -qt_XTranslateKey(register QXCoreDesc *dpy, - KeyCode keycode, - register unsigned int modifiers, - unsigned int *modifiers_return, - KeySym *keysym_return) -{ - int per; - register KeySym *syms; - KeySym sym, lsym, usym; - - if (! dpy->keysyms) - return 0; - *modifiers_return = ((ShiftMask|LockMask) - | dpy->mode_switch | dpy->num_lock); - if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) - { - *keysym_return = NoSymbol; - return 1; - } - per = dpy->keysyms_per_keycode; - syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; - while ((per > 2) && (syms[per - 1] == NoSymbol)) - per--; - if ((per > 2) && (modifiers & dpy->mode_switch)) { - syms += 2; - per -= 2; - } - if ((modifiers & dpy->num_lock) && - (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { - if ((modifiers & ShiftMask) || - ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock))) - *keysym_return = syms[0]; - else - *keysym_return = syms[1]; - } else if (!(modifiers & ShiftMask) && - (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) { - if ((per == 1) || (syms[1] == NoSymbol)) - XConvertCase(syms[0], keysym_return, &usym); - else - *keysym_return = syms[0]; - } else if (!(modifiers & LockMask) || - (dpy->lock_meaning != XK_Caps_Lock)) { - if ((per == 1) || ((usym = syms[1]) == NoSymbol)) - XConvertCase(syms[0], &lsym, &usym); - *keysym_return = usym; - } else { - if ((per == 1) || ((sym = syms[1]) == NoSymbol)) - sym = syms[0]; - XConvertCase(sym, &lsym, &usym); - if (!(modifiers & ShiftMask) && (sym != syms[0]) && - ((sym != usym) || (lsym == usym))) - XConvertCase(syms[0], &lsym, &usym); - *keysym_return = usym; - } - if (*keysym_return == XK_VoidSymbol) - *keysym_return = NoSymbol; - return 1; -} - - - - -QKeyMapperPrivate::QKeyMapperPrivate() - : keyboardInputDirection(Qt::LeftToRight), xkb_currentGroup(0) -{ - memset(&coreDesc, 0, sizeof(coreDesc)); - -#ifndef QT_NO_XKB - if (X11->use_xkb) { - // get the current group - XkbStateRec xkbState; - if (XkbGetState(X11->display, XkbUseCoreKbd, &xkbState) == Success) - xkb_currentGroup = xkbState.group; - } -#endif -} - -QKeyMapperPrivate::~QKeyMapperPrivate() -{ - if (coreDesc.keysyms) - XFree(coreDesc.keysyms); -} - -QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *event) -{ -#ifndef QT_NO_XKB - if (X11->use_xkb) - return possibleKeysXKB(event); -#endif - return possibleKeysCore(event); -} - -enum { MaxBits = sizeof(uint) * 8 }; -static QString translateKeySym(KeySym keysym, uint xmodifiers, - int &code, Qt::KeyboardModifiers &modifiers, - QByteArray &chars, int &count); - -QList<int> QKeyMapperPrivate::possibleKeysXKB(QKeyEvent *event) -{ -#ifndef QT_NO_XKB - const int xkeycode = event->nativeScanCode(); - const uint xmodifiers = event->nativeModifiers(); - - // first, translate key only using lock modifiers (there are no Qt equivalents for these, so we must - // always use them when determining the baseKeySym) - KeySym baseKeySym; - uint consumedModifiers; - if (!XkbLookupKeySym(X11->display, xkeycode, (xmodifiers & (LockMask | qt_num_lock_mask)), - &consumedModifiers, &baseKeySym)) - return QList<int>(); - - QList<int> result; - - // translate sym -> code - Qt::KeyboardModifiers baseModifiers = 0; - int baseCode = -1; - QByteArray chars; - int count = 0; - QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count); - if (baseCode == -1) { - if (text.isEmpty()) - return QList<int>(); - baseCode = text.at(0).unicode(); - } - - if (baseCode && baseCode < 0xfffe) - baseCode = QChar(baseCode).toUpper().unicode(); - result += (baseCode | baseModifiers); - - int pos1Bits[MaxBits]; - int num1Bits = 0; - - for (int i = 0; i < MaxBits; ++i) { - if (consumedModifiers & (1 << i)) - pos1Bits[num1Bits++] = i; - } - - const int numPerms = (1 << num1Bits); - - // translate the key again using each permutation of consumedModifiers - for (int i = 1; i < numPerms; ++i) { - uint val = 0; - for (int j = 0; j < num1Bits; ++j) { - if (i & (1 << j)) - val |= (1 << pos1Bits[j]); - } - - if ((xmodifiers & val) != val) - continue; - - KeySym sym; - uint mods; - if (!XkbLookupKeySym(X11->display, xkeycode, val, &mods, &sym)) - continue; - - // translate sym -> code - Qt::KeyboardModifiers modifiers = 0; - int code = -1; - chars.clear(); - count = 0; - // mask out the modifiers needed to translate keycode - text = translateKeySym(sym, xmodifiers & ~val, code, modifiers, chars, count); - if (code == -1) { - if (text.isEmpty()) - continue; - code = text.at(0).unicode(); - } - - if (code && code < 0xfffe) - code = QChar(code).toUpper().unicode(); - - if (code == Qt::Key_Tab && (baseModifiers & Qt::ShiftModifier)) { - // map shift+tab to shift+backtab - code = Qt::Key_Backtab; - text = QString(); - } - - if (code == baseCode) - continue; - - result += (code | modifiers); - } - -#if 0 - qDebug() << "possibleKeysXKB()" << hex << result; -#endif - return result; -#else - Q_UNUSED(event); - return QList<int>(); -#endif // QT_NO_XKB -} - -QList<int> QKeyMapperPrivate::possibleKeysCore(QKeyEvent *event) -{ - const int xkeycode = event->nativeScanCode(); - const uint xmodifiers = event->nativeModifiers(); - - // first, translate key only using lock modifiers (there are no Qt equivalents for these, so we must - // always use them when determining the baseKeySym) - KeySym baseKeySym; - uint consumedModifiers; - if (!qt_XTranslateKey(&coreDesc, xkeycode, (xmodifiers & (LockMask | qt_num_lock_mask)), - &consumedModifiers, &baseKeySym)) - return QList<int>(); - - QList<int> result; - - // translate sym -> code - Qt::KeyboardModifiers baseModifiers = 0; - int baseCode = -1; - QByteArray chars; - int count = 0; - QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count); - if (baseCode == -1) { - if (text.isEmpty()) - return QList<int>(); - baseCode = text.at(0).unicode(); - } - - if (baseCode && baseCode < 0xfffe) - baseCode = QChar(baseCode).toUpper().unicode(); - result += (baseCode | baseModifiers); - - int pos1Bits[MaxBits]; - int num1Bits = 0; - - for (int i = 0; i < MaxBits; ++i) { - if (consumedModifiers & (1 << i)) - pos1Bits[num1Bits++] = i; - } - - const int numPerms = (1 << num1Bits); - - // translate the key again using each permutation of consumedModifiers - for (int i = 1; i < numPerms; ++i) { - uint val = 0; - for (int j = 0; j < num1Bits; ++j) { - if (i & (1 << j)) - val |= (1 << pos1Bits[j]); - } - - if ((xmodifiers & val) != val) - continue; - - KeySym sym; - uint mods; - if (!qt_XTranslateKey(&coreDesc, xkeycode, val, &mods, &sym)) - continue; - - // translate sym -> code - Qt::KeyboardModifiers modifiers = 0; - int code = -1; - chars.clear(); - count = 0; - // mask out the modifiers needed to translate keycode - text = translateKeySym(sym, xmodifiers & ~val, code, modifiers, chars, count); - if (code == -1) { - if (text.isEmpty()) - continue; - code = text.at(0).unicode(); - } - - if (code && code < 0xfffe) - code = QChar(code).toUpper().unicode(); - - if (code == Qt::Key_Tab && (baseModifiers & Qt::ShiftModifier)) { - // map shift+tab to shift+backtab - code = Qt::Key_Backtab; - text = QString(); - } - - if (code == baseCode) - continue; - - result += (code | modifiers); - } - -#if 0 - qDebug() << "possibleKeysCore()" << hex << result; -#endif - return result; -} - -// for parsing the _XKB_RULES_NAMES property -enum { - RulesFileIndex = 0, - ModelIndex = 1, - LayoutIndex = 2, - VariantIndex = 3, - OptionsIndex = 4 -}; - -void QKeyMapperPrivate::clearMappings() -{ -#ifndef QT_NO_XKB - if (X11->use_xkb) { - // try to determine the layout name and input direction by reading the _XKB_RULES_NAMES property off - // the root window - QByteArray layoutName; - QByteArray variantName; - - Atom type = XNone; - int format = 0; - ulong nitems = 0; - ulong bytesAfter = 0; - uchar *data = 0; - if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024, - false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success - && type == XA_STRING && format == 8 && nitems > 2) { - /* - index 0 == rules file name - index 1 == model name - index 2 == layout name - index 3 == variant name - index 4 == options - */ - char *names[5] = { 0, 0, 0, 0, 0 }; - char *p = reinterpret_cast<char *>(data), *end = p + nitems; - int i = 0; - do { - names[i++] = p; - p += qstrlen(p) + 1; - } while (p < end); - - // the layout names and variants are saved in the _XKB_RULES_NAMES property as a comma separated list - QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(','); - if (uint(xkb_currentGroup) < uint(layoutNames.count())) - layoutName = layoutNames.at(xkb_currentGroup); - QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(','); - if (uint(xkb_currentGroup) < uint(variantNames.count())) - variantName = variantNames.at(xkb_currentGroup); - } - - // ### ??? - // if (keyboardLayoutName.isEmpty()) - // qWarning("Qt: unable to determine keyboard layout, please talk to qt-info@nokia.com"); ? - - keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName); - keyboardInputDirection = keyboardInputLocale.textDirection(); - -#if 0 - qDebug() << "keyboard input locale =" - << keyboardInputLocale.name() - << "direction =" - << keyboardInputDirection; -#endif - if (data) - XFree(data); - } else -#endif // QT_NO_XKB - { - if (coreDesc.keysyms) - XFree(coreDesc.keysyms); - - coreDesc.min_keycode = 8; - coreDesc.max_keycode = 255; - XDisplayKeycodes(X11->display, &coreDesc.min_keycode, &coreDesc.max_keycode); - - coreDesc.keysyms_per_keycode = 0; - coreDesc.keysyms = XGetKeyboardMapping(X11->display, - coreDesc.min_keycode, - coreDesc.max_keycode - coreDesc.min_keycode + 1, - &coreDesc.keysyms_per_keycode); - -#if 0 - qDebug() << "min_keycode =" << coreDesc.min_keycode; - qDebug() << "max_keycode =" << coreDesc.max_keycode; - qDebug() << "keysyms_per_keycode =" << coreDesc.keysyms_per_keycode; - qDebug() << "keysyms =" << coreDesc.keysyms; -#endif - - // ### cannot get/guess the locale with the core protocol - keyboardInputLocale = QLocale::c(); - // ### could examine group 0 for RTL keys - keyboardInputDirection = Qt::LeftToRight; - } - - qt_alt_mask = 0; - qt_meta_mask = 0; - qt_super_mask = 0; - qt_hyper_mask = 0; - qt_mode_switch_mask = 0; - - // look at the modifier mapping, and get the correct masks for alt, meta, super, hyper, and mode_switch -#ifndef QT_NO_XKB - if (X11->use_xkb) { - XkbDescPtr xkbDesc = XkbGetMap(X11->display, XkbAllClientInfoMask, XkbUseCoreKbd); - for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) { - const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0; - if (mask == 0) { - // key is not bound to a modifier - continue; - } - - for (int j = 0; j < XkbKeyGroupsWidth(xkbDesc, i); ++j) { - KeySym keySym = XkbKeySym(xkbDesc, i, j); - if (keySym == NoSymbol) - continue; - SETMASK(keySym, mask); - } - } - XkbFreeKeyboard(xkbDesc, XkbAllComponentsMask, true); - } else -#endif // QT_NO_XKB - { - coreDesc.lock_meaning = NoSymbol; - - XModifierKeymap *map = XGetModifierMapping(X11->display); - - if (map) { - int i, maskIndex = 0, mapIndex = 0; - for (maskIndex = 0; maskIndex < 8; maskIndex++) { - for (i = 0; i < map->max_keypermod; i++) { - if (map->modifiermap[mapIndex]) { - KeySym sym; - int x = 0; - do { - sym = XKeycodeToKeysym(X11->display, map->modifiermap[mapIndex], x++); - } while (sym == NoSymbol && x < coreDesc.keysyms_per_keycode); - const uchar mask = 1 << maskIndex; - SETMASK(sym, mask); - } - mapIndex++; - } - } - - // determine the meaning of the Lock modifier - for (i = 0; i < map->max_keypermod; ++i) { - for (int x = 0; x < coreDesc.keysyms_per_keycode; ++x) { - KeySym sym = XKeycodeToKeysym(X11->display, map->modifiermap[LockMapIndex], x); - if (sym == XK_Caps_Lock || sym == XK_ISO_Lock) { - coreDesc.lock_meaning = XK_Caps_Lock; - break; - } else if (sym == XK_Shift_Lock) { - coreDesc.lock_meaning = XK_Shift_Lock; - } - } - } - - XFreeModifiermap(map); - } - - // for qt_XTranslateKey() - coreDesc.num_lock = qt_num_lock_mask; - coreDesc.mode_switch = qt_mode_switch_mask; - -#if 0 - qDebug() << "lock_meaning =" << coreDesc.lock_meaning; - qDebug() << "num_lock =" << coreDesc.num_lock; - qDebug() << "mode_switch =" << coreDesc.mode_switch; -#endif - } - - // set default modifier masks if needed - if( qt_alt_mask == 0 ) - qt_alt_mask = Mod1Mask; - if( qt_meta_mask == 0 ) - qt_meta_mask = Mod4Mask; - - // if we don't have a meta key (or it's hidden behind alt), use super or hyper to generate - // Qt::Key_Meta and Qt::MetaModifier, since most newer XFree86/Xorg installations map the Windows - // key to Super - if (qt_meta_mask == 0 || qt_meta_mask == qt_alt_mask) { - // no meta keys... s,meta,super, - qt_meta_mask = qt_super_mask; - if (qt_meta_mask == 0 || qt_meta_mask == qt_alt_mask) { - // no super keys either? guess we'll use hyper then - qt_meta_mask = qt_hyper_mask; - } - } - -#if 0 - qDebug() << "qt_alt_mask =" << hex << qt_alt_mask; - qDebug() << "qt_meta_mask =" << hex << qt_meta_mask; - qDebug() << "qt_super_mask =" << hex << qt_super_mask; - qDebug() << "qt_hyper_mask =" << hex << qt_hyper_mask; - qDebug() << "qt_mode_switch_mask =" << hex << qt_mode_switch_mask; - qDebug() << "qt_num_lock_mask =" << hex << qt_num_lock_mask; -#endif -} - -extern bool qt_sm_blockUserInput; - -// -// Keyboard event translation -// - -#ifndef XK_ISO_Left_Tab -#define XK_ISO_Left_Tab 0xFE20 -#endif - -#ifndef XK_dead_hook -#define XK_dead_hook 0xFE61 -#endif - -#ifndef XK_dead_horn -#define XK_dead_horn 0xFE62 -#endif - -#ifndef XK_Codeinput -#define XK_Codeinput 0xFF37 -#endif - -#ifndef XK_Kanji_Bangou -#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */ -#endif - -// Fix old X libraries -#ifndef XK_KP_Home -#define XK_KP_Home 0xFF95 -#endif -#ifndef XK_KP_Left -#define XK_KP_Left 0xFF96 -#endif -#ifndef XK_KP_Up -#define XK_KP_Up 0xFF97 -#endif -#ifndef XK_KP_Right -#define XK_KP_Right 0xFF98 -#endif -#ifndef XK_KP_Down -#define XK_KP_Down 0xFF99 -#endif -#ifndef XK_KP_Prior -#define XK_KP_Prior 0xFF9A -#endif -#ifndef XK_KP_Next -#define XK_KP_Next 0xFF9B -#endif -#ifndef XK_KP_End -#define XK_KP_End 0xFF9C -#endif -#ifndef XK_KP_Insert -#define XK_KP_Insert 0xFF9E -#endif -#ifndef XK_KP_Delete -#define XK_KP_Delete 0xFF9F -#endif - -// the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special -// multimedia keys. They are included here as not every system has them. -#define XF86XK_MonBrightnessUp 0x1008FF02 -#define XF86XK_MonBrightnessDown 0x1008FF03 -#define XF86XK_KbdLightOnOff 0x1008FF04 -#define XF86XK_KbdBrightnessUp 0x1008FF05 -#define XF86XK_KbdBrightnessDown 0x1008FF06 -#define XF86XK_Standby 0x1008FF10 -#define XF86XK_AudioLowerVolume 0x1008FF11 -#define XF86XK_AudioMute 0x1008FF12 -#define XF86XK_AudioRaiseVolume 0x1008FF13 -#define XF86XK_AudioPlay 0x1008FF14 -#define XF86XK_AudioStop 0x1008FF15 -#define XF86XK_AudioPrev 0x1008FF16 -#define XF86XK_AudioNext 0x1008FF17 -#define XF86XK_HomePage 0x1008FF18 -#define XF86XK_Mail 0x1008FF19 -#define XF86XK_Start 0x1008FF1A -#define XF86XK_Search 0x1008FF1B -#define XF86XK_AudioRecord 0x1008FF1C -#define XF86XK_Calculator 0x1008FF1D -#define XF86XK_Memo 0x1008FF1E -#define XF86XK_ToDoList 0x1008FF1F -#define XF86XK_Calendar 0x1008FF20 -#define XF86XK_PowerDown 0x1008FF21 -#define XF86XK_ContrastAdjust 0x1008FF22 -#define XF86XK_Back 0x1008FF26 -#define XF86XK_Forward 0x1008FF27 -#define XF86XK_Stop 0x1008FF28 -#define XF86XK_Refresh 0x1008FF29 -#define XF86XK_PowerOff 0x1008FF2A -#define XF86XK_WakeUp 0x1008FF2B -#define XF86XK_Eject 0x1008FF2C -#define XF86XK_ScreenSaver 0x1008FF2D -#define XF86XK_WWW 0x1008FF2E -#define XF86XK_Sleep 0x1008FF2F -#define XF86XK_Favorites 0x1008FF30 -#define XF86XK_AudioPause 0x1008FF31 -#define XF86XK_AudioMedia 0x1008FF32 -#define XF86XK_MyComputer 0x1008FF33 -#define XF86XK_LightBulb 0x1008FF35 -#define XF86XK_Shop 0x1008FF36 -#define XF86XK_History 0x1008FF37 -#define XF86XK_OpenURL 0x1008FF38 -#define XF86XK_AddFavorite 0x1008FF39 -#define XF86XK_HotLinks 0x1008FF3A -#define XF86XK_BrightnessAdjust 0x1008FF3B -#define XF86XK_Finance 0x1008FF3C -#define XF86XK_Community 0x1008FF3D -#define XF86XK_AudioRewind 0x1008FF3E -#define XF86XK_BackForward 0x1008FF3F -#define XF86XK_Launch0 0x1008FF40 -#define XF86XK_Launch1 0x1008FF41 -#define XF86XK_Launch2 0x1008FF42 -#define XF86XK_Launch3 0x1008FF43 -#define XF86XK_Launch4 0x1008FF44 -#define XF86XK_Launch5 0x1008FF45 -#define XF86XK_Launch6 0x1008FF46 -#define XF86XK_Launch7 0x1008FF47 -#define XF86XK_Launch8 0x1008FF48 -#define XF86XK_Launch9 0x1008FF49 -#define XF86XK_LaunchA 0x1008FF4A -#define XF86XK_LaunchB 0x1008FF4B -#define XF86XK_LaunchC 0x1008FF4C -#define XF86XK_LaunchD 0x1008FF4D -#define XF86XK_LaunchE 0x1008FF4E -#define XF86XK_LaunchF 0x1008FF4F -#define XF86XK_ApplicationLeft 0x1008FF50 -#define XF86XK_ApplicationRight 0x1008FF51 -#define XF86XK_Book 0x1008FF52 -#define XF86XK_CD 0x1008FF53 -#define XF86XK_Calculater 0x1008FF54 -#define XF86XK_Clear 0x1008FF55 -#define XF86XK_ClearGrab 0x1008FE21 -#define XF86XK_Close 0x1008FF56 -#define XF86XK_Copy 0x1008FF57 -#define XF86XK_Cut 0x1008FF58 -#define XF86XK_Display 0x1008FF59 -#define XF86XK_DOS 0x1008FF5A -#define XF86XK_Documents 0x1008FF5B -#define XF86XK_Excel 0x1008FF5C -#define XF86XK_Explorer 0x1008FF5D -#define XF86XK_Game 0x1008FF5E -#define XF86XK_Go 0x1008FF5F -#define XF86XK_iTouch 0x1008FF60 -#define XF86XK_LogOff 0x1008FF61 -#define XF86XK_Market 0x1008FF62 -#define XF86XK_Meeting 0x1008FF63 -#define XF86XK_MenuKB 0x1008FF65 -#define XF86XK_MenuPB 0x1008FF66 -#define XF86XK_MySites 0x1008FF67 -#define XF86XK_News 0x1008FF69 -#define XF86XK_OfficeHome 0x1008FF6A -#define XF86XK_Option 0x1008FF6C -#define XF86XK_Paste 0x1008FF6D -#define XF86XK_Phone 0x1008FF6E -#define XF86XK_Reply 0x1008FF72 -#define XF86XK_Reload 0x1008FF73 -#define XF86XK_RotateWindows 0x1008FF74 -#define XF86XK_RotationPB 0x1008FF75 -#define XF86XK_RotationKB 0x1008FF76 -#define XF86XK_Save 0x1008FF77 -#define XF86XK_Send 0x1008FF7B -#define XF86XK_Spell 0x1008FF7C -#define XF86XK_SplitScreen 0x1008FF7D -#define XF86XK_Support 0x1008FF7E -#define XF86XK_TaskPane 0x1008FF7F -#define XF86XK_Terminal 0x1008FF80 -#define XF86XK_Tools 0x1008FF81 -#define XF86XK_Travel 0x1008FF82 -#define XF86XK_Video 0x1008FF87 -#define XF86XK_Word 0x1008FF89 -#define XF86XK_Xfer 0x1008FF8A -#define XF86XK_ZoomIn 0x1008FF8B -#define XF86XK_ZoomOut 0x1008FF8C -#define XF86XK_Away 0x1008FF8D -#define XF86XK_Messenger 0x1008FF8E -#define XF86XK_WebCam 0x1008FF8F -#define XF86XK_MailForward 0x1008FF90 -#define XF86XK_Pictures 0x1008FF91 -#define XF86XK_Music 0x1008FF92 -#define XF86XK_Battery 0x1008FF93 -#define XF86XK_Bluetooth 0x1008FF94 -#define XF86XK_WLAN 0x1008FF95 -#define XF86XK_UWB 0x1008FF96 -#define XF86XK_AudioForward 0x1008FF97 -#define XF86XK_AudioRepeat 0x1008FF98 -#define XF86XK_AudioRandomPlay 0x1008FF99 -#define XF86XK_Subtitle 0x1008FF9A -#define XF86XK_AudioCycleTrack 0x1008FF9B -#define XF86XK_Time 0x1008FF9F -#define XF86XK_Select 0x1008FFA0 -#define XF86XK_View 0x1008FFA1 -#define XF86XK_TopMenu 0x1008FFA2 -#define XF86XK_Suspend 0x1008FFA7 -#define XF86XK_Hibernate 0x1008FFA8 - - -// end of XF86keysyms.h - -// Special keys used by Qtopia, mapped into the X11 private keypad range. -#define QTOPIAXK_Select 0x11000601 -#define QTOPIAXK_Yes 0x11000602 -#define QTOPIAXK_No 0x11000603 -#define QTOPIAXK_Cancel 0x11000604 -#define QTOPIAXK_Printer 0x11000605 -#define QTOPIAXK_Execute 0x11000606 -#define QTOPIAXK_Sleep 0x11000607 -#define QTOPIAXK_Play 0x11000608 -#define QTOPIAXK_Zoom 0x11000609 -#define QTOPIAXK_Context1 0x1100060A -#define QTOPIAXK_Context2 0x1100060B -#define QTOPIAXK_Context3 0x1100060C -#define QTOPIAXK_Context4 0x1100060D -#define QTOPIAXK_Call 0x1100060E -#define QTOPIAXK_Hangup 0x1100060F -#define QTOPIAXK_Flip 0x11000610 - -// keyboard mapping table -static const unsigned int KeyTbl[] = { - - // misc keys - - XK_Escape, Qt::Key_Escape, - XK_Tab, Qt::Key_Tab, - XK_ISO_Left_Tab, Qt::Key_Backtab, - XK_BackSpace, Qt::Key_Backspace, - XK_Return, Qt::Key_Return, - XK_Insert, Qt::Key_Insert, - XK_Delete, Qt::Key_Delete, - XK_Clear, Qt::Key_Delete, - XK_Pause, Qt::Key_Pause, - XK_Print, Qt::Key_Print, - 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq - 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq - - // cursor movement - - XK_Home, Qt::Key_Home, - XK_End, Qt::Key_End, - XK_Left, Qt::Key_Left, - XK_Up, Qt::Key_Up, - XK_Right, Qt::Key_Right, - XK_Down, Qt::Key_Down, - XK_Prior, Qt::Key_PageUp, - XK_Next, Qt::Key_PageDown, - - // modifiers - - XK_Shift_L, Qt::Key_Shift, - XK_Shift_R, Qt::Key_Shift, - XK_Shift_Lock, Qt::Key_Shift, - XK_Control_L, Qt::Key_Control, - XK_Control_R, Qt::Key_Control, - XK_Meta_L, Qt::Key_Meta, - XK_Meta_R, Qt::Key_Meta, - XK_Alt_L, Qt::Key_Alt, - XK_Alt_R, Qt::Key_Alt, - XK_Caps_Lock, Qt::Key_CapsLock, - XK_Num_Lock, Qt::Key_NumLock, - XK_Scroll_Lock, Qt::Key_ScrollLock, - XK_Super_L, Qt::Key_Super_L, - XK_Super_R, Qt::Key_Super_R, - XK_Menu, Qt::Key_Menu, - XK_Hyper_L, Qt::Key_Hyper_L, - XK_Hyper_R, Qt::Key_Hyper_R, - XK_Help, Qt::Key_Help, - 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab - 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) - 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) - - // numeric and function keypad keys - - XK_KP_Space, Qt::Key_Space, - XK_KP_Tab, Qt::Key_Tab, - XK_KP_Enter, Qt::Key_Enter, - //XK_KP_F1, Qt::Key_F1, - //XK_KP_F2, Qt::Key_F2, - //XK_KP_F3, Qt::Key_F3, - //XK_KP_F4, Qt::Key_F4, - XK_KP_Home, Qt::Key_Home, - XK_KP_Left, Qt::Key_Left, - XK_KP_Up, Qt::Key_Up, - XK_KP_Right, Qt::Key_Right, - XK_KP_Down, Qt::Key_Down, - XK_KP_Prior, Qt::Key_PageUp, - XK_KP_Next, Qt::Key_PageDown, - XK_KP_End, Qt::Key_End, - XK_KP_Begin, Qt::Key_Clear, - XK_KP_Insert, Qt::Key_Insert, - XK_KP_Delete, Qt::Key_Delete, - XK_KP_Equal, Qt::Key_Equal, - XK_KP_Multiply, Qt::Key_Asterisk, - XK_KP_Add, Qt::Key_Plus, - XK_KP_Separator, Qt::Key_Comma, - XK_KP_Subtract, Qt::Key_Minus, - XK_KP_Decimal, Qt::Key_Period, - XK_KP_Divide, Qt::Key_Slash, - - // International input method support keys - - // International & multi-key character composition - XK_ISO_Level3_Shift, Qt::Key_AltGr, - XK_Multi_key, Qt::Key_Multi_key, - XK_Codeinput, Qt::Key_Codeinput, - XK_SingleCandidate, Qt::Key_SingleCandidate, - XK_MultipleCandidate, Qt::Key_MultipleCandidate, - XK_PreviousCandidate, Qt::Key_PreviousCandidate, - - // Misc Functions - XK_Mode_switch, Qt::Key_Mode_switch, - XK_script_switch, Qt::Key_Mode_switch, - - // Japanese keyboard support - XK_Kanji, Qt::Key_Kanji, - XK_Muhenkan, Qt::Key_Muhenkan, - //XK_Henkan_Mode, Qt::Key_Henkan_Mode, - XK_Henkan_Mode, Qt::Key_Henkan, - XK_Henkan, Qt::Key_Henkan, - XK_Romaji, Qt::Key_Romaji, - XK_Hiragana, Qt::Key_Hiragana, - XK_Katakana, Qt::Key_Katakana, - XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, - XK_Zenkaku, Qt::Key_Zenkaku, - XK_Hankaku, Qt::Key_Hankaku, - XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, - XK_Touroku, Qt::Key_Touroku, - XK_Massyo, Qt::Key_Massyo, - XK_Kana_Lock, Qt::Key_Kana_Lock, - XK_Kana_Shift, Qt::Key_Kana_Shift, - XK_Eisu_Shift, Qt::Key_Eisu_Shift, - XK_Eisu_toggle, Qt::Key_Eisu_toggle, - //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, - //XK_Zen_Koho, Qt::Key_Zen_Koho, - //XK_Mae_Koho, Qt::Key_Mae_Koho, - XK_Kanji_Bangou, Qt::Key_Codeinput, - XK_Zen_Koho, Qt::Key_MultipleCandidate, - XK_Mae_Koho, Qt::Key_PreviousCandidate, - -#ifdef XK_KOREAN - // Korean keyboard support - XK_Hangul, Qt::Key_Hangul, - XK_Hangul_Start, Qt::Key_Hangul_Start, - XK_Hangul_End, Qt::Key_Hangul_End, - XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, - XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, - XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, - //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, - XK_Hangul_Codeinput, Qt::Key_Codeinput, - XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, - XK_Hangul_Banja, Qt::Key_Hangul_Banja, - XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, - XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, - //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, - //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, - //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, - XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, - XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, - XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, - XK_Hangul_Special, Qt::Key_Hangul_Special, - //XK_Hangul_switch, Qt::Key_Hangul_switch, - XK_Hangul_switch, Qt::Key_Mode_switch, -#endif // XK_KOREAN - - // dead keys - XK_dead_grave, Qt::Key_Dead_Grave, - XK_dead_acute, Qt::Key_Dead_Acute, - XK_dead_circumflex, Qt::Key_Dead_Circumflex, - XK_dead_tilde, Qt::Key_Dead_Tilde, - XK_dead_macron, Qt::Key_Dead_Macron, - XK_dead_breve, Qt::Key_Dead_Breve, - XK_dead_abovedot, Qt::Key_Dead_Abovedot, - XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, - XK_dead_abovering, Qt::Key_Dead_Abovering, - XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, - XK_dead_caron, Qt::Key_Dead_Caron, - XK_dead_cedilla, Qt::Key_Dead_Cedilla, - XK_dead_ogonek, Qt::Key_Dead_Ogonek, - XK_dead_iota, Qt::Key_Dead_Iota, - XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, - XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, - XK_dead_belowdot, Qt::Key_Dead_Belowdot, - XK_dead_hook, Qt::Key_Dead_Hook, - XK_dead_horn, Qt::Key_Dead_Horn, - - // Special keys from X.org - This include multimedia keys, - // wireless/bluetooth/uwb keys, special launcher keys, etc. - XF86XK_Back, Qt::Key_Back, - XF86XK_Forward, Qt::Key_Forward, - XF86XK_Stop, Qt::Key_Stop, - XF86XK_Refresh, Qt::Key_Refresh, - XF86XK_Favorites, Qt::Key_Favorites, - XF86XK_AudioMedia, Qt::Key_LaunchMedia, - XF86XK_OpenURL, Qt::Key_OpenUrl, - XF86XK_HomePage, Qt::Key_HomePage, - XF86XK_Search, Qt::Key_Search, - XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, - XF86XK_AudioMute, Qt::Key_VolumeMute, - XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, - XF86XK_AudioPlay, Qt::Key_MediaPlay, - XF86XK_AudioStop, Qt::Key_MediaStop, - XF86XK_AudioPrev, Qt::Key_MediaPrevious, - XF86XK_AudioNext, Qt::Key_MediaNext, - XF86XK_AudioRecord, Qt::Key_MediaRecord, - XF86XK_Mail, Qt::Key_LaunchMail, - XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 5: remap properly - XF86XK_Calculator, Qt::Key_Launch1, - XF86XK_Memo, Qt::Key_Memo, - XF86XK_ToDoList, Qt::Key_ToDoList, - XF86XK_Calendar, Qt::Key_Calendar, - XF86XK_PowerDown, Qt::Key_PowerDown, - XF86XK_ContrastAdjust, Qt::Key_ContrastAdjust, - XF86XK_Standby, Qt::Key_Standby, - XF86XK_MonBrightnessUp, Qt::Key_MonBrightnessUp, - XF86XK_MonBrightnessDown, Qt::Key_MonBrightnessDown, - XF86XK_KbdLightOnOff, Qt::Key_KeyboardLightOnOff, - XF86XK_KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp, - XF86XK_KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown, - XF86XK_PowerOff, Qt::Key_PowerOff, - XF86XK_WakeUp, Qt::Key_WakeUp, - XF86XK_Eject, Qt::Key_Eject, - XF86XK_ScreenSaver, Qt::Key_ScreenSaver, - XF86XK_WWW, Qt::Key_WWW, - XF86XK_Sleep, Qt::Key_Sleep, - XF86XK_LightBulb, Qt::Key_LightBulb, - XF86XK_Shop, Qt::Key_Shop, - XF86XK_History, Qt::Key_History, - XF86XK_AddFavorite, Qt::Key_AddFavorite, - XF86XK_HotLinks, Qt::Key_HotLinks, - XF86XK_BrightnessAdjust, Qt::Key_BrightnessAdjust, - XF86XK_Finance, Qt::Key_Finance, - XF86XK_Community, Qt::Key_Community, - XF86XK_AudioRewind, Qt::Key_AudioRewind, - XF86XK_BackForward, Qt::Key_BackForward, - XF86XK_ApplicationLeft, Qt::Key_ApplicationLeft, - XF86XK_ApplicationRight, Qt::Key_ApplicationRight, - XF86XK_Book, Qt::Key_Book, - XF86XK_CD, Qt::Key_CD, - XF86XK_Calculater, Qt::Key_Calculator, - XF86XK_Clear, Qt::Key_Clear, - XF86XK_ClearGrab, Qt::Key_ClearGrab, - XF86XK_Close, Qt::Key_Close, - XF86XK_Copy, Qt::Key_Copy, - XF86XK_Cut, Qt::Key_Cut, - XF86XK_Display, Qt::Key_Display, - XF86XK_DOS, Qt::Key_DOS, - XF86XK_Documents, Qt::Key_Documents, - XF86XK_Excel, Qt::Key_Excel, - XF86XK_Explorer, Qt::Key_Explorer, - XF86XK_Game, Qt::Key_Game, - XF86XK_Go, Qt::Key_Go, - XF86XK_iTouch, Qt::Key_iTouch, - XF86XK_LogOff, Qt::Key_LogOff, - XF86XK_Market, Qt::Key_Market, - XF86XK_Meeting, Qt::Key_Meeting, - XF86XK_MenuKB, Qt::Key_MenuKB, - XF86XK_MenuPB, Qt::Key_MenuPB, - XF86XK_MySites, Qt::Key_MySites, - XF86XK_News, Qt::Key_News, - XF86XK_OfficeHome, Qt::Key_OfficeHome, - XF86XK_Option, Qt::Key_Option, - XF86XK_Paste, Qt::Key_Paste, - XF86XK_Phone, Qt::Key_Phone, - XF86XK_Reply, Qt::Key_Reply, - XF86XK_Reload, Qt::Key_Reload, - XF86XK_RotateWindows, Qt::Key_RotateWindows, - XF86XK_RotationPB, Qt::Key_RotationPB, - XF86XK_RotationKB, Qt::Key_RotationKB, - XF86XK_Save, Qt::Key_Save, - XF86XK_Send, Qt::Key_Send, - XF86XK_Spell, Qt::Key_Spell, - XF86XK_SplitScreen, Qt::Key_SplitScreen, - XF86XK_Support, Qt::Key_Support, - XF86XK_TaskPane, Qt::Key_TaskPane, - XF86XK_Terminal, Qt::Key_Terminal, - XF86XK_Tools, Qt::Key_Tools, - XF86XK_Travel, Qt::Key_Travel, - XF86XK_Video, Qt::Key_Video, - XF86XK_Word, Qt::Key_Word, - XF86XK_Xfer, Qt::Key_Xfer, - XF86XK_ZoomIn, Qt::Key_ZoomIn, - XF86XK_ZoomOut, Qt::Key_ZoomOut, - XF86XK_Away, Qt::Key_Away, - XF86XK_Messenger, Qt::Key_Messenger, - XF86XK_WebCam, Qt::Key_WebCam, - XF86XK_MailForward, Qt::Key_MailForward, - XF86XK_Pictures, Qt::Key_Pictures, - XF86XK_Music, Qt::Key_Music, - XF86XK_Battery, Qt::Key_Battery, - XF86XK_Bluetooth, Qt::Key_Bluetooth, - XF86XK_WLAN, Qt::Key_WLAN, - XF86XK_UWB, Qt::Key_UWB, - XF86XK_AudioForward, Qt::Key_AudioForward, - XF86XK_AudioRepeat, Qt::Key_AudioRepeat, - XF86XK_AudioRandomPlay, Qt::Key_AudioRandomPlay, - XF86XK_Subtitle, Qt::Key_Subtitle, - XF86XK_AudioCycleTrack, Qt::Key_AudioCycleTrack, - XF86XK_Time, Qt::Key_Time, - XF86XK_Select, Qt::Key_Select, - XF86XK_View, Qt::Key_View, - XF86XK_TopMenu, Qt::Key_TopMenu, - XF86XK_Bluetooth, Qt::Key_Bluetooth, - XF86XK_Suspend, Qt::Key_Suspend, - XF86XK_Hibernate, Qt::Key_Hibernate, - XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 5: remap properly - XF86XK_Launch1, Qt::Key_Launch3, - XF86XK_Launch2, Qt::Key_Launch4, - XF86XK_Launch3, Qt::Key_Launch5, - XF86XK_Launch4, Qt::Key_Launch6, - XF86XK_Launch5, Qt::Key_Launch7, - XF86XK_Launch6, Qt::Key_Launch8, - XF86XK_Launch7, Qt::Key_Launch9, - XF86XK_Launch8, Qt::Key_LaunchA, - XF86XK_Launch9, Qt::Key_LaunchB, - XF86XK_LaunchA, Qt::Key_LaunchC, - XF86XK_LaunchB, Qt::Key_LaunchD, - XF86XK_LaunchC, Qt::Key_LaunchE, - XF86XK_LaunchD, Qt::Key_LaunchF, - XF86XK_LaunchE, Qt::Key_LaunchG, - XF86XK_LaunchF, Qt::Key_LaunchH, - - // Qtopia keys - QTOPIAXK_Select, Qt::Key_Select, - QTOPIAXK_Yes, Qt::Key_Yes, - QTOPIAXK_No, Qt::Key_No, - QTOPIAXK_Cancel, Qt::Key_Cancel, - QTOPIAXK_Printer, Qt::Key_Printer, - QTOPIAXK_Execute, Qt::Key_Execute, - QTOPIAXK_Sleep, Qt::Key_Sleep, - QTOPIAXK_Play, Qt::Key_Play, - QTOPIAXK_Zoom, Qt::Key_Zoom, - QTOPIAXK_Context1, Qt::Key_Context1, - QTOPIAXK_Context2, Qt::Key_Context2, - QTOPIAXK_Context3, Qt::Key_Context3, - QTOPIAXK_Context4, Qt::Key_Context4, - QTOPIAXK_Call, Qt::Key_Call, - QTOPIAXK_Hangup, Qt::Key_Hangup, - QTOPIAXK_Flip, Qt::Key_Flip, - - 0, 0 -}; - -static int translateKeySym(uint key) -{ - int code = -1; - int i = 0; // any other keys - while (KeyTbl[i]) { - if (key == KeyTbl[i]) { - code = (int)KeyTbl[i+1]; - break; - } - i += 2; - } - if (qt_meta_mask) { - // translate Super/Hyper keys to Meta if we're using them as the MetaModifier - if (qt_meta_mask == qt_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) { - code = Qt::Key_Meta; - } else if (qt_meta_mask == qt_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) { - code = Qt::Key_Meta; - } - } - return code; -} - -#if !defined(QT_NO_XIM) -static const unsigned short katakanaKeysymsToUnicode[] = { - 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, - 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, - 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, - 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, - 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, - 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, - 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, - 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C -}; - -static const unsigned short cyrillicKeysymsToUnicode[] = { - 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f, - 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f, - 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, - 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, - 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, - 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, - 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, - 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, - 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, - 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a -}; - -static const unsigned short greekKeysymsToUnicode[] = { - 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, - 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, - 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, - 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, - 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, - 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, - 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -static const unsigned short technicalKeysymsToUnicode[] = { - 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1, - 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8, - 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B, - 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, - 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000, - 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, - 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000 -}; - -static const unsigned short specialKeysymsToUnicode[] = { - 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000, - 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, - 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, - 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -static const unsigned short publishingKeysymsToUnicode[] = { - 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, - 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, - 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, - 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000, - 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, - 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af, - 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, - 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae, - 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa, - 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000, - 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642, - 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000 -}; - -static const unsigned short aplKeysymsToUnicode[] = { - 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000, - 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000, - 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb, - 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000, - 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000 -}; - -static const unsigned short koreanKeysymsToUnicode[] = { - 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, - 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, - 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, - 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, - 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, - 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, - 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab, - 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, - 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, - 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d, - 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e, - 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9 -}; - -static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4) -{ - switch (byte3) { - case 0x04: - // katakana - if (byte4 > 0xa0 && byte4 < 0xe0) - return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]); - else if (byte4 == 0x7e) - return QChar(0x203e); // Overline - break; - case 0x06: - // russian, use lookup table - if (byte4 > 0xa0) - return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]); - break; - case 0x07: - // greek - if (byte4 > 0xa0) - return QChar(greekKeysymsToUnicode[byte4 - 0xa0]); - break; - case 0x08: - // technical - if (byte4 > 0xa0) - return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]); - break; - case 0x09: - // special - if (byte4 >= 0xe0) - return QChar(specialKeysymsToUnicode[byte4 - 0xe0]); - break; - case 0x0a: - // publishing - if (byte4 > 0xa0) - return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]); - break; - case 0x0b: - // APL - if (byte4 > 0xa0) - return QChar(aplKeysymsToUnicode[byte4 - 0xa0]); - break; - case 0x0e: - // Korean - if (byte4 > 0xa0) - return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]); - break; - default: - break; - } - return QChar(0x0); -} -#endif - -static QString translateKeySym(KeySym keysym, uint xmodifiers, - int &code, Qt::KeyboardModifiers &modifiers, - QByteArray &chars, int &count) -{ - // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars - - extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp - QTextCodec *mapper = qt_input_mapper; - QChar converted; - - if (count == 0 && keysym < 0xff00) { - unsigned char byte3 = (unsigned char)(keysym >> 8); - int mib = -1; - switch(byte3) { - case 0: // Latin 1 - case 1: // Latin 2 - case 2: //latin 3 - case 3: // latin4 - mib = byte3 + 4; break; - case 5: // arabic - mib = 82; break; - case 12: // Hebrew - mib = 85; break; - case 13: // Thai - mib = 2259; break; - case 4: // kana - case 6: // cyrillic - case 7: // greek - case 8: // technical, no mapping here at the moment - case 9: // Special - case 10: // Publishing - case 11: // APL - case 14: // Korean, no mapping - mib = -1; // manual conversion - mapper = 0; -#if !defined(QT_NO_XIM) - converted = keysymToUnicode(byte3, keysym & 0xff); -#endif - case 0x20: - // currency symbols - if (keysym >= 0x20a0 && keysym <= 0x20ac) { - mib = -1; // manual conversion - mapper = 0; - converted = (uint)keysym; - } - break; - default: - break; - } - if (mib != -1) { - mapper = QTextCodec::codecForMib(mib); - if (chars.isEmpty()) - chars.resize(1); - chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later - count++; - } - } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) { - converted = (ushort) (keysym - 0x1000000); - mapper = 0; - } - if (count < (int)chars.size()-1) - chars[count] = '\0'; - - QString text; - if (!mapper && converted.unicode() != 0x0) { - text = converted; - } else if (!chars.isEmpty()) { - // convert chars (8bit) to text (unicode). - if (mapper) - text = mapper->toUnicode(chars.data(), count, 0); - if (text.isEmpty()) { - // no mapper, or codec couldn't convert to unicode (this - // can happen when running in the C locale or with no LANG - // set). try converting from latin-1 - text = QString::fromLatin1(chars); - } - } - - modifiers = X11->translateModifiers(xmodifiers); - - // Commentary in X11/keysymdef says that X codes match ASCII, so it - // is safe to use the locale functions to process X codes in ISO8859-1. - // - // This is mainly for compatibility - applications should not use the - // Qt keycodes between 128 and 255, but should rather use the - // QKeyEvent::text(). - // - extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp - if (keysym < 128 || (keysym < 256 && (!qt_input_mapper || qt_input_mapper->mibEnum()==4))) { - // upper-case key, if known - code = isprint((int)keysym) ? toupper((int)keysym) : 0; - } else if (keysym >= XK_F1 && keysym <= XK_F35) { - // function keys - code = Qt::Key_F1 + ((int)keysym - XK_F1); - } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) { - if (keysym >= XK_KP_0) { - // numeric keypad keys - code = Qt::Key_0 + ((int)keysym - XK_KP_0); - } else { - code = translateKeySym(keysym); - } - modifiers |= Qt::KeypadModifier; - } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) { - code = text.unicode()->toUpper().unicode(); - } else { - // any other keys - code = translateKeySym(keysym); - - if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) { - // map shift+tab to shift+backtab, QShortcutMap knows about it - // and will handle it. - code = Qt::Key_Backtab; - text = QString(); - } - } - - return text; -} - -extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp - -bool QKeyMapperPrivate::translateKeyEventInternal(QWidget *keyWidget, - const XEvent *event, - KeySym &keysym, - int& count, - QString& text, - Qt::KeyboardModifiers &modifiers, - int& code, - QEvent::Type &type, - bool statefulTranslation) -{ - XKeyEvent xkeyevent = event->xkey; - int keycode = event->xkey.keycode; - // save the modifier state, we will use the keystate uint later by passing - // it to translateButtonState - uint keystate = event->xkey.state; - - type = (event->type == XKeyPress) ? QEvent::KeyPress : QEvent::KeyRelease; - - static int directionKeyEvent = 0; - static unsigned int lastWinId = 0; - - // translate pending direction change - if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyRelease) { - if (directionKeyEvent == Qt::Key_Direction_R || directionKeyEvent == Qt::Key_Direction_L) { - type = QEvent::KeyPress; - code = directionKeyEvent; - text = QString(); - directionKeyEvent = 0; - lastWinId = 0; - return true; - } else { - directionKeyEvent = 0; - lastWinId = 0; - } - } - - // some XmbLookupString implementations don't return buffer overflow correctly, - // so we increase the input buffer to allow for long strings... - // 256 chars * 2 bytes + 1 null-term == 513 bytes - QByteArray chars; - chars.resize(513); - - count = XLookupString(&xkeyevent, chars.data(), chars.size(), &keysym, 0); - if (count && !keycode) { - extern int qt_ximComposingKeycode; // from qapplication_x11.cpp - keycode = qt_ximComposingKeycode; - qt_ximComposingKeycode = 0; - } - - // translate the keysym + xmodifiers to Qt::Key_* + Qt::KeyboardModifiers - text = translateKeySym(keysym, keystate, code, modifiers, chars, count); - - // Watch for keypresses and if its a key belonging to the Ctrl-Shift - // direction-changing accel, remember it. - // We keep track of those keys instead of using the event's state - // (to figure out whether the Ctrl modifier is held while Shift is pressed, - // or Shift is held while Ctrl is pressed) since the 'state' doesn't tell - // us whether the modifier held is Left or Right. - if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyPress) { - if (keysym == XK_Control_L || keysym == XK_Control_R - || keysym == XK_Shift_L || keysym == XK_Shift_R) { - if (!directionKeyEvent) { - directionKeyEvent = keysym; - // This code exists in order to check that - // the event is occurred in the same widget. - lastWinId = keyWidget->internalWinId(); - } - } else { - // this can no longer be a direction-changing accel. - // if any other key was pressed. - directionKeyEvent = Qt::Key_Space; - } - - if (directionKeyEvent && lastWinId == keyWidget->internalWinId()) { - if ((keysym == XK_Shift_L && directionKeyEvent == XK_Control_L) - || (keysym == XK_Control_L && directionKeyEvent == XK_Shift_L)) { - directionKeyEvent = Qt::Key_Direction_L; - } else if ((keysym == XK_Shift_R && directionKeyEvent == XK_Control_R) - || (keysym == XK_Control_R && directionKeyEvent == XK_Shift_R)) { - directionKeyEvent = Qt::Key_Direction_R; - } - } else if (directionKeyEvent == Qt::Key_Direction_L - || directionKeyEvent == Qt::Key_Direction_R) { - directionKeyEvent = Qt::Key_Space; // invalid - } - } - - return true; -} - - -struct qt_auto_repeat_data -{ - // match the window and keycode with timestamp delta of 10 ms - Window window; - KeyCode keycode; - Time timestamp; - - // queue scanner state - bool release; - bool error; -}; - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static Bool qt_keypress_scanner(Display *, XEvent *event, XPointer arg) -{ - if (event->type != XKeyPress && event->type != XKeyRelease) - return false; - - qt_auto_repeat_data *data = (qt_auto_repeat_data *) arg; - if (data->error) - return false; - - if (event->xkey.window != data->window || - event->xkey.keycode != data->keycode) { - // deal breakers: key events in a different window or an event - // with a different key code - data->error = true; - return false; - } - - if (event->type == XKeyPress) { - data->error = (! data->release || event->xkey.time - data->timestamp > 10); - return (! data->error); - } - - // must be XKeyRelease event - if (data->release) { - // found a second release - data->error = true; - return false; - } - - // found a single release - data->release = true; - data->timestamp = event->xkey.time; - - return false; -} - -static Bool qt_keyrelease_scanner(Display *, XEvent *event, XPointer arg) -{ - const qt_auto_repeat_data *data = (const qt_auto_repeat_data *) arg; - return (event->type == XKeyRelease && - event->xkey.window == data->window && - event->xkey.keycode == data->keycode); -} - -#if defined(Q_C_CALLBACKS) -} -#endif - -bool QKeyMapperPrivate::translateKeyEvent(QWidget *keyWidget, const XEvent *event, bool grab) -{ - int code = -1; - int count = 0; - Qt::KeyboardModifiers modifiers; - - if (qt_sm_blockUserInput) // block user interaction during session management - return true; - - Display *dpy = X11->display; - - if (!keyWidget->isEnabled()) - return true; - - QEvent::Type type; - bool autor = false; - QString text; - - KeySym keysym = 0; - translateKeyEventInternal(keyWidget, event, keysym, count, text, modifiers, code, type); - - // was this the last auto-repeater? - qt_auto_repeat_data auto_repeat_data; - auto_repeat_data.window = event->xkey.window; - auto_repeat_data.keycode = event->xkey.keycode; - auto_repeat_data.timestamp = event->xkey.time; - - static uint curr_autorep = 0; - if (event->type == XKeyPress) { - if (curr_autorep == event->xkey.keycode) { - autor = true; - curr_autorep = 0; - } - } else { - // look ahead for auto-repeat - XEvent nextpress; - - auto_repeat_data.release = true; - auto_repeat_data.error = false; - if (XCheckIfEvent(dpy, &nextpress, &qt_keypress_scanner, - (XPointer) &auto_repeat_data)) { - autor = true; - - // Put it back... we COULD send the event now and not need - // the static curr_autorep variable. - XPutBackEvent(dpy,&nextpress); - } - curr_autorep = autor ? event->xkey.keycode : 0; - } - -#ifndef QT_NO_IM - QInputContext *qic = keyWidget->inputContext(); -#endif - - // compress keys - if (!text.isEmpty() && keyWidget->testAttribute(Qt::WA_KeyCompression) && -#ifndef QT_NO_IM - // Ordinary input methods require discrete key events to work - // properly, so key compression has to be disabled when input - // context exists. - // - // And further consideration, some complex input method - // require all key press/release events discretely even if - // the input method awares of key compression and compressed - // keys are ordinary alphabets. For example, the uim project - // is planning to implement "combinational shift" feature for - // a Japanese input method, uim-skk. It will work as follows. - // - // 1. press "r" - // 2. press "u" - // 3. release both "r" and "u" in arbitrary order - // 4. above key sequence generates "Ru" - // - // Of course further consideration about other participants - // such as key repeat mechanism is required to implement such - // feature. - !qic && -#endif // QT_NO_IM - // do not compress keys if the key event we just got above matches - // one of the key ranges used to compute stopCompression - !((code >= Qt::Key_Escape && code <= Qt::Key_SysReq) - || (code >= Qt::Key_Home && code <= Qt::Key_PageDown) - || (code >= Qt::Key_Super_L && code <= Qt::Key_Direction_R) - || (code == 0) - || (text.length() == 1 && text.unicode()->unicode() == '\n'))) { - // the widget wants key compression so it gets it - - // sync the event queue, this makes key compress work better - XSync(dpy, false); - - for (;;) { - XEvent evRelease; - XEvent evPress; - if (!XCheckTypedWindowEvent(dpy,event->xkey.window, - XKeyRelease,&evRelease)) - break; - if (!XCheckTypedWindowEvent(dpy,event->xkey.window, - XKeyPress,&evPress)) { - XPutBackEvent(dpy, &evRelease); - break; - } - QString textIntern; - int codeIntern = -1; - int countIntern = 0; - Qt::KeyboardModifiers modifiersIntern; - QEvent::Type t; - KeySym keySymIntern; - translateKeyEventInternal(keyWidget, &evPress, keySymIntern, countIntern, textIntern, - modifiersIntern, codeIntern, t); - // use stopCompression to stop key compression for the following - // key event ranges: - bool stopCompression = - // 1) misc keys - (codeIntern >= Qt::Key_Escape && codeIntern <= Qt::Key_SysReq) - // 2) cursor movement - || (codeIntern >= Qt::Key_Home && codeIntern <= Qt::Key_PageDown) - // 3) extra keys - || (codeIntern >= Qt::Key_Super_L && codeIntern <= Qt::Key_Direction_R) - // 4) something that a) doesn't translate to text or b) translates - // to newline text - || (codeIntern == 0) - || (textIntern.length() == 1 && textIntern.unicode()->unicode() == '\n') - || (codeIntern == Qt::Key_unknown); - - if (modifiersIntern == modifiers && !textIntern.isEmpty() && !stopCompression) { - text += textIntern; - count += countIntern; - } else { - XPutBackEvent(dpy, &evPress); - XPutBackEvent(dpy, &evRelease); - break; - } - } - } - - // autorepeat compression makes sense for all widgets (Windows - // does it automatically ....) - if (event->type == XKeyPress && text.length() <= 1 -#ifndef QT_NO_IM - // input methods need discrete key events - && !qic -#endif// QT_NO_IM - ) { - XEvent dummy; - - for (;;) { - auto_repeat_data.release = false; - auto_repeat_data.error = false; - if (! XCheckIfEvent(dpy, &dummy, &qt_keypress_scanner, - (XPointer) &auto_repeat_data)) - break; - if (! XCheckIfEvent(dpy, &dummy, &qt_keyrelease_scanner, - (XPointer) &auto_repeat_data)) - break; - - count++; - if (!text.isEmpty()) - text += text[0]; - } - } - - return QKeyMapper::sendKeyEvent(keyWidget, grab, type, code, modifiers, text, autor, - qMax(qMax(count,1), int(text.length())), - event->xkey.keycode, keysym, event->xkey.state); -} - -bool QKeyMapper::sendKeyEvent(QWidget *keyWidget, bool grab, - QEvent::Type type, int code, Qt::KeyboardModifiers modifiers, - const QString &text, bool autorepeat, int count, - quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, - bool *) -{ - // try the menukey first - if (type == QEvent::KeyPress && code == Qt::Key_Menu) { - QVariant v = keyWidget->inputMethodQuery(Qt::ImMicroFocus); - QPoint globalPos; - QPoint pos; - if (v.isNull()) { - globalPos = QCursor::pos(); - pos = keyWidget->mapFromGlobal(globalPos); - } else { - pos = v.toRect().center(); - globalPos = keyWidget->mapToGlobal(pos); - } - QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, globalPos); - qt_sendSpontaneousEvent(keyWidget, &e); - if(e.isAccepted()) - return true; - } - - Q_UNUSED(grab); - QKeyEventEx e(type, code, modifiers, text, autorepeat, qMax(qMax(count,1), int(text.length())), - nativeScanCode, nativeVirtualKey, nativeModifiers); - return qt_sendSpontaneousEvent(keyWidget, &e); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qkeymapper_x11_p.cpp b/src/widgets/platforms/x11/qkeymapper_x11_p.cpp deleted file mode 100644 index 80352ee797..0000000000 --- a/src/widgets/platforms/x11/qkeymapper_x11_p.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// This file is auto-generated, do not edit! -// (Generated using util/xkbdatagen) - -static struct { - const char *layout; - const char *variant; // 0 means any variant - Qt::LayoutDirection direction; - QLocale::Language language; - QLocale::Country country; -} xkbLayoutData[] = { - // name = us, description = U.S. English - { "us", "", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates }, - // name = us:intl, description = U.S. English - { "us", "intl", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates }, - // name = us:alt-intl, description = U.S. English - { "us", "alt-intl", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates }, - // name = us:dvorak, description = U.S. English - { "us", "dvorak", Qt::LeftToRight, QLocale::English, QLocale::UnitedStates }, - // name = us:rus, description = U.S. English - { "us", "rus", Qt::LeftToRight, QLocale::Russian, QLocale::UnitedStates }, - // name = ara, description = Arabic - { "ara", "", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates }, - // name = ara:azerty, description = Arabic - { "ara", "azerty", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates }, - // name = ara:azerty_digits, description = Arabic - { "ara", "azerty_digits", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates }, - // name = ara:digits, description = Arabic - { "ara", "digits", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates }, - // name = ara:qwerty, description = Arabic - { "ara", "qwerty", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates }, - // name = ara:qwerty_digits, description = Arabic - { "ara", "qwerty_digits", Qt::RightToLeft, QLocale::Arabic, QLocale::UnitedArabEmirates }, - // name = al, description = Albania - { "al", "", Qt::LeftToRight, QLocale::Albanian, QLocale::Albania }, - // name = am, description = Armenia - { "am", "", Qt::LeftToRight, QLocale::Armenian, QLocale::Armenia }, - // name = am:phonetic, description = Armenia - { "am", "phonetic", Qt::LeftToRight, QLocale::Armenian, QLocale::Armenia }, - // name = az, description = Azerbaijan - { "az", "", Qt::LeftToRight, QLocale::Azerbaijani, QLocale::Azerbaijan }, - // name = az:cyrillic, description = Azerbaijan - { "az", "cyrillic", Qt::LeftToRight, QLocale::Azerbaijani, QLocale::Azerbaijan }, - // name = by, description = Belarus - { "by", "", Qt::LeftToRight, QLocale::Byelorussian, QLocale::Belarus }, - // name = by:winkeys, description = Belarus - { "by", "winkeys", Qt::LeftToRight, QLocale::Byelorussian, QLocale::Belarus }, - // name = be, description = Belgium - { "be", "", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium }, - // name = be:iso-alternate, description = Belgium - { "be", "iso-alternate", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium }, - // name = be:nodeadkeys, description = Belgium - { "be", "nodeadkeys", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium }, - // name = be:sundeadkeys, description = Belgium - { "be", "sundeadkeys", Qt::LeftToRight, QLocale::Dutch, QLocale::Belgium }, - // name = bd, description = Bangladesh - { "bd", "", Qt::LeftToRight, QLocale::Bengali, QLocale::Bangladesh }, - // name = bd:probhat, description = Bangladesh - { "bd", "probhat", Qt::LeftToRight, QLocale::Bengali, QLocale::Bangladesh }, - // name = in, description = India - { "in", "", Qt::LeftToRight, QLocale::Hindi, QLocale::India }, - // name = in:ben, description = India - { "in", "ben", Qt::LeftToRight, QLocale::Bengali, QLocale::India }, - // name = in:ben_probhat, description = India - { "in", "ben_probhat", Qt::LeftToRight, QLocale::Bengali, QLocale::India }, - // name = in:guj, description = India - { "in", "guj", Qt::LeftToRight, QLocale::Gujarati, QLocale::India }, - // name = in:guru, description = India - { "in", "guru", Qt::LeftToRight, QLocale::Punjabi, QLocale::India }, - // name = in:kan, description = India - { "in", "kan", Qt::LeftToRight, QLocale::Kannada, QLocale::India }, - // name = in:mal, description = India - { "in", "mal", Qt::LeftToRight, QLocale::Malayalam, QLocale::India }, - // name = in:ori, description = India - { "in", "ori", Qt::LeftToRight, QLocale::Oriya, QLocale::India }, - // name = in:tam_unicode, description = India - { "in", "tam_unicode", Qt::LeftToRight, QLocale::Tamil, QLocale::India }, - // name = in:tam_TAB, description = India - { "in", "tam_TAB", Qt::LeftToRight, QLocale::Tamil, QLocale::India }, - // name = in:tam_TSCII, description = India - { "in", "tam_TSCII", Qt::LeftToRight, QLocale::Tamil, QLocale::India }, - // name = in:tam, description = India - { "in", "tam", Qt::LeftToRight, QLocale::Tamil, QLocale::India }, - // name = in:tel, description = India - { "in", "tel", Qt::LeftToRight, QLocale::Telugu, QLocale::India }, - // name = in:urd, description = India - { "in", "urd", Qt::RightToLeft, QLocale::Urdu, QLocale::India }, - // name = ba, description = Bosnia and Herzegovina - { "ba", "", Qt::LeftToRight, QLocale::Bosnian, QLocale::BosniaAndHerzegowina }, - // name = br, description = Brazil - { "br", "", Qt::LeftToRight, QLocale::Portuguese, QLocale::Brazil }, - // name = br:nodeadkeys, description = Brazil - { "br", "nodeadkeys", Qt::LeftToRight, QLocale::Portuguese, QLocale::Brazil }, - // name = bg, description = Bulgaria - { "bg", "", Qt::LeftToRight, QLocale::Bulgarian, QLocale::Bulgaria }, - // name = bg:phonetic, description = Bulgaria - { "bg", "phonetic", Qt::LeftToRight, QLocale::Bulgarian, QLocale::Bulgaria }, - // name = mm, description = Myanmar - { "mm", "", Qt::LeftToRight, QLocale::Burmese, QLocale::Myanmar }, - // name = ca, description = Canada - { "ca", "", Qt::LeftToRight, QLocale::English, QLocale::Canada }, - // name = ca:fr-dvorak, description = Canada - { "ca", "fr-dvorak", Qt::LeftToRight, QLocale::French, QLocale::Canada }, - // name = ca:fr-legacy, description = Canada - { "ca", "fr-legacy", Qt::LeftToRight, QLocale::French, QLocale::Canada }, - // name = ca:multi, description = Canada - { "ca", "multi", Qt::LeftToRight, QLocale::English, QLocale::Canada }, - // name = ca:multi-2gr, description = Canada - { "ca", "multi-2gr", Qt::LeftToRight, QLocale::English, QLocale::Canada }, - // name = ca:ike, description = Canada - { "ca", "ike", Qt::LeftToRight, QLocale::Inuktitut, QLocale::Canada }, - // name = hr, description = Croatia - { "hr", "", Qt::LeftToRight, QLocale::Croatian, QLocale::Croatia }, - // name = hr:us, description = Croatia - { "hr", "us", Qt::LeftToRight, QLocale::Croatian, QLocale::Croatia }, - // name = cz, description = Czechia - { "cz", "", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic }, - // name = cz:bksl, description = Czechia - { "cz", "bksl", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic }, - // name = cz:qwerty, description = Czechia - { "cz", "qwerty", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic }, - // name = cz:qwerty_bksl, description = Czechia - { "cz", "qwerty_bksl", Qt::LeftToRight, QLocale::Czech, QLocale::CzechRepublic }, - // name = dk, description = Denmark - { "dk", "", Qt::LeftToRight, QLocale::Danish, QLocale::Denmark }, - // name = dk:nodeadkeys, description = Denmark - { "dk", "nodeadkeys", Qt::LeftToRight, QLocale::Danish, QLocale::Denmark }, - // name = nl, description = Netherlands - { "nl", "", Qt::LeftToRight, QLocale::Dutch, QLocale::Netherlands }, - // name = bt, description = Bhutan - { "bt", "", Qt::LeftToRight, QLocale::Bhutani, QLocale::Bhutan }, - // name = ee, description = Estonia - { "ee", "", Qt::LeftToRight, QLocale::Estonian, QLocale::Estonia }, - // name = ee:nodeadkeys, description = Estonia - { "ee", "nodeadkeys", Qt::LeftToRight, QLocale::Estonian, QLocale::Estonia }, - // name = ir, description = Iran - { "ir", "", Qt::RightToLeft, QLocale::Persian, QLocale::Iran }, - // name = fo, description = Faroe Islands - { "fo", "", Qt::LeftToRight, QLocale::Faroese, QLocale::FaroeIslands }, - // name = fo:nodeadkeys, description = Faroe Islands - { "fo", "nodeadkeys", Qt::LeftToRight, QLocale::Faroese, QLocale::FaroeIslands }, - // name = fi, description = Finland - { "fi", "", Qt::LeftToRight, QLocale::Finnish, QLocale::Finland }, - // name = fi:nodeadkeys, description = Finland - { "fi", "nodeadkeys", Qt::LeftToRight, QLocale::Finnish, QLocale::Finland }, - // name = fi:smi, description = Finland - { "fi", "smi", Qt::LeftToRight, QLocale::Finnish, QLocale::Finland }, - // name = fr, description = France - { "fr", "", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = fr:nodeadkeys, description = France - { "fr", "nodeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = fr:sundeadkeys, description = France - { "fr", "sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = fr:latin9, description = France - { "fr", "latin9", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = fr:latin9_nodeadkeys, description = France - { "fr", "latin9_nodeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = fr:latin9_sundeadkeys, description = France - { "fr", "latin9_sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = fr:dvorak, description = France - { "fr", "dvorak", Qt::LeftToRight, QLocale::French, QLocale::France }, - // name = ge, description = Georgia - { "ge", "", Qt::LeftToRight, QLocale::Georgian, QLocale::Georgia }, - // name = ge:ru, description = Georgia - { "ge", "ru", Qt::LeftToRight, QLocale::Russian, QLocale::Georgia }, - // name = de, description = Germany - { "de", "", Qt::LeftToRight, QLocale::German, QLocale::Germany }, - // name = de:deadacute, description = Germany - { "de", "deadacute", Qt::LeftToRight, QLocale::German, QLocale::Germany }, - // name = de:deadgraveacute, description = Germany - { "de", "deadgraveacute", Qt::LeftToRight, QLocale::German, QLocale::Germany }, - // name = de:nodeadkeys, description = Germany - { "de", "nodeadkeys", Qt::LeftToRight, QLocale::German, QLocale::Germany }, - // name = de:ro, description = Germany - { "de", "ro", Qt::LeftToRight, QLocale::Romanian, QLocale::Germany }, - // name = de:ro_nodeadkeys, description = Germany - { "de", "ro_nodeadkeys", Qt::LeftToRight, QLocale::Romanian, QLocale::Germany }, - // name = de:dvorak, description = Germany - { "de", "dvorak", Qt::LeftToRight, QLocale::German, QLocale::Germany }, - // name = gr, description = Greece - { "gr", "", Qt::LeftToRight, QLocale::Greek, QLocale::Greece }, - // name = gr:extended, description = Greece - { "gr", "extended", Qt::LeftToRight, QLocale::Greek, QLocale::Greece }, - // name = gr:nodeadkeys, description = Greece - { "gr", "nodeadkeys", Qt::LeftToRight, QLocale::Greek, QLocale::Greece }, - // name = gr:polytonic, description = Greece - { "gr", "polytonic", Qt::LeftToRight, QLocale::Greek, QLocale::Greece }, - // name = hu, description = Hungary - { "hu", "", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:standard, description = Hungary - { "hu", "standard", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:nodeadkeys, description = Hungary - { "hu", "nodeadkeys", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:qwerty, description = Hungary - { "hu", "qwerty", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwertz_comma_dead, description = Hungary - { "hu", "101_qwertz_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwertz_comma_nodead, description = Hungary - { "hu", "101_qwertz_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwertz_dot_dead, description = Hungary - { "hu", "101_qwertz_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwertz_dot_nodead, description = Hungary - { "hu", "101_qwertz_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwerty_comma_dead, description = Hungary - { "hu", "101_qwerty_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwerty_comma_nodead, description = Hungary - { "hu", "101_qwerty_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwerty_dot_dead, description = Hungary - { "hu", "101_qwerty_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:101_qwerty_dot_nodead, description = Hungary - { "hu", "101_qwerty_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwertz_comma_dead, description = Hungary - { "hu", "102_qwertz_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwertz_comma_nodead, description = Hungary - { "hu", "102_qwertz_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwertz_dot_dead, description = Hungary - { "hu", "102_qwertz_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwertz_dot_nodead, description = Hungary - { "hu", "102_qwertz_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwerty_comma_dead, description = Hungary - { "hu", "102_qwerty_comma_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwerty_comma_nodead, description = Hungary - { "hu", "102_qwerty_comma_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwerty_dot_dead, description = Hungary - { "hu", "102_qwerty_dot_dead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = hu:102_qwerty_dot_nodead, description = Hungary - { "hu", "102_qwerty_dot_nodead", Qt::LeftToRight, QLocale::Hungarian, QLocale::Hungary }, - // name = is, description = Iceland - { "is", "", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland }, - // name = is:Sundeadkeys, description = Iceland - { "is", "Sundeadkeys", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland }, - // name = is:nodeadkeys, description = Iceland - { "is", "nodeadkeys", Qt::LeftToRight, QLocale::Icelandic, QLocale::Iceland }, - // name = il, description = Israel - { "il", "", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, - // name = il:lyx, description = Israel - { "il", "lyx", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, - // name = il:si1452, description = Israel - { "il", "si1452", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, - // name = il:phonetic, description = Israel - { "il", "phonetic", Qt::RightToLeft, QLocale::Hebrew, QLocale::Israel }, - // name = it, description = Italy - { "it", "", Qt::LeftToRight, QLocale::Italian, QLocale::Italy }, - // name = it:nodeadkeys, description = Italy - { "it", "nodeadkeys", Qt::LeftToRight, QLocale::Italian, QLocale::Italy }, - // name = jp, description = Japan - { "jp", "", Qt::LeftToRight, QLocale::Japanese, QLocale::Japan }, - // name = kg, description = Kyrgyzstan - { "kg", "", Qt::LeftToRight, QLocale::Kirghiz, QLocale::Kyrgyzstan }, - // name = la, description = Laos - { "la", "", Qt::LeftToRight, QLocale::Laothian, QLocale::Lao }, - // name = latam, description = Latin American - { "latam", "", Qt::LeftToRight, QLocale::Spanish, QLocale::Mexico }, - // name = latam:nodeadkeys, description = Latin American - { "latam", "nodeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Mexico }, - // name = latam:sundeadkeys, description = Latin American - { "latam", "sundeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Mexico }, - // name = lt, description = Lithuania - { "lt", "", Qt::LeftToRight, QLocale::Lithuanian, QLocale::Lithuania }, - // name = lt:std, description = Lithuania - { "lt", "std", Qt::LeftToRight, QLocale::Lithuanian, QLocale::Lithuania }, - // name = lt:us, description = Lithuania - { "lt", "us", Qt::LeftToRight, QLocale::Lithuanian, QLocale::Lithuania }, - // name = lv, description = Latvia - { "lv", "", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia }, - // name = lv:apostrophe, description = Latvia - { "lv", "apostrophe", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia }, - // name = lv:tilde, description = Latvia - { "lv", "tilde", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia }, - // name = lv:fkey, description = Latvia - { "lv", "fkey", Qt::LeftToRight, QLocale::Latvian, QLocale::Latvia }, - // name = mao, description = Maori - { "mao", "", Qt::LeftToRight, QLocale::Maori, QLocale::NewZealand }, - // name = mkd, description = Macedonian - { "mkd", "", Qt::LeftToRight, QLocale::Macedonian, QLocale::Macedonia }, - // name = mkd:nodeadkeys, description = Macedonian - { "mkd", "nodeadkeys", Qt::LeftToRight, QLocale::Macedonian, QLocale::Macedonia }, - // name = mt, description = Malta - { "mt", "", Qt::LeftToRight, QLocale::Maltese, QLocale::Malta }, - // name = mt:us, description = Malta - { "mt", "us", Qt::LeftToRight, QLocale::Maltese, QLocale::Malta }, - // name = mn, description = Mongolia - { "mn", "", Qt::LeftToRight, QLocale::Mongolian, QLocale::Mongolia }, - // name = no, description = Norway - { "no", "", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway }, - // name = no:nodeadkeys, description = Norway - { "no", "nodeadkeys", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway }, - // name = no:dvorak, description = Norway - { "no", "dvorak", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway }, - // name = no:smi, description = Norway - { "no", "smi", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway }, - // name = no:smi_nodeadkeys, description = Norway - { "no", "smi_nodeadkeys", Qt::LeftToRight, QLocale::Norwegian, QLocale::Norway }, - // name = pl, description = Poland - { "pl", "", Qt::LeftToRight, QLocale::Polish, QLocale::Poland }, - // name = pl:qwertz, description = Poland - { "pl", "qwertz", Qt::LeftToRight, QLocale::Polish, QLocale::Poland }, - // name = pl:dvorak, description = Poland - { "pl", "dvorak", Qt::LeftToRight, QLocale::Polish, QLocale::Poland }, - // name = pl:dvorak_quotes, description = Poland - { "pl", "dvorak_quotes", Qt::LeftToRight, QLocale::Polish, QLocale::Poland }, - // name = pl:dvorak_altquotes, description = Poland - { "pl", "dvorak_altquotes", Qt::LeftToRight, QLocale::Polish, QLocale::Poland }, - // name = pt, description = Portugal - { "pt", "", Qt::LeftToRight, QLocale::Portuguese, QLocale::Portugal }, - // name = pt:nodeadkeys, description = Portugal - { "pt", "nodeadkeys", Qt::LeftToRight, QLocale::Portuguese, QLocale::Portugal }, - // name = pt:sundeadkeys, description = Portugal - { "pt", "sundeadkeys", Qt::LeftToRight, QLocale::Portuguese, QLocale::Portugal }, - // name = ro, description = Romania - { "ro", "", Qt::LeftToRight, QLocale::Romanian, QLocale::Romania }, - // name = ro:us, description = Romania - { "ro", "us", Qt::LeftToRight, QLocale::English, QLocale::Romania }, - // name = ro:de, description = Romania - { "ro", "de", Qt::LeftToRight, QLocale::German, QLocale::Romania }, - // name = ru, description = Russia - { "ru", "", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation }, - // name = ru:phonetic, description = Russia - { "ru", "phonetic", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation }, - // name = ru:typewriter, description = Russia - { "ru", "typewriter", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation }, - // name = ru:winkeys, description = Russia - { "ru", "winkeys", Qt::LeftToRight, QLocale::Russian, QLocale::RussianFederation }, - // name = srp, description = Serbian - { "srp", "", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:yz, description = Serbian - { "srp", "yz", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:latin, description = Serbian - { "srp", "latin", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:latinunicode, description = Serbian - { "srp", "latinunicode", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:latinyz, description = Serbian - { "srp", "latinyz", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:latinunicodeyz, description = Serbian - { "srp", "latinunicodeyz", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:alternatequotes, description = Serbian - { "srp", "alternatequotes", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = srp:latinalternatequotes, description = Serbian - { "srp", "latinalternatequotes", Qt::LeftToRight, QLocale::Serbian, QLocale::SerbiaAndMontenegro }, - // name = si, description = Slovenia - { "si", "", Qt::LeftToRight, QLocale::Slovenian, QLocale::Slovenia }, - // name = sk, description = Slovakia - { "sk", "", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia }, - // name = sk:bksl, description = Slovakia - { "sk", "bksl", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia }, - // name = sk:qwerty, description = Slovakia - { "sk", "qwerty", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia }, - // name = sk:qwerty_bksl, description = Slovakia - { "sk", "qwerty_bksl", Qt::LeftToRight, QLocale::Slovak, QLocale::Slovakia }, - // name = es, description = Spain - { "es", "", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain }, - // name = es:nodeadkeys, description = Spain - { "es", "nodeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain }, - // name = es:sundeadkeys, description = Spain - { "es", "sundeadkeys", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain }, - // name = es:dvorak, description = Spain - { "es", "dvorak", Qt::LeftToRight, QLocale::Spanish, QLocale::Spain }, - // name = se, description = Sweden - { "se", "", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden }, - // name = se:nodeadkeys, description = Sweden - { "se", "nodeadkeys", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden }, - // name = se:dvorak, description = Sweden - { "se", "dvorak", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden }, - // name = se:rus, description = Sweden - { "se", "rus", Qt::LeftToRight, QLocale::Russian, QLocale::Sweden }, - // name = se:rus_nodeadkeys, description = Sweden - { "se", "rus_nodeadkeys", Qt::LeftToRight, QLocale::Russian, QLocale::Sweden }, - // name = se:smi, description = Sweden - { "se", "smi", Qt::LeftToRight, QLocale::Swedish, QLocale::Sweden }, - // name = ch, description = Switzerland - { "ch", "", Qt::LeftToRight, QLocale::German, QLocale::Switzerland }, - // name = ch:de_nodeadkeys, description = Switzerland - { "ch", "de_nodeadkeys", Qt::LeftToRight, QLocale::German, QLocale::Switzerland }, - // name = ch:de_sundeadkeys, description = Switzerland - { "ch", "de_sundeadkeys", Qt::LeftToRight, QLocale::German, QLocale::Switzerland }, - // name = ch:fr, description = Switzerland - { "ch", "fr", Qt::LeftToRight, QLocale::French, QLocale::Switzerland }, - // name = ch:fr_nodeadkeys, description = Switzerland - { "ch", "fr_nodeadkeys", Qt::LeftToRight, QLocale::French, QLocale::Switzerland }, - // name = ch:fr_sundeadkeys, description = Switzerland - { "ch", "fr_sundeadkeys", Qt::LeftToRight, QLocale::French, QLocale::Switzerland }, - // name = sy, description = Syria - { "sy", "", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, - // name = sy:syc, description = Syria - { "sy", "syc", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, - // name = sy:syc_phonetic, description = Syria - { "sy", "syc_phonetic", Qt::RightToLeft, QLocale::Syriac, QLocale::SyrianArabRepublic }, - // name = tj, description = Tajikistan - { "tj", "", Qt::LeftToRight, QLocale::Tajik, QLocale::Tajikistan }, - // name = lk, description = Sri Lanka - { "lk", "", Qt::LeftToRight, QLocale::Singhalese, QLocale::SriLanka }, - // name = lk:tam_unicode, description = Sri Lanka - { "lk", "tam_unicode", Qt::LeftToRight, QLocale::Tamil, QLocale::SriLanka }, - // name = lk:tam_TAB, description = Sri Lanka - { "lk", "tam_TAB", Qt::LeftToRight, QLocale::Tamil, QLocale::SriLanka }, - // name = lk:tam_TSCII, description = Sri Lanka - { "lk", "tam_TSCII", Qt::LeftToRight, QLocale::Tamil, QLocale::SriLanka }, - // name = lk:sin_phonetic, description = Sri Lanka - { "lk", "sin_phonetic", Qt::LeftToRight, QLocale::Singhalese, QLocale::SriLanka }, - // name = th, description = Thailand - { "th", "", Qt::LeftToRight, QLocale::Thai, QLocale::Thailand }, - // name = th:tis, description = Thailand - { "th", "tis", Qt::LeftToRight, QLocale::Thai, QLocale::Thailand }, - // name = th:pat, description = Thailand - { "th", "pat", Qt::LeftToRight, QLocale::Thai, QLocale::Thailand }, - // name = tr, description = Turkish - { "tr", "", Qt::LeftToRight, QLocale::Turkish, QLocale::Turkey }, - // name = tr:f, description = Turkish - { "tr", "f", Qt::LeftToRight, QLocale::Turkish, QLocale::Turkey }, - // name = tr:alt, description = Turkish - { "tr", "alt", Qt::LeftToRight, QLocale::Turkish, QLocale::Turkey }, - // name = ua, description = Ukraine - { "ua", "", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine }, - // name = ua:phonetic, description = Ukraine - { "ua", "phonetic", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine }, - // name = ua:typewriter, description = Ukraine - { "ua", "typewriter", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine }, - // name = ua:winkeys, description = Ukraine - { "ua", "winkeys", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine }, - // name = ua:rstu, description = Ukraine - { "ua", "rstu", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine }, - // name = ua:rstu_ru, description = Ukraine - { "ua", "rstu_ru", Qt::LeftToRight, QLocale::Ukrainian, QLocale::Ukraine }, - // name = gb, description = United Kingdom - { "gb", "", Qt::LeftToRight, QLocale::English, QLocale::UnitedKingdom }, - // name = gb:intl, description = United Kingdom - { "gb", "intl", Qt::LeftToRight, QLocale::English, QLocale::UnitedKingdom }, - // name = gb:dvorak, description = United Kingdom - { "gb", "dvorak", Qt::LeftToRight, QLocale::English, QLocale::UnitedKingdom }, - // name = uz, description = Uzbekistan - { "uz", "", Qt::LeftToRight, QLocale::Uzbek, QLocale::Uzbekistan }, - // name = vn, description = Vietnam - { "vn", "", Qt::LeftToRight, QLocale::Vietnamese, QLocale::VietNam }, - // name = nec_vndr/jp, description = PC-98xx Series - { "nec_vndr/jp", "", Qt::LeftToRight, QLocale::Japanese, QLocale::Japan }, - // name = ie, description = Ireland - { "ie", "", Qt::LeftToRight, QLocale::Irish, QLocale::Ireland }, - // name = ie:CloGaelach, description = Ireland - { "ie", "CloGaelach", Qt::LeftToRight, QLocale::Gaelic, QLocale::Ireland }, - // name = ie:UnicodeExpert, description = Ireland - { "ie", "UnicodeExpert", Qt::LeftToRight, QLocale::Irish, QLocale::Ireland }, - // name = ie:ogam, description = Ireland - { "ie", "ogam", Qt::LeftToRight, QLocale::Gaelic, QLocale::Ireland }, - // name = ie:ogam_is434, description = Ireland - { "ie", "ogam_is434", Qt::LeftToRight, QLocale::Gaelic, QLocale::Ireland }, - // name = pk, description = Pakistan - { "pk", "", Qt::RightToLeft, QLocale::Urdu, QLocale::Pakistan }, - { 0, 0, Qt::LeftToRight, QLocale::C, QLocale::AnyCountry } -}; diff --git a/src/widgets/platforms/x11/qmotifdnd_x11.cpp b/src/widgets/platforms/x11/qmotifdnd_x11.cpp deleted file mode 100644 index 77f6ce5827..0000000000 --- a/src/widgets/platforms/x11/qmotifdnd_x11.cpp +++ /dev/null @@ -1,1031 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* The following copyright notice pertains to the code as contributed -to Qt, not to Nokia's modifications. It is replicated -in doc/dnd.doc, where the documentation system can see it. */ - -/* Copyright 1996 Daniel Dardailler. - - Permission to use, copy, modify, distribute, and sell this software - for any purpose is hereby granted without fee, provided that the above - copyright notice appear in all copies and that both that copyright - notice and this permission notice appear in supporting documentation, - and that the name of Daniel Dardailler not be used in advertising or - publicity pertaining to distribution of the software without specific, - written prior permission. Daniel Dardailler makes no representations - about the suitability of this software for any purpose. It is - provided "as is" without express or implied warranty. - - Modifications Copyright 1999 Matt Koss, under the same license as - above. -************************************************************/ - -/***********************************************************/ -/* Motif Drag&Drop Dynamic Protocol messaging API code */ -/* Only requires Xlib layer - not MT safe */ -/* Author: Daniel Dardailler, daniel@x.org */ -/* Adapted by: Matt Koss, koss@napri.sk */ -/* Further adaptions by: Nokia Corporation and/or its subsidiary(-ies) */ -/***********************************************************/ - -#include "qplatformdefs.h" - -#include "qapplication.h" - -#ifndef QT_NO_DRAGANDDROP - -#include "qdebug.h" -#include "qtextcodec.h" -#include "qwidget.h" -#include "qevent.h" -#include "qt_x11_p.h" -#include "qx11info_x11.h" -#include "qiodevice.h" -#include "qdnd_p.h" - -#include <stdlib.h> - -QT_BEGIN_NAMESPACE - -static Window sourceWindow = XNone; -static QWidget *dropWidget = 0; -static Qt::DropAction lastAcceptedAction = Qt::IgnoreAction; - -static Atom Dnd_selection = 0; -static Time Dnd_selection_time; - -static Atom * src_targets ; -static ushort num_src_targets ; - -// Motif definitions -#define DndVersion 1 -#define DndRevision 0 -#define DndIncludeVersion (DndVersion * 10 + DndRevision) - -/* The following values are used in the DndData structure */ - -/* protocol style */ -#define DND_DRAG_NONE 0 -#define DND_DRAG_DROP_ONLY 1 -#define DND_DRAG_DYNAMIC 5 - -/* message type */ -#define DND_TOP_LEVEL_ENTER 0 -#define DND_TOP_LEVEL_LEAVE 1 -#define DND_DRAG_MOTION 2 -#define DND_DROP_SITE_ENTER 3 -#define DND_DROP_SITE_LEAVE 4 -#define DND_DROP_START 5 -#define DND_OPERATION_CHANGED 8 - -/* operation(s) */ -#define DND_NOOP 0L -#define DND_MOVE (1L << 0) -#define DND_COPY (1L << 1) -#define DND_LINK (1L << 2) - -static Qt::DropActions DndOperationsToQtDropActions(uchar op) -{ - Qt::DropActions actions = Qt::IgnoreAction; - if (op | DND_MOVE) - actions |= Qt::MoveAction; - if (op | DND_COPY) - actions |= Qt::CopyAction; - if (op | DND_LINK) - actions |= Qt::LinkAction; - return actions; -} - -static uchar QtDropActionToDndOperation(Qt::DropAction action) -{ - switch (action & Qt::ActionMask) { - case Qt::CopyAction: - default: - return DND_COPY; - case Qt::MoveAction: - return DND_MOVE; - case Qt::LinkAction: - return DND_LINK; - } -} - - -/* status */ -#define DND_NO_DROP_SITE 1 -#define DND_INVALID_DROP_SITE 2 -#define DND_VALID_DROP_SITE 3 - -/* completion */ -#define DND_DROP 0 -#define DND_DROP_HELP 1 -#define DND_DROP_CANCEL 2 - -#define BYTE unsigned char -#define CARD32 unsigned int -#define CARD16 unsigned short -#define INT16 signed short - -/* Client side structure used in the API */ -typedef struct { - unsigned char reason; /* message type: DND_TOP_LEVEL_ENTER, etc */ - Time time ; - unsigned char operation; - unsigned char operations; - unsigned char status; - unsigned char completion; - short x ; - short y ; - Window src_window ; - Atom property ; -} DndData ; - - -typedef struct _DndSrcProp { - BYTE byte_order ; - BYTE protocol_version ; - CARD16 target_index ; - CARD32 selection ; -} DndSrcProp ; - -typedef struct _DndReceiverProp { - BYTE byte_order ; - BYTE protocol_version ; - BYTE protocol_style ; - BYTE pad1; - CARD32 proxy_window; - CARD16 num_drop_sites ; - CARD16 pad2; - CARD32 total_size; -} DndReceiverProp ; - -/* need to use some union hack since window and property are in - different order depending on the message ... */ -typedef struct _DndTop { - CARD32 src_window; - CARD32 property; -} DndTop ; - -typedef struct _DndPot { - INT16 x; - INT16 y; - CARD32 property; - CARD32 src_window; -} DndPot ; - -typedef struct _DndMessage { - BYTE reason; - BYTE byte_order; - CARD16 flags; - CARD32 time; - union { - DndTop top ; - DndPot pot ; - } data ; -} DndMessage ; - -typedef struct { - BYTE byte_order; - BYTE protocol_version; - CARD16 num_target_lists; - CARD32 data_size; - /* then come series of CARD16,CARD32,CARD32,CARD32... */ -} DndTargets; - - -/* protocol version */ -#define DND_PROTOCOL_VERSION 0 - - -#define DND_EVENT_TYPE_MASK ((BYTE)0x80) -#define DND_EVENT_TYPE_SHIFT 7 -#define DND_CLEAR_EVENT_TYPE ((BYTE)0x7F) - -/* message_type is data[0] of the client_message - this return 1 (receiver bit up) or 0 (initiator) */ -#define DND_GET_EVENT_TYPE(message_type) \ -((char) (((message_type) & DND_EVENT_TYPE_MASK) >> DND_EVENT_TYPE_SHIFT)) - -/* event_type can be 0 (initiator) or 1 (receiver) */ -#define DND_SET_EVENT_TYPE(event_type) \ -(((BYTE)(event_type) << DND_EVENT_TYPE_SHIFT) & DND_EVENT_TYPE_MASK) - - -#define DND_OPERATION_MASK ((CARD16) 0x000F) -#define DND_OPERATION_SHIFT 0 -#define DND_STATUS_MASK ((CARD16) 0x00F0) -#define DND_STATUS_SHIFT 4 -#define DND_OPERATIONS_MASK ((CARD16) 0x0F00) -#define DND_OPERATIONS_SHIFT 8 -#define DND_COMPLETION_MASK ((CARD16) 0xF000) -#define DND_COMPLETION_SHIFT 12 - -#define DND_GET_OPERATION(flags) \ -((unsigned char) \ -(((flags) & DND_OPERATION_MASK) >> DND_OPERATION_SHIFT)) - -#define DND_SET_OPERATION(operation) \ -(((CARD16)(operation) << DND_OPERATION_SHIFT)\ -& DND_OPERATION_MASK) - -#define DND_GET_STATUS(flags) \ -((unsigned char) \ -(((flags) & DND_STATUS_MASK) >> DND_STATUS_SHIFT)) - -#define DND_SET_STATUS(status) \ -(((CARD16)(status) << DND_STATUS_SHIFT)\ -& DND_STATUS_MASK) - -#define DND_GET_OPERATIONS(flags) \ -((unsigned char) \ -(((flags) & DND_OPERATIONS_MASK) >> DND_OPERATIONS_SHIFT)) - -#define DND_SET_OPERATIONS(operation) \ -(((CARD16)(operation) << DND_OPERATIONS_SHIFT)\ -& DND_OPERATIONS_MASK) - -#define DND_GET_COMPLETION(flags) \ -((unsigned char) \ -(((flags) & DND_COMPLETION_MASK) >> DND_COMPLETION_SHIFT)) - -#define DND_SET_COMPLETION(completion) \ -(((CARD16)(completion) << DND_COMPLETION_SHIFT)\ -& DND_COMPLETION_MASK) - - -#define SWAP4BYTES(l) {\ -struct { unsigned t :32;} bit32;\ -char n, *tp = (char *) &bit32;\ -bit32.t = l;\ -n = tp[0]; tp[0] = tp[3]; tp[3] = n;\ -n = tp[1]; tp[1] = tp[2]; tp[2] = n;\ -l = bit32.t;\ -} - -#define SWAP2BYTES(s) {\ -struct { unsigned t :16; } bit16;\ -char n, *tp = (char *) &bit16;\ -bit16.t = s;\ -n = tp[0]; tp[0] = tp[1]; tp[1] = n;\ -s = bit16.t;\ -} - - -/** Private extern functions */ - -static unsigned char DndByteOrder (); - - -/***** Targets/Index stuff */ - -typedef struct { - int num_targets; - Atom *targets; -} DndTargetsTableEntryRec, * DndTargetsTableEntry; - -typedef struct { - int num_entries; - DndTargetsTableEntry entries; -} DndTargetsTableRec, * DndTargetsTable; - - -static ushort _DndIndexToTargets(Display * display, - int index, - Atom ** targets); - -extern void qt_x11_intern_atom(const char *, Atom *); - -///////////////////////////////////////////////////////////////// - -static unsigned char DndByteOrder () -{ - static unsigned char byte_order = 0; - - if (!byte_order) { - unsigned int endian = 1; - byte_order = (*((char *)&endian))?'l':'B'; - } - return byte_order ; -} - - - -static void DndReadSourceProperty(Display * dpy, - Window window, Atom dnd_selection, - Atom ** targets, unsigned short * num_targets) -{ - unsigned char *retval = 0; - Atom type ; - int format ; - unsigned long bytesafter, lengthRtn; - - if ((XGetWindowProperty (dpy, window, dnd_selection, 0L, 100000L, - False, ATOM(_MOTIF_DRAG_INITIATOR_INFO), &type, - &format, &lengthRtn, &bytesafter, - &retval) != Success) - || (type == XNone)) { - *num_targets = 0; - return ; - } - - DndSrcProp * src_prop = (DndSrcProp *)retval; - - if (src_prop->byte_order != DndByteOrder()) { - SWAP2BYTES(src_prop->target_index); - SWAP4BYTES(src_prop->selection); - } - - *num_targets = _DndIndexToTargets(dpy, src_prop->target_index, targets); - - XFree((char*)src_prop); -} - - -/* Position the _MOTIF_DRAG_RECEIVER_INFO property on the dropsite window. - Called by the receiver of the drop to indicate the - supported protocol style : dynamic, drop_only or none */ -static void DndWriteReceiverProperty(Display * dpy, Window window, - unsigned char protocol_style) -{ - DndReceiverProp receiver_prop; - - // squelch potential valgrind errors about uninitialized reads - memset(&receiver_prop, 0, sizeof(receiver_prop)); - - receiver_prop.byte_order = DndByteOrder() ; - receiver_prop.protocol_version = DND_PROTOCOL_VERSION; - receiver_prop.protocol_style = protocol_style ; - receiver_prop.proxy_window = XNone ; - receiver_prop.num_drop_sites = 0 ; - receiver_prop.total_size = sizeof(DndReceiverProp); - - /* write the buffer to the property */ - XChangeProperty (dpy, window, ATOM(_MOTIF_DRAG_RECEIVER_INFO), ATOM(_MOTIF_DRAG_RECEIVER_INFO), - 8, PropModeReplace, - (unsigned char *)&receiver_prop, - sizeof(DndReceiverProp)); -} - - -/* protocol style equiv (preregister stuff really) */ -#define DND_DRAG_DROP_ONLY_EQUIV 3 -#define DND_DRAG_DYNAMIC_EQUIV1 2 -#define DND_DRAG_DYNAMIC_EQUIV2 4 - - -/* Produce a client message to be sent by the caller */ -static void DndFillClientMessage(Display * dpy, Window window, - XClientMessageEvent *cm, - DndData * dnd_data, - char receiver) -{ - DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ; - - cm->display = dpy; - cm->type = ClientMessage; - cm->serial = LastKnownRequestProcessed(dpy); - cm->send_event = True; - cm->window = window; - cm->format = 8; - cm->message_type = ATOM(_MOTIF_DRAG_AND_DROP_MESSAGE); - - dnd_message->reason = dnd_data->reason | DND_SET_EVENT_TYPE(receiver); - - dnd_message->byte_order = DndByteOrder(); - - /* we're filling in flags with more stuff that necessary, - depending on the reason, but it doesn't matter */ - dnd_message->flags = 0 ; - dnd_message->flags |= DND_SET_STATUS(dnd_data->status) ; - dnd_message->flags |= DND_SET_OPERATION(dnd_data->operation) ; - dnd_message->flags |= DND_SET_OPERATIONS(dnd_data->operations) ; - dnd_message->flags |= DND_SET_COMPLETION(dnd_data->completion) ; - - dnd_message->time = dnd_data->time ; - - switch(dnd_data->reason) { - case DND_DROP_SITE_LEAVE: break ; - case DND_TOP_LEVEL_ENTER: - case DND_TOP_LEVEL_LEAVE: - dnd_message->data.top.src_window = dnd_data->src_window ; - dnd_message->data.top.property = dnd_data->property ; - break ; /* cannot fall through since the byte layout is different in - both set of messages, see top and pot union stuff */ - - case DND_DRAG_MOTION: - case DND_OPERATION_CHANGED: - case DND_DROP_SITE_ENTER: - case DND_DROP_START: - dnd_message->data.pot.x = dnd_data->x ; /* mouse position */ - dnd_message->data.pot.y = dnd_data->y ; - dnd_message->data.pot.src_window = dnd_data->src_window ; - dnd_message->data.pot.property = dnd_data->property ; - break ; - default: - break ; - } - -} - -static Bool DndParseClientMessage(XClientMessageEvent *cm, DndData * dnd_data, - char * receiver) -{ - DndMessage * dnd_message = (DndMessage*)&cm->data.b[0] ; - - if (cm->message_type != ATOM(_MOTIF_DRAG_AND_DROP_MESSAGE)) { - return False ; - } - - if (dnd_message->byte_order != DndByteOrder()) { - SWAP2BYTES(dnd_message->flags); - SWAP4BYTES(dnd_message->time); - } /* do the rest in the switch */ - - dnd_data->reason = dnd_message->reason ; - if (DND_GET_EVENT_TYPE(dnd_data->reason)) - *receiver = 1 ; - else - *receiver = 0 ; - dnd_data->reason &= DND_CLEAR_EVENT_TYPE ; - - dnd_data->time = dnd_message->time ; - - /* we're reading in more stuff that necessary. but who cares */ - dnd_data->status = DND_GET_STATUS(dnd_message->flags) ; - dnd_data->operation = DND_GET_OPERATION(dnd_message->flags) ; - dnd_data->operations = DND_GET_OPERATIONS(dnd_message->flags) ; - dnd_data->completion = DND_GET_COMPLETION(dnd_message->flags) ; - - switch(dnd_data->reason) { - case DND_TOP_LEVEL_ENTER: - case DND_TOP_LEVEL_LEAVE: - if (dnd_message->byte_order != DndByteOrder()) { - SWAP4BYTES(dnd_message->data.top.src_window); - SWAP4BYTES(dnd_message->data.top.property); - } - dnd_data->src_window = dnd_message->data.top.src_window ; - dnd_data->property = dnd_message->data.top.property ; - break ; /* cannot fall through, see above comment in write msg */ - - case DND_DRAG_MOTION: - case DND_OPERATION_CHANGED: - case DND_DROP_SITE_ENTER: - case DND_DROP_START: - if (dnd_message->byte_order != DndByteOrder()) { - SWAP2BYTES(dnd_message->data.pot.x); - SWAP2BYTES(dnd_message->data.pot.y); - SWAP4BYTES(dnd_message->data.pot.property); - SWAP4BYTES(dnd_message->data.pot.src_window); - } - dnd_data->x = dnd_message->data.pot.x ; - dnd_data->y = dnd_message->data.pot.y ; - dnd_data->property = dnd_message->data.pot.property ; - dnd_data->src_window = dnd_message->data.pot.src_window ; - break ; - - case DND_DROP_SITE_LEAVE: - break; - default: - break ; - } - - return True ; -} - - -static Window MotifWindow(Display *display) -{ - Atom type; - int format; - unsigned long size; - unsigned long bytes_after; - unsigned char *property = 0; - Window motif_window ; - - /* this version does no caching, so it's slow: round trip each time */ - - if ((XGetWindowProperty (display, RootWindow(display, 0), - ATOM(_MOTIF_DRAG_WINDOW), - 0L, 100000L, False, AnyPropertyType, - &type, &format, &size, &bytes_after, - &property) == Success) && - (type != XNone)) { - motif_window = *(Window *)property; - } else { - XSetWindowAttributes sAttributes; - - /* really, this should be done on a separate connection, - with XSetCloseDownMode (RetainPermanent), so that - others don't have to recreate it; hopefully, some real - Motif application will be around to do it */ - - sAttributes.override_redirect = True; - sAttributes.event_mask = PropertyChangeMask; - motif_window = XCreateWindow (display, - RootWindow (display, 0), - -170, -560, 1, 1, 0, 0, - InputOnly, CopyFromParent, - (CWOverrideRedirect |CWEventMask), - &sAttributes); - XMapWindow (display, motif_window); - } - - if (property) { - XFree ((char *)property); - } - - return (motif_window); -} - - -static DndTargetsTable TargetsTable(Display *display) -{ - Atom type; - int format; - unsigned long size; - unsigned long bytes_after; - Window motif_window = MotifWindow(display) ; - unsigned char *retval; - DndTargetsTable targets_table ; - int i,j ; - char * target_data ; - - /* this version does no caching, so it's slow: round trip each time */ - /* ideally, register for property notify on this target_list - atom and update when necessary only */ - - if ((XGetWindowProperty (display, motif_window, - ATOM(_MOTIF_DRAG_TARGETS), 0L, 100000L, - False, ATOM(_MOTIF_DRAG_TARGETS), - &type, &format, &size, &bytes_after, - &retval) != Success) || - type == XNone) { - qWarning("QMotifDND: Cannot get property on Motif window"); - return 0; - } - - DndTargets * target_prop = (DndTargets *)retval; - - if (target_prop->protocol_version != DND_PROTOCOL_VERSION) { - qWarning("QMotifDND: Protocol mismatch"); - } - - if (target_prop->byte_order != DndByteOrder()) { - /* need to swap num_target_lists and size */ - SWAP2BYTES(target_prop->num_target_lists); - SWAP4BYTES(target_prop->data_size); - } - - /* now parse DndTarget prop data in a TargetsTable */ - - targets_table = (DndTargetsTable)malloc(sizeof(DndTargetsTableRec)); - targets_table->num_entries = target_prop->num_target_lists ; - targets_table->entries = (DndTargetsTableEntry) - malloc(sizeof(DndTargetsTableEntryRec) * target_prop->num_target_lists); - - target_data = (char*)target_prop + sizeof(*target_prop) ; - - for (i = 0 ; i < targets_table->num_entries; i++) { - CARD16 num_targets ; - CARD32 atom ; - - memcpy(&num_targets, target_data, 2); - target_data += 2; - - /* potential swap needed here */ - if (target_prop->byte_order != DndByteOrder()) - SWAP2BYTES(num_targets); - - targets_table->entries[i].num_targets = num_targets ; - targets_table->entries[i].targets = (Atom *) - malloc(sizeof(Atom) * targets_table->entries[i].num_targets); - - - for (j = 0; j < num_targets; j++) { - memcpy(&atom, target_data, 4); - target_data += 4; - - /* another potential swap needed here */ - if (target_prop->byte_order != DndByteOrder()) - SWAP4BYTES(atom); - - targets_table->entries[i].targets[j] = (Atom) atom ; - } - } - - if (target_prop) { - XFree((char *)target_prop); - } - - return targets_table ; -} - - -static ushort _DndIndexToTargets(Display * display, - int index, - Atom ** targets) -{ - DndTargetsTable targets_table; - int i ; - - /* again, slow: no caching here, alloc/free each time */ - - if (!(targets_table = TargetsTable (display)) || - (index >= targets_table->num_entries)) { - if (targets_table) - XFree((char*)targets_table); - return 0; - } - - /* transfer the correct target list index */ - *targets = (Atom*)malloc(sizeof(Atom)*targets_table-> - entries[index].num_targets); - memcpy((char*)*targets, - (char*)targets_table->entries[index].targets, - sizeof(Atom)*targets_table->entries[index].num_targets); - - /* free the target table and its guts */ - for (i=0 ; i < targets_table->num_entries; i++) - XFree((char*)targets_table->entries[i].targets); - - int tmp = targets_table->entries[index].num_targets; - XFree((char*)targets_table); - - return tmp; // targets_table->entries[index].num_targets; -} - - -QByteArray QX11Data::motifdndFormat(int n) -{ - if (!motifdnd_active) - return 0; // should not happen - - if (n >= num_src_targets) - return 0; - - Atom target = src_targets[n]; - - if (target == XA_STRING) - return "text/plain;charset=ISO-8859-1"; - if (target == ATOM(UTF8_STRING)) - return "text/plain;charset=UTF-8"; - if (target == ATOM(COMPOUND_TEXT)) - return QByteArray("text/plain;charset=") + QTextCodec::codecForLocale()->name(); - if (target == ATOM(TEXT)) - return "text/plain"; - - return ("x-motif-dnd/" + X11->xdndAtomToString(target)); -} - - -QVariant QX11Data::motifdndObtainData(const char *mimeType) -{ - QByteArray result; - - if (Dnd_selection == 0 || !dropWidget) - return result; - - // try to convert the selection to the requested property - // qDebug("trying to convert to '%s'", mimeType); - - int n=0; - QByteArray f; - do { - f = motifdndFormat(n); - if (f.isEmpty()) - return result; - n++; - } while(qstricmp(mimeType, f.data())); - - Atom conversion_type = XNone; - if (f == "text/plain;charset=ISO-8859-1") { - conversion_type = XA_STRING; - } else if (f == "text/plain;charset=UTF-8") { - conversion_type = ATOM(UTF8_STRING); - } else if (f == (QByteArray("text/plain;charset=") + QTextCodec::codecForLocale()->name())) { - conversion_type = ATOM(COMPOUND_TEXT); - } else if (f == "text/plain") { - conversion_type = ATOM(TEXT); - } else if (f.startsWith("x-motif-dnd/")) { - // strip off the "x-motif-dnd/" prefix - conversion_type = X11->xdndStringToAtom(f.remove(0, 12)); - } - - if (XGetSelectionOwner(X11->display, Dnd_selection) == XNone) { - return result; // should never happen? - } - - QWidget* tw = dropWidget; - if ((dropWidget->windowType() == Qt::Desktop)) { - tw = new QWidget; - } - - // convert selection to the appropriate type - XConvertSelection (X11->display, Dnd_selection, conversion_type, - Dnd_selection, tw->internalWinId(), Dnd_selection_time); - - XFlush(X11->display); - - XEvent xevent; - bool got=X11->clipboardWaitForEvent(tw->internalWinId(), SelectionNotify, &xevent, 5000); - if (got) { - Atom type; - - if (X11->clipboardReadProperty(tw->internalWinId(), Dnd_selection, true, &result, 0, &type, 0)) { - } - } - - // we have to convert selection in order to indicate success to the initiator - XConvertSelection (X11->display, Dnd_selection, ATOM(XmTRANSFER_SUCCESS), - Dnd_selection, tw->internalWinId(), Dnd_selection_time); - - // wait again for SelectionNotify event - X11->clipboardWaitForEvent(tw->internalWinId(), SelectionNotify, &xevent, 5000); - - if ((dropWidget->windowType() == Qt::Desktop)) { - delete tw; - } - - return result; -} - - -void QX11Data::motifdndEnable(QWidget *widget, bool) -{ - DndWriteReceiverProperty(display, widget->internalWinId(), DND_DRAG_DYNAMIC); -} - - -void QX11Data::motifdndHandle(QWidget *widget, const XEvent * xe, bool /* passive */) -{ - XEvent event = *xe; - XClientMessageEvent cm ; - DndData dnd_data ; - char receiver ; - - if (!(DndParseClientMessage ((XClientMessageEvent*)&event, - &dnd_data, &receiver))) { - return; - } - - switch (dnd_data.reason) { - - case DND_DRAG_MOTION: - { - QPoint p = widget->mapFromGlobal(QPoint(dnd_data.x, dnd_data.y)); - QWidget *c = widget->childAt(p); - - if (!c || !c->acceptDrops()) { - // not over a drop site - if (dropWidget) { - QDragLeaveEvent dragLeaveEvent; - QApplication::sendEvent(dropWidget, &dragLeaveEvent); - - dropWidget = 0; - lastAcceptedAction = Qt::IgnoreAction; - - dnd_data.reason = DND_DROP_SITE_LEAVE; - dnd_data.time = X11->time; - DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); - XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ; - } else { - dnd_data.reason = DND_DRAG_MOTION; - dnd_data.status = DND_NO_DROP_SITE; - dnd_data.time = X11->time; - dnd_data.operation = DND_NOOP; - dnd_data.operations = DND_NOOP; - DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); - XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm) ; - } - } else { - Q_ASSERT(c != 0); - p = c->mapFrom(widget, p); - - if (dropWidget != c) { - if (dropWidget) { - QDragLeaveEvent le; - QApplication::sendEvent(dropWidget, &le); - } - - dropWidget = c; - lastAcceptedAction = Qt::IgnoreAction; - - const Qt::DropActions possibleActions = - DndOperationsToQtDropActions(dnd_data.operations); - QDragEnterEvent de(p, possibleActions, QDragManager::self()->dropData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - QApplication::sendEvent(dropWidget, &de); - - dnd_data.reason = DND_DROP_SITE_ENTER; - dnd_data.time = X11->time; - if (de.isAccepted()) { - lastAcceptedAction = de.dropAction(); - - dnd_data.status = DND_VALID_DROP_SITE; - dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction); - } else { - dnd_data.status = DND_INVALID_DROP_SITE; - dnd_data.operation = DND_NOOP; - dnd_data.operations = DND_NOOP; - } - DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); - XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); - } else { - const Qt::DropActions possibleActions = - DndOperationsToQtDropActions(dnd_data.operations); - QDragMoveEvent me(p, possibleActions, QDragManager::self()->dropData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - if (lastAcceptedAction != Qt::IgnoreAction) { - me.setDropAction(lastAcceptedAction); - me.accept(); - } - QApplication::sendEvent(dropWidget, &me); - - dnd_data.reason = DND_DRAG_MOTION; - dnd_data.time = X11->time; - - if (me.isAccepted()) { - lastAcceptedAction = me.dropAction(); - - dnd_data.status = DND_VALID_DROP_SITE; - dnd_data.operation = QtDropActionToDndOperation(lastAcceptedAction); - } else { - dnd_data.status = DND_INVALID_DROP_SITE; - dnd_data.operation = DND_NOOP; - dnd_data.operations = DND_NOOP; - } - - DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, receiver); - XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); - } - } - - break; - } - - case DND_TOP_LEVEL_ENTER: - { - /* get the size of our drop site for later use */ - - motifdnd_active = true; - sourceWindow = dnd_data.src_window; - - /* no answer needed, just read source property */ - DndReadSourceProperty (event.xclient.display, - sourceWindow, - dnd_data.property, - &src_targets, &num_src_targets); - - break; - } - - case DND_TOP_LEVEL_LEAVE: - { - XEvent nextEvent; - if (XCheckTypedWindowEvent(X11->display, widget->winId(), ClientMessage, &nextEvent)) { - // we just want to check, not eat (should use XPeekIfEvent) - XPutBackEvent(X11->display, &nextEvent); - - if (DndParseClientMessage (&nextEvent.xclient, &dnd_data, &receiver) - && dnd_data.reason == DND_DROP_START) { - // expecting drop next, keeping DnD alive - break; - } - } - - // not expecting drop, need to send drag leave events and such here - if (dropWidget) { - QDragLeaveEvent le; - QApplication::sendEvent(dropWidget, &le); - } - - sourceWindow = XNone; - dropWidget = 0; - lastAcceptedAction = Qt::IgnoreAction; - - motifdnd_active = false; - - break; - } - - case DND_OPERATION_CHANGED: - // ### need to echo - break; - - case DND_DROP_START: - { - Q_ASSERT(motifdnd_active); - Q_ASSERT(sourceWindow == dnd_data.src_window); - - if (!dropWidget || lastAcceptedAction == Qt::IgnoreAction) { - // echo DROP_START - dnd_data.reason = DND_DROP_START; - dnd_data.status = DND_NO_DROP_SITE; - dnd_data.operation = DND_NOOP; - dnd_data.operations = DND_NOOP; - DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0); - XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); - - // we have to convert selection in order to indicate failure to the initiator - XConvertSelection (X11->display, dnd_data.property, ATOM(XmTRANSFER_FAILURE), - dnd_data.property, dnd_data.src_window, dnd_data.time); - - if (dropWidget) { - QDragLeaveEvent e; - QApplication::sendEvent(dropWidget, &e); - } - - motifdnd_active = false; - sourceWindow = XNone; - dropWidget = 0; - lastAcceptedAction = Qt::IgnoreAction; - - return; - } - - // store selection and its time - Dnd_selection = dnd_data.property; - Dnd_selection_time = dnd_data.time; - - QPoint p(dnd_data.x, dnd_data.y); - QDropEvent de(dropWidget->mapFromGlobal(p), Qt::CopyAction, QDragManager::self()->dropData, - QApplication::mouseButtons(), QApplication::keyboardModifiers()); - if (lastAcceptedAction != Qt::IgnoreAction) { - de.setDropAction(lastAcceptedAction); - de.accept(); - } - QApplication::sendEvent(dropWidget, &de); - - // reset - Dnd_selection = XNone; - Dnd_selection_time = 0; - - // echo DROP_START depending on the result of the dropEvent - if (de.isAccepted()) { - dnd_data.reason = DND_DROP_START; - dnd_data.status = DND_VALID_DROP_SITE; - dnd_data.operation = QtDropActionToDndOperation(de.dropAction()); - } else { - dnd_data.reason = DND_DROP_START; - dnd_data.status = DND_NO_DROP_SITE; - dnd_data.operation = DND_NOOP; - dnd_data.operations = DND_NOOP; - } - DndFillClientMessage (event.xclient.display, sourceWindow, &cm, &dnd_data, 0); - XSendEvent(event.xbutton.display, sourceWindow, False, 0, (XEvent *)&cm); - - sourceWindow = XNone; - dropWidget = 0; - lastAcceptedAction = Qt::IgnoreAction; - - motifdnd_active = false; - - break; - } - - default: - break; - } // end of switch (dnd_data.reason) -} - -QT_END_NAMESPACE - -#endif // QT_NO_DRAGANDDROP diff --git a/src/widgets/platforms/x11/qpaintdevice_x11.cpp b/src/widgets/platforms/x11/qpaintdevice_x11.cpp deleted file mode 100644 index d7ecb06885..0000000000 --- a/src/widgets/platforms/x11/qpaintdevice_x11.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpaintdevice.h" -#include "qpainter.h" -#include "qwidget.h" -#include "qbitmap.h" -#include "qapplication.h" -#include <private/qt_x11_p.h> -#include "qx11info_x11.h" - -QT_BEGIN_NAMESPACE - -/*! \internal - - Returns the X11 Drawable of the paint device. 0 is returned if it - can't be obtained. -*/ - -Drawable Q_WIDGETS_EXPORT qt_x11Handle(const QPaintDevice *pd) -{ - if (!pd) return 0; - if (pd->devType() == QInternal::Widget) - return static_cast<const QWidget *>(pd)->handle(); - else if (pd->devType() == QInternal::Pixmap) - return static_cast<const QPixmap *>(pd)->handle(); - return 0; -} - -/*! - \relates QPaintDevice - - Returns the QX11Info structure for the \a pd paint device. 0 is - returned if it can't be obtained. -*/ -const Q_WIDGETS_EXPORT QX11Info *qt_x11Info(const QPaintDevice *pd) -{ - if (!pd) return 0; - if (pd->devType() == QInternal::Widget) - return &static_cast<const QWidget *>(pd)->x11Info(); - else if (pd->devType() == QInternal::Pixmap) - return &static_cast<const QPixmap *>(pd)->x11Info(); - return 0; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qpaintengine_x11.cpp b/src/widgets/platforms/x11/qpaintengine_x11.cpp deleted file mode 100644 index 3cb3e3caf7..0000000000 --- a/src/widgets/platforms/x11/qpaintengine_x11.cpp +++ /dev/null @@ -1,2499 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" - -#include "private/qpixmap_x11_p.h" - -#include "qapplication.h" -#include "qdebug.h" -#include "qfont.h" -#include "qwidget.h" -#include "qbitmap.h" -#include "qpixmapcache.h" -#include "qtextcodec.h" -#include "qcoreevent.h" -#include "qiodevice.h" -#include <qmath.h> - -#include "qpainter_p.h" -#include <qtextlayout.h> -#include <qvarlengtharray.h> -#include <private/qfont_p.h> -#include <private/qtextengine_p.h> -#include <private/qpaintengine_x11_p.h> -#include <private/qfontengine_x11_p.h> -#include <private/qwidget_p.h> -#include <private/qpainterpath_p.h> - -#include "qpen.h" -#include "qcolor.h" -#include "qcolormap.h" - -#include <private/qpaintengine_p.h> -#include "qpaintengine_x11_p.h" - -#include <private/qt_x11_p.h> -#include <private/qnumeric_p.h> -#include <limits.h> - -#ifndef QT_NO_XRENDER -#include <private/qtessellator_p.h> -#endif - -#include <private/qhexstring_p.h> - -QT_BEGIN_NAMESPACE - -extern Drawable qt_x11Handle(const QPaintDevice *pd); -extern const QX11Info *qt_x11Info(const QPaintDevice *pd); -extern QPixmap qt_pixmapForBrush(int brushStyle, bool invert); //in qbrush.cpp -extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); - -// use the same rounding as in qrasterizer.cpp (6 bit fixed point) -static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; - -#undef X11 // defined in qt_x11_p.h -/*! - Returns the X11 specific pen GC for the painter \a p. Note that - QPainter::begin() must be called before this function returns a - valid GC. -*/ -Q_WIDGETS_EXPORT GC qt_x11_get_pen_gc(QPainter *p) -{ - if (p && p->paintEngine() - && p->paintEngine()->isActive() - && p->paintEngine()->type() == QPaintEngine::X11) { - return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc; - } - return 0; -} - -/*! - Returns the X11 specific brush GC for the painter \a p. Note that - QPainter::begin() must be called before this function returns a - valid GC. -*/ -Q_WIDGETS_EXPORT GC qt_x11_get_brush_gc(QPainter *p) -{ - if (p && p->paintEngine() - && p->paintEngine()->isActive() - && p->paintEngine()->type() == QPaintEngine::X11) { - return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc_brush; - } - return 0; -} -#define X11 qt_x11Data - -#ifndef QT_NO_XRENDER -static const int compositionModeToRenderOp[QPainter::CompositionMode_Xor + 1] = { - PictOpOver, //CompositionMode_SourceOver, - PictOpOverReverse, //CompositionMode_DestinationOver, - PictOpClear, //CompositionMode_Clear, - PictOpSrc, //CompositionMode_Source, - PictOpDst, //CompositionMode_Destination, - PictOpIn, //CompositionMode_SourceIn, - PictOpInReverse, //CompositionMode_DestinationIn, - PictOpOut, //CompositionMode_SourceOut, - PictOpOutReverse, //CompositionMode_DestinationOut, - PictOpAtop, //CompositionMode_SourceAtop, - PictOpAtopReverse, //CompositionMode_DestinationAtop, - PictOpXor //CompositionMode_Xor -}; - -static inline int qpainterOpToXrender(QPainter::CompositionMode mode) -{ - Q_ASSERT(mode <= QPainter::CompositionMode_Xor); - return compositionModeToRenderOp[mode]; -} -#endif - -// hack, so we don't have to make QRegion::clipRectangles() public or include -// X11 headers in qregion.h -Q_WIDGETS_EXPORT void *qt_getClipRects(const QRegion &r, int &num) -{ - return r.clipRectangles(num); -} - -static inline void x11SetClipRegion(Display *dpy, GC gc, GC gc2, -#ifndef QT_NO_XRENDER - Picture picture, -#else - Qt::HANDLE picture, -#endif - const QRegion &r) -{ - int num; - XRectangle *rects = (XRectangle *)qt_getClipRects(r, num); - - if (gc) - XSetClipRectangles( dpy, gc, 0, 0, rects, num, YXBanded ); - if (gc2) - XSetClipRectangles( dpy, gc2, 0, 0, rects, num, YXBanded ); - -#ifndef QT_NO_XRENDER - if (picture) - XRenderSetPictureClipRectangles(dpy, picture, 0, 0, rects, num); -#else - Q_UNUSED(picture); -#endif // QT_NO_XRENDER -} - - -static inline void x11ClearClipRegion(Display *dpy, GC gc, GC gc2, -#ifndef QT_NO_XRENDER - Picture picture -#else - Qt::HANDLE picture -#endif - ) -{ - if (gc) - XSetClipMask(dpy, gc, XNone); - if (gc2) - XSetClipMask(dpy, gc2, XNone); - -#ifndef QT_NO_XRENDER - if (picture) { - XRenderPictureAttributes attrs; - attrs.clip_mask = XNone; - XRenderChangePicture (dpy, picture, CPClipMask, &attrs); - } -#else - Q_UNUSED(picture); -#endif // QT_NO_XRENDER -} - - -#define DITHER_SIZE 16 -static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = { - { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, - { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, - { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, - { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, - { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, - { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, - { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, - { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, - { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, - { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, - { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, - { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, - { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, - { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, - { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, - { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } -}; - -static QPixmap qt_patternForAlpha(uchar alpha, int screen) -{ - QPixmap pm; - QString key = QLatin1Literal("$qt-alpha-brush$") - % HexString<uchar>(alpha) - % HexString<int>(screen); - - if (!QPixmapCache::find(key, pm)) { - // #### why not use a mono image here???? - QImage pattern(DITHER_SIZE, DITHER_SIZE, QImage::Format_ARGB32); - pattern.fill(0xffffffff); - for (int y = 0; y < DITHER_SIZE; ++y) { - for (int x = 0; x < DITHER_SIZE; ++x) { - if (base_dither_matrix[x][y] <= alpha) - pattern.setPixel(x, y, 0x00000000); - } - } - pm = QBitmap::fromImage(pattern); - pm.x11SetScreen(screen); - QPixmapCache::insert(key, pm); - } - return pm; -} - -#if !defined(QT_NO_XRENDER) - -class QXRenderTessellator : public QTessellator -{ -public: - QXRenderTessellator() : traps(0), allocated(0), size(0) {} - ~QXRenderTessellator() { free(traps); } - XTrapezoid *traps; - int allocated; - int size; - void addTrap(const Trapezoid &trap); - QRect tessellate(const QPointF *points, int nPoints, bool winding) { - size = 0; - setWinding(winding); - return QTessellator::tessellate(points, nPoints).toRect(); - } - void done() { - if (allocated > 64) { - free(traps); - traps = 0; - allocated = 0; - } - } -}; - -void QXRenderTessellator::addTrap(const Trapezoid &trap) -{ - if (size == allocated) { - allocated = qMax(2*allocated, 64); - traps = q_check_ptr((XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid))); - } - traps[size].top = Q27Dot5ToXFixed(trap.top); - traps[size].bottom = Q27Dot5ToXFixed(trap.bottom); - traps[size].left.p1.x = Q27Dot5ToXFixed(trap.topLeft->x); - traps[size].left.p1.y = Q27Dot5ToXFixed(trap.topLeft->y); - traps[size].left.p2.x = Q27Dot5ToXFixed(trap.bottomLeft->x); - traps[size].left.p2.y = Q27Dot5ToXFixed(trap.bottomLeft->y); - traps[size].right.p1.x = Q27Dot5ToXFixed(trap.topRight->x); - traps[size].right.p1.y = Q27Dot5ToXFixed(trap.topRight->y); - traps[size].right.p2.x = Q27Dot5ToXFixed(trap.bottomRight->x); - traps[size].right.p2.y = Q27Dot5ToXFixed(trap.bottomRight->y); - ++size; -} - -#endif // !defined(QT_NO_XRENDER) - - -#ifndef QT_NO_XRENDER -static Picture getPatternFill(int screen, const QBrush &b) -{ - if (!X11->use_xrender) - return XNone; - - XRenderColor color = X11->preMultiply(b.color()); - XRenderColor bg_color; - - bg_color = X11->preMultiply(QColor(0, 0, 0, 0)); - - for (int i = 0; i < X11->pattern_fill_count; ++i) { - if (X11->pattern_fills[i].screen == screen - && X11->pattern_fills[i].opaque == false - && X11->pattern_fills[i].style == b.style() - && X11->pattern_fills[i].color.alpha == color.alpha - && X11->pattern_fills[i].color.red == color.red - && X11->pattern_fills[i].color.green == color.green - && X11->pattern_fills[i].color.blue == color.blue - && X11->pattern_fills[i].bg_color.alpha == bg_color.alpha - && X11->pattern_fills[i].bg_color.red == bg_color.red - && X11->pattern_fills[i].bg_color.green == bg_color.green - && X11->pattern_fills[i].bg_color.blue == bg_color.blue) - return X11->pattern_fills[i].picture; - } - // none found, replace one - int i = qrand() % 16; - - if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) { - XRenderFreePicture (X11->display, X11->pattern_fills[i].picture); - X11->pattern_fills[i].picture = 0; - } - - if (!X11->pattern_fills[i].picture) { - Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 8, 8, 32); - XRenderPictureAttributes attrs; - attrs.repeat = True; - X11->pattern_fills[i].picture = XRenderCreatePicture (X11->display, pixmap, - XRenderFindStandardFormat(X11->display, PictStandardARGB32), - CPRepeat, &attrs); - XFreePixmap (X11->display, pixmap); - } - - X11->pattern_fills[i].screen = screen; - X11->pattern_fills[i].color = color; - X11->pattern_fills[i].bg_color = bg_color; - X11->pattern_fills[i].opaque = false; - X11->pattern_fills[i].style = b.style(); - - XRenderFillRectangle(X11->display, PictOpSrc, X11->pattern_fills[i].picture, &bg_color, 0, 0, 8, 8); - - QPixmap pattern(qt_pixmapForBrush(b.style(), true)); - XRenderPictureAttributes attrs; - attrs.repeat = true; - XRenderChangePicture(X11->display, pattern.x11PictureHandle(), CPRepeat, &attrs); - - Picture fill_fg = X11->getSolidFill(screen, b.color()); - XRenderComposite(X11->display, PictOpOver, fill_fg, pattern.x11PictureHandle(), - X11->pattern_fills[i].picture, - 0, 0, 0, 0, 0, 0, 8, 8); - - return X11->pattern_fills[i].picture; -} - -static void qt_render_bitmap(Display *dpy, int scrn, Picture src, Picture dst, - int sx, int sy, int x, int y, int sw, int sh, - const QPen &pen) -{ - Picture fill_fg = X11->getSolidFill(scrn, pen.color()); - XRenderComposite(dpy, PictOpOver, - fill_fg, src, dst, sx, sy, sx, sy, x, y, sw, sh); -} -#endif - -void QX11PaintEnginePrivate::init() -{ - dpy = 0; - scrn = 0; - hd = 0; - picture = 0; - xinfo = 0; -#ifndef QT_NO_XRENDER - current_brush = 0; - composition_mode = PictOpOver; - tessellator = new QXRenderTessellator; -#endif -} - -void QX11PaintEnginePrivate::setupAdaptedOrigin(const QPoint &p) -{ - if (adapted_pen_origin) - XSetTSOrigin(dpy, gc, p.x(), p.y()); - if (adapted_brush_origin) - XSetTSOrigin(dpy, gc_brush, p.x(), p.y()); -} - -void QX11PaintEnginePrivate::resetAdaptedOrigin() -{ - if (adapted_pen_origin) - XSetTSOrigin(dpy, gc, 0, 0); - if (adapted_brush_origin) - XSetTSOrigin(dpy, gc_brush, 0, 0); -} - -void QX11PaintEnginePrivate::clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly) -{ - int clipped_count = 0; - qt_float_point *clipped_points = 0; - polygonClipper.clipPolygon((qt_float_point *) poly.data(), poly.size(), - &clipped_points, &clipped_count); - clipped_poly->resize(clipped_count); - for (int i=0; i<clipped_count; ++i) - (*clipped_poly)[i] = *((QPointF *)(&clipped_points[i])); -} - -void QX11PaintEnginePrivate::systemStateChanged() -{ - Q_Q(QX11PaintEngine); - QPainter *painter = q->state ? static_cast<QPainterState *>(q->state)->painter : 0; - if (painter && painter->hasClipping()) { - if (q->testDirty(QPaintEngine::DirtyTransform)) - q->updateMatrix(q->state->transform()); - QPolygonF clip_poly_dev(matrix.map(painter->clipPath().toFillPolygon())); - QPolygonF clipped_poly_dev; - clipPolygon_dev(clip_poly_dev, &clipped_poly_dev); - q->updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip); - } else { - q->updateClipRegion_dev(QRegion(), Qt::NoClip); - } -} - -static QPaintEngine::PaintEngineFeatures qt_decide_features() -{ - QPaintEngine::PaintEngineFeatures features = - QPaintEngine::PrimitiveTransform - | QPaintEngine::PatternBrush - | QPaintEngine::AlphaBlend - | QPaintEngine::PainterPaths - | QPaintEngine::RasterOpModes; - - if (X11->use_xrender) { - features |= QPaintEngine::Antialiasing; - features |= QPaintEngine::PorterDuff; - features |= QPaintEngine::MaskedBrush; -#if 0 - if (X11->xrender_version > 10) { - features |= QPaintEngine::LinearGradientFill; - // ### - } -#endif - } - - return features; -} - -/* - * QX11PaintEngine members - */ - -QX11PaintEngine::QX11PaintEngine() - : QPaintEngine(*(new QX11PaintEnginePrivate), qt_decide_features()) -{ - d_func()->init(); -} - -QX11PaintEngine::QX11PaintEngine(QX11PaintEnginePrivate &dptr) - : QPaintEngine(dptr, qt_decide_features()) -{ - d_func()->init(); -} - -QX11PaintEngine::~QX11PaintEngine() -{ -#ifndef QT_NO_XRENDER - Q_D(QX11PaintEngine); - delete d->tessellator; -#endif -} - -bool QX11PaintEngine::begin(QPaintDevice *pdev) -{ - Q_D(QX11PaintEngine); - d->xinfo = qt_x11Info(pdev); - QWidget *w = d->pdev->devType() == QInternal::Widget ? static_cast<QWidget *>(d->pdev) : 0; - const bool isAlienWidget = w && !w->internalWinId() && w->testAttribute(Qt::WA_WState_Created); -#ifndef QT_NO_XRENDER - if (w) { - if (isAlienWidget) - d->picture = (::Picture)w->nativeParentWidget()->x11PictureHandle(); - else - d->picture = (::Picture)w->x11PictureHandle(); - } else if (pdev->devType() == QInternal::Pixmap) { - const QPixmap *pm = static_cast<const QPixmap *>(pdev); - QX11PlatformPixmap *data = static_cast<QX11PlatformPixmap*>(pm->data.data()); - if (X11->use_xrender && data->depth() != 32 && data->x11_mask) - data->convertToARGB32(); - d->picture = (::Picture)static_cast<const QPixmap *>(pdev)->x11PictureHandle(); - } -#else - d->picture = 0; -#endif - d->hd = !isAlienWidget ? qt_x11Handle(pdev) : qt_x11Handle(w->nativeParentWidget()); - - Q_ASSERT(d->xinfo != 0); - d->dpy = d->xinfo->display(); // get display variable - d->scrn = d->xinfo->screen(); // get screen variable - - d->crgn = QRegion(); - d->gc = XCreateGC(d->dpy, d->hd, 0, 0); - d->gc_brush = XCreateGC(d->dpy, d->hd, 0, 0); - d->has_alpha_brush = false; - d->has_alpha_pen = false; - d->has_clipping = false; - d->has_complex_xform = false; - d->has_scaling_xform = false; - d->has_non_scaling_xform = true; - d->xform_scale = 1; - d->has_custom_pen = false; - d->matrix = QTransform(); - d->pdev_depth = d->pdev->depth(); - d->render_hints = 0; - d->txop = QTransform::TxNone; - d->use_path_fallback = false; -#if !defined(QT_NO_XRENDER) - d->composition_mode = PictOpOver; -#endif - d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3; - d->opacity = 1; - - // Set up the polygon clipper. Note: This will only work in - // polyline mode as long as we have a buffer zone, since a - // polyline may be clipped into several non-connected polylines. - const int BUFFERZONE = 1000; - QRect devClipRect(-BUFFERZONE, -BUFFERZONE, - pdev->width() + 2*BUFFERZONE, pdev->height() + 2*BUFFERZONE); - d->polygonClipper.setBoundingRect(devClipRect); - - if (isAlienWidget) { - // Set system clip for alien widgets painting outside the paint event. - // This is not a problem with native windows since the windowing system - // will handle the clip. - QWidgetPrivate *wd = w->d_func(); - QRegion widgetClip(wd->clipRect()); - wd->clipToEffectiveMask(widgetClip); - wd->subtractOpaqueSiblings(widgetClip); - widgetClip.translate(w->mapTo(w->nativeParentWidget(), QPoint())); - setSystemClip(widgetClip); - } - - QPixmap::x11SetDefaultScreen(d->xinfo->screen()); - - if (w && w->testAttribute(Qt::WA_PaintUnclipped)) { // paint direct on device - updatePen(QPen(Qt::black)); - updateBrush(QBrush(Qt::white), QPoint()); - XSetSubwindowMode(d->dpy, d->gc, IncludeInferiors); - XSetSubwindowMode(d->dpy, d->gc_brush, IncludeInferiors); -#ifndef QT_NO_XRENDER - XRenderPictureAttributes attrs; - attrs.subwindow_mode = IncludeInferiors; - XRenderChangePicture(d->dpy, d->picture, CPSubwindowMode, &attrs); -#endif - } - - setDirty(QPaintEngine::DirtyClipRegion); - setDirty(QPaintEngine::DirtyPen); - setDirty(QPaintEngine::DirtyBrush); - setDirty(QPaintEngine::DirtyBackground); - - return true; -} - -bool QX11PaintEngine::end() -{ - Q_D(QX11PaintEngine); - -#if !defined(QT_NO_XRENDER) - if (d->picture) { - // reset clipping/subwindow mode on our render picture - XRenderPictureAttributes attrs; - attrs.subwindow_mode = ClipByChildren; - attrs.clip_mask = XNone; - XRenderChangePicture(d->dpy, d->picture, CPClipMask|CPSubwindowMode, &attrs); - } -#endif - - if (d->gc_brush && d->pdev->painters < 2) { - XFreeGC(d->dpy, d->gc_brush); - d->gc_brush = 0; - } - - if (d->gc && d->pdev->painters < 2) { - XFreeGC(d->dpy, d->gc); - d->gc = 0; - } - - // Restore system clip for alien widgets painting outside the paint event. - if (d->pdev->devType() == QInternal::Widget && !static_cast<QWidget *>(d->pdev)->internalWinId()) - setSystemClip(QRegion()); - - return true; -} - -static bool clipLine(QLineF *line, const QRect &rect) -{ - qreal x1 = line->x1(); - qreal x2 = line->x2(); - qreal y1 = line->y1(); - qreal y2 = line->y2(); - - qreal left = rect.x(); - qreal right = rect.x() + rect.width() - 1; - qreal top = rect.y(); - qreal bottom = rect.y() + rect.height() - 1; - - enum { Left, Right, Top, Bottom }; - // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html - int p1 = ((x1 < left) << Left) - | ((x1 > right) << Right) - | ((y1 < top) << Top) - | ((y1 > bottom) << Bottom); - int p2 = ((x2 < left) << Left) - | ((x2 > right) << Right) - | ((y2 < top) << Top) - | ((y2 > bottom) << Bottom); - - if (p1 & p2) - // completely outside - return false; - - if (p1 | p2) { - qreal dx = x2 - x1; - qreal dy = y2 - y1; - - // clip x coordinates - if (x1 < left) { - y1 += dy/dx * (left - x1); - x1 = left; - } else if (x1 > right) { - y1 -= dy/dx * (x1 - right); - x1 = right; - } - if (x2 < left) { - y2 += dy/dx * (left - x2); - x2 = left; - } else if (x2 > right) { - y2 -= dy/dx * (x2 - right); - x2 = right; - } - p1 = ((y1 < top) << Top) - | ((y1 > bottom) << Bottom); - p2 = ((y2 < top) << Top) - | ((y2 > bottom) << Bottom); - if (p1 & p2) - return false; - // clip y coordinates - if (y1 < top) { - x1 += dx/dy * (top - y1); - y1 = top; - } else if (y1 > bottom) { - x1 -= dx/dy * (y1 - bottom); - y1 = bottom; - } - if (y2 < top) { - x2 += dx/dy * (top - y2); - y2 = top; - } else if (y2 > bottom) { - x2 -= dx/dy * (y2 - bottom); - y2 = bottom; - } - *line = QLineF(QPointF(x1, y1), QPointF(x2, y2)); - } - return true; -} - -void QX11PaintEngine::drawLines(const QLine *lines, int lineCount) -{ - Q_ASSERT(lines); - Q_ASSERT(lineCount); - Q_D(QX11PaintEngine); - if (d->has_alpha_brush - || d->has_alpha_pen - || d->has_custom_pen - || (d->cpen.widthF() > 0 && d->has_complex_xform - && !d->has_non_scaling_xform) - || (d->render_hints & QPainter::Antialiasing)) { - for (int i = 0; i < lineCount; ++i) { - QPainterPath path(lines[i].p1()); - path.lineTo(lines[i].p2()); - drawPath(path); - } - return; - } - - if (d->has_pen) { - for (int i = 0; i < lineCount; ++i) { - QLineF linef; - if (d->txop == QTransform::TxNone) { - linef = lines[i]; - } else { - linef = d->matrix.map(QLineF(lines[i])); - } - if (clipLine(&linef, d->polygonClipper.boundingRect())) { - int x1 = qRound(linef.x1() + aliasedCoordinateDelta); - int y1 = qRound(linef.y1() + aliasedCoordinateDelta); - int x2 = qRound(linef.x2() + aliasedCoordinateDelta); - int y2 = qRound(linef.y2() + aliasedCoordinateDelta); - - XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2); - } - } - } -} - -void QX11PaintEngine::drawLines(const QLineF *lines, int lineCount) -{ - Q_ASSERT(lines); - Q_ASSERT(lineCount); - Q_D(QX11PaintEngine); - if (d->has_alpha_brush - || d->has_alpha_pen - || d->has_custom_pen - || (d->cpen.widthF() > 0 && d->has_complex_xform - && !d->has_non_scaling_xform) - || (d->render_hints & QPainter::Antialiasing)) { - for (int i = 0; i < lineCount; ++i) { - QPainterPath path(lines[i].p1()); - path.lineTo(lines[i].p2()); - drawPath(path); - } - return; - } - - if (d->has_pen) { - for (int i = 0; i < lineCount; ++i) { - QLineF linef = d->matrix.map(lines[i]); - if (clipLine(&linef, d->polygonClipper.boundingRect())) { - int x1 = qRound(linef.x1() + aliasedCoordinateDelta); - int y1 = qRound(linef.y1() + aliasedCoordinateDelta); - int x2 = qRound(linef.x2() + aliasedCoordinateDelta); - int y2 = qRound(linef.y2() + aliasedCoordinateDelta); - - XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2); - } - } - } -} - -static inline QLine clipStraightLine(const QRect &clip, const QLine &l) -{ - if (l.p1().x() == l.p2().x()) { - int x = qBound(clip.left(), l.p1().x(), clip.right()); - int y1 = qBound(clip.top(), l.p1().y(), clip.bottom()); - int y2 = qBound(clip.top(), l.p2().y(), clip.bottom()); - - return QLine(x, y1, x, y2); - } else { - Q_ASSERT(l.p1().y() == l.p2().y()); - - int x1 = qBound(clip.left(), l.p1().x(), clip.right()); - int x2 = qBound(clip.left(), l.p2().x(), clip.right()); - int y = qBound(clip.top(), l.p1().y(), clip.bottom()); - - return QLine(x1, y, x2, y); - } -} - -void QX11PaintEngine::drawRects(const QRectF *rects, int rectCount) -{ - Q_D(QX11PaintEngine); - Q_ASSERT(rects); - Q_ASSERT(rectCount); - - if (rectCount != 1 - || d->has_pen - || d->has_alpha_brush - || d->has_complex_xform - || d->has_custom_pen - || d->cbrush.style() != Qt::SolidPattern) - { - QPaintEngine::drawRects(rects, rectCount); - return; - } - - QPoint alignedOffset; - if (d->txop == QTransform::TxTranslate) { - QPointF offset(d->matrix.dx(), d->matrix.dy()); - alignedOffset = offset.toPoint(); - if (offset != QPointF(alignedOffset)) { - QPaintEngine::drawRects(rects, rectCount); - return; - } - } - - const QRectF& r = rects[0]; - QRect alignedRect = r.toAlignedRect(); - if (r != QRectF(alignedRect)) { - QPaintEngine::drawRects(rects, rectCount); - return; - } - alignedRect.translate(alignedOffset); - - QRect clip(d->polygonClipper.boundingRect()); - alignedRect = alignedRect.intersected(clip); - if (alignedRect.isEmpty()) - return; - - // simple-case: - // the rectangle is pixel-aligned - // the fill brush is just a solid non-alpha color - // the painter transform is only integer translation - // ignore: antialiasing and just XFillRectangles directly - XRectangle xrect; - xrect.x = short(alignedRect.x()); - xrect.y = short(alignedRect.y()); - xrect.width = ushort(alignedRect.width()); - xrect.height = ushort(alignedRect.height()); - XFillRectangles(d->dpy, d->hd, d->gc_brush, &xrect, 1); -} - -void QX11PaintEngine::drawRects(const QRect *rects, int rectCount) -{ - Q_D(QX11PaintEngine); - Q_ASSERT(rects); - Q_ASSERT(rectCount); - - if (d->has_alpha_pen - || d->has_complex_xform - || d->has_custom_pen - || (d->render_hints & QPainter::Antialiasing)) - { - for (int i = 0; i < rectCount; ++i) { - QPainterPath path; - path.addRect(rects[i]); - drawPath(path); - } - return; - } - - QRect clip(d->polygonClipper.boundingRect()); - QPoint offset(qRound(d->matrix.dx()), qRound(d->matrix.dy())); -#if !defined(QT_NO_XRENDER) - ::Picture pict = d->picture; - - if (X11->use_xrender && pict && d->has_brush && d->pdev_depth != 1 - && (d->has_texture || d->has_alpha_brush)) - { - XRenderColor xc; - if (!d->has_texture && !d->has_pattern) - xc = X11->preMultiply(d->cbrush.color()); - - for (int i = 0; i < rectCount; ++i) { - QRect r(rects[i]); - if (d->txop == QTransform::TxTranslate) - r.translate(offset); - - if (r.width() == 0 || r.height() == 0) { - if (d->has_pen) { - const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height())); - XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y()); - } - continue; - } - - r = r.intersected(clip); - if (r.isEmpty()) - continue; - if (d->has_texture || d->has_pattern) { - XRenderComposite(d->dpy, d->composition_mode, d->current_brush, 0, pict, - qRound(r.x() - d->bg_origin.x()), qRound(r.y() - d->bg_origin.y()), - 0, 0, r.x(), r.y(), r.width(), r.height()); - } else { - XRenderFillRectangle(d->dpy, d->composition_mode, pict, &xc, r.x(), r.y(), r.width(), r.height()); - } - if (d->has_pen) - XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height()); - } - } else -#endif // !QT_NO_XRENDER - { - if (d->has_brush && d->has_pen) { - for (int i = 0; i < rectCount; ++i) { - QRect r(rects[i]); - if (d->txop == QTransform::TxTranslate) - r.translate(offset); - - if (r.width() == 0 || r.height() == 0) { - const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height())); - XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y()); - continue; - } - - r = r.intersected(clip); - if (r.isEmpty()) - continue; - d->setupAdaptedOrigin(r.topLeft()); - XFillRectangle(d->dpy, d->hd, d->gc_brush, r.x(), r.y(), r.width(), r.height()); - XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height()); - } - d->resetAdaptedOrigin(); - } else { - QVarLengthArray<XRectangle> xrects(rectCount); - int numClipped = rectCount; - for (int i = 0; i < rectCount; ++i) { - QRect r(rects[i]); - if (d->txop == QTransform::TxTranslate) - r.translate(offset); - - if (r.width() == 0 || r.height() == 0) { - --numClipped; - if (d->has_pen) { - const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height())); - XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y()); - } - continue; - } - - r = r.intersected(clip); - if (r.isEmpty()) { - --numClipped; - continue; - } - xrects[i].x = short(r.x()); - xrects[i].y = short(r.y()); - xrects[i].width = ushort(r.width()); - xrects[i].height = ushort(r.height()); - } - if (numClipped) { - d->setupAdaptedOrigin(rects[0].topLeft()); - if (d->has_brush) - XFillRectangles(d->dpy, d->hd, d->gc_brush, xrects.data(), numClipped); - else if (d->has_pen) - XDrawRectangles(d->dpy, d->hd, d->gc, xrects.data(), numClipped); - d->resetAdaptedOrigin(); - } - } - } -} - -static inline void setCapStyle(int cap_style, GC gc) -{ - ulong mask = GCCapStyle; - XGCValues vals; - vals.cap_style = cap_style; - XChangeGC(X11->display, gc, mask, &vals); -} - -void QX11PaintEngine::drawPoints(const QPoint *points, int pointCount) -{ - Q_ASSERT(points); - Q_ASSERT(pointCount); - Q_D(QX11PaintEngine); - - if (!d->has_pen) - return; - - // use the same test here as in drawPath to ensure that we don't use the path fallback - // and end up in XDrawLines for pens with width <= 1 - if (d->cpen.widthF() > 1.0f - || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing))) - || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate)) - { - Qt::PenCapStyle capStyle = d->cpen.capStyle(); - if (capStyle == Qt::FlatCap) { - setCapStyle(CapProjecting, d->gc); - d->cpen.setCapStyle(Qt::SquareCap); - } - const QPoint *end = points + pointCount; - while (points < end) { - QPainterPath path; - path.moveTo(*points); - path.lineTo(points->x()+.005, points->y()); - drawPath(path); - ++points; - } - - if (capStyle == Qt::FlatCap) { - setCapStyle(CapButt, d->gc); - d->cpen.setCapStyle(capStyle); - } - return; - } - - static const int BUF_SIZE = 1024; - XPoint xPoints[BUF_SIZE]; - int i = 0, j = 0; - while (i < pointCount) { - while (i < pointCount && j < BUF_SIZE) { - const QPoint &xformed = d->matrix.map(points[i]); - int x = xformed.x(); - int y = xformed.y(); - if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) { - xPoints[j].x = x; - xPoints[j].y = y; - ++j; - } - ++i; - } - if (j) - XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin); - - j = 0; - } -} - -void QX11PaintEngine::drawPoints(const QPointF *points, int pointCount) -{ - Q_ASSERT(points); - Q_ASSERT(pointCount); - Q_D(QX11PaintEngine); - - if (!d->has_pen) - return; - - // use the same test here as in drawPath to ensure that we don't use the path fallback - // and end up in XDrawLines for pens with width <= 1 - if (d->cpen.widthF() > 1.0f - || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing))) - || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate)) - { - Qt::PenCapStyle capStyle = d->cpen.capStyle(); - if (capStyle == Qt::FlatCap) { - setCapStyle(CapProjecting, d->gc); - d->cpen.setCapStyle(Qt::SquareCap); - } - - const QPointF *end = points + pointCount; - while (points < end) { - QPainterPath path; - path.moveTo(*points); - path.lineTo(points->x() + 0.005, points->y()); - drawPath(path); - ++points; - } - if (capStyle == Qt::FlatCap) { - setCapStyle(CapButt, d->gc); - d->cpen.setCapStyle(capStyle); - } - return; - } - - static const int BUF_SIZE = 1024; - XPoint xPoints[BUF_SIZE]; - int i = 0, j = 0; - while (i < pointCount) { - while (i < pointCount && j < BUF_SIZE) { - const QPointF &xformed = d->matrix.map(points[i]); - int x = qFloor(xformed.x()); - int y = qFloor(xformed.y()); - - if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) { - xPoints[j].x = x; - xPoints[j].y = y; - ++j; - } - ++i; - } - if (j) - XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin); - - j = 0; - } -} - -QPainter::RenderHints QX11PaintEngine::supportedRenderHints() const -{ -#if !defined(QT_NO_XRENDER) - if (X11->use_xrender) - return QPainter::Antialiasing; -#endif - return QFlag(0); -} - -void QX11PaintEngine::updateState(const QPaintEngineState &state) -{ - Q_D(QX11PaintEngine); - QPaintEngine::DirtyFlags flags = state.state(); - - - if (flags & DirtyOpacity) { - d->opacity = state.opacity(); - // Force update pen/brush as to get proper alpha colors propagated - flags |= DirtyPen; - flags |= DirtyBrush; - } - - if (flags & DirtyTransform) updateMatrix(state.transform()); - if (flags & DirtyPen) updatePen(state.pen()); - if (flags & (DirtyBrush | DirtyBrushOrigin)) updateBrush(state.brush(), state.brushOrigin()); - if (flags & DirtyFont) updateFont(state.font()); - - if (state.state() & DirtyClipEnabled) { - if (state.isClipEnabled()) { - QPolygonF clip_poly_dev(d->matrix.map(painter()->clipPath().toFillPolygon())); - QPolygonF clipped_poly_dev; - d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev); - updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip); - } else { - updateClipRegion_dev(QRegion(), Qt::NoClip); - } - } - - if (flags & DirtyClipPath) { - QPolygonF clip_poly_dev(d->matrix.map(state.clipPath().toFillPolygon())); - QPolygonF clipped_poly_dev; - d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev); - updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon(), state.clipPath().fillRule()), - state.clipOperation()); - } else if (flags & DirtyClipRegion) { - extern QPainterPath qt_regionToPath(const QRegion ®ion); - QPainterPath clip_path = qt_regionToPath(state.clipRegion()); - QPolygonF clip_poly_dev(d->matrix.map(clip_path.toFillPolygon())); - QPolygonF clipped_poly_dev; - d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev); - updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), state.clipOperation()); - } - if (flags & DirtyHints) updateRenderHints(state.renderHints()); - if (flags & DirtyCompositionMode) { - int function = GXcopy; - if (state.compositionMode() >= QPainter::RasterOp_SourceOrDestination) { - switch (state.compositionMode()) { - case QPainter::RasterOp_SourceOrDestination: - function = GXor; - break; - case QPainter::RasterOp_SourceAndDestination: - function = GXand; - break; - case QPainter::RasterOp_SourceXorDestination: - function = GXxor; - break; - case QPainter::RasterOp_NotSourceAndNotDestination: - function = GXnor; - break; - case QPainter::RasterOp_NotSourceOrNotDestination: - function = GXnand; - break; - case QPainter::RasterOp_NotSourceXorDestination: - function = GXequiv; - break; - case QPainter::RasterOp_NotSource: - function = GXcopyInverted; - break; - case QPainter::RasterOp_SourceAndNotDestination: - function = GXandReverse; - break; - case QPainter::RasterOp_NotSourceAndDestination: - function = GXandInverted; - break; - default: - function = GXcopy; - } - } -#if !defined(QT_NO_XRENDER) - else { - d->composition_mode = - qpainterOpToXrender(state.compositionMode()); - } -#endif - XSetFunction(X11->display, d->gc, function); - XSetFunction(X11->display, d->gc_brush, function); - } - d->decidePathFallback(); - d->decideCoordAdjust(); -} - -void QX11PaintEngine::updateRenderHints(QPainter::RenderHints hints) -{ - Q_D(QX11PaintEngine); - d->render_hints = hints; - -#if !defined(QT_NO_XRENDER) - if (X11->use_xrender && d->picture) { - XRenderPictureAttributes attrs; - attrs.poly_edge = (hints & QPainter::Antialiasing) ? PolyEdgeSmooth : PolyEdgeSharp; - XRenderChangePicture(d->dpy, d->picture, CPPolyEdge, &attrs); - } -#endif -} - -void QX11PaintEngine::updatePen(const QPen &pen) -{ - Q_D(QX11PaintEngine); - d->cpen = pen; - int cp = CapButt; - int jn = JoinMiter; - int ps = pen.style(); - - if (d->opacity < 1.0) { - QColor c = d->cpen.color(); - c.setAlpha(qRound(c.alpha()*d->opacity)); - d->cpen.setColor(c); - } - - d->has_pen = (ps != Qt::NoPen); - d->has_alpha_pen = (pen.color().alpha() != 255); - - switch (pen.capStyle()) { - case Qt::SquareCap: - cp = CapProjecting; - break; - case Qt::RoundCap: - cp = CapRound; - break; - case Qt::FlatCap: - default: - cp = CapButt; - break; - } - switch (pen.joinStyle()) { - case Qt::BevelJoin: - jn = JoinBevel; - break; - case Qt::RoundJoin: - jn = JoinRound; - break; - case Qt::MiterJoin: - default: - jn = JoinMiter; - break; - } - - d->adapted_pen_origin = false; - - char dashes[10]; // custom pen dashes - int dash_len = 0; // length of dash list - int xStyle = LineSolid; - - /* - We are emulating Windows here. Windows treats cpen.width() == 1 - (or 0) as a very special case. The fudge variable unifies this - case with the general case. - */ - qreal pen_width = pen.widthF(); - int scale = qRound(pen_width < 1 ? 1 : pen_width); - int space = (pen_width < 1 && pen_width > 0 ? 1 : (2 * scale)); - int dot = 1 * scale; - int dash = 4 * scale; - - d->has_custom_pen = false; - - switch (ps) { - case Qt::NoPen: - case Qt::SolidLine: - xStyle = LineSolid; - break; - case Qt::DashLine: - dashes[0] = dash; - dashes[1] = space; - dash_len = 2; - xStyle = LineOnOffDash; - break; - case Qt::DotLine: - dashes[0] = dot; - dashes[1] = space; - dash_len = 2; - xStyle = LineOnOffDash; - break; - case Qt::DashDotLine: - dashes[0] = dash; - dashes[1] = space; - dashes[2] = dot; - dashes[3] = space; - dash_len = 4; - xStyle = LineOnOffDash; - break; - case Qt::DashDotDotLine: - dashes[0] = dash; - dashes[1] = space; - dashes[2] = dot; - dashes[3] = space; - dashes[4] = dot; - dashes[5] = space; - dash_len = 6; - xStyle = LineOnOffDash; - break; - case Qt::CustomDashLine: - d->has_custom_pen = true; - break; - } - - ulong mask = GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth - | GCCapStyle | GCJoinStyle | GCLineStyle; - XGCValues vals; - vals.graphics_exposures = false; - if (d->pdev_depth == 1) { - vals.foreground = qGray(pen.color().rgb()) > 127 ? 0 : 1; - vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1; - } else if (d->pdev->devType() == QInternal::Pixmap && d->pdev_depth == 32 - && X11->use_xrender) { - vals.foreground = pen.color().rgba(); - vals.background = QColor(Qt::transparent).rgba(); - } else { - QColormap cmap = QColormap::instance(d->scrn); - vals.foreground = cmap.pixel(pen.color()); - vals.background = cmap.pixel(QColor(Qt::transparent)); - } - - - vals.line_width = qRound(pen.widthF()); - vals.cap_style = cp; - vals.join_style = jn; - vals.line_style = xStyle; - - XChangeGC(d->dpy, d->gc, mask, &vals); - - if (dash_len) { // make dash list - XSetDashes(d->dpy, d->gc, 0, dashes, dash_len); - } - - if (!d->has_clipping) { // if clipping is set the paintevent clip region is merged with the clip region - QRegion sysClip = systemClip(); - if (!sysClip.isEmpty()) - x11SetClipRegion(d->dpy, d->gc, 0, d->picture, sysClip); - else - x11ClearClipRegion(d->dpy, d->gc, 0, d->picture); - } -} - -void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin) -{ - Q_D(QX11PaintEngine); - d->cbrush = brush; - d->bg_origin = origin; - d->adapted_brush_origin = false; -#if !defined(QT_NO_XRENDER) - d->current_brush = 0; -#endif - if (d->opacity < 1.0) { - QColor c = d->cbrush.color(); - c.setAlpha(qRound(c.alpha()*d->opacity)); - d->cbrush.setColor(c); - } - - int s = FillSolid; - int bs = d->cbrush.style(); - d->has_brush = (bs != Qt::NoBrush); - d->has_pattern = bs >= Qt::Dense1Pattern && bs <= Qt::DiagCrossPattern; - d->has_texture = bs == Qt::TexturePattern; - d->has_alpha_brush = brush.color().alpha() != 255; - d->has_alpha_texture = d->has_texture && d->cbrush.texture().hasAlphaChannel(); - - ulong mask = GCForeground | GCBackground | GCGraphicsExposures - | GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle; - XGCValues vals; - vals.graphics_exposures = false; - if (d->pdev_depth == 1) { - vals.foreground = qGray(d->cbrush.color().rgb()) > 127 ? 0 : 1; - vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1; - } else if (X11->use_xrender && d->pdev->devType() == QInternal::Pixmap - && d->pdev_depth == 32) { - vals.foreground = d->cbrush.color().rgba(); - vals.background = QColor(Qt::transparent).rgba(); - } else { - QColormap cmap = QColormap::instance(d->scrn); - vals.foreground = cmap.pixel(d->cbrush.color()); - vals.background = cmap.pixel(QColor(Qt::transparent)); - - if (!X11->use_xrender && d->has_brush && !d->has_pattern && !brush.isOpaque()) { - QPixmap pattern = qt_patternForAlpha(brush.color().alpha(), d->scrn); - mask |= GCStipple; - vals.stipple = pattern.handle(); - s = FillStippled; - d->adapted_brush_origin = true; - } - } - vals.cap_style = CapButt; - vals.join_style = JoinMiter; - vals.line_style = LineSolid; - - if (d->has_pattern || d->has_texture) { - if (bs == Qt::TexturePattern) { - d->brush_pm = qt_toX11Pixmap(d->cbrush.texture()); -#if !defined(QT_NO_XRENDER) - if (X11->use_xrender) { - XRenderPictureAttributes attrs; - attrs.repeat = true; - XRenderChangePicture(d->dpy, d->brush_pm.x11PictureHandle(), CPRepeat, &attrs); - QX11PlatformPixmap *data = static_cast<QX11PlatformPixmap*>(d->brush_pm.data.data()); - if (data->mask_picture) - XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs); - } -#endif - } else { - d->brush_pm = qt_toX11Pixmap(qt_pixmapForBrush(bs, true)); - } - d->brush_pm.x11SetScreen(d->scrn); - if (d->brush_pm.depth() == 1) { - mask |= GCStipple; - vals.stipple = d->brush_pm.handle(); - s = FillStippled; -#if !defined(QT_NO_XRENDER) - if (X11->use_xrender) { - d->bitmap_texture = QPixmap(d->brush_pm.size()); - d->bitmap_texture.fill(Qt::transparent); - d->bitmap_texture = qt_toX11Pixmap(d->bitmap_texture); - d->bitmap_texture.x11SetScreen(d->scrn); - - ::Picture src = X11->getSolidFill(d->scrn, d->cbrush.color()); - XRenderComposite(d->dpy, PictOpSrc, src, d->brush_pm.x11PictureHandle(), - d->bitmap_texture.x11PictureHandle(), - 0, 0, d->brush_pm.width(), d->brush_pm.height(), - 0, 0, d->brush_pm.width(), d->brush_pm.height()); - - XRenderPictureAttributes attrs; - attrs.repeat = true; - XRenderChangePicture(d->dpy, d->bitmap_texture.x11PictureHandle(), CPRepeat, &attrs); - - d->current_brush = d->bitmap_texture.x11PictureHandle(); - } -#endif - } else { - mask |= GCTile; -#ifndef QT_NO_XRENDER - if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) { - d->brush_pm.detach(); - QX11PlatformPixmap *brushData = static_cast<QX11PlatformPixmap*>(d->brush_pm.data.data()); - brushData->convertToARGB32(); - } -#endif - vals.tile = (d->brush_pm.depth() == d->pdev_depth - ? d->brush_pm.handle() - : static_cast<QX11PlatformPixmap*>(d->brush_pm.data.data())->x11ConvertToDefaultDepth()); - s = FillTiled; -#if !defined(QT_NO_XRENDER) - d->current_brush = d->cbrush.texture().x11PictureHandle(); -#endif - } - - mask |= GCTileStipXOrigin | GCTileStipYOrigin; - vals.ts_x_origin = qRound(origin.x()); - vals.ts_y_origin = qRound(origin.y()); - } -#if !defined(QT_NO_XRENDER) - else if (d->has_alpha_brush) { - d->current_brush = X11->getSolidFill(d->scrn, d->cbrush.color()); - } -#endif - - vals.fill_style = s; - XChangeGC(d->dpy, d->gc_brush, mask, &vals); - if (!d->has_clipping) { - QRegion sysClip = systemClip(); - if (!sysClip.isEmpty()) - x11SetClipRegion(d->dpy, d->gc_brush, 0, d->picture, sysClip); - else - x11ClearClipRegion(d->dpy, d->gc_brush, 0, d->picture); - } -} - -void QX11PaintEngine::drawEllipse(const QRectF &rect) -{ - QRect aligned = rect.toAlignedRect(); - if (aligned == rect) - drawEllipse(aligned); - else - QPaintEngine::drawEllipse(rect); -} - -void QX11PaintEngine::drawEllipse(const QRect &rect) -{ - if (rect.isEmpty()) { - drawRects(&rect, 1); - return; - } - - Q_D(QX11PaintEngine); - QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1); - QRect r(rect); - if (d->txop < QTransform::TxRotate) { - r = d->matrix.mapRect(rect); - } else if (d->txop == QTransform::TxRotate && rect.width() == rect.height()) { - QPainterPath path; - path.addEllipse(rect); - r = d->matrix.map(path).boundingRect().toRect(); - } - - if (d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->render_hints & QPainter::Antialiasing) - || d->has_alpha_texture || devclip.intersected(r) != r - || (d->has_complex_xform - && !(d->has_non_scaling_xform && rect.width() == rect.height()))) - { - QPainterPath path; - path.addEllipse(rect); - drawPath(path); - return; - } - - int x = r.x(); - int y = r.y(); - int w = r.width(); - int h = r.height(); - if (w < 1 || h < 1) - return; - if (w == 1 && h == 1) { - XDrawPoint(d->dpy, d->hd, d->has_pen ? d->gc : d->gc_brush, x, y); - return; - } - d->setupAdaptedOrigin(rect.topLeft()); - if (d->has_brush) { // draw filled ellipse - XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64); - if (!d->has_pen) // make smoother outline - XDrawArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64); - } - if (d->has_pen) // draw outline - XDrawArc(d->dpy, d->hd, d->gc, x, y, w, h, 0, 360*64); - d->resetAdaptedOrigin(); -} - - - -void QX11PaintEnginePrivate::fillPolygon_translated(const QPointF *polygonPoints, int pointCount, - QX11PaintEnginePrivate::GCMode gcMode, - QPaintEngine::PolygonDrawMode mode) -{ - - QVarLengthArray<QPointF> translated_points(pointCount); - QPointF offset(matrix.dx(), matrix.dy()); - - qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0; - if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing)) - offset += QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta); - - for (int i = 0; i < pointCount; ++i) { - translated_points[i] = polygonPoints[i] + offset; - - translated_points[i].rx() = qRound(translated_points[i].x()) + offs; - translated_points[i].ry() = qRound(translated_points[i].y()) + offs; - } - - fillPolygon_dev(translated_points.data(), pointCount, gcMode, mode); -} - -#ifndef QT_NO_XRENDER -static void qt_XRenderCompositeTrapezoids(Display *dpy, - int op, - Picture src, - Picture dst, - _Xconst XRenderPictFormat *maskFormat, - int xSrc, - int ySrc, - const XTrapezoid *traps, int size) -{ - const int MAX_TRAPS = 50000; - while (size) { - int to_draw = size; - if (to_draw > MAX_TRAPS) - to_draw = MAX_TRAPS; - XRenderCompositeTrapezoids(dpy, op, src, dst, - maskFormat, - xSrc, ySrc, - traps, to_draw); - size -= to_draw; - traps += to_draw; - } -} -#endif - -void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount, - QX11PaintEnginePrivate::GCMode gcMode, - QPaintEngine::PolygonDrawMode mode) -{ - Q_Q(QX11PaintEngine); - - int clippedCount = 0; - qt_float_point *clippedPoints = 0; - -#ifndef QT_NO_XRENDER - //can change if we switch to pen if gcMode != BrushGC - bool has_fill_texture = has_texture; - bool has_fill_pattern = has_pattern; - ::Picture src; -#endif - QBrush fill; - GC fill_gc; - if (gcMode == BrushGC) { - fill = cbrush; - fill_gc = gc_brush; -#ifndef QT_NO_XRENDER - if (current_brush) - src = current_brush; - else - src = X11->getSolidFill(scrn, fill.color()); -#endif - } else { - fill = QBrush(cpen.brush()); - fill_gc = gc; -#ifndef QT_NO_XRENDER - //we use the pens brush - has_fill_texture = (fill.style() == Qt::TexturePattern); - has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern); - if (has_fill_texture) - src = fill.texture().x11PictureHandle(); - else if (has_fill_pattern) - src = getPatternFill(scrn, fill); - else - src = X11->getSolidFill(scrn, fill.color()); -#endif - } - - polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount, - &clippedPoints, &clippedCount); - -#ifndef QT_NO_XRENDER - bool solid_fill = fill.color().alpha() == 255; - if (has_fill_texture && fill.texture().depth() == 1 && solid_fill) { - has_fill_texture = false; - has_fill_pattern = true; - } - - bool antialias = render_hints & QPainter::Antialiasing; - - if (X11->use_xrender - && picture - && !has_fill_pattern - && (clippedCount > 0) - && (fill.style() != Qt::NoBrush) - && ((has_fill_texture && fill.texture().hasAlpha()) || antialias || !solid_fill || has_alpha_pen != has_alpha_brush)) - { - if (tessellator->size > 0) { - XRenderPictureAttributes attrs; - attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp; - XRenderChangePicture(dpy, picture, CPPolyEdge, &attrs); - int x_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.x) - bg_origin.x()); - int y_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.y) - bg_origin.y()); - qt_XRenderCompositeTrapezoids(dpy, composition_mode, src, picture, - antialias - ? XRenderFindStandardFormat(dpy, PictStandardA8) - : XRenderFindStandardFormat(dpy, PictStandardA1), - x_offset, y_offset, - tessellator->traps, tessellator->size); - tessellator->done(); - } - } else -#endif - if (fill.style() != Qt::NoBrush) { - if (clippedCount > 200000) { - QPolygon poly; - for (int i = 0; i < clippedCount; ++i) - poly << QPoint(qFloor(clippedPoints[i].x), qFloor(clippedPoints[i].y)); - - const QRect bounds = poly.boundingRect(); - const QRect aligned = bounds - & QRect(QPoint(), QSize(pdev->width(), pdev->height())); - - QImage img(aligned.size(), QImage::Format_ARGB32_Premultiplied); - img.fill(0); - - QPainter painter(&img); - painter.translate(-aligned.x(), -aligned.y()); - painter.setPen(Qt::NoPen); - painter.setBrush(fill); - if (gcMode == BrushGC) - painter.setBrushOrigin(q->painter()->brushOrigin()); - painter.drawPolygon(poly); - painter.end(); - - q->drawImage(aligned, img, img.rect(), Qt::AutoColor); - } else if (clippedCount > 0) { - QVarLengthArray<XPoint> xpoints(clippedCount); - for (int i = 0; i < clippedCount; ++i) { - xpoints[i].x = qFloor(clippedPoints[i].x); - xpoints[i].y = qFloor(clippedPoints[i].y); - } - if (mode == QPaintEngine::WindingMode) - XSetFillRule(dpy, fill_gc, WindingRule); - setupAdaptedOrigin(QPoint(xpoints[0].x, xpoints[0].y)); - XFillPolygon(dpy, hd, fill_gc, - xpoints.data(), clippedCount, - mode == QPaintEngine::ConvexMode ? Convex : Complex, CoordModeOrigin); - resetAdaptedOrigin(); - if (mode == QPaintEngine::WindingMode) - XSetFillRule(dpy, fill_gc, EvenOddRule); - } - } -} - -void QX11PaintEnginePrivate::strokePolygon_translated(const QPointF *polygonPoints, int pointCount, bool close) -{ - QVarLengthArray<QPointF> translated_points(pointCount); - QPointF offset(matrix.dx(), matrix.dy()); - for (int i = 0; i < pointCount; ++i) - translated_points[i] = polygonPoints[i] + offset; - strokePolygon_dev(translated_points.data(), pointCount, close); -} - -void QX11PaintEnginePrivate::strokePolygon_dev(const QPointF *polygonPoints, int pointCount, bool close) -{ - int clippedCount = 0; - qt_float_point *clippedPoints = 0; - polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount, - &clippedPoints, &clippedCount, close); - - if (clippedCount > 0) { - QVarLengthArray<XPoint> xpoints(clippedCount); - for (int i = 0; i < clippedCount; ++i) { - xpoints[i].x = qRound(clippedPoints[i].x + aliasedCoordinateDelta); - xpoints[i].y = qRound(clippedPoints[i].y + aliasedCoordinateDelta); - } - uint numberPoints = qMin(clippedCount, xlibMaxLinePoints); - XPoint *pts = xpoints.data(); - XDrawLines(dpy, hd, gc, pts, numberPoints, CoordModeOrigin); - pts += numberPoints; - clippedCount -= numberPoints; - numberPoints = qMin(clippedCount, xlibMaxLinePoints-1); - while (clippedCount) { - XDrawLines(dpy, hd, gc, pts-1, numberPoints+1, CoordModeOrigin); - pts += numberPoints; - clippedCount -= numberPoints; - numberPoints = qMin(clippedCount, xlibMaxLinePoints-1); - } - } -} - -void QX11PaintEngine::drawPolygon(const QPointF *polygonPoints, int pointCount, PolygonDrawMode mode) -{ - Q_D(QX11PaintEngine); - if (d->use_path_fallback) { - QPainterPath path(polygonPoints[0]); - for (int i = 1; i < pointCount; ++i) - path.lineTo(polygonPoints[i]); - if (mode == PolylineMode) { - QBrush oldBrush = d->cbrush; - d->cbrush = QBrush(Qt::NoBrush); - path.setFillRule(Qt::WindingFill); - drawPath(path); - d->cbrush = oldBrush; - } else { - path.setFillRule(mode == OddEvenMode ? Qt::OddEvenFill : Qt::WindingFill); - path.closeSubpath(); - drawPath(path); - } - return; - } - if (mode != PolylineMode && d->has_brush) - d->fillPolygon_translated(polygonPoints, pointCount, QX11PaintEnginePrivate::BrushGC, mode); - - if (d->has_pen) - d->strokePolygon_translated(polygonPoints, pointCount, mode != PolylineMode); -} - - -void QX11PaintEnginePrivate::fillPath(const QPainterPath &path, QX11PaintEnginePrivate::GCMode gc_mode, bool transform) -{ - qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0; - - QPainterPath clippedPath; - QPainterPath clipPath; - clipPath.addRect(polygonClipper.boundingRect()); - - if (transform) - clippedPath = (path*matrix).intersected(clipPath); - else - clippedPath = path.intersected(clipPath); - - QList<QPolygonF> polys = clippedPath.toFillPolygons(); - for (int i = 0; i < polys.size(); ++i) { - QVarLengthArray<QPointF> translated_points(polys.at(i).size()); - - for (int j = 0; j < polys.at(i).size(); ++j) { - translated_points[j] = polys.at(i).at(j); - if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing)) { - translated_points[j].rx() = qRound(translated_points[j].rx() + aliasedCoordinateDelta) + offs; - translated_points[j].ry() = qRound(translated_points[j].ry() + aliasedCoordinateDelta) + offs; - } - } - - fillPolygon_dev(translated_points.data(), polys.at(i).size(), gc_mode, - path.fillRule() == Qt::OddEvenFill ? QPaintEngine::OddEvenMode : QPaintEngine::WindingMode); - } -} - -void QX11PaintEngine::drawPath(const QPainterPath &path) -{ - Q_D(QX11PaintEngine); - if (path.isEmpty()) - return; - - if (d->has_brush) - d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true); - if (d->has_pen - && ((X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing))) - || (!d->cpen.isCosmetic() && d->txop > QTransform::TxTranslate - && !d->has_non_scaling_xform) - || (d->cpen.style() == Qt::CustomDashLine))) { - QPainterPathStroker stroker; - if (d->cpen.style() == Qt::CustomDashLine) { - stroker.setDashPattern(d->cpen.dashPattern()); - stroker.setDashOffset(d->cpen.dashOffset()); - } else { - stroker.setDashPattern(d->cpen.style()); - } - stroker.setCapStyle(d->cpen.capStyle()); - stroker.setJoinStyle(d->cpen.joinStyle()); - QPainterPath stroke; - qreal width = d->cpen.widthF(); - QPolygonF poly; - QRectF deviceRect(0, 0, d->pdev->width(), d->pdev->height()); - // necessary to get aliased alphablended primitives to be drawn correctly - if (d->cpen.isCosmetic() || d->has_scaling_xform) { - if (d->cpen.isCosmetic()) - stroker.setWidth(width == 0 ? 1 : width); - else - stroker.setWidth(width * d->xform_scale); - stroker.d_ptr->stroker.setClipRect(deviceRect); - stroke = stroker.createStroke(path * d->matrix); - if (stroke.isEmpty()) - return; - stroke.setFillRule(Qt::WindingFill); - d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, false); - } else { - stroker.setWidth(width); - stroker.d_ptr->stroker.setClipRect(d->matrix.inverted().mapRect(deviceRect)); - stroke = stroker.createStroke(path); - if (stroke.isEmpty()) - return; - stroke.setFillRule(Qt::WindingFill); - d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, true); - } - } else if (d->has_pen) { - // if we have a cosmetic pen - use XDrawLine() for speed - QList<QPolygonF> polys = path.toSubpathPolygons(d->matrix); - for (int i = 0; i < polys.size(); ++i) - d->strokePolygon_dev(polys.at(i).data(), polys.at(i).size(), false); - } -} - -Q_WIDGETS_EXPORT void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image, - Drawable hd, GC gc, Display *dpy, Visual *visual, int depth) -{ - Q_ASSERT(image.format() == QImage::Format_RGB32); - Q_ASSERT(image.depth() == 32); - - XImage *xi; - // Note: this code assumes either RGB or BGR, 8 bpc server layouts - const uint red_mask = (uint) visual->red_mask; - bool bgr_layout = (red_mask == 0xff); - - const int w = rect.width(); - const int h = rect.height(); - - QImage im; - int image_byte_order = ImageByteOrder(X11->display); - if ((QSysInfo::ByteOrder == QSysInfo::BigEndian && ((image_byte_order == LSBFirst) || bgr_layout)) - || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian) - || (image_byte_order == LSBFirst && bgr_layout)) - { - im = image.copy(rect); - const int iw = im.bytesPerLine() / 4; - uint *data = (uint *)im.bits(); - for (int i=0; i < h; i++) { - uint *p = data; - uint *end = p + w; - if (bgr_layout && image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian) { - while (p < end) { - *p = ((*p << 8) & 0xffffff00) | ((*p >> 24) & 0x000000ff); - p++; - } - } else if ((image_byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) - || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) { - while (p < end) { - *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) - | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); - p++; - } - } else if ((image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian) - || (image_byte_order == LSBFirst && bgr_layout)) - { - while (p < end) { - *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff) - | ((*p ) & 0xff00ff00); - p++; - } - } - data += iw; - } - xi = XCreateImage(dpy, visual, depth, ZPixmap, - 0, (char *) im.bits(), w, h, 32, im.bytesPerLine()); - } else { - xi = XCreateImage(dpy, visual, depth, ZPixmap, - 0, (char *) image.scanLine(rect.y())+rect.x()*sizeof(uint), w, h, 32, image.bytesPerLine()); - } - XPutImage(dpy, hd, gc, xi, 0, 0, pos.x(), pos.y(), w, h); - xi->data = 0; // QImage owns these bits - XDestroyImage(xi); -} - -void QX11PaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags) -{ - Q_D(QX11PaintEngine); - - if (image.format() == QImage::Format_RGB32 - && d->pdev_depth >= 24 && image.depth() == 32 - && r.size() == sr.size()) - { - int sx = qRound(sr.x()); - int sy = qRound(sr.y()); - int x = qRound(r.x()); - int y = qRound(r.y()); - int w = qRound(r.width()); - int h = qRound(r.height()); - - qt_x11_drawImage(QRect(sx, sy, w, h), QPoint(x, y), image, d->hd, d->gc, d->dpy, - (Visual *)d->xinfo->visual(), d->pdev_depth); - } else { - QPaintEngine::drawImage(r, image, sr, flags); - } -} - -void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRectF &_sr) -{ - Q_D(QX11PaintEngine); - QRectF sr = _sr; - int x = qRound(r.x()); - int y = qRound(r.y()); - int sx = qRound(sr.x()); - int sy = qRound(sr.y()); - int sw = qRound(sr.width()); - int sh = qRound(sr.height()); - - QPixmap pixmap = qt_toX11Pixmap(px); - if(pixmap.isNull()) - return; - - if ((d->xinfo && d->xinfo->screen() != pixmap.x11Info().screen()) - || (pixmap.x11Info().screen() != DefaultScreen(X11->display))) { - QPixmap* p = const_cast<QPixmap *>(&pixmap); - p->x11SetScreen(d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display)); - } - - QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen()); - -#ifndef QT_NO_XRENDER - ::Picture src_pict = static_cast<QX11PlatformPixmap*>(pixmap.data.data())->picture; - if (src_pict && d->picture) { - const int pDepth = pixmap.depth(); - if (pDepth == 1 && (d->has_alpha_pen)) { - qt_render_bitmap(d->dpy, d->scrn, src_pict, d->picture, - sx, sy, x, y, sw, sh, d->cpen); - return; - } else if (pDepth != 1 && (pDepth == 32 || pDepth != d->pdev_depth)) { - XRenderComposite(d->dpy, d->composition_mode, - src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh); - return; - } - } -#endif - - bool mono_src = pixmap.depth() == 1; - bool mono_dst = d->pdev_depth == 1; - bool restore_clip = false; - - if (static_cast<QX11PlatformPixmap*>(pixmap.data.data())->x11_mask) { // pixmap has a mask - QBitmap comb(sw, sh); - GC cgc = XCreateGC(d->dpy, comb.handle(), 0, 0); - XSetForeground(d->dpy, cgc, 0); - XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh); - XSetBackground(d->dpy, cgc, 0); - XSetForeground(d->dpy, cgc, 1); - if (!d->crgn.isEmpty()) { - int num; - XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num); - XSetClipRectangles(d->dpy, cgc, -x, -y, rects, num, Unsorted); - } else if (d->has_clipping) { - XSetClipRectangles(d->dpy, cgc, 0, 0, 0, 0, Unsorted); - } - XSetFillStyle(d->dpy, cgc, FillOpaqueStippled); - XSetTSOrigin(d->dpy, cgc, -sx, -sy); - XSetStipple(d->dpy, cgc, - static_cast<QX11PlatformPixmap*>(pixmap.data.data())->x11_mask); - XFillRectangle(d->dpy, comb.handle(), cgc, 0, 0, sw, sh); - XFreeGC(d->dpy, cgc); - - XSetClipOrigin(d->dpy, d->gc, x, y); - XSetClipMask(d->dpy, d->gc, comb.handle()); - restore_clip = true; - } - - if (mono_src) { - if (!d->crgn.isEmpty()) { - Pixmap comb = XCreatePixmap(d->dpy, d->hd, sw, sh, 1); - GC cgc = XCreateGC(d->dpy, comb, 0, 0); - XSetForeground(d->dpy, cgc, 0); - XFillRectangle(d->dpy, comb, cgc, 0, 0, sw, sh); - int num; - XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num); - XSetClipRectangles(d->dpy, cgc, -x, -y, rects, num, Unsorted); - XCopyArea(d->dpy, pixmap.handle(), comb, cgc, sx, sy, sw, sh, 0, 0); - XFreeGC(d->dpy, cgc); - - XSetClipMask(d->dpy, d->gc, comb); - XSetClipOrigin(d->dpy, d->gc, x, y); - XFreePixmap(d->dpy, comb); - } else { - XSetClipMask(d->dpy, d->gc, pixmap.handle()); - XSetClipOrigin(d->dpy, d->gc, x - sx, y - sy); - } - - if (mono_dst) { - XSetForeground(d->dpy, d->gc, qGray(d->cpen.color().rgb()) > 127 ? 0 : 1); - } else { - QColormap cmap = QColormap::instance(d->scrn); - XSetForeground(d->dpy, d->gc, cmap.pixel(d->cpen.color())); - } - XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh); - restore_clip = true; - } else if (mono_dst && !mono_src) { - QBitmap bitmap(pixmap); - XCopyArea(d->dpy, bitmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y); - } else { - XCopyArea(d->dpy, pixmap.handle(), d->hd, d->gc, sx, sy, sw, sh, x, y); - } - - if (d->pdev->devType() == QInternal::Pixmap) { - const QPixmap *px = static_cast<const QPixmap*>(d->pdev); - Pixmap src_mask = static_cast<QX11PlatformPixmap*>(pixmap.data.data())->x11_mask; - Pixmap dst_mask = static_cast<QX11PlatformPixmap*>(px->data.data())->x11_mask; - if (dst_mask) { - GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0); - if (src_mask) { // copy src mask into dst mask - XCopyArea(d->dpy, src_mask, dst_mask, cgc, sx, sy, sw, sh, x, y); - } else { // no src mask, but make sure the area copied is opaque in dest - XSetBackground(d->dpy, cgc, 0); - XSetForeground(d->dpy, cgc, 1); - XFillRectangle(d->dpy, dst_mask, cgc, x, y, sw, sh); - } - XFreeGC(d->dpy, cgc); - } - } - - if (restore_clip) { - XSetClipOrigin(d->dpy, d->gc, 0, 0); - int num; - XRectangle *rects = (XRectangle *)qt_getClipRects(d->crgn, num); - if (num == 0) - XSetClipMask(d->dpy, d->gc, XNone); - else - XSetClipRectangles(d->dpy, d->gc, 0, 0, rects, num, Unsorted); - } -} - -void QX11PaintEngine::updateMatrix(const QTransform &mtx) -{ - Q_D(QX11PaintEngine); - d->txop = mtx.type(); - d->matrix = mtx; - - d->has_complex_xform = (d->txop > QTransform::TxTranslate); - - extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); - bool scaling = qt_scaleForTransform(d->matrix, &d->xform_scale); - d->has_scaling_xform = scaling && d->xform_scale != 1.0; - d->has_non_scaling_xform = scaling && d->xform_scale == 1.0; -} - -/* - NB! the clip region is expected to be in dev coordinates -*/ -void QX11PaintEngine::updateClipRegion_dev(const QRegion &clipRegion, Qt::ClipOperation op) -{ - Q_D(QX11PaintEngine); - QRegion sysClip = systemClip(); - if (op == Qt::NoClip) { - d->has_clipping = false; - d->crgn = sysClip; - if (!sysClip.isEmpty()) { - x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, sysClip); - } else { - x11ClearClipRegion(d->dpy, d->gc, d->gc_brush, d->picture); - } - return; - } - - switch (op) { - case Qt::IntersectClip: - if (d->has_clipping) { - d->crgn &= clipRegion; - break; - } - // fall through - case Qt::ReplaceClip: - if (!sysClip.isEmpty()) - d->crgn = clipRegion.intersected(sysClip); - else - d->crgn = clipRegion; - break; - default: - break; - } - d->has_clipping = true; - x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, d->crgn); -} - -void QX11PaintEngine::updateFont(const QFont &) -{ -} - -Qt::HANDLE QX11PaintEngine::handle() const -{ - Q_D(const QX11PaintEngine); - Q_ASSERT(isActive()); - Q_ASSERT(d->hd); - return d->hd; -} - -extern void qt_draw_tile(QPaintEngine *, qreal, qreal, qreal, qreal, const QPixmap &, - qreal, qreal); - -void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &p) -{ - int x = qRound(r.x()); - int y = qRound(r.y()); - int w = qRound(r.width()); - int h = qRound(r.height()); - int sx = qRound(p.x()); - int sy = qRound(p.y()); - - bool mono_src = pixmap.depth() == 1; - Q_D(QX11PaintEngine); - - if ((d->xinfo && d->xinfo->screen() != pixmap.x11Info().screen()) - || (pixmap.x11Info().screen() != DefaultScreen(X11->display))) { - QPixmap* p = const_cast<QPixmap *>(&pixmap); - p->x11SetScreen(d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display)); - } - - QPixmap::x11SetDefaultScreen(pixmap.x11Info().screen()); - -#ifndef QT_NO_XRENDER - if (X11->use_xrender && d->picture && pixmap.x11PictureHandle()) { -#if 0 - // ### Qt 5: enable this - XRenderPictureAttributes attrs; - attrs.repeat = true; - XRenderChangePicture(d->dpy, pixmap.x11PictureHandle(), CPRepeat, &attrs); - - if (mono_src) { - qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture, - sx, sy, x, y, w, h, d->cpen); - } else { - XRenderComposite(d->dpy, d->composition_mode, - pixmap.x11PictureHandle(), XNone, d->picture, - sx, sy, 0, 0, x, y, w, h); - } -#else - const int numTiles = (w / pixmap.width()) * (h / pixmap.height()); - if (numTiles < 100) { - // this is essentially qt_draw_tile(), inlined for - // the XRenderComposite call - int yPos, xPos, drawH, drawW, yOff, xOff; - yPos = y; - yOff = sy; - while(yPos < y + h) { - drawH = pixmap.height() - yOff; // Cropping first row - if (yPos + drawH > y + h) // Cropping last row - drawH = y + h - yPos; - xPos = x; - xOff = sx; - while(xPos < x + w) { - drawW = pixmap.width() - xOff; // Cropping first column - if (xPos + drawW > x + w) // Cropping last column - drawW = x + w - xPos; - if (mono_src) { - qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture, - xOff, yOff, xPos, yPos, drawW, drawH, d->cpen); - } else { - XRenderComposite(d->dpy, d->composition_mode, - pixmap.x11PictureHandle(), XNone, d->picture, - xOff, yOff, 0, 0, xPos, yPos, drawW, drawH); - } - xPos += drawW; - xOff = 0; - } - yPos += drawH; - yOff = 0; - } - } else { - w = qMin(w, d->pdev->width() - x); - h = qMin(h, d->pdev->height() - y); - if (w <= 0 || h <= 0) - return; - - const int pw = w + sx; - const int ph = h + sy; - QPixmap pm(pw, ph); - if (pixmap.hasAlpha() || mono_src) - pm.fill(Qt::transparent); - - const int mode = pixmap.hasAlpha() ? PictOpOver : PictOpSrc; - const ::Picture pmPicture = pm.x11PictureHandle(); - - // first tile - XRenderComposite(d->dpy, mode, - pixmap.x11PictureHandle(), XNone, pmPicture, - 0, 0, 0, 0, 0, 0, qMin(pw, pixmap.width()), qMin(ph, pixmap.height())); - - // first row of tiles - int xPos = pixmap.width(); - const int sh = qMin(ph, pixmap.height()); - while (xPos < pw) { - const int sw = qMin(xPos, pw - xPos); - XRenderComposite(d->dpy, mode, - pmPicture, XNone, pmPicture, - 0, 0, 0, 0, xPos, 0, sw, sh); - xPos *= 2; - } - - // remaining rows - int yPos = pixmap.height(); - const int sw = pw; - while (yPos < ph) { - const int sh = qMin(yPos, ph - yPos); - XRenderComposite(d->dpy, mode, - pmPicture, XNone, pmPicture, - 0, 0, 0, 0, 0, yPos, sw, sh); - yPos *= 2; - } - - // composite - if (mono_src) - qt_render_bitmap(d->dpy, d->scrn, pmPicture, d->picture, - sx, sy, x, y, w, h, d->cpen); - else - XRenderComposite(d->dpy, d->composition_mode, - pmPicture, XNone, d->picture, - sx, sy, 0, 0, x, y, w, h); - } -#endif - } else -#endif // !QT_NO_XRENDER - if (pixmap.depth() > 1 && !static_cast<QX11PlatformPixmap*>(pixmap.data.data())->x11_mask) { - XSetTile(d->dpy, d->gc, pixmap.handle()); - XSetFillStyle(d->dpy, d->gc, FillTiled); - XSetTSOrigin(d->dpy, d->gc, x-sx, y-sy); - XFillRectangle(d->dpy, d->hd, d->gc, x, y, w, h); - XSetTSOrigin(d->dpy, d->gc, 0, 0); - XSetFillStyle(d->dpy, d->gc, FillSolid); - } else { - qt_draw_tile(this, x, y, w, h, pixmap, sx, sy); - } -} - -void QX11PaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) -{ - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - - switch(ti.fontEngine->type()) { - case QFontEngine::TestFontEngine: - case QFontEngine::Box: - d_func()->drawBoxTextItem(p, ti); - break; - case QFontEngine::XLFD: - drawXLFD(p, ti); - break; -#ifndef QT_NO_FONTCONFIG - case QFontEngine::Freetype: - drawFreetype(p, ti); - break; -#endif - default: - Q_ASSERT(false); - } -} - -void QX11PaintEngine::drawXLFD(const QPointF &p, const QTextItemInt &ti) -{ - Q_D(QX11PaintEngine); - - if (d->txop > QTransform::TxTranslate) { - // XServer or font don't support server side transformations, need to do it by hand - QPaintEngine::drawTextItem(p, ti); - return; - } - - if (!ti.glyphs.numGlyphs) - return; - - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix = d->matrix; - matrix.translate(p.x(), p.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - QFontEngineXLFD *xlfd = static_cast<QFontEngineXLFD *>(ti.fontEngine); - Qt::HANDLE font_id = xlfd->fontStruct()->fid; - - XSetFont(d->dpy, d->gc, font_id); - - const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); - for (int i = 0; i < glyphs.size(); i++) { - int xp = qRound(positions[i].x + offs); - int yp = qRound(positions[i].y + offs); - if (xp < SHRT_MAX && xp > SHRT_MIN && yp > SHRT_MIN && yp < SHRT_MAX) { - XChar2b ch; - ch.byte1 = glyphs[i] >> 8; - ch.byte2 = glyphs[i] & 0xff; - XDrawString16(d->dpy, d->hd, d->gc, xp, yp, &ch, 1); - } - } -} - -#ifndef QT_NO_FONTCONFIG -static QPainterPath path_for_glyphs(const QVarLengthArray<glyph_t> &glyphs, - const QVarLengthArray<QFixedPoint> &positions, - const QFontEngineFT *ft) -{ - QPainterPath path; - path.setFillRule(Qt::WindingFill); - ft->lockFace(); - int i = 0; - while (i < glyphs.size()) { - QFontEngineFT::Glyph *glyph = ft->loadGlyph(glyphs[i], QFontEngineFT::Format_Mono); - // #### fix case where we don't get a glyph - if (!glyph) - break; - - Q_ASSERT(glyph->format == QFontEngineFT::Format_Mono); - int n = 0; - int h = glyph->height; - int xp = qRound(positions[i].x); - int yp = qRound(positions[i].y); - - xp += glyph->x; - yp += -glyph->y + glyph->height; - int pitch = ((glyph->width + 31) & ~31) >> 3; - - uchar *src = glyph->data; - while (h--) { - for (int x = 0; x < glyph->width; ++x) { - bool set = src[x >> 3] & (0x80 >> (x & 7)); - if (set) { - QRect r(xp + x, yp - h, 1, 1); - while (x < glyph->width-1 && src[(x+1) >> 3] & (0x80 >> ((x+1) & 7))) { - ++x; - r.setRight(r.right()+1); - } - - path.addRect(r); - ++n; - } - } - src += pitch; - } - ++i; - } - ft->unlockFace(); - return path; -} - -void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti) -{ - Q_D(QX11PaintEngine); - if (!ti.glyphs.numGlyphs) - return; - - QFontEngineX11FT *ft = static_cast<QFontEngineX11FT *>(ti.fontEngine); - - if (!d->cpen.isSolid()) { - QPaintEngine::drawTextItem(p, ti); - return; - } - - const bool xrenderPath = (X11->use_xrender - && !(d->pdev->devType() == QInternal::Pixmap - && static_cast<const QPixmap *>(d->pdev)->data->pixelType() == QPlatformPixmap::BitmapType)); - - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - - if (xrenderPath) - matrix = d->matrix; - matrix.translate(p.x(), p.y()); - ft->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (glyphs.count() == 0) - return; - -#ifndef QT_NO_XRENDER - QFontEngineFT::QGlyphSet *set = ft->defaultGlyphs(); - if (d->txop >= QTransform::TxScale && xrenderPath) - set = ft->loadTransformedGlyphSet(d->matrix); - - if (!set || set->outline_drawing - || !ft->loadGlyphs(set, glyphs.constData(), glyphs.size(), positions.constData(), QFontEngineFT::Format_Render)) - { - QPaintEngine::drawTextItem(p, ti); - return; - } - - if (xrenderPath) { - GlyphSet glyphSet = set->id; - const QColor &pen = d->cpen.color(); - ::Picture src = X11->getSolidFill(d->scrn, pen); - XRenderPictFormat *maskFormat = 0; - if (ft->xglyph_format != PictStandardA1) - maskFormat = XRenderFindStandardFormat(X11->display, ft->xglyph_format); - - enum { t_min = SHRT_MIN, t_max = SHRT_MAX }; - - int i = 0; - for (; i < glyphs.size() - && (positions[i].x < t_min || positions[i].x > t_max - || positions[i].y < t_min || positions[i].y > t_max); - ++i) - ; - - if (i >= glyphs.size()) - return; - ++i; - - QFixed xp = positions[i - 1].x; - QFixed yp = positions[i - 1].y; - QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); - - XGlyphElt32 elt; - elt.glyphset = glyphSet; - elt.chars = &glyphs[i - 1]; - elt.nchars = 1; - elt.xOff = qRound(xp + offs); - elt.yOff = qRound(yp + offs); - for (; i < glyphs.size(); ++i) { - if (positions[i].x < t_min || positions[i].x > t_max - || positions[i].y < t_min || positions[i].y > t_max) { - break; - } - QFontEngineFT::Glyph *g = ft->cachedGlyph(glyphs[i - 1]); - if (g - && positions[i].x == xp + g->advance - && positions[i].y == yp - && elt.nchars < 253 // don't draw more than 253 characters as some X servers - // hang with it - ) { - elt.nchars++; - xp += g->advance; - } else { - xp = positions[i].x; - yp = positions[i].y; - - XRenderCompositeText32(X11->display, PictOpOver, src, d->picture, - maskFormat, 0, 0, 0, 0, - &elt, 1); - elt.chars = &glyphs[i]; - elt.nchars = 1; - elt.xOff = qRound(xp + offs); - elt.yOff = qRound(yp + offs); - } - } - XRenderCompositeText32(X11->display, PictOpOver, src, d->picture, - maskFormat, 0, 0, 0, 0, - &elt, 1); - - return; - - } -#endif - - QPainterPath path = path_for_glyphs(glyphs, positions, ft); - if (path.elementCount() <= 1) - return; - Q_ASSERT((path.elementCount() % 5) == 0); - if (d->txop >= QTransform::TxScale) { - painter()->save(); - painter()->setBrush(d->cpen.brush()); - painter()->setPen(Qt::NoPen); - painter()->drawPath(path); - painter()->restore(); - return; - } - - const int rectcount = 256; - XRectangle rects[rectcount]; - int num_rects = 0; - - QPoint delta(qRound(d->matrix.dx()), qRound(d->matrix.dy())); - QRect clip(d->polygonClipper.boundingRect()); - for (int i=0; i < path.elementCount(); i+=5) { - int x = qRound(path.elementAt(i).x); - int y = qRound(path.elementAt(i).y); - int w = qRound(path.elementAt(i+1).x) - x; - int h = qRound(path.elementAt(i+2).y) - y; - - QRect rect = QRect(x + delta.x(), y + delta.y(), w, h); - rect = rect.intersected(clip); - if (rect.isEmpty()) - continue; - - rects[num_rects].x = short(rect.x()); - rects[num_rects].y = short(rect.y()); - rects[num_rects].width = ushort(rect.width()); - rects[num_rects].height = ushort(rect.height()); - ++num_rects; - if (num_rects == rectcount) { - XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects); - num_rects = 0; - } - } - if (num_rects > 0) - XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects); - -} -#endif // !QT_NO_XRENDER - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qpaintengine_x11_p.h b/src/widgets/platforms/x11/qpaintengine_x11_p.h deleted file mode 100644 index 2ff339bbe1..0000000000 --- a/src/widgets/platforms/x11/qpaintengine_x11_p.h +++ /dev/null @@ -1,246 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPAINTENGINE_X11_P_H -#define QPAINTENGINE_X11_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qpaintengine.h" -#include "QtGui/qregion.h" -#include "QtGui/qpen.h" -#include "QtCore/qpoint.h" -#include "private/qpaintengine_p.h" -#include "private/qpainter_p.h" -#include "private/qpolygonclipper_p.h" - -typedef unsigned long Picture; - -QT_BEGIN_NAMESPACE - -class QX11PaintEnginePrivate; -class QFontEngineFT; -class QXRenderTessellator; - -struct qt_float_point -{ - qreal x, y; -}; - -class QX11PaintEngine : public QPaintEngine -{ - Q_DECLARE_PRIVATE(QX11PaintEngine) -public: - QX11PaintEngine(); - ~QX11PaintEngine(); - - bool begin(QPaintDevice *pdev); - bool end(); - - void updateState(const QPaintEngineState &state); - - void updatePen(const QPen &pen); - void updateBrush(const QBrush &brush, const QPointF &pt); - void updateRenderHints(QPainter::RenderHints hints); - void updateFont(const QFont &font); - void updateMatrix(const QTransform &matrix); - void updateClipRegion_dev(const QRegion ®ion, Qt::ClipOperation op); - - void drawLines(const QLine *lines, int lineCount); - void drawLines(const QLineF *lines, int lineCount); - - void drawRects(const QRect *rects, int rectCount); - void drawRects(const QRectF *rects, int rectCount); - - void drawPoints(const QPoint *points, int pointCount); - void drawPoints(const QPointF *points, int pointCount); - - void drawEllipse(const QRect &r); - void drawEllipse(const QRectF &r); - - virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - inline void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) - { QPaintEngine::drawPolygon(points, pointCount, mode); } - - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); - void drawPath(const QPainterPath &path); - void drawTextItem(const QPointF &p, const QTextItem &textItem); - void drawImage(const QRectF &r, const QImage &img, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - - virtual Qt::HANDLE handle() const; - inline Type type() const { return QPaintEngine::X11; } - - QPainter::RenderHints supportedRenderHints() const; - -protected: - QX11PaintEngine(QX11PaintEnginePrivate &dptr); - - void drawXLFD(const QPointF &p, const QTextItemInt &si); -#ifndef QT_NO_FONTCONFIG - void drawFreetype(const QPointF &p, const QTextItemInt &si); -#endif - - friend class QPixmap; - friend class QFontEngineBox; - friend Q_WIDGETS_EXPORT GC qt_x11_get_pen_gc(QPainter *); - friend Q_WIDGETS_EXPORT GC qt_x11_get_brush_gc(QPainter *); - -private: - Q_DISABLE_COPY(QX11PaintEngine) -}; - -class QX11PaintEnginePrivate : public QPaintEnginePrivate -{ - Q_DECLARE_PUBLIC(QX11PaintEngine) -public: - QX11PaintEnginePrivate() - { - scrn = -1; - hd = 0; - picture = 0; - gc = gc_brush = 0; - dpy = 0; - xinfo = 0; - txop = QTransform::TxNone; - has_clipping = false; - render_hints = 0; - xform_scale = 1; -#ifndef QT_NO_XRENDER - tessellator = 0; -#endif - } - enum GCMode { - PenGC, - BrushGC - }; - - void init(); - void fillPolygon_translated(const QPointF *points, int pointCount, GCMode gcMode, - QPaintEngine::PolygonDrawMode mode); - void fillPolygon_dev(const QPointF *points, int pointCount, GCMode gcMode, - QPaintEngine::PolygonDrawMode mode); - void fillPath(const QPainterPath &path, GCMode gcmode, bool transform); - void strokePolygon_dev(const QPointF *points, int pointCount, bool close); - void strokePolygon_translated(const QPointF *points, int pointCount, bool close); - void setupAdaptedOrigin(const QPoint &p); - void resetAdaptedOrigin(); - void decidePathFallback() { - use_path_fallback = has_alpha_brush - || has_alpha_pen - || has_custom_pen - || has_complex_xform - || (render_hints & QPainter::Antialiasing); - } - void decideCoordAdjust() { - adjust_coords = !(render_hints & QPainter::Antialiasing) - && (has_alpha_pen - || (has_alpha_brush && has_pen && !has_alpha_pen) - || (cpen.style() > Qt::SolidLine)); - } - void clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly); - void systemStateChanged(); - - Display *dpy; - int scrn; - int pdev_depth; - Qt::HANDLE hd; - QPixmap brush_pm; -#if !defined (QT_NO_XRENDER) - Qt::HANDLE picture; - Qt::HANDLE current_brush; - QPixmap bitmap_texture; - int composition_mode; -#else - Qt::HANDLE picture; -#endif - GC gc; - GC gc_brush; - - QPen cpen; - QBrush cbrush; - QRegion crgn; - QTransform matrix; - qreal opacity; - - uint has_complex_xform : 1; - uint has_scaling_xform : 1; - uint has_non_scaling_xform : 1; - uint has_custom_pen : 1; - uint use_path_fallback : 1; - uint adjust_coords : 1; - uint has_clipping : 1; - uint adapted_brush_origin : 1; - uint adapted_pen_origin : 1; - uint has_pen : 1; - uint has_brush : 1; - uint has_texture : 1; - uint has_alpha_texture : 1; - uint has_pattern : 1; - uint has_alpha_pen : 1; - uint has_alpha_brush : 1; - uint render_hints; - - const QX11Info *xinfo; - QPointF bg_origin; - QTransform::TransformationType txop; - qreal xform_scale; - QPolygonClipper<qt_float_point, qt_float_point, float> polygonClipper; - - int xlibMaxLinePoints; -#ifndef QT_NO_XRENDER - QXRenderTessellator *tessellator; -#endif -}; - -QT_END_NAMESPACE - -#endif // QPAINTENGINE_X11_P_H diff --git a/src/widgets/platforms/x11/qpixmap_x11.cpp b/src/widgets/platforms/x11/qpixmap_x11.cpp deleted file mode 100644 index 500d1e3ddf..0000000000 --- a/src/widgets/platforms/x11/qpixmap_x11.cpp +++ /dev/null @@ -1,2419 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// Uncomment the next line to enable the MIT Shared Memory extension -// -// WARNING: This has some problems: -// -// 1. Consumes a 800x600 pixmap -// 2. Qt does not handle the ShmCompletion message, so you will -// get strange effects if you xForm() repeatedly. -// -// #define QT_MITSHM - -#if defined(Q_OS_WIN32) && defined(QT_MITSHM) -#undef QT_MITSHM -#endif - -#include "qplatformdefs.h" - -#include "qdebug.h" -#include "qiodevice.h" -#include "qpixmap_x11_p.h" -#include "qbitmap.h" -#include "qcolormap.h" -#include "qimage.h" -#include "qmatrix.h" -#include "qapplication.h" -#include <private/qpaintengine_x11_p.h> -#include <private/qt_x11_p.h> -#include "qx11info_x11.h" -#include <private/qdrawhelper_p.h> -#include <private/qimage_p.h> -#include <private/qimagepixmapcleanuphooks_p.h> - -#include <stdlib.h> - -#if defined(Q_CC_MIPS) -# define for if(0){}else for -#endif - -QT_BEGIN_NAMESPACE - -QPixmap qt_toX11Pixmap(const QImage &image) -{ - QPlatformPixmap *data = - new QX11PlatformPixmap(image.depth() == 1 - ? QPlatformPixmap::BitmapType - : QPlatformPixmap::PixmapType); - - data->fromImage(image, Qt::AutoColor); - - return QPixmap(data); -} - -QPixmap qt_toX11Pixmap(const QPixmap &pixmap) -{ - if (pixmap.isNull()) - return QPixmap(); - - if (QPixmap(pixmap).data_ptr()->classId() == QPlatformPixmap::X11Class) - return pixmap; - - return qt_toX11Pixmap(pixmap.toImage()); -} - -// For thread-safety: -// image->data does not belong to X11, so we must free it ourselves. - -inline static void qSafeXDestroyImage(XImage *x) -{ - if (x->data) { - free(x->data); - x->data = 0; - } - XDestroyImage(x); -} - -QBitmap QX11PlatformPixmap::mask_to_bitmap(int screen) const -{ - if (!x11_mask) - return QBitmap(); - QPixmap::x11SetDefaultScreen(screen); - QBitmap bm(w, h); - GC gc = XCreateGC(X11->display, bm.handle(), 0, 0); - XCopyArea(X11->display, x11_mask, bm.handle(), gc, 0, 0, - bm.data->width(), bm.data->height(), 0, 0); - XFreeGC(X11->display, gc); - return bm; -} - -Qt::HANDLE QX11PlatformPixmap::bitmap_to_mask(const QBitmap &bitmap, int screen) -{ - if (bitmap.isNull()) - return 0; - QBitmap bm = bitmap; - bm.x11SetScreen(screen); - - Pixmap mask = XCreatePixmap(X11->display, RootWindow(X11->display, screen), - bm.data->width(), bm.data->height(), 1); - GC gc = XCreateGC(X11->display, mask, 0, 0); - XCopyArea(X11->display, bm.handle(), mask, gc, 0, 0, - bm.data->width(), bm.data->height(), 0, 0); - XFreeGC(X11->display, gc); - return mask; -} - - -/***************************************************************************** - MIT Shared Memory Extension support: makes xForm noticeably (~20%) faster. - *****************************************************************************/ - -#if defined(QT_MITSHM) - -static bool xshminit = false; -static XShmSegmentInfo xshminfo; -static XImage *xshmimg = 0; -static Pixmap xshmpm = 0; - -static void qt_cleanup_mitshm() -{ - if (xshmimg == 0) - return; - Display *dpy = QX11Info::appDisplay(); - if (xshmpm) { - XFreePixmap(dpy, xshmpm); - xshmpm = 0; - } - XShmDetach(dpy, &xshminfo); xshmimg->data = 0; - qSafeXDestroyImage(xshmimg); xshmimg = 0; - shmdt(xshminfo.shmaddr); - shmctl(xshminfo.shmid, IPC_RMID, 0); -} - -static bool qt_create_mitshm_buffer(const QPaintDevice* dev, int w, int h) -{ - static int major, minor; - static Bool pixmaps_ok; - Display *dpy = dev->data->xinfo->display(); - int dd = dev->x11Depth(); - Visual *vis = (Visual*)dev->x11Visual(); - - if (xshminit) { - qt_cleanup_mitshm(); - } else { - if (!XShmQueryVersion(dpy, &major, &minor, &pixmaps_ok)) - return false; // MIT Shm not supported - qAddPostRoutine(qt_cleanup_mitshm); - xshminit = true; - } - - xshmimg = XShmCreateImage(dpy, vis, dd, ZPixmap, 0, &xshminfo, w, h); - if (!xshmimg) - return false; - - bool ok; - xshminfo.shmid = shmget(IPC_PRIVATE, - xshmimg->bytes_per_line * xshmimg->height, - IPC_CREAT | 0777); - ok = xshminfo.shmid != -1; - if (ok) { - xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0); - xshminfo.shmaddr = xshmimg->data; - ok = (xshminfo.shmaddr != (char*)-1); - } - xshminfo.readOnly = false; - if (ok) - ok = XShmAttach(dpy, &xshminfo); - if (!ok) { - qSafeXDestroyImage(xshmimg); - xshmimg = 0; - if (xshminfo.shmaddr) - shmdt(xshminfo.shmaddr); - if (xshminfo.shmid != -1) - shmctl(xshminfo.shmid, IPC_RMID, 0); - return false; - } - if (pixmaps_ok) - xshmpm = XShmCreatePixmap(dpy, DefaultRootWindow(dpy), xshmimg->data, - &xshminfo, w, h, dd); - - return true; -} - -#else - -// If extern, need a dummy. -// -// static bool qt_create_mitshm_buffer(QPaintDevice*, int, int) -// { -// return false; -// } - -#endif // QT_MITSHM - - -/***************************************************************************** - Internal functions - *****************************************************************************/ - -extern const uchar *qt_get_bitflip_array(); // defined in qimage.cpp - -// Returns position of highest bit set or -1 if none -static int highest_bit(uint v) -{ - int i; - uint b = (uint)1 << 31; - for (i=31; ((b & v) == 0) && i>=0; i--) - b >>= 1; - return i; -} - -// Returns position of lowest set bit in 'v' as an integer (0-31), or -1 -static int lowest_bit(uint v) -{ - int i; - ulong lb; - lb = 1; - for (i=0; ((v & lb) == 0) && i<32; i++, lb<<=1) {} - return i==32 ? -1 : i; -} - -// Counts the number of bits set in 'v' -static uint n_bits(uint v) -{ - int i = 0; - while (v) { - v = v & (v - 1); - i++; - } - return i; -} - -static uint *red_scale_table = 0; -static uint *green_scale_table = 0; -static uint *blue_scale_table = 0; - -static void cleanup_scale_tables() -{ - delete[] red_scale_table; - delete[] green_scale_table; - delete[] blue_scale_table; -} - -/* - Could do smart bitshifting, but the "obvious" algorithm only works for - nBits >= 4. This is more robust. -*/ -static void build_scale_table(uint **table, uint nBits) -{ - if (nBits > 7) { - qWarning("build_scale_table: internal error, nBits = %i", nBits); - return; - } - if (!*table) { - static bool firstTable = true; - if (firstTable) { - qAddPostRoutine(cleanup_scale_tables); - firstTable = false; - } - *table = new uint[256]; - } - int maxVal = (1 << nBits) - 1; - int valShift = 8 - nBits; - int i; - for(i = 0 ; i < maxVal + 1 ; i++) - (*table)[i << valShift] = i*255/maxVal; -} - -static int defaultScreen = -1; - -/***************************************************************************** - QPixmap member functions - *****************************************************************************/ - -QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0); -int Q_WIDGETS_EXPORT qt_x11_preferred_pixmap_depth = 0; - -QX11PlatformPixmap::QX11PlatformPixmap(PixelType type) - : QPlatformPixmap(type, X11Class), gl_surface(0), hd(0), - flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), - share_mode(QPixmap::ImplicitlyShared), pengine(0) -{ -} - -QPlatformPixmap *QX11PlatformPixmap::createCompatiblePlatformPixmap() const -{ - return new QX11PlatformPixmap(pixelType()); -} - -void QX11PlatformPixmap::resize(int width, int height) -{ - setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); - - w = width; - h = height; - is_null = (w <= 0 || h <= 0); - - if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) { - QX11InfoData* xd = xinfo.getX11Data(true); - xd->screen = defaultScreen; - xd->depth = QX11Info::appDepth(xd->screen); - xd->cells = QX11Info::appCells(xd->screen); - xd->colormap = QX11Info::appColormap(xd->screen); - xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen); - xd->visual = (Visual *)QX11Info::appVisual(xd->screen); - xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen); - xinfo.setX11Data(xd); - } - - int dd = xinfo.depth(); - - if (qt_x11_preferred_pixmap_depth) - dd = qt_x11_preferred_pixmap_depth; - - bool make_null = w <= 0 || h <= 0; // create null pixmap - d = (pixelType() == BitmapType ? 1 : dd); - if (make_null || d == 0) { - w = 0; - h = 0; - is_null = true; - hd = 0; - picture = 0; - d = 0; - if (!make_null) - qWarning("QPixmap: Invalid pixmap parameters"); - return; - } - hd = (Qt::HANDLE)XCreatePixmap(X11->display, - RootWindow(X11->display, xinfo.screen()), - w, h, d); -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - XRenderPictFormat *format = d == 1 - ? XRenderFindStandardFormat(X11->display, PictStandardA1) - : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual()); - picture = XRenderCreatePicture(X11->display, hd, format, 0, 0); - } -#endif // QT_NO_XRENDER -} - -struct QX11AlphaDetector -{ - bool hasAlpha() const { - if (checked) - return has; - // Will implicitly also check format and return quickly for opaque types... - checked = true; - has = image->isNull() ? false : const_cast<QImage *>(image)->data_ptr()->checkForAlphaPixels(); - return has; - } - - bool hasXRenderAndAlpha() const { - if (!X11->use_xrender) - return false; - return hasAlpha(); - } - - QX11AlphaDetector(const QImage *i, Qt::ImageConversionFlags flags) - : image(i), checked(false), has(false) - { - if (flags & Qt::NoOpaqueDetection) { - checked = true; - has = image->hasAlphaChannel(); - } - } - - const QImage *image; - mutable bool checked; - mutable bool has; -}; - -void QX11PlatformPixmap::fromImage(const QImage &img, - Qt::ImageConversionFlags flags) -{ - setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); - - w = img.width(); - h = img.height(); - d = img.depth(); - is_null = (w <= 0 || h <= 0); - - if (is_null) { - w = h = 0; - return; - } - - if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) { - QX11InfoData* xd = xinfo.getX11Data(true); - xd->screen = defaultScreen; - xd->depth = QX11Info::appDepth(xd->screen); - xd->cells = QX11Info::appCells(xd->screen); - xd->colormap = QX11Info::appColormap(xd->screen); - xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen); - xd->visual = (Visual *)QX11Info::appVisual(xd->screen); - xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen); - xinfo.setX11Data(xd); - } - - if (pixelType() == BitmapType) { - bitmapFromImage(img); - return; - } - - if (uint(w) >= 32768 || uint(h) >= 32768) { - w = h = 0; - is_null = true; - return; - } - - QX11AlphaDetector alphaCheck(&img, flags); - int dd = alphaCheck.hasXRenderAndAlpha() ? 32 : xinfo.depth(); - - if (qt_x11_preferred_pixmap_depth) - dd = qt_x11_preferred_pixmap_depth; - - QImage image = img; - - // must be monochrome - if (dd == 1 || (flags & Qt::ColorMode_Mask) == Qt::MonoOnly) { - if (d != 1) { - // dither - image = image.convertToFormat(QImage::Format_MonoLSB, flags); - d = 1; - } - } else { // can be both - bool conv8 = false; - if (d > 8 && dd <= 8) { // convert to 8 bit - if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither) - flags = (flags & ~Qt::DitherMode_Mask) - | Qt::PreferDither; - conv8 = true; - } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) { - conv8 = (d == 1); // native depth wanted - } else if (d == 1) { - if (image.colorCount() == 2) { - QRgb c0 = image.color(0); // Auto: convert to best - QRgb c1 = image.color(1); - conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255); - } else { - // eg. 1-color monochrome images (they do exist). - conv8 = true; - } - } - if (conv8) { - image = image.convertToFormat(QImage::Format_Indexed8, flags); - d = 8; - } - } - - if (d == 1 || d == 16 || d == 24) { - image = image.convertToFormat(QImage::Format_RGB32, flags); - fromImage(image, Qt::AutoColor); - return; - } - - Display *dpy = X11->display; - Visual *visual = (Visual *)xinfo.visual(); - XImage *xi = 0; - bool trucol = (visual->c_class >= TrueColor); - int nbytes = image.byteCount(); - uchar *newbits= 0; - -#ifndef QT_NO_XRENDER - if (alphaCheck.hasXRenderAndAlpha()) { - const QImage &cimage = image; - - d = 32; - - if (QX11Info::appDepth() != d) { - if (xinfo.x11data) { - xinfo.x11data->depth = d; - } else { - QX11InfoData *xd = xinfo.getX11Data(true); - xd->screen = QX11Info::appScreen(); - xd->depth = d; - xd->cells = QX11Info::appCells(); - xd->colormap = QX11Info::appColormap(); - xd->defaultColormap = QX11Info::appDefaultColormap(); - xd->visual = (Visual *)QX11Info::appVisual(); - xd->defaultVisual = QX11Info::appDefaultVisual(); - xinfo.setX11Data(xd); - } - } - - hd = (Qt::HANDLE)XCreatePixmap(dpy, RootWindow(dpy, xinfo.screen()), - w, h, d); - picture = XRenderCreatePicture(X11->display, hd, - XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0); - - xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0); - Q_CHECK_PTR(xi); - newbits = (uchar *)malloc(xi->bytes_per_line*h); - Q_CHECK_PTR(newbits); - xi->data = (char *)newbits; - - switch(cimage.format()) { - case QImage::Format_Indexed8: { - QVector<QRgb> colorTable = cimage.colorTable(); - uint *xidata = (uint *)xi->data; - for (int y = 0; y < h; ++y) { - const uchar *p = cimage.scanLine(y); - for (int x = 0; x < w; ++x) { - const QRgb rgb = colorTable[p[x]]; - const int a = qAlpha(rgb); - if (a == 0xff) - *xidata = rgb; - else - // RENDER expects premultiplied alpha - *xidata = qRgba(qt_div_255(qRed(rgb) * a), - qt_div_255(qGreen(rgb) * a), - qt_div_255(qBlue(rgb) * a), - a); - ++xidata; - } - } - } - break; - case QImage::Format_RGB32: { - uint *xidata = (uint *)xi->data; - for (int y = 0; y < h; ++y) { - const QRgb *p = (const QRgb *) cimage.scanLine(y); - for (int x = 0; x < w; ++x) - *xidata++ = p[x] | 0xff000000; - } - } - break; - case QImage::Format_ARGB32: { - uint *xidata = (uint *)xi->data; - for (int y = 0; y < h; ++y) { - const QRgb *p = (const QRgb *) cimage.scanLine(y); - for (int x = 0; x < w; ++x) { - const QRgb rgb = p[x]; - const int a = qAlpha(rgb); - if (a == 0xff) - *xidata = rgb; - else - // RENDER expects premultiplied alpha - *xidata = qRgba(qt_div_255(qRed(rgb) * a), - qt_div_255(qGreen(rgb) * a), - qt_div_255(qBlue(rgb) * a), - a); - ++xidata; - } - } - - } - break; - case QImage::Format_ARGB32_Premultiplied: { - uint *xidata = (uint *)xi->data; - for (int y = 0; y < h; ++y) { - const QRgb *p = (const QRgb *) cimage.scanLine(y); - memcpy(xidata, p, w*sizeof(QRgb)); - xidata += w; - } - } - break; - default: - Q_ASSERT(false); - } - - if ((xi->byte_order == MSBFirst) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) { - uint *xidata = (uint *)xi->data; - uint *xiend = xidata + w*h; - while (xidata < xiend) { - *xidata = (*xidata >> 24) - | ((*xidata >> 8) & 0xff00) - | ((*xidata << 8) & 0xff0000) - | (*xidata << 24); - ++xidata; - } - } - - GC gc = XCreateGC(dpy, hd, 0, 0); - XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h); - XFreeGC(dpy, gc); - - qSafeXDestroyImage(xi); - - return; - } -#endif // QT_NO_XRENDER - - if (trucol) { // truecolor display - if (image.format() == QImage::Format_ARGB32_Premultiplied) - image = image.convertToFormat(QImage::Format_ARGB32); - - const QImage &cimage = image; - QRgb pix[256]; // pixel translation table - const bool d8 = (d == 8); - const uint red_mask = (uint)visual->red_mask; - const uint green_mask = (uint)visual->green_mask; - const uint blue_mask = (uint)visual->blue_mask; - const int red_shift = highest_bit(red_mask) - 7; - const int green_shift = highest_bit(green_mask) - 7; - const int blue_shift = highest_bit(blue_mask) - 7; - const uint rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1; - const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1; - const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1; - - if (d8) { // setup pixel translation - QVector<QRgb> ctable = cimage.colorTable(); - for (int i=0; i < cimage.colorCount(); i++) { - int r = qRed (ctable[i]); - int g = qGreen(ctable[i]); - int b = qBlue (ctable[i]); - r = red_shift > 0 ? r << red_shift : r >> -red_shift; - g = green_shift > 0 ? g << green_shift : g >> -green_shift; - b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift; - pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask) - | ~(blue_mask | green_mask | red_mask); - } - } - - xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0); - Q_CHECK_PTR(xi); - newbits = (uchar *)malloc(xi->bytes_per_line*h); - Q_CHECK_PTR(newbits); - if (!newbits) // no memory - return; - int bppc = xi->bits_per_pixel; - - bool contig_bits = n_bits(red_mask) == rbits && - n_bits(green_mask) == gbits && - n_bits(blue_mask) == bbits; - bool dither_tc = - // Want it? - (flags & Qt::Dither_Mask) != Qt::ThresholdDither && - (flags & Qt::DitherMode_Mask) != Qt::AvoidDither && - // Need it? - bppc < 24 && !d8 && - // Can do it? (Contiguous bits?) - contig_bits; - - static bool init=false; - static int D[16][16]; - if (dither_tc && !init) { - // I also contributed this code to XV - WWA. - /* - The dither matrix, D, is obtained with this formula: - - D2 = [0 2] - [3 1] - - - D2*n = [4*Dn 4*Dn+2*Un] - [4*Dn+3*Un 4*Dn+1*Un] - */ - int n,i,j; - init=1; - - /* Set D2 */ - D[0][0]=0; - D[1][0]=2; - D[0][1]=3; - D[1][1]=1; - - /* Expand using recursive definition given above */ - for (n=2; n<16; n*=2) { - for (i=0; i<n; i++) { - for (j=0; j<n; j++) { - D[i][j]*=4; - D[i+n][j]=D[i][j]+2; - D[i][j+n]=D[i][j]+3; - D[i+n][j+n]=D[i][j]+1; - } - } - } - init=true; - } - - enum { BPP8, - BPP16_565, BPP16_555, - BPP16_MSB, BPP16_LSB, - BPP24_888, - BPP24_MSB, BPP24_LSB, - BPP32_8888, - BPP32_MSB, BPP32_LSB - } mode = BPP8; - - bool same_msb_lsb = (xi->byte_order == MSBFirst) == (QSysInfo::ByteOrder == QSysInfo::BigEndian); - - if(bppc == 8) // 8 bit - mode = BPP8; - else if(bppc == 16) { // 16 bit MSB/LSB - if(red_shift == 8 && green_shift == 3 && blue_shift == -3 && !d8 && same_msb_lsb) - mode = BPP16_565; - else if(red_shift == 7 && green_shift == 2 && blue_shift == -3 && !d8 && same_msb_lsb) - mode = BPP16_555; - else - mode = (xi->byte_order == LSBFirst) ? BPP16_LSB : BPP16_MSB; - } else if(bppc == 24) { // 24 bit MSB/LSB - if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb) - mode = BPP24_888; - else - mode = (xi->byte_order == LSBFirst) ? BPP24_LSB : BPP24_MSB; - } else if(bppc == 32) { // 32 bit MSB/LSB - if(red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb) - mode = BPP32_8888; - else - mode = (xi->byte_order == LSBFirst) ? BPP32_LSB : BPP32_MSB; - } else - qFatal("Logic error 3"); - -#define GET_PIXEL \ - uint pixel; \ - if (d8) pixel = pix[*src++]; \ - else { \ - int r = qRed (*p); \ - int g = qGreen(*p); \ - int b = qBlue (*p++); \ - r = red_shift > 0 \ - ? r << red_shift : r >> -red_shift; \ - g = green_shift > 0 \ - ? g << green_shift : g >> -green_shift; \ - b = blue_shift > 0 \ - ? b << blue_shift : b >> -blue_shift; \ - pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \ - | ~(blue_mask | green_mask | red_mask); \ - } - -#define GET_PIXEL_DITHER_TC \ - int r = qRed (*p); \ - int g = qGreen(*p); \ - int b = qBlue (*p++); \ - const int thres = D[x%16][y%16]; \ - if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \ - > thres) \ - r += (1<<(8-rbits)); \ - if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \ - > thres) \ - g += (1<<(8-gbits)); \ - if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \ - > thres) \ - b += (1<<(8-bbits)); \ - r = red_shift > 0 \ - ? r << red_shift : r >> -red_shift; \ - g = green_shift > 0 \ - ? g << green_shift : g >> -green_shift; \ - b = blue_shift > 0 \ - ? b << blue_shift : b >> -blue_shift; \ - uint pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask); - -// again, optimized case -// can't be optimized that much :( -#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \ - rbits,gbits,bbits) \ - const int thres = D[x%16][y%16]; \ - int r = qRed (*p); \ - if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \ - > thres) \ - r += (1<<(8-rbits)); \ - int g = qGreen(*p); \ - if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \ - > thres) \ - g += (1<<(8-gbits)); \ - int b = qBlue (*p++); \ - if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \ - > thres) \ - b += (1<<(8-bbits)); \ - uint pixel = ((r red_shift) & red_mask) \ - | ((g green_shift) & green_mask) \ - | ((b blue_shift) & blue_mask); - -#define CYCLE(body) \ - for (int y=0; y<h; y++) { \ - const uchar* src = cimage.scanLine(y); \ - uchar* dst = newbits + xi->bytes_per_line*y; \ - const QRgb* p = (const QRgb *)src; \ - body \ - } - - if (dither_tc) { - switch (mode) { - case BPP16_565: - CYCLE( - quint16* dst16 = (quint16*)dst; - for (int x=0; x<w; x++) { - GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5) - *dst16++ = pixel; - } - ) - break; - case BPP16_555: - CYCLE( - quint16* dst16 = (quint16*)dst; - for (int x=0; x<w; x++) { - GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5) - *dst16++ = pixel; - } - ) - break; - case BPP16_MSB: // 16 bit MSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL_DITHER_TC - *dst++ = (pixel >> 8); - *dst++ = pixel; - } - ) - break; - case BPP16_LSB: // 16 bit LSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL_DITHER_TC - *dst++ = pixel; - *dst++ = pixel >> 8; - } - ) - break; - default: - qFatal("Logic error"); - } - } else { - switch (mode) { - case BPP8: // 8 bit - CYCLE( - Q_UNUSED(p); - for (int x=0; x<w; x++) - *dst++ = pix[*src++]; - ) - break; - case BPP16_565: - CYCLE( - quint16* dst16 = (quint16*)dst; - for (int x = 0; x < w; x++) { - *dst16++ = ((*p >> 8) & 0xf800) - | ((*p >> 5) & 0x7e0) - | ((*p >> 3) & 0x1f); - ++p; - } - ) - break; - case BPP16_555: - CYCLE( - quint16* dst16 = (quint16*)dst; - for (int x=0; x<w; x++) { - *dst16++ = ((*p >> 9) & 0x7c00) - | ((*p >> 6) & 0x3e0) - | ((*p >> 3) & 0x1f); - ++p; - } - ) - break; - case BPP16_MSB: // 16 bit MSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL - *dst++ = (pixel >> 8); - *dst++ = pixel; - } - ) - break; - case BPP16_LSB: // 16 bit LSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL - *dst++ = pixel; - *dst++ = pixel >> 8; - } - ) - break; - case BPP24_888: // 24 bit MSB - CYCLE( - for (int x=0; x<w; x++) { - *dst++ = qRed (*p); - *dst++ = qGreen(*p); - *dst++ = qBlue (*p++); - } - ) - break; - case BPP24_MSB: // 24 bit MSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL - *dst++ = pixel >> 16; - *dst++ = pixel >> 8; - *dst++ = pixel; - } - ) - break; - case BPP24_LSB: // 24 bit LSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL - *dst++ = pixel; - *dst++ = pixel >> 8; - *dst++ = pixel >> 16; - } - ) - break; - case BPP32_8888: - CYCLE( - memcpy(dst, p, w * 4); - ) - break; - case BPP32_MSB: // 32 bit MSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL - *dst++ = pixel >> 24; - *dst++ = pixel >> 16; - *dst++ = pixel >> 8; - *dst++ = pixel; - } - ) - break; - case BPP32_LSB: // 32 bit LSB - CYCLE( - for (int x=0; x<w; x++) { - GET_PIXEL - *dst++ = pixel; - *dst++ = pixel >> 8; - *dst++ = pixel >> 16; - *dst++ = pixel >> 24; - } - ) - break; - default: - qFatal("Logic error 2"); - } - } - xi->data = (char *)newbits; - } - - if (d == 8 && !trucol) { // 8 bit pixmap - int pop[256]; // pixel popularity - - if (image.colorCount() == 0) - image.setColorCount(1); - - const QImage &cimage = image; - memset(pop, 0, sizeof(int)*256); // reset popularity array - for (int i = 0; i < h; i++) { // for each scanline... - const uchar* p = cimage.scanLine(i); - const uchar *end = p + w; - while (p < end) // compute popularity - pop[*p++]++; - } - - newbits = (uchar *)malloc(nbytes); // copy image into newbits - Q_CHECK_PTR(newbits); - if (!newbits) // no memory - return; - uchar* p = newbits; - memcpy(p, cimage.bits(), nbytes); // copy image data into newbits - - /* - * The code below picks the most important colors. It is based on the - * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley. - */ - - struct PIX { // pixel sort element - uchar r,g,b,n; // color + pad - int use; // popularity - int index; // index in colormap - int mindist; - }; - int ncols = 0; - for (int i=0; i< cimage.colorCount(); i++) { // compute number of colors - if (pop[i] > 0) - ncols++; - } - for (int i = cimage.colorCount(); i < 256; i++) // ignore out-of-range pixels - pop[i] = 0; - - // works since we make sure above to have at least - // one color in the image - if (ncols == 0) - ncols = 1; - - PIX pixarr[256]; // pixel array - PIX pixarr_sorted[256]; // pixel array (sorted) - memset(pixarr, 0, ncols*sizeof(PIX)); - PIX *px = &pixarr[0]; - int maxpop = 0; - int maxpix = 0; - uint j = 0; - QVector<QRgb> ctable = cimage.colorTable(); - for (int i = 0; i < 256; i++) { // init pixel array - if (pop[i] > 0) { - px->r = qRed (ctable[i]); - px->g = qGreen(ctable[i]); - px->b = qBlue (ctable[i]); - px->n = 0; - px->use = pop[i]; - if (pop[i] > maxpop) { // select most popular entry - maxpop = pop[i]; - maxpix = j; - } - px->index = i; - px->mindist = 1000000; - px++; - j++; - } - } - pixarr_sorted[0] = pixarr[maxpix]; - pixarr[maxpix].use = 0; - - for (int i = 1; i < ncols; i++) { // sort pixels - int minpix = -1, mindist = -1; - px = &pixarr_sorted[i-1]; - int r = px->r; - int g = px->g; - int b = px->b; - int dist; - if ((i & 1) || i<10) { // sort on max distance - for (int j=0; j<ncols; j++) { - px = &pixarr[j]; - if (px->use) { - dist = (px->r - r)*(px->r - r) + - (px->g - g)*(px->g - g) + - (px->b - b)*(px->b - b); - if (px->mindist > dist) - px->mindist = dist; - if (px->mindist > mindist) { - mindist = px->mindist; - minpix = j; - } - } - } - } else { // sort on max popularity - for (int j=0; j<ncols; j++) { - px = &pixarr[j]; - if (px->use) { - dist = (px->r - r)*(px->r - r) + - (px->g - g)*(px->g - g) + - (px->b - b)*(px->b - b); - if (px->mindist > dist) - px->mindist = dist; - if (px->use > mindist) { - mindist = px->use; - minpix = j; - } - } - } - } - pixarr_sorted[i] = pixarr[minpix]; - pixarr[minpix].use = 0; - } - - QColormap cmap = QColormap::instance(xinfo.screen()); - uint pix[256]; // pixel translation table - px = &pixarr_sorted[0]; - for (int i = 0; i < ncols; i++) { // allocate colors - QColor c(px->r, px->g, px->b); - pix[px->index] = cmap.pixel(c); - px++; - } - - p = newbits; - for (int i = 0; i < nbytes; i++) { // translate pixels - *p = pix[*p]; - p++; - } - } - - if (!xi) { // X image not created - xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0); - if (xi->bits_per_pixel == 16) { // convert 8 bpp ==> 16 bpp - ushort *p2; - int p2inc = xi->bytes_per_line/sizeof(ushort); - ushort *newerbits = (ushort *)malloc(xi->bytes_per_line * h); - Q_CHECK_PTR(newerbits); - if (!newerbits) // no memory - return; - uchar* p = newbits; - for (int y = 0; y < h; y++) { // OOPS: Do right byte order!! - p2 = newerbits + p2inc*y; - for (int x = 0; x < w; x++) - *p2++ = *p++; - } - free(newbits); - newbits = (uchar *)newerbits; - } else if (xi->bits_per_pixel != 8) { - qWarning("QPixmap::fromImage: Display not supported " - "(bpp=%d)", xi->bits_per_pixel); - } - xi->data = (char *)newbits; - } - - hd = (Qt::HANDLE)XCreatePixmap(X11->display, - RootWindow(X11->display, xinfo.screen()), - w, h, dd); - - GC gc = XCreateGC(dpy, hd, 0, 0); - XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h); - XFreeGC(dpy, gc); - - qSafeXDestroyImage(xi); - d = dd; - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - XRenderPictFormat *format = d == 1 - ? XRenderFindStandardFormat(X11->display, PictStandardA1) - : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual()); - picture = XRenderCreatePicture(X11->display, hd, format, 0, 0); - } -#endif - - if (alphaCheck.hasAlpha()) { - QBitmap m = QBitmap::fromImage(image.createAlphaMask(flags)); - setMask(m); - } -} - -Qt::HANDLE QX11PlatformPixmap::createBitmapFromImage(const QImage &image) -{ - QImage img = image.convertToFormat(QImage::Format_MonoLSB); - const QRgb c0 = QColor(Qt::black).rgb(); - const QRgb c1 = QColor(Qt::white).rgb(); - if (img.color(0) == c0 && img.color(1) == c1) { - img.invertPixels(); - img.setColor(0, c1); - img.setColor(1, c0); - } - - char *bits; - uchar *tmp_bits; - int w = img.width(); - int h = img.height(); - int bpl = (w + 7) / 8; - int ibpl = img.bytesPerLine(); - if (bpl != ibpl) { - tmp_bits = new uchar[bpl*h]; - bits = (char *)tmp_bits; - uchar *p, *b; - int y; - b = tmp_bits; - p = img.scanLine(0); - for (y = 0; y < h; y++) { - memcpy(b, p, bpl); - b += bpl; - p += ibpl; - } - } else { - bits = (char *)img.bits(); - tmp_bits = 0; - } - Qt::HANDLE hd = (Qt::HANDLE)XCreateBitmapFromData(X11->display, - QX11Info::appRootWindow(), - bits, w, h); - if (tmp_bits) // Avoid purify complaint - delete [] tmp_bits; - return hd; -} - -void QX11PlatformPixmap::bitmapFromImage(const QImage &image) -{ - w = image.width(); - h = image.height(); - d = 1; - is_null = (w <= 0 || h <= 0); - hd = createBitmapFromImage(image); -#ifndef QT_NO_XRENDER - if (X11->use_xrender) - picture = XRenderCreatePicture(X11->display, hd, - XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0); -#endif // QT_NO_XRENDER -} - -void QX11PlatformPixmap::fill(const QColor &fillColor) -{ - if (fillColor.alpha() != 255) { -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - if (!picture || d != 32) - convertToARGB32(/*preserveContents = */false); - - ::Picture src = X11->getSolidFill(xinfo.screen(), fillColor); - XRenderComposite(X11->display, PictOpSrc, src, 0, picture, - 0, 0, width(), height(), - 0, 0, width(), height()); - } else -#endif - { - QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied); - im.fill(PREMUL(fillColor.rgba())); - release(); - fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither); - } - return; - } - - GC gc = XCreateGC(X11->display, hd, 0, 0); - if (depth() == 1) { - XSetForeground(X11->display, gc, qGray(fillColor.rgb()) > 127 ? 0 : 1); - } else if (X11->use_xrender && d >= 24) { - XSetForeground(X11->display, gc, fillColor.rgba()); - } else { - XSetForeground(X11->display, gc, - QColormap::instance(xinfo.screen()).pixel(fillColor)); - } - XFillRectangle(X11->display, hd, gc, 0, 0, width(), height()); - XFreeGC(X11->display, gc); -} - -QX11PlatformPixmap::~QX11PlatformPixmap() -{ - // Cleanup hooks have to be called before the handles are freed - if (is_cached) { - QImagePixmapCleanupHooks::executePlatformPixmapDestructionHooks(this); - is_cached = false; - } - - release(); -} - -void QX11PlatformPixmap::release() -{ - delete pengine; - pengine = 0; - - if (!X11) { - // At this point, the X server will already have freed our resources, - // so there is nothing to do. - return; - } - - if (x11_mask) { -#ifndef QT_NO_XRENDER - if (mask_picture) - XRenderFreePicture(X11->display, mask_picture); - mask_picture = 0; -#endif - XFreePixmap(X11->display, x11_mask); - x11_mask = 0; - } - - if (hd) { -#ifndef QT_NO_XRENDER - if (picture) { - XRenderFreePicture(X11->display, picture); - picture = 0; - } -#endif // QT_NO_XRENDER - - if (hd2) { - XFreePixmap(xinfo.display(), hd2); - hd2 = 0; - } - if (!(flags & Readonly)) - XFreePixmap(xinfo.display(), hd); - hd = 0; - } -} - -QPixmap QX11PlatformPixmap::alphaChannel() const -{ - if (!hasAlphaChannel()) { - QPixmap pm(w, h); - pm.fill(Qt::white); - return pm; - } - QImage im(toImage()); - return QPixmap::fromImage(im.alphaChannel(), Qt::OrderedDither); -} - -void QX11PlatformPixmap::setAlphaChannel(const QPixmap &alpha) -{ - QImage image(toImage()); - image.setAlphaChannel(alpha.toImage()); - release(); - fromImage(image, Qt::OrderedDither | Qt::OrderedAlphaDither); -} - - -QBitmap QX11PlatformPixmap::mask() const -{ - QBitmap mask; -#ifndef QT_NO_XRENDER - if (picture && d == 32) { - // #### slow - there must be a better way.. - mask = QBitmap::fromImage(toImage().createAlphaMask()); - } else -#endif - if (d == 1) { - QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this); - mask = QPixmap(that); - } else { - mask = mask_to_bitmap(xinfo.screen()); - } - return mask; -} - -/*! - Sets a mask bitmap. - - The \a newmask bitmap defines the clip mask for this pixmap. Every - pixel in \a newmask corresponds to a pixel in this pixmap. Pixel - value 1 means opaque and pixel value 0 means transparent. The mask - must have the same size as this pixmap. - - \warning Setting the mask on a pixmap will cause any alpha channel - data to be cleared. For example: - \snippet doc/src/snippets/image/image.cpp 2 - Now, alpha and alphacopy are visually different. - - Setting a null mask resets the mask. - - The effect of this function is undefined when the pixmap is being - painted on. - - \sa mask(), {QPixmap#Pixmap Transformations}{Pixmap - Transformations}, QBitmap -*/ -void QX11PlatformPixmap::setMask(const QBitmap &newmask) -{ - if (newmask.isNull()) { // clear mask -#ifndef QT_NO_XRENDER - if (picture && d == 32) { - QX11PlatformPixmap newData(pixelType()); - newData.resize(w, h); - newData.fill(Qt::black); - XRenderComposite(X11->display, PictOpOver, - picture, 0, newData.picture, - 0, 0, 0, 0, 0, 0, w, h); - release(); - *this = newData; - // the new QX11PlatformPixmap object isn't referenced yet, so - // ref it - ref.ref(); - - // the below is to make sure the QX11PlatformPixmap destructor - // doesn't delete our newly created render picture - newData.hd = 0; - newData.x11_mask = 0; - newData.picture = 0; - newData.mask_picture = 0; - newData.hd2 = 0; - } else -#endif - if (x11_mask) { -#ifndef QT_NO_XRENDER - if (picture) { - XRenderPictureAttributes attrs; - attrs.alpha_map = 0; - XRenderChangePicture(X11->display, picture, CPAlphaMap, - &attrs); - } - if (mask_picture) - XRenderFreePicture(X11->display, mask_picture); - mask_picture = 0; -#endif - XFreePixmap(X11->display, x11_mask); - x11_mask = 0; - } - return; - } - -#ifndef QT_NO_XRENDER - if (picture && d == 32) { - XRenderComposite(X11->display, PictOpSrc, - picture, newmask.x11PictureHandle(), - picture, 0, 0, 0, 0, 0, 0, w, h); - } else -#endif - if (depth() == 1) { - XGCValues vals; - vals.function = GXand; - GC gc = XCreateGC(X11->display, hd, GCFunction, &vals); - XCopyArea(X11->display, newmask.handle(), hd, gc, 0, 0, - width(), height(), 0, 0); - XFreeGC(X11->display, gc); - } else { - // ##### should or the masks together - if (x11_mask) { - XFreePixmap(X11->display, x11_mask); -#ifndef QT_NO_XRENDER - if (mask_picture) - XRenderFreePicture(X11->display, mask_picture); -#endif - } - x11_mask = QX11PlatformPixmap::bitmap_to_mask(newmask, xinfo.screen()); -#ifndef QT_NO_XRENDER - if (picture) { - mask_picture = XRenderCreatePicture(X11->display, x11_mask, - XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0); - XRenderPictureAttributes attrs; - attrs.alpha_map = mask_picture; - XRenderChangePicture(X11->display, picture, CPAlphaMap, &attrs); - } -#endif - } -} - -int QX11PlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const -{ - switch (metric) { - case QPaintDevice::PdmWidth: - return w; - case QPaintDevice::PdmHeight: - return h; - case QPaintDevice::PdmNumColors: - return 1 << d; - case QPaintDevice::PdmDepth: - return d; - case QPaintDevice::PdmWidthMM: { - const int screen = xinfo.screen(); - const int mm = DisplayWidthMM(X11->display, screen) * w - / DisplayWidth(X11->display, screen); - return mm; - } - case QPaintDevice::PdmHeightMM: { - const int screen = xinfo.screen(); - const int mm = (DisplayHeightMM(X11->display, screen) * h) - / DisplayHeight(X11->display, screen); - return mm; - } - case QPaintDevice::PdmDpiX: - case QPaintDevice::PdmPhysicalDpiX: - return QX11Info::appDpiX(xinfo.screen()); - case QPaintDevice::PdmDpiY: - case QPaintDevice::PdmPhysicalDpiY: - return QX11Info::appDpiY(xinfo.screen()); - default: - qWarning("QX11PlatformPixmap::metric(): Invalid metric"); - return 0; - } -} - -struct QXImageWrapper -{ - XImage *xi; -}; - -bool QX11PlatformPixmap::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const -{ - XImage *xi = xiWrapper.xi; - - // ARGB32_Premultiplied - if (picture && depth() == 32) - return true; - - Visual *visual = (Visual *)xinfo.visual(); - - // RGB32 - if (depth() == 24 && xi->bits_per_pixel == 32 && visual->red_mask == 0xff0000 - && visual->green_mask == 0xff00 && visual->blue_mask == 0xff) - return true; - - // RGB16 - if (depth() == 16 && xi->bits_per_pixel == 16 && visual->red_mask == 0xf800 - && visual->green_mask == 0x7e0 && visual->blue_mask == 0x1f) - return true; - - return false; -} - -QImage QX11PlatformPixmap::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const -{ - XImage *xi = xiWrapper.xi; - - QImage::Format format = QImage::Format_ARGB32_Premultiplied; - if (depth() == 24) - format = QImage::Format_RGB32; - else if (depth() == 16) - format = QImage::Format_RGB16; - - QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format); - // take ownership - image.data_ptr()->own_data = true; - xi->data = 0; - - // we may have to swap the byte order - if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) - || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) - { - for (int i=0; i < image.height(); i++) { - if (depth() == 16) { - ushort *p = (ushort*)image.scanLine(i); - ushort *end = p + image.width(); - while (p < end) { - *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); - p++; - } - } else { - uint *p = (uint*)image.scanLine(i); - uint *end = p + image.width(); - while (p < end) { - *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) - | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); - p++; - } - } - } - } - - // fix-up alpha channel - if (format == QImage::Format_RGB32) { - QRgb *p = (QRgb *)image.bits(); - for (int y = 0; y < xi->height; ++y) { - for (int x = 0; x < xi->width; ++x) - p[x] |= 0xff000000; - p += xi->bytes_per_line / 4; - } - } - - XDestroyImage(xi); - return image; -} - -QImage QX11PlatformPixmap::toImage(const QRect &rect) const -{ - QXImageWrapper xiWrapper; - xiWrapper.xi = XGetImage(X11->display, hd, rect.x(), rect.y(), rect.width(), rect.height(), - AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap); - - Q_CHECK_PTR(xiWrapper.xi); - if (!xiWrapper.xi) - return QImage(); - - if (!x11_mask && canTakeQImageFromXImage(xiWrapper)) - return takeQImageFromXImage(xiWrapper); - - QImage image = toImage(xiWrapper, rect); - qSafeXDestroyImage(xiWrapper.xi); - return image; -} - -/*! - Converts the pixmap to a QImage. Returns a null image if the - conversion fails. - - If the pixmap has 1-bit depth, the returned image will also be 1 - bit deep. If the pixmap has 2- to 8-bit depth, the returned image - has 8-bit depth. If the pixmap has greater than 8-bit depth, the - returned image has 32-bit depth. - - Note that for the moment, alpha masks on monochrome images are - ignored. - - \sa fromImage(), {QImage#Image Formats}{Image Formats} -*/ - -QImage QX11PlatformPixmap::toImage() const -{ - return toImage(QRect(0, 0, w, h)); -} - -QImage QX11PlatformPixmap::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const -{ - XImage *xi = xiWrapper.xi; - - int d = depth(); - Visual *visual = (Visual *)xinfo.visual(); - bool trucol = (visual->c_class >= TrueColor) && d > 1; - - QImage::Format format = QImage::Format_Mono; - if (d > 1 && d <= 8) { - d = 8; - format = QImage::Format_Indexed8; - } - // we could run into the situation where d == 8 AND trucol is true, which can - // cause problems when converting to and from images. in this case, always treat - // the depth as 32... - if (d > 8 || trucol) { - d = 32; - format = QImage::Format_RGB32; - } - - if (d == 1 && xi->bitmap_bit_order == LSBFirst) - format = QImage::Format_MonoLSB; - if (x11_mask && format == QImage::Format_RGB32) - format = QImage::Format_ARGB32; - - QImage image(xi->width, xi->height, format); - if (image.isNull()) // could not create image - return image; - - QImage alpha; - if (x11_mask) { - if (rect.contains(QRect(0, 0, w, h))) - alpha = mask().toImage(); - else - alpha = mask().toImage().copy(rect); - } - bool ale = alpha.format() == QImage::Format_MonoLSB; - - if (trucol) { // truecolor - const uint red_mask = (uint)visual->red_mask; - const uint green_mask = (uint)visual->green_mask; - const uint blue_mask = (uint)visual->blue_mask; - const int red_shift = highest_bit(red_mask) - 7; - const int green_shift = highest_bit(green_mask) - 7; - const int blue_shift = highest_bit(blue_mask) - 7; - - const uint red_bits = n_bits(red_mask); - const uint green_bits = n_bits(green_mask); - const uint blue_bits = n_bits(blue_mask); - - static uint red_table_bits = 0; - static uint green_table_bits = 0; - static uint blue_table_bits = 0; - - if (red_bits < 8 && red_table_bits != red_bits) { - build_scale_table(&red_scale_table, red_bits); - red_table_bits = red_bits; - } - if (blue_bits < 8 && blue_table_bits != blue_bits) { - build_scale_table(&blue_scale_table, blue_bits); - blue_table_bits = blue_bits; - } - if (green_bits < 8 && green_table_bits != green_bits) { - build_scale_table(&green_scale_table, green_bits); - green_table_bits = green_bits; - } - - int r, g, b; - - QRgb *dst; - uchar *src; - uint pixel; - int bppc = xi->bits_per_pixel; - - if (bppc > 8 && xi->byte_order == LSBFirst) - bppc++; - - for (int y = 0; y < xi->height; ++y) { - uchar* asrc = x11_mask ? alpha.scanLine(y) : 0; - dst = (QRgb *)image.scanLine(y); - src = (uchar *)xi->data + xi->bytes_per_line*y; - for (int x = 0; x < xi->width; x++) { - switch (bppc) { - case 8: - pixel = *src++; - break; - case 16: // 16 bit MSB - pixel = src[1] | (uint)src[0] << 8; - src += 2; - break; - case 17: // 16 bit LSB - pixel = src[0] | (uint)src[1] << 8; - src += 2; - break; - case 24: // 24 bit MSB - pixel = src[2] | (uint)src[1] << 8 | (uint)src[0] << 16; - src += 3; - break; - case 25: // 24 bit LSB - pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16; - src += 3; - break; - case 32: // 32 bit MSB - pixel = src[3] | (uint)src[2] << 8 | (uint)src[1] << 16 | (uint)src[0] << 24; - src += 4; - break; - case 33: // 32 bit LSB - pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24; - src += 4; - break; - default: // should not really happen - x = xi->width; // leave loop - y = xi->height; - pixel = 0; // eliminate compiler warning - qWarning("QPixmap::convertToImage: Invalid depth %d", bppc); - } - if (red_shift > 0) - r = (pixel & red_mask) >> red_shift; - else - r = (pixel & red_mask) << -red_shift; - if (green_shift > 0) - g = (pixel & green_mask) >> green_shift; - else - g = (pixel & green_mask) << -green_shift; - if (blue_shift > 0) - b = (pixel & blue_mask) >> blue_shift; - else - b = (pixel & blue_mask) << -blue_shift; - - if (red_bits < 8) - r = red_scale_table[r]; - if (green_bits < 8) - g = green_scale_table[g]; - if (blue_bits < 8) - b = blue_scale_table[b]; - - if (x11_mask) { - if (ale) { - *dst++ = (asrc[x >> 3] & (1 << (x & 7))) ? qRgba(r, g, b, 0xff) : 0; - } else { - *dst++ = (asrc[x >> 3] & (0x80 >> (x & 7))) ? qRgba(r, g, b, 0xff) : 0; - } - } else { - *dst++ = qRgb(r, g, b); - } - } - } - } else if (xi->bits_per_pixel == d) { // compatible depth - char *xidata = xi->data; // copy each scanline - int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line); - for (int y=0; y<xi->height; y++) { - memcpy(image.scanLine(y), xidata, bpl); - xidata += xi->bytes_per_line; - } - } else { - /* Typically 2 or 4 bits display depth */ - qWarning("QPixmap::convertToImage: Display not supported (bpp=%d)", - xi->bits_per_pixel); - return QImage(); - } - - if (d == 1) { // bitmap - image.setColorCount(2); - image.setColor(0, qRgb(255,255,255)); - image.setColor(1, qRgb(0,0,0)); - } else if (!trucol) { // pixmap with colormap - register uchar *p; - uchar *end; - uchar use[256]; // pixel-in-use table - uchar pix[256]; // pixel translation table - int ncols, bpl; - memset(use, 0, 256); - memset(pix, 0, 256); - bpl = image.bytesPerLine(); - - if (x11_mask) { // which pixels are used? - for (int i = 0; i < xi->height; i++) { - uchar* asrc = alpha.scanLine(i); - p = image.scanLine(i); - if (ale) { - for (int x = 0; x < xi->width; x++) { - if (asrc[x >> 3] & (1 << (x & 7))) - use[*p] = 1; - ++p; - } - } else { - for (int x = 0; x < xi->width; x++) { - if (asrc[x >> 3] & (0x80 >> (x & 7))) - use[*p] = 1; - ++p; - } - } - } - } else { - for (int i = 0; i < xi->height; i++) { - p = image.scanLine(i); - end = p + bpl; - while (p < end) - use[*p++] = 1; - } - } - ncols = 0; - for (int i = 0; i < 256; i++) { // build translation table - if (use[i]) - pix[i] = ncols++; - } - for (int i = 0; i < xi->height; i++) { // translate pixels - p = image.scanLine(i); - end = p + bpl; - while (p < end) { - *p = pix[*p]; - p++; - } - } - if (x11_mask) { - int trans; - if (ncols < 256) { - trans = ncols++; - image.setColorCount(ncols); // create color table - image.setColor(trans, 0x00000000); - } else { - image.setColorCount(ncols); // create color table - // oh dear... no spare "transparent" pixel. - // use first pixel in image (as good as any). - trans = image.scanLine(0)[0]; - } - for (int i = 0; i < xi->height; i++) { - uchar* asrc = alpha.scanLine(i); - p = image.scanLine(i); - if (ale) { - for (int x = 0; x < xi->width; x++) { - if (!(asrc[x >> 3] & (1 << (x & 7)))) - *p = trans; - ++p; - } - } else { - for (int x = 0; x < xi->width; x++) { - if (!(asrc[x >> 3] & (1 << (7 -(x & 7))))) - *p = trans; - ++p; - } - } - } - } else { - image.setColorCount(ncols); // create color table - } - QVector<QColor> colors = QColormap::instance(xinfo.screen()).colormap(); - int j = 0; - for (int i=0; i<colors.size(); i++) { // translate pixels - if (use[i]) - image.setColor(j++, 0xff000000 | colors.at(i).rgb()); - } - } - - return image; -} - -/*! - Returns a copy of the pixmap that is transformed using the given - transformation \a matrix and transformation \a mode. The original - pixmap is not changed. - - The transformation \a matrix is internally adjusted to compensate - for unwanted translation; i.e. the pixmap produced is the smallest - pixmap that contains all the transformed points of the original - pixmap. Use the trueMatrix() function to retrieve the actual - matrix used for transforming the pixmap. - - This function is slow because it involves transformation to a - QImage, non-trivial computations and a transformation back to a - QPixmap. - - \sa trueMatrix(), {QPixmap#Pixmap Transformations}{Pixmap - Transformations} -*/ -QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, - Qt::TransformationMode mode ) const -{ - if (mode == Qt::SmoothTransformation || transform.type() >= QTransform::TxProject) { - QImage image = toImage(); - return QPixmap::fromImage(image.transformed(transform, mode)); - } - - uint w = 0; - uint h = 0; // size of target pixmap - uint ws, hs; // size of source pixmap - uchar *dptr; // data in target pixmap - uint dbpl, dbytes; // bytes per line/bytes total - uchar *sptr; // data in original pixmap - int sbpl; // bytes per line in original - int bpp; // bits per pixel - bool depth1 = depth() == 1; - Display *dpy = X11->display; - - ws = width(); - hs = height(); - - QTransform mat(transform.m11(), transform.m12(), transform.m13(), - transform.m21(), transform.m22(), transform.m23(), - 0., 0., 1); - bool complex_xform = false; - qreal scaledWidth; - qreal scaledHeight; - - if (mat.type() <= QTransform::TxScale) { - scaledHeight = qAbs(mat.m22()) * hs + 0.9999; - scaledWidth = qAbs(mat.m11()) * ws + 0.9999; - h = qAbs(int(scaledHeight)); - w = qAbs(int(scaledWidth)); - } else { // rotation or shearing - QPolygonF a(QRectF(0, 0, ws, hs)); - a = mat.map(a); - QRect r = a.boundingRect().toAlignedRect(); - w = r.width(); - h = r.height(); - scaledWidth = w; - scaledHeight = h; - complex_xform = true; - } - mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix - - bool invertible; - mat = mat.inverted(&invertible); // invert matrix - - if (h == 0 || w == 0 || !invertible - || qAbs(scaledWidth) >= 32768 || qAbs(scaledHeight) >= 32768 ) - // error, return null pixmap - return QPixmap(); - -#if defined(QT_MITSHM) - static bool try_once = true; - if (try_once) { - try_once = false; - if (!xshminit) - qt_create_mitshm_buffer(this, 800, 600); - } - - bool use_mitshm = xshmimg && !depth1 && - xshmimg->width >= w && xshmimg->height >= h; -#endif - XImage *xi = XGetImage(X11->display, handle(), 0, 0, ws, hs, AllPlanes, - depth1 ? XYPixmap : ZPixmap); - - if (!xi) - return QPixmap(); - - sbpl = xi->bytes_per_line; - sptr = (uchar *)xi->data; - bpp = xi->bits_per_pixel; - - if (depth1) - dbpl = (w+7)/8; - else - dbpl = ((w*bpp+31)/32)*4; - dbytes = dbpl*h; - -#if defined(QT_MITSHM) - if (use_mitshm) { - dptr = (uchar *)xshmimg->data; - uchar fillbyte = bpp == 8 ? white.pixel() : 0xff; - for (int y=0; y<h; y++) - memset(dptr + y*xshmimg->bytes_per_line, fillbyte, dbpl); - } else { -#endif - dptr = (uchar *)malloc(dbytes); // create buffer for bits - Q_CHECK_PTR(dptr); - if (depth1) // fill with zeros - memset(dptr, 0, dbytes); - else if (bpp == 8) // fill with background color - memset(dptr, WhitePixel(X11->display, xinfo.screen()), dbytes); - else - memset(dptr, 0, dbytes); -#if defined(QT_MITSHM) - } -#endif - - // #define QT_DEBUG_XIMAGE -#if defined(QT_DEBUG_XIMAGE) - qDebug("----IMAGE--INFO--------------"); - qDebug("width............. %d", xi->width); - qDebug("height............ %d", xi->height); - qDebug("xoffset........... %d", xi->xoffset); - qDebug("format............ %d", xi->format); - qDebug("byte order........ %d", xi->byte_order); - qDebug("bitmap unit....... %d", xi->bitmap_unit); - qDebug("bitmap bit order.. %d", xi->bitmap_bit_order); - qDebug("depth............. %d", xi->depth); - qDebug("bytes per line.... %d", xi->bytes_per_line); - qDebug("bits per pixel.... %d", xi->bits_per_pixel); -#endif - - int type; - if (xi->bitmap_bit_order == MSBFirst) - type = QT_XFORM_TYPE_MSBFIRST; - else - type = QT_XFORM_TYPE_LSBFIRST; - int xbpl, p_inc; - if (depth1) { - xbpl = (w+7)/8; - p_inc = dbpl - xbpl; - } else { - xbpl = (w*bpp)/8; - p_inc = dbpl - xbpl; -#if defined(QT_MITSHM) - if (use_mitshm) - p_inc = xshmimg->bytes_per_line - xbpl; -#endif - } - - if (!qt_xForm_helper(mat, xi->xoffset, type, bpp, dptr, xbpl, p_inc, h, sptr, sbpl, ws, hs)){ - qWarning("QPixmap::transform: display not supported (bpp=%d)",bpp); - QPixmap pm; - return pm; - } - - qSafeXDestroyImage(xi); - - if (depth1) { // mono bitmap - QBitmap bm = QBitmap::fromData(QSize(w, h), dptr, - BitmapBitOrder(X11->display) == MSBFirst - ? QImage::Format_Mono - : QImage::Format_MonoLSB); - free(dptr); - return bm; - } else { // color pixmap - QX11PlatformPixmap *x11Data = new QX11PlatformPixmap(QPlatformPixmap::PixmapType); - QPixmap pm(x11Data); - x11Data->flags &= ~QX11PlatformPixmap::Uninitialized; - x11Data->xinfo = xinfo; - x11Data->d = d; - x11Data->w = w; - x11Data->h = h; - x11Data->is_null = (w <= 0 || h <= 0); - x11Data->hd = (Qt::HANDLE)XCreatePixmap(X11->display, - RootWindow(X11->display, xinfo.screen()), - w, h, d); - x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - XRenderPictFormat *format = x11Data->d == 32 - ? XRenderFindStandardFormat(X11->display, PictStandardARGB32) - : XRenderFindVisualFormat(X11->display, (Visual *) x11Data->xinfo.visual()); - x11Data->picture = XRenderCreatePicture(X11->display, x11Data->hd, format, 0, 0); - } -#endif // QT_NO_XRENDER - - GC gc = XCreateGC(X11->display, x11Data->hd, 0, 0); -#if defined(QT_MITSHM) - if (use_mitshm) { - XCopyArea(dpy, xshmpm, x11Data->hd, gc, 0, 0, w, h, 0, 0); - } else -#endif - { - xi = XCreateImage(dpy, (Visual*)x11Data->xinfo.visual(), - x11Data->d, - ZPixmap, 0, (char *)dptr, w, h, 32, 0); - XPutImage(dpy, pm.handle(), gc, xi, 0, 0, 0, 0, w, h); - qSafeXDestroyImage(xi); - } - XFreeGC(X11->display, gc); - - if (x11_mask) { // xform mask, too - pm.setMask(mask_to_bitmap(xinfo.screen()).transformed(transform)); - } else if (d != 32 && complex_xform) { // need a mask! - QBitmap mask(ws, hs); - mask.fill(Qt::color1); - pm.setMask(mask.transformed(transform)); - } - return pm; - } -} - -int QPixmap::x11SetDefaultScreen(int screen) -{ - int old = defaultScreen; - defaultScreen = screen; - return old; -} - -void QPixmap::x11SetScreen(int screen) -{ - if (paintingActive()) { - qWarning("QPixmap::x11SetScreen(): Cannot change screens during painting"); - return; - } - - if (isNull()) - return; - - if (data->classId() != QPlatformPixmap::X11Class) - return; - - if (screen < 0) - screen = QX11Info::appScreen(); - - QX11PlatformPixmap *x11Data = static_cast<QX11PlatformPixmap*>(data.data()); - if (screen == x11Data->xinfo.screen()) - return; // nothing to do - - if (isNull()) { - QX11InfoData* xd = x11Data->xinfo.getX11Data(true); - xd->screen = screen; - xd->depth = QX11Info::appDepth(screen); - xd->cells = QX11Info::appCells(screen); - xd->colormap = QX11Info::appColormap(screen); - xd->defaultColormap = QX11Info::appDefaultColormap(screen); - xd->visual = (Visual *)QX11Info::appVisual(screen); - xd->defaultVisual = QX11Info::appDefaultVisual(screen); - x11Data->xinfo.setX11Data(xd); - return; - } -#if 0 - qDebug("QPixmap::x11SetScreen for %p from %d to %d. Size is %d/%d", x11Data, x11Data->xinfo.screen(), screen, width(), height()); -#endif - - x11SetDefaultScreen(screen); - *this = qt_toX11Pixmap(toImage()); -} - -QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) -{ - if (w == 0 || h == 0) - return QPixmap(); - - Display *dpy = X11->display; - XWindowAttributes window_attr; - if (!XGetWindowAttributes(dpy, window, &window_attr)) - return QPixmap(); - - if (w < 0) - w = window_attr.width - x; - if (h < 0) - h = window_attr.height - y; - - // determine the screen - int scr; - for (scr = 0; scr < ScreenCount(dpy); ++scr) { - if (window_attr.root == RootWindow(dpy, scr)) // found it - break; - } - if (scr >= ScreenCount(dpy)) // sanity check - return QPixmap(); - - - // get the depth of the root window - XWindowAttributes root_attr; - if (!XGetWindowAttributes(dpy, window_attr.root, &root_attr)) - return QPixmap(); - - if (window_attr.depth == root_attr.depth) { - // if the depth of the specified window and the root window are the - // same, grab pixels from the root window (so that we get the any - // overlapping windows and window manager frames) - - // map x and y to the root window - WId unused; - if (!XTranslateCoordinates(dpy, window, window_attr.root, x, y, - &x, &y, &unused)) - return QPixmap(); - - window = window_attr.root; - window_attr = root_attr; - } - - QX11PlatformPixmap *data = new QX11PlatformPixmap(QPlatformPixmap::PixmapType); - - void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a); - qt_x11_getX11InfoForWindow(&data->xinfo,window_attr); - - data->resize(w, h); - - QPixmap pm(data); - - data->flags &= ~QX11PlatformPixmap::Uninitialized; - pm.x11SetScreen(scr); - - GC gc = XCreateGC(dpy, pm.handle(), 0, 0); - XSetSubwindowMode(dpy, gc, IncludeInferiors); - XCopyArea(dpy, window, pm.handle(), gc, x, y, w, h, 0, 0); - XFreeGC(dpy, gc); - - return pm; -} - -bool QX11PlatformPixmap::hasAlphaChannel() const -{ - return d == 32; -} - -const QX11Info &QPixmap::x11Info() const -{ - if (data && data->classId() == QPlatformPixmap::X11Class) - return static_cast<QX11PlatformPixmap*>(data.data())->xinfo; - else { - static QX11Info nullX11Info; - return nullX11Info; - } -} - -#if !defined(QT_NO_XRENDER) -static XRenderPictFormat *qt_renderformat_for_depth(const QX11Info &xinfo, int depth) -{ - if (depth == 1) - return XRenderFindStandardFormat(X11->display, PictStandardA1); - else if (depth == 32) - return XRenderFindStandardFormat(X11->display, PictStandardARGB32); - else - return XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual()); -} -#endif - -QPaintEngine* QX11PlatformPixmap::paintEngine() const -{ - QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this); - - if ((flags & Readonly) && share_mode == QPixmap::ImplicitlyShared) { - // if someone wants to draw onto us, copy the shared contents - // and turn it into a fully fledged QPixmap - ::Pixmap hd_copy = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), - w, h, d); -#if !defined(QT_NO_XRENDER) - XRenderPictFormat *format = qt_renderformat_for_depth(xinfo, d); - ::Picture picture_copy = XRenderCreatePicture(X11->display, hd_copy, format, 0, 0); - - if (picture && d == 32) { - XRenderComposite(X11->display, PictOpSrc, picture, 0, picture_copy, - 0, 0, 0, 0, 0, 0, w, h); - XRenderFreePicture(X11->display, picture); - that->picture = picture_copy; - } else -#endif - { - GC gc = XCreateGC(X11->display, hd_copy, 0, 0); - XCopyArea(X11->display, hd, hd_copy, gc, 0, 0, w, h, 0, 0); - XFreeGC(X11->display, gc); - } - that->hd = hd_copy; - that->flags &= ~QX11PlatformPixmap::Readonly; - } - - if (!that->pengine) - that->pengine = new QX11PaintEngine; - return that->pengine; -} - -Qt::HANDLE QPixmap::x11PictureHandle() const -{ -#ifndef QT_NO_XRENDER - if (data && data->classId() == QPlatformPixmap::X11Class) - return static_cast<const QX11PlatformPixmap*>(data.data())->picture; - else - return 0; -#else - return 0; -#endif // QT_NO_XRENDER -} - -Qt::HANDLE QX11PlatformPixmap::x11ConvertToDefaultDepth() -{ -#ifndef QT_NO_XRENDER - if (d == QX11Info::appDepth() || !X11->use_xrender) - return hd; - if (!hd2) { - hd2 = XCreatePixmap(xinfo.display(), hd, w, h, QX11Info::appDepth()); - XRenderPictFormat *format = XRenderFindVisualFormat(xinfo.display(), - (Visual*) xinfo.visual()); - Picture pic = XRenderCreatePicture(xinfo.display(), hd2, format, 0, 0); - XRenderComposite(xinfo.display(), PictOpSrc, picture, - XNone, pic, 0, 0, 0, 0, 0, 0, w, h); - XRenderFreePicture(xinfo.display(), pic); - } - return hd2; -#else - return hd; -#endif -} - -void QX11PlatformPixmap::copy(const QPlatformPixmap *data, const QRect &rect) -{ - if (data->pixelType() == BitmapType) { - fromImage(data->toImage().copy(rect), Qt::AutoColor); - return; - } - - const QX11PlatformPixmap *x11Data = static_cast<const QX11PlatformPixmap*>(data); - - setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); - - flags &= ~Uninitialized; - xinfo = x11Data->xinfo; - d = x11Data->d; - w = rect.width(); - h = rect.height(); - is_null = (w <= 0 || h <= 0); - hd = (Qt::HANDLE)XCreatePixmap(X11->display, - RootWindow(X11->display, x11Data->xinfo.screen()), - w, h, d); -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - XRenderPictFormat *format = d == 32 - ? XRenderFindStandardFormat(X11->display, PictStandardARGB32) - : XRenderFindVisualFormat(X11->display, (Visual *)xinfo.visual()); - picture = XRenderCreatePicture(X11->display, hd, format, 0, 0); - } -#endif // QT_NO_XRENDER - if (x11Data->x11_mask) { - x11_mask = XCreatePixmap(X11->display, hd, w, h, 1); -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - mask_picture = XRenderCreatePicture(X11->display, x11_mask, - XRenderFindStandardFormat(X11->display, PictStandardA1), 0, 0); - XRenderPictureAttributes attrs; - attrs.alpha_map = x11Data->mask_picture; - XRenderChangePicture(X11->display, x11Data->picture, CPAlphaMap, &attrs); - } -#endif - } - -#if !defined(QT_NO_XRENDER) - if (x11Data->picture && x11Data->d == 32) { - XRenderComposite(X11->display, PictOpSrc, - x11Data->picture, 0, picture, - rect.x(), rect.y(), 0, 0, 0, 0, w, h); - } else -#endif - { - GC gc = XCreateGC(X11->display, hd, 0, 0); - XCopyArea(X11->display, x11Data->hd, hd, gc, - rect.x(), rect.y(), w, h, 0, 0); - if (x11Data->x11_mask) { - GC monogc = XCreateGC(X11->display, x11_mask, 0, 0); - XCopyArea(X11->display, x11Data->x11_mask, x11_mask, monogc, - rect.x(), rect.y(), w, h, 0, 0); - XFreeGC(X11->display, monogc); - } - XFreeGC(X11->display, gc); - } -} - -bool QX11PlatformPixmap::scroll(int dx, int dy, const QRect &rect) -{ - GC gc = XCreateGC(X11->display, hd, 0, 0); - XCopyArea(X11->display, hd, hd, gc, - rect.left(), rect.top(), rect.width(), rect.height(), - rect.left() + dx, rect.top() + dy); - XFreeGC(X11->display, gc); - return true; -} - -#if !defined(QT_NO_XRENDER) -void QX11PlatformPixmap::convertToARGB32(bool preserveContents) -{ - if (!X11->use_xrender) - return; - - // Q_ASSERT(count == 1); - if ((flags & Readonly) && share_mode == QPixmap::ExplicitlyShared) - return; - - Pixmap pm = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), - w, h, 32); - Picture p = XRenderCreatePicture(X11->display, pm, - XRenderFindStandardFormat(X11->display, PictStandardARGB32), 0, 0); - if (picture) { - if (preserveContents) - XRenderComposite(X11->display, PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h); - if (!(flags & Readonly)) - XRenderFreePicture(X11->display, picture); - } - if (hd && !(flags & Readonly)) - XFreePixmap(X11->display, hd); - if (x11_mask) { - XFreePixmap(X11->display, x11_mask); - if (mask_picture) - XRenderFreePicture(X11->display, mask_picture); - x11_mask = 0; - mask_picture = 0; - } - hd = pm; - picture = p; - d = 32; -} -#endif - -QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode) -{ - Window root; - int x; - int y; - uint width; - uint height; - uint border_width; - uint depth; - XWindowAttributes win_attribs; - int num_screens = ScreenCount(X11->display); - int screen = 0; - - XGetGeometry(X11->display, pixmap, &root, &x, &y, &width, &height, &border_width, &depth); - XGetWindowAttributes(X11->display, root, &win_attribs); - - for (; screen < num_screens; ++screen) { - if (win_attribs.screen == ScreenOfDisplay(X11->display, screen)) - break; - } - - QX11PlatformPixmap *data = new QX11PlatformPixmap(depth == 1 ? QPlatformPixmap::BitmapType : QPlatformPixmap::PixmapType); - data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1)); - data->flags = QX11PlatformPixmap::Readonly; - data->share_mode = mode; - data->w = width; - data->h = height; - data->is_null = (width <= 0 || height <= 0); - data->d = depth; - data->hd = pixmap; - - if (defaultScreen >= 0 && defaultScreen != screen) { - QX11InfoData* xd = data->xinfo.getX11Data(true); - xd->screen = defaultScreen; - xd->depth = QX11Info::appDepth(xd->screen); - xd->cells = QX11Info::appCells(xd->screen); - xd->colormap = QX11Info::appColormap(xd->screen); - xd->defaultColormap = QX11Info::appDefaultColormap(xd->screen); - xd->visual = (Visual *)QX11Info::appVisual(xd->screen); - xd->defaultVisual = QX11Info::appDefaultVisual(xd->screen); - data->xinfo.setX11Data(xd); - } - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - XRenderPictFormat *format = qt_renderformat_for_depth(data->xinfo, depth); - data->picture = XRenderCreatePicture(X11->display, data->hd, format, 0, 0); - } -#endif // QT_NO_XRENDER - - return QPixmap(data); -} - - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qpixmap_x11_p.h b/src/widgets/platforms/x11/qpixmap_x11_p.h deleted file mode 100644 index fce32cbe3e..0000000000 --- a/src/widgets/platforms/x11/qpixmap_x11_p.h +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPIXMAPDATA_X11_P_H -#define QPIXMAPDATA_X11_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/qplatformpixmap_qpa.h> -#include <QtGui/qplatformpixmapfactory_p.h> - -#include "QtGui/qx11info_x11.h" - -QT_BEGIN_NAMESPACE - -class QX11PaintEngine; - -struct QXImageWrapper; - -class Q_WIDGETS_EXPORT QX11PlatformPixmap : public QPlatformPixmap -{ -public: - QX11PlatformPixmap(PixelType type); -// QX11PlatformPixmap(PixelType type, int width, int height); -// QX11PlatformPixmap(PixelType type, const QImage &image, -// Qt::ImageConversionFlags flags); - ~QX11PlatformPixmap(); - - QPlatformPixmap *createCompatiblePlatformPixmap() const; - - void resize(int width, int height); - void fromImage(const QImage &image, Qt::ImageConversionFlags flags); - void copy(const QPlatformPixmap *data, const QRect &rect); - bool scroll(int dx, int dy, const QRect &rect); - - void fill(const QColor &color); - QBitmap mask() const; - void setMask(const QBitmap &mask); - bool hasAlphaChannel() const; - void setAlphaChannel(const QPixmap &alphaChannel); - QPixmap alphaChannel() const; - QPixmap transformed(const QTransform &transform, - Qt::TransformationMode mode) const; - QImage toImage() const; - QImage toImage(const QRect &rect) const; - QPaintEngine* paintEngine() const; - - Qt::HANDLE handle() const { return hd; } - Qt::HANDLE x11ConvertToDefaultDepth(); - - static Qt::HANDLE createBitmapFromImage(const QImage &image); - - void* gl_surface; -#ifndef QT_NO_XRENDER - void convertToARGB32(bool preserveContents = true); -#endif - -protected: - int metric(QPaintDevice::PaintDeviceMetric metric) const; - -private: - friend class QPixmap; - friend class QBitmap; - friend class QX11PaintEngine; - friend class QX11WindowSurface; - friend class QRasterWindowSurface; - friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags - friend class QEglContext; // Needs gl_surface - friend class QGLContext; // Needs gl_surface - friend class QX11GLPlatformPixmap; // Needs gl_surface - friend class QMeeGoLivePlatformPixmap; // Needs gl_surface and flags - friend bool qt_createEGLSurfaceForPixmap(QPlatformPixmap*, bool); // Needs gl_surface - - void release(); - - QImage toImage(const QXImageWrapper &xi, const QRect &rect) const; - - QBitmap mask_to_bitmap(int screen) const; - static Qt::HANDLE bitmap_to_mask(const QBitmap &, int screen); - void bitmapFromImage(const QImage &image); - - bool canTakeQImageFromXImage(const QXImageWrapper &xi) const; - QImage takeQImageFromXImage(const QXImageWrapper &xi) const; - - Qt::HANDLE hd; - - enum Flag { - NoFlags = 0x0, - Uninitialized = 0x1, - Readonly = 0x2, - InvertedWhenBoundToTexture = 0x4, - GlSurfaceCreatedWithAlpha = 0x8 - }; - uint flags; - - QX11Info xinfo; - Qt::HANDLE x11_mask; - Qt::HANDLE picture; - Qt::HANDLE mask_picture; - Qt::HANDLE hd2; // sorted in the default display depth - QPixmap::ShareMode share_mode; - - QX11PaintEngine *pengine; -}; - -QT_END_NAMESPACE - -#endif // QPIXMAPDATA_X11_P_H - diff --git a/src/widgets/platforms/x11/qregion_x11.cpp b/src/widgets/platforms/x11/qregion_x11.cpp deleted file mode 100644 index a96ec6dc96..0000000000 --- a/src/widgets/platforms/x11/qregion_x11.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_x11_p.h> - -#include <limits.h> - -QT_BEGIN_NAMESPACE - -QRegion::QRegionData QRegion::shared_empty = {Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0}; - -void QRegion::updateX11Region() const -{ - d->rgn = XCreateRegion(); - if (!d->qt_rgn) - return; - - int n = d->qt_rgn->numRects; - const QRect *rect = (n == 1 ? &d->qt_rgn->extents : d->qt_rgn->rects.constData()); - while (n--) { - XRectangle r; - r.x = qMax(SHRT_MIN, rect->x()); - r.y = qMax(SHRT_MIN, rect->y()); - r.width = qMin((int)USHRT_MAX, rect->width()); - r.height = qMin((int)USHRT_MAX, rect->height()); - XUnionRectWithRegion(&r, d->rgn, d->rgn); - ++rect; - } -} - -void *QRegion::clipRectangles(int &num) const -{ - if (!d->xrectangles && !(d == &shared_empty || d->qt_rgn->numRects == 0)) { - XRectangle *r = static_cast<XRectangle*>(malloc(d->qt_rgn->numRects * sizeof(XRectangle))); - d->xrectangles = r; - int n = d->qt_rgn->numRects; - const QRect *rect = (n == 1 ? &d->qt_rgn->extents : d->qt_rgn->rects.constData()); - while (n--) { - r->x = qMax(SHRT_MIN, rect->x()); - r->y = qMax(SHRT_MIN, rect->y()); - r->width = qMin((int)USHRT_MAX, rect->width()); - r->height = qMin((int)USHRT_MAX, rect->height()); - ++r; - ++rect; - } - } - if (d == &shared_empty || d->qt_rgn->numRects == 0) - num = 0; - else - num = d->qt_rgn->numRects; - return d->xrectangles; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qsound_x11.cpp b/src/widgets/platforms/x11/qsound_x11.cpp deleted file mode 100644 index c83c26a027..0000000000 --- a/src/widgets/platforms/x11/qsound_x11.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsound.h" - -#ifndef QT_NO_SOUND - -#include "qhash.h" -#include "qsocketnotifier.h" -#include "qapplication.h" -#include "qsound_p.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_NAS - -QT_BEGIN_INCLUDE_NAMESPACE -#include <audio/audiolib.h> -#include <audio/soundlib.h> -QT_END_INCLUDE_NAMESPACE - -static AuServer *nas=0; - -static AuBool eventPred(AuServer *, AuEvent *e, AuPointer p) -{ - if (e && (e->type == AuEventTypeElementNotify)) { - if (e->auelementnotify.flow == *((AuFlowID *)p)) - return true; - } - return false; -} - -class QAuBucketNAS : public QAuBucket { -public: - QAuBucketNAS(AuBucketID b, AuFlowID f = 0) : id(b), flow(f), stopped(true), numplaying(0) { } - ~QAuBucketNAS() - { - if (nas) { - AuSync(nas, false); - AuDestroyBucket(nas, id, NULL); - - AuEvent ev; - while (AuScanEvents(nas, AuEventsQueuedAfterFlush, true, eventPred, &flow, &ev)) - ; - } - } - - AuBucketID id; - AuFlowID flow; - bool stopped; - int numplaying; -}; - -class QAuServerNAS : public QAuServer { - Q_OBJECT - - QSocketNotifier* sn; - -public: - QAuServerNAS(QObject* parent); - ~QAuServerNAS(); - - void init(QSound*); - void play(const QString& filename); - void play(QSound*); - void stop(QSound*); - bool okay(); - void setDone(QSound*); - -public slots: - void dataReceived(); - void soundDestroyed(QObject *o); - -private: - QAuBucketNAS* bucket(QSound* s) - { - return (QAuBucketNAS*)QAuServer::bucket(s); - } -}; - -QAuServerNAS::QAuServerNAS(QObject* parent) : - QAuServer(parent) -{ - setObjectName(QLatin1String("Network Audio System")); - nas = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL); - if (nas) { - AuSetCloseDownMode(nas, AuCloseDownDestroy, NULL); - // Ask Qt for async messages... - sn=new QSocketNotifier(AuServerConnectionNumber(nas), - QSocketNotifier::Read); - QObject::connect(sn, SIGNAL(activated(int)), - this, SLOT(dataReceived())); - } else { - sn = 0; - } -} - -QAuServerNAS::~QAuServerNAS() -{ - if (nas) - AuCloseServer(nas); - delete sn; - nas = 0; -} - -typedef QHash<void*,QAuServerNAS*> AuServerHash; -static AuServerHash *inprogress=0; - -void QAuServerNAS::soundDestroyed(QObject *o) -{ - if (inprogress) { - QSound *so = static_cast<QSound *>(o); - while (inprogress->remove(so)) - ; // Loop while remove returns true - } -} - -void QAuServerNAS::play(const QString& filename) -{ - if (nas) { - int iv=100; - AuFixedPoint volume=AuFixedPointFromFraction(iv,100); - AuSoundPlayFromFile(nas, filename.toLocal8Bit().constData(), AuNone, volume, - NULL, NULL, NULL, NULL, NULL, NULL); - AuFlush(nas); - dataReceived(); - AuFlush(nas); - qApp->flush(); - } -} - -static void callback(AuServer*, AuEventHandlerRec*, AuEvent* e, AuPointer p) -{ - if (inprogress->contains(p) && e) { - if (e->type==AuEventTypeElementNotify && - e->auelementnotify.kind==AuElementNotifyKindState) { - if (e->auelementnotify.cur_state == AuStateStop) { - AuServerHash::Iterator it = inprogress->find(p); - if (it != inprogress->end()) - (*it)->setDone((QSound*)p); - } - } - } -} - -void QAuServerNAS::setDone(QSound* s) -{ - if (nas) { - decLoop(s); - if (s->loopsRemaining() && !bucket(s)->stopped) { - bucket(s)->stopped = true; - play(s); - } else { - if (--(bucket(s)->numplaying) == 0) - bucket(s)->stopped = true; - inprogress->remove(s); - } - } -} - -void QAuServerNAS::play(QSound* s) -{ - if (nas) { - ++(bucket(s)->numplaying); - if (!bucket(s)->stopped) { - stop(s); - } - - bucket(s)->stopped = false; - if (!inprogress) - inprogress = new AuServerHash; - inprogress->insert(s,this); - int iv=100; - AuFixedPoint volume=AuFixedPointFromFraction(iv,100); - QAuBucketNAS *b = bucket(s); - AuSoundPlayFromBucket(nas, b->id, AuNone, volume, - callback, s, 0, &b->flow, NULL, NULL, NULL); - AuFlush(nas); - dataReceived(); - AuFlush(nas); - qApp->flush(); - } -} - -void QAuServerNAS::stop(QSound* s) -{ - if (nas && !bucket(s)->stopped) { - bucket(s)->stopped = true; - AuStopFlow(nas, bucket(s)->flow, NULL); - AuFlush(nas); - dataReceived(); - AuFlush(nas); - qApp->flush(); - } -} - -void QAuServerNAS::init(QSound* s) -{ - connect(s, SIGNAL(destroyed(QObject*)), - this, SLOT(soundDestroyed(QObject*))); - - if (nas) { - AuBucketID b_id = - AuSoundCreateBucketFromFile(nas, s->fileName().toLocal8Bit().constData(), - 0 /*AuAccessAllMasks*/, NULL, NULL); - setBucket(s, new QAuBucketNAS(b_id)); - } -} - -bool QAuServerNAS::okay() -{ - return !!nas; -} - -void QAuServerNAS::dataReceived() -{ - AuHandleEvents(nas); -} - -QT_BEGIN_INCLUDE_NAMESPACE -#include "qsound_x11.moc" -QT_END_INCLUDE_NAMESPACE - -#endif - - -class QAuServerNull : public QAuServer -{ -public: - QAuServerNull(QObject* parent); - - void play(const QString&) { } - void play(QSound*s) { while(decLoop(s) > 0) /* nothing */ ; } - void stop(QSound*) { } - bool okay() { return false; } -}; - -QAuServerNull::QAuServerNull(QObject* parent) - : QAuServer(parent) -{ -} - - -QAuServer* qt_new_audio_server() -{ -#ifndef QT_NO_NAS - QAuServer* s = new QAuServerNAS(qApp); - if (s->okay()) - return s; - else - delete s; -#endif - return new QAuServerNull(qApp); -} - -QT_END_NAMESPACE - -#endif // QT_NO_SOUND diff --git a/src/widgets/platforms/x11/qt_x11_p.h b/src/widgets/platforms/x11/qt_x11_p.h deleted file mode 100644 index ea808fb8a2..0000000000 --- a/src/widgets/platforms/x11/qt_x11_p.h +++ /dev/null @@ -1,757 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT_X11_P_H -#define QT_X11_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qwindowdefs.h" -#include "QtCore/qlist.h" -#include "QtCore/qvariant.h" - -// the following is necessary to work around breakage in many versions -// of XFree86's Xlib.h still in use -// ### which versions? -#if defined(_XLIB_H_) // crude hack, but... -#error "cannot include <X11/Xlib.h> before this file" -#endif -#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback -#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback -#define XSetIMValues qt_XSetIMValues -#include <X11/Xlib.h> -#undef XRegisterIMInstantiateCallback -#undef XUnregisterIMInstantiateCallback -#undef XSetIMValues - -#include <X11/Xutil.h> -#include <X11/Xos.h> -#ifdef index -# undef index -#endif -#ifdef rindex -# undef rindex -#endif -#ifdef Q_OS_VXWORS -# ifdef open -# undef open -# endif -# ifdef getpid -# undef getpid -# endif -#endif // Q_OS_VXWORKS -#include <X11/Xatom.h> - -//#define QT_NO_SHAPE -#ifdef QT_NO_SHAPE -# define XShapeCombineRegion(a,b,c,d,e,f,g) -# define XShapeCombineMask(a,b,c,d,e,f,g) -#else -# include <X11/extensions/shape.h> -#endif // QT_NO_SHAPE - - -#if !defined (QT_NO_TABLET) -# include <X11/extensions/XInput.h> -#if defined (Q_OS_IRIX) -# include <X11/extensions/SGIMisc.h> -# include <wacom.h> -#endif -#endif // QT_NO_TABLET - - -// #define QT_NO_XINERAMA -#ifndef QT_NO_XINERAMA -# if 0 // ### Xsun, but how to detect it? -// Xinerama is only supported in Solaris 7 with patches 107648/108376 and -// Solaris 8 or above which introduce the X11R6.4 Xserver. -// To switch the Xinerama functionality on, you need to add the "+xinerama" -// argument to the Xsun start line. -// At least Solaris 7 and 8 are missing Xinerama system headers and function -// declarations (bug 4284701). -// The Xinerama API is not documented. In theory it could change but it -// probably won't because Sun are using it in at least dtlogin (bug 4221829). -extern "C" Bool XPanoramiXQueryExtension( - Display*, - int*, - int* -); -extern "C" Status XPanoramiXQueryVersion( - Display*, - int*, - int* -); -extern "C" Status XPanoramiXGetState( - Display*, - Drawable, - XPanoramiXInfo* -); -extern "C" Status XPanoramiXGetScreenCount( - Display *, - Drawable, - XPanoramiXInfo* -); -extern "C" Status XPanoramiXGetScreenSize( - Display*, - Drawable, - int, - XPanoramiXInfo* -); -# else // XFree86 -// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3). -extern "C" { -# include <X11/extensions/Xinerama.h> -} -# endif -#endif // QT_NO_XINERAMA - -// #define QT_NO_XRANDR -#ifndef QT_NO_XRANDR -# include <X11/extensions/Xrandr.h> -#endif // QT_NO_XRANDR - -// #define QT_NO_XRENDER -#ifndef QT_NO_XRENDER -# include <X11/extensions/Xrender.h> -#endif // QT_NO_XRENDER - -#ifndef QT_NO_XSYNC -extern "C" { -# include "X11/extensions/sync.h" -} -#endif - -// #define QT_NO_XKB -#ifndef QT_NO_XKB -# include <X11/XKBlib.h> -#endif // QT_NO_XKB - - -#if !defined(XlibSpecificationRelease) -# define X11R4 -typedef char *XPointer; -#else -# undef X11R4 -#endif - -// #define QT_NO_XIM -#if defined(X11R4) -// X11R4 does not have XIM -#define QT_NO_XIM -#elif defined(Q_OS_OSF) && (XlibSpecificationRelease < 6) -// broken in Xlib up to OSF/1 3.2 -#define QT_NO_XIM -#elif defined(Q_OS_AIX) -// broken in Xlib up to what version of AIX? -#define QT_NO_XIM -#elif defined(QT_NO_DEBUG) && defined(Q_OS_IRIX) -// XmbLookupString broken on IRIX -// XCreateIC broken when compiling -64 on IRIX 6.5.2 -#define QT_NO_XIM -#elif defined(Q_OS_HPUX) && defined(__LP64__) -// XCreateIC broken when compiling 64-bit ELF on HP-UX 11.0 -#define QT_NO_XIM -#elif defined(Q_OS_SCO) -// ### suggested by user... -// ### #define QT_NO_XIM -#endif // QT_NO_XIM - -#ifndef QT_NO_XFIXES -typedef Bool (*PtrXFixesQueryExtension)(Display *, int *, int *); -typedef Status (*PtrXFixesQueryVersion)(Display *, int *, int *); -typedef void (*PtrXFixesSetCursorName)(Display *dpy, Cursor cursor, const char *name); -typedef void (*PtrXFixesSelectSelectionInput)(Display *dpy, Window win, Atom selection, unsigned long eventMask); -#endif // QT_NO_XFIXES - -#ifndef QT_NO_XCURSOR -#include <X11/Xcursor/Xcursor.h> -typedef Cursor (*PtrXcursorLibraryLoadCursor)(Display *, const char *); -#endif // QT_NO_XCURSOR - -#ifndef QT_NO_XINERAMA -typedef Bool (*PtrXineramaQueryExtension)(Display *dpy, int *event_base, int *error_base); -typedef Bool (*PtrXineramaIsActive)(Display *dpy); -typedef XineramaScreenInfo *(*PtrXineramaQueryScreens)(Display *dpy, int *number); -#endif // QT_NO_XINERAMA - -#ifndef QT_NO_XRANDR -typedef void (*PtrXRRSelectInput)(Display *, Window, int); -typedef int (*PtrXRRUpdateConfiguration)(XEvent *); -typedef int (*PtrXRRRootToScreen)(Display *, Window); -typedef Bool (*PtrXRRQueryExtension)(Display *, int *, int *); -typedef XRRScreenSize *(*PtrXRRSizes)(Display *, int, int *); -#endif // QT_NO_XRANDR - -#ifndef QT_NO_XINPUT -typedef int (*PtrXCloseDevice)(Display *, XDevice *); -typedef XDeviceInfo* (*PtrXListInputDevices)(Display *, int *); -typedef XDevice* (*PtrXOpenDevice)(Display *, XID); -typedef void (*PtrXFreeDeviceList)(XDeviceInfo *); -typedef int (*PtrXSelectExtensionEvent)(Display *, Window, XEventClass *, int); -#endif // QT_NO_XINPUT - -/* - * Solaris patch 108652-47 and higher fixes crases in - * XRegisterIMInstantiateCallback, but the function doesn't seem to - * work. - * - * Instead, we disabled R6 input, and open the input method - * immediately at application start. - */ -#if !defined(QT_NO_XIM) && (XlibSpecificationRelease >= 6) && \ - !defined(Q_OS_SOLARIS) -#define USE_X11R6_XIM - -//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback -//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2. -//######### Many old X11R6 header files lack XSetIMValues. -//######### Therefore, we have to declare these functions ourselves. - -extern "C" Bool XRegisterIMInstantiateCallback( - Display*, - struct _XrmHashBucketRec*, - char*, - char*, - XIMProc, //XFree86 has XIDProc, which has to be wrong - XPointer -); - -extern "C" Bool XUnregisterIMInstantiateCallback( - Display*, - struct _XrmHashBucketRec*, - char*, - char*, - XIMProc, //XFree86 has XIDProc, which has to be wrong - XPointer -); - -extern "C" char *XSetIMValues(XIM /* im */, ...); - -#endif - -#ifndef QT_NO_FONTCONFIG -#include <fontconfig/fontconfig.h> -#endif - -#ifndef QT_NO_XIM -// some platforms (eg. Solaris 2.51) don't have these defines in Xlib.h -#ifndef XNResetState -#define XNResetState "resetState" -#endif -#ifndef XIMPreserveState -#define XIMPreserveState (1L<<1) -#endif -#endif - - -#ifndef X11R4 -# include <X11/Xlocale.h> -#endif // X11R4 - - -#ifndef QT_NO_MITSHM -# include <X11/extensions/XShm.h> -#endif // QT_NO_MITSHM - -QT_BEGIN_NAMESPACE - -class QWidget; - -struct QX11InfoData { - uint ref; - int screen; - int dpiX; - int dpiY; - int depth; - int cells; - Colormap colormap; - Visual *visual; - bool defaultColormap; - bool defaultVisual; - int subpixel; -}; - -class QDrag; -struct QXdndDropTransaction -{ - Time timestamp; - Window target; - Window proxy_target; - QWidget *targetWidget; - QWidget *embedding_widget; - QDrag *object; -}; - -class QMimeData; - -struct QX11Data; -extern Q_WIDGETS_EXPORT QX11Data *qt_x11Data; - -enum DesktopEnvironment { - DE_UNKNOWN, - DE_KDE, - DE_GNOME, - DE_CDE, - DE_MEEGO_COMPOSITOR, - DE_4DWM -}; - -struct QX11Data -{ - static Qt::KeyboardModifiers translateModifiers(int s); - - Window findClientWindow(Window, Atom, bool); - - // from qclipboard_x11.cpp - bool clipboardWaitForEvent(Window win, int type, XEvent *event, int timeout); - bool clipboardReadProperty(Window win, Atom property, bool deleteProperty, - QByteArray *buffer, int *size, Atom *type, int *format); - QByteArray clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm); - - // from qdnd_x11.cpp - bool dndEnable(QWidget* w, bool on); - static void xdndSetup(); - void xdndHandleEnter(QWidget *, const XEvent *, bool); - void xdndHandlePosition(QWidget *, const XEvent *, bool); - void xdndHandleStatus(QWidget *, const XEvent *, bool); - void xdndHandleLeave(QWidget *, const XEvent *, bool); - void xdndHandleDrop(QWidget *, const XEvent *, bool); - void xdndHandleFinished(QWidget *, const XEvent *, bool); - void xdndHandleSelectionRequest(const XSelectionRequestEvent *); - static bool xdndHandleBadwindow(); - QByteArray xdndAtomToString(Atom a); - Atom xdndStringToAtom(const char *); - - QString xdndMimeAtomToString(Atom a); - Atom xdndMimeStringToAtom(const QString &mimeType); - QStringList xdndMimeFormatsForAtom(Atom a); - bool xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat); - QList<Atom> xdndMimeAtomsForFormat(const QString &format); - QVariant xdndMimeConvertToFormat(Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding); - Atom xdndMimeAtomForFormat(const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding); - - QList<QXdndDropTransaction> dndDropTransactions; - - // from qmotifdnd_x11.cpp - void motifdndHandle(QWidget *, const XEvent *, bool); - void motifdndEnable(QWidget *, bool); - QVariant motifdndObtainData(const char *format); - QByteArray motifdndFormat(int n); - bool motifdnd_active; - - Display *display; - char *displayName; - bool foreignDisplay; - // current focus model - enum { - FM_Unknown = -1, - FM_Other = 0, - FM_PointerRoot = 1 - }; - int focus_model; - - // true if Qt is compiled w/ RANDR support and RANDR is supported on the connected Display - bool use_xrandr; - int xrandr_major; - int xrandr_eventbase; - int xrandr_errorbase; - - // true if Qt is compiled w/ RENDER support and RENDER is supported on the connected Display - bool use_xrender; - int xrender_major; - int xrender_version; - - // true if Qt is compiled w/ XFIXES support and XFIXES is supported on the connected Display - bool use_xfixes; - int xfixes_major; - int xfixes_eventbase; - int xfixes_errorbase; - -#ifndef QT_NO_XFIXES - PtrXFixesQueryExtension ptrXFixesQueryExtension; - PtrXFixesQueryVersion ptrXFixesQueryVersion; - PtrXFixesSetCursorName ptrXFixesSetCursorName; - PtrXFixesSelectSelectionInput ptrXFixesSelectSelectionInput; -#endif - -#ifndef QT_NO_XINPUT - PtrXCloseDevice ptrXCloseDevice; - PtrXListInputDevices ptrXListInputDevices; - PtrXOpenDevice ptrXOpenDevice; - PtrXFreeDeviceList ptrXFreeDeviceList; - PtrXSelectExtensionEvent ptrXSelectExtensionEvent; -#endif // QT_NO_XINPUT - - - // true if Qt is compiled w/ MIT-SHM support and MIT-SHM is supported on the connected Display - bool use_mitshm; - bool use_mitshm_pixmaps; - int mitshm_major; - - // true if Qt is compiled w/ Tablet support and we have a tablet. - bool use_xinput; - int xinput_major; - int xinput_eventbase; - int xinput_errorbase; - - // for XKEYBOARD support - bool use_xkb; - int xkb_major; - int xkb_eventbase; - int xkb_errorbase; - - QList<QWidget *> deferred_map; - struct ScrollInProgress { - long id; - QWidget* scrolled_widget; - int dx, dy; - }; - long sip_serial; - QList<ScrollInProgress> sip_list; - - // window managers list of supported "stuff" - Atom *net_supported_list; - // list of virtual root windows - Window *net_virtual_root_list; - // client leader window - Window wm_client_leader; - - QX11InfoData *screens; - Visual **argbVisuals; - Colormap *argbColormaps; - int screenCount; - int defaultScreen; - - Time time; - Time userTime; - - QString default_im; - - // starts to ignore bad window errors from X - static inline void ignoreBadwindow() { - qt_x11Data->ignore_badwindow = true; - qt_x11Data->seen_badwindow = false; - } - - // ends ignoring bad window errors and returns whether an error had happened. - static inline bool badwindow() { - qt_x11Data->ignore_badwindow = false; - return qt_x11Data->seen_badwindow; - } - - bool ignore_badwindow; - bool seen_badwindow; - - // options - int visual_class; - int visual_id; - int color_count; - bool custom_cmap; - - // outside visual/colormap - Visual *visual; - Colormap colormap; - -#ifndef QT_NO_XRENDER - enum { solid_fill_count = 16 }; - struct SolidFills { - XRenderColor color; - int screen; - Picture picture; - } solid_fills[solid_fill_count]; - enum { pattern_fill_count = 16 }; - struct PatternFills { - XRenderColor color; - XRenderColor bg_color; - int screen; - int style; - bool opaque; - Picture picture; - } pattern_fills[pattern_fill_count]; - Picture getSolidFill(int screen, const QColor &c); - XRenderColor preMultiply(const QColor &c); -#endif - - bool has_fontconfig; - qreal fc_scale; - bool fc_antialias; - int fc_hint_style; - - char *startupId; - - DesktopEnvironment desktopEnvironment : 8; - uint desktopVersion : 8; /* Used only for KDE */ - - /* Warning: if you modify this list, modify the names of atoms in qapplication_x11.cpp as well! */ - enum X11Atom { - // window-manager <-> client protocols - WM_PROTOCOLS, - WM_DELETE_WINDOW, - WM_TAKE_FOCUS, - _NET_WM_PING, - _NET_WM_CONTEXT_HELP, - _NET_WM_SYNC_REQUEST, - _NET_WM_SYNC_REQUEST_COUNTER, - - // ICCCM window state - WM_STATE, - WM_CHANGE_STATE, - - // Session management - WM_CLIENT_LEADER, - WM_WINDOW_ROLE, - SM_CLIENT_ID, - - // Clipboard - CLIPBOARD, - INCR, - TARGETS, - MULTIPLE, - TIMESTAMP, - SAVE_TARGETS, - CLIP_TEMPORARY, - _QT_SELECTION, - _QT_CLIPBOARD_SENTINEL, - _QT_SELECTION_SENTINEL, - CLIPBOARD_MANAGER, - - RESOURCE_MANAGER, - - _XSETROOT_ID, - - _QT_SCROLL_DONE, - _QT_INPUT_ENCODING, - - _MOTIF_WM_HINTS, - - DTWM_IS_RUNNING, - ENLIGHTENMENT_DESKTOP, - _DT_SAVE_MODE, - _SGI_DESKS_MANAGER, - - // EWMH (aka NETWM) - _NET_SUPPORTED, - _NET_VIRTUAL_ROOTS, - _NET_WORKAREA, - - _NET_MOVERESIZE_WINDOW, - _NET_WM_MOVERESIZE, - - _NET_WM_NAME, - _NET_WM_ICON_NAME, - _NET_WM_ICON, - - _NET_WM_PID, - - _NET_WM_WINDOW_OPACITY, - - _NET_WM_STATE, - _NET_WM_STATE_ABOVE, - _NET_WM_STATE_BELOW, - _NET_WM_STATE_FULLSCREEN, - _NET_WM_STATE_MAXIMIZED_HORZ, - _NET_WM_STATE_MAXIMIZED_VERT, - _NET_WM_STATE_MODAL, - _NET_WM_STATE_STAYS_ON_TOP, - _NET_WM_STATE_DEMANDS_ATTENTION, - - _NET_WM_USER_TIME, - _NET_WM_USER_TIME_WINDOW, - _NET_WM_FULL_PLACEMENT, - - _NET_WM_WINDOW_TYPE, - _NET_WM_WINDOW_TYPE_DESKTOP, - _NET_WM_WINDOW_TYPE_DOCK, - _NET_WM_WINDOW_TYPE_TOOLBAR, - _NET_WM_WINDOW_TYPE_MENU, - _NET_WM_WINDOW_TYPE_UTILITY, - _NET_WM_WINDOW_TYPE_SPLASH, - _NET_WM_WINDOW_TYPE_DIALOG, - _NET_WM_WINDOW_TYPE_DROPDOWN_MENU, - _NET_WM_WINDOW_TYPE_POPUP_MENU, - _NET_WM_WINDOW_TYPE_TOOLTIP, - _NET_WM_WINDOW_TYPE_NOTIFICATION, - _NET_WM_WINDOW_TYPE_COMBO, - _NET_WM_WINDOW_TYPE_DND, - _NET_WM_WINDOW_TYPE_NORMAL, - _KDE_NET_WM_WINDOW_TYPE_OVERRIDE, - - _KDE_NET_WM_FRAME_STRUT, - - _NET_STARTUP_INFO, - _NET_STARTUP_INFO_BEGIN, - - _NET_SUPPORTING_WM_CHECK, - - _NET_WM_CM_S0, - - _NET_SYSTEM_TRAY_VISUAL, - - _NET_ACTIVE_WINDOW, - - // Property formats - COMPOUND_TEXT, - TEXT, - UTF8_STRING, - - // Xdnd - XdndEnter, - XdndPosition, - XdndStatus, - XdndLeave, - XdndDrop, - XdndFinished, - XdndTypelist, - XdndActionList, - - XdndSelection, - - XdndAware, - XdndProxy, - - XdndActionCopy, - XdndActionLink, - XdndActionMove, - XdndActionPrivate, - - // Motif DND - _MOTIF_DRAG_AND_DROP_MESSAGE, - _MOTIF_DRAG_INITIATOR_INFO, - _MOTIF_DRAG_RECEIVER_INFO, - _MOTIF_DRAG_WINDOW, - _MOTIF_DRAG_TARGETS, - - XmTRANSFER_SUCCESS, - XmTRANSFER_FAILURE, - - // Xkb - _XKB_RULES_NAMES, - - // XEMBED - _XEMBED, - _XEMBED_INFO, - - XWacomStylus, - XWacomCursor, - XWacomEraser, - - XTabletStylus, - XTabletEraser, - - NPredefinedAtoms, - - _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, - NAtoms - }; - Atom atoms[NAtoms]; - - bool isSupportedByWM(Atom atom); - - bool compositingManagerRunning; - -#ifndef QT_NO_XCURSOR - PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor; -#endif // QT_NO_XCURSOR - -#ifndef QT_NO_XINERAMA - PtrXineramaQueryExtension ptrXineramaQueryExtension; - PtrXineramaIsActive ptrXineramaIsActive; - PtrXineramaQueryScreens ptrXineramaQueryScreens; -#endif // QT_NO_XINERAMA - -#ifndef QT_NO_XRANDR - PtrXRRSelectInput ptrXRRSelectInput; - PtrXRRUpdateConfiguration ptrXRRUpdateConfiguration; - PtrXRRRootToScreen ptrXRRRootToScreen; - PtrXRRQueryExtension ptrXRRQueryExtension; - PtrXRRSizes ptrXRRSizes; -#endif // QT_NO_XRANDR -}; - -extern QX11Data *qt_x11Data; -#define ATOM(x) qt_x11Data->atoms[QX11Data::x] -#define X11 qt_x11Data - -// rename a couple of X defines to get rid of name clashes -// resolve the conflict between X11's FocusIn and QEvent::FocusIn -enum { - XFocusOut = FocusOut, - XFocusIn = FocusIn, - XKeyPress = KeyPress, - XKeyRelease = KeyRelease, - XNone = None, - XRevertToParent = RevertToParent, - XGrayScale = GrayScale, - XCursorShape = CursorShape -}; -#undef FocusOut -#undef FocusIn -#undef KeyPress -#undef KeyRelease -#undef None -#undef RevertToParent -#undef GrayScale -#undef CursorShape - -#ifdef FontChange -#undef FontChange -#endif - -Q_DECLARE_TYPEINFO(XPoint, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(XRectangle, Q_PRIMITIVE_TYPE); -Q_DECLARE_TYPEINFO(XChar2b, Q_PRIMITIVE_TYPE); -#ifndef QT_NO_XRENDER -Q_DECLARE_TYPEINFO(XGlyphElt32, Q_PRIMITIVE_TYPE); -#endif - - -QT_END_NAMESPACE - -#endif // QT_X11_P_H diff --git a/src/widgets/platforms/x11/qwidget_x11.cpp b/src/widgets/platforms/x11/qwidget_x11.cpp deleted file mode 100644 index 5bb59b26c9..0000000000 --- a/src/widgets/platforms/x11/qwidget_x11.cpp +++ /dev/null @@ -1,3149 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qevent.h" -#include "qwidget.h" -#include "qdesktopwidget.h" -#include "qapplication.h" -#include "qapplication_p.h" -#include "qnamespace.h" -#include "qpainter.h" -#include "qbitmap.h" -#include "qlayout.h" -#include "qtextcodec.h" -#include "qelapsedtimer.h" -#include "qcursor.h" -#include "qstack.h" -#include "qcolormap.h" -#include "qdebug.h" -#include "qmenu.h" -#include "private/qmenu_p.h" -#include "private/qbackingstore_p.h" -#include "private/qwindowsurface_x11_p.h" - -//extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); //qapplication_x11.cpp - -#include <private/qpixmap_x11_p.h> -#include <private/qpaintengine_x11_p.h> -#include "qt_x11_p.h" -#include "qx11info_x11.h" - -#include <stdlib.h> - -//#define ALIEN_DEBUG - -// defined in qapplication_x11.cpp -//bool qt_wstate_iconified(WId); -//void qt_updated_rootinfo(); - - -#if !defined(QT_NO_IM) -#include "qinputcontext.h" -#include "qinputcontextfactory.h" -#endif - -#include "qwidget_p.h" - -#define XCOORD_MAX 16383 -#define WRECT_MAX 8191 - -QT_BEGIN_NAMESPACE - -extern bool qt_nograb(); - -QWidget *QWidgetPrivate::mouseGrabber = 0; -QWidget *QWidgetPrivate::keyboardGrabber = 0; - -void qt_net_remove_user_time(QWidget *tlw); -void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp); - -int qt_x11_create_desktop_on_screen = -1; - -extern void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp); - -// MWM support -struct QtMWMHints { - ulong flags, functions, decorations; - long input_mode; - ulong status; -}; - -enum { - MWM_HINTS_FUNCTIONS = (1L << 0), - - MWM_FUNC_ALL = (1L << 0), - MWM_FUNC_RESIZE = (1L << 1), - MWM_FUNC_MOVE = (1L << 2), - MWM_FUNC_MINIMIZE = (1L << 3), - MWM_FUNC_MAXIMIZE = (1L << 4), - MWM_FUNC_CLOSE = (1L << 5), - - MWM_HINTS_DECORATIONS = (1L << 1), - - MWM_DECOR_ALL = (1L << 0), - MWM_DECOR_BORDER = (1L << 1), - MWM_DECOR_RESIZEH = (1L << 2), - MWM_DECOR_TITLE = (1L << 3), - MWM_DECOR_MENU = (1L << 4), - MWM_DECOR_MINIMIZE = (1L << 5), - MWM_DECOR_MAXIMIZE = (1L << 6), - - MWM_HINTS_INPUT_MODE = (1L << 2), - - MWM_INPUT_MODELESS = 0L, - MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, - MWM_INPUT_FULL_APPLICATION_MODAL = 3L -}; - - -static QtMWMHints getMWMHints(Display *display, Window window) -{ - QtMWMHints mwmhints; - - Atom type; - int format; - ulong nitems, bytesLeft; - uchar *data = 0; - if ((XGetWindowProperty(display, window, ATOM(_MOTIF_WM_HINTS), 0, 5, false, - ATOM(_MOTIF_WM_HINTS), &type, &format, &nitems, &bytesLeft, - &data) == Success) - && (type == ATOM(_MOTIF_WM_HINTS) - && format == 32 - && nitems >= 5)) { - mwmhints = *(reinterpret_cast<QtMWMHints *>(data)); - } else { - mwmhints.flags = 0L; - mwmhints.functions = MWM_FUNC_ALL; - mwmhints.decorations = MWM_DECOR_ALL; - mwmhints.input_mode = 0L; - mwmhints.status = 0L; - } - - if (data) - XFree(data); - - return mwmhints; -} - -static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints) -{ - if (mwmhints.flags != 0l) { - XChangeProperty(display, window, ATOM(_MOTIF_WM_HINTS), ATOM(_MOTIF_WM_HINTS), 32, - PropModeReplace, (unsigned char *) &mwmhints, 5); - } else { - XDeleteProperty(display, window, ATOM(_MOTIF_WM_HINTS)); - } -} - -// Returns true if we should set WM_TRANSIENT_FOR on \a w -static inline bool isTransient(const QWidget *w) -{ - return ((w->windowType() == Qt::Dialog - || w->windowType() == Qt::Sheet - || w->windowType() == Qt::Tool - || w->windowType() == Qt::SplashScreen - || w->windowType() == Qt::ToolTip - || w->windowType() == Qt::Drawer - || w->windowType() == Qt::Popup) - && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); -} - -static void do_size_hints(QWidget* widget, QWExtra *x); - -/***************************************************************************** - QWidget member functions - *****************************************************************************/ - -const uint stdWidgetEventMask = // X event mask - (uint)( - KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask | - KeymapStateMask | - ButtonMotionMask | PointerMotionMask | - EnterWindowMask | LeaveWindowMask | - FocusChangeMask | - ExposureMask | - PropertyChangeMask | - StructureNotifyMask - ); - -const uint stdDesktopEventMask = // X event mask - (uint)( - KeymapStateMask | - EnterWindowMask | LeaveWindowMask | - PropertyChangeMask - ); - - -/* - The qt_ functions below are implemented in qwidgetcreate_x11.cpp. -*/ - -Window qt_XCreateWindow(const QWidget *creator, - Display *display, Window parent, - int x, int y, uint w, uint h, - int borderwidth, int depth, - uint windowclass, Visual *visual, - ulong valuemask, XSetWindowAttributes *attributes); -Window qt_XCreateSimpleWindow(const QWidget *creator, - Display *display, Window parent, - int x, int y, uint w, uint h, int borderwidth, - ulong border, ulong background); -void qt_XDestroyWindow(const QWidget *destroyer, - Display *display, Window window); - - -static void qt_insert_sip(QWidget* scrolled_widget, int dx, int dy) -{ - if (!scrolled_widget->isWindow() && !scrolled_widget->internalWinId()) - return; - QX11Data::ScrollInProgress sip = { X11->sip_serial++, scrolled_widget, dx, dy }; - X11->sip_list.append(sip); - - XClientMessageEvent client_message; - client_message.type = ClientMessage; - client_message.window = scrolled_widget->internalWinId(); - client_message.format = 32; - client_message.message_type = ATOM(_QT_SCROLL_DONE); - client_message.data.l[0] = sip.id; - - XSendEvent(X11->display, scrolled_widget->internalWinId(), False, NoEventMask, - (XEvent*)&client_message); -} - -static int qt_sip_count(QWidget* scrolled_widget) -{ - int sips=0; - - for (int i = 0; i < X11->sip_list.size(); ++i) { - const QX11Data::ScrollInProgress &sip = X11->sip_list.at(i); - if (sip.scrolled_widget == scrolled_widget) - sips++; - } - - return sips; -} - -static void create_wm_client_leader() -{ - if (X11->wm_client_leader) return; - - X11->wm_client_leader = - XCreateSimpleWindow(X11->display, - QX11Info::appRootWindow(), - 0, 0, 1, 1, 0, 0, 0); - - // set client leader property to itself - XChangeProperty(X11->display, - X11->wm_client_leader, ATOM(WM_CLIENT_LEADER), - XA_WINDOW, 32, PropModeReplace, - (unsigned char *)&X11->wm_client_leader, 1); - -#ifndef QT_NO_SESSIONMANAGER - // If we are session managed, inform the window manager about it - QByteArray session = qApp->sessionId().toLatin1(); - if (!session.isEmpty()) { - XChangeProperty(X11->display, - X11->wm_client_leader, ATOM(SM_CLIENT_ID), - XA_STRING, 8, PropModeReplace, - (unsigned char *)session.data(), session.size()); - } -#endif -} - -/*! - \internal - Update the X11 cursor of the widget w. - \a force is true if this function is called from dispatchEnterLeave, it means that the - mouse is actually directly under this widget. - */ -void qt_x11_enforce_cursor(QWidget * w, bool force) -{ - if (!w->testAttribute(Qt::WA_WState_Created)) - return; - - static QPointer<QWidget> lastUnderMouse = 0; - if (force) { - lastUnderMouse = w; - } else if (lastUnderMouse && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) { - w = lastUnderMouse; - } else if (!w->internalWinId()) { - return; //the mouse is not under this widget, and it's not native, so don't change it - } - - while (!w->internalWinId() && w->parentWidget() && !w->isWindow() && !w->testAttribute(Qt::WA_SetCursor)) - w = w->parentWidget(); - - QWidget *nativeParent = w; - if (!w->internalWinId()) - nativeParent = w->nativeParentWidget(); - // This does the same as effectiveWinId(), but since it is possible - // to not have a native parent widget due to a special hack in - // qwidget for reparenting widgets to a different X11 screen, - // added additional check to make sure native parent widget exists. - if (!nativeParent || !nativeParent->internalWinId()) - return; - WId winid = nativeParent->internalWinId(); - - if (w->isWindow() || w->testAttribute(Qt::WA_SetCursor)) { -#ifndef QT_NO_CURSOR - QCursor *oc = QApplication::overrideCursor(); - if (oc) { - XDefineCursor(X11->display, winid, oc->handle()); - } else if (w->isEnabled()) { - XDefineCursor(X11->display, winid, w->cursor().handle()); - } else { - // enforce the windows behavior of clearing the cursor on - // disabled widgets - XDefineCursor(X11->display, winid, XNone); - } -#endif - } else { - XDefineCursor(X11->display, winid, XNone); - } -} - -Q_WIDGETS_EXPORT void qt_x11_enforce_cursor(QWidget * w) -{ - qt_x11_enforce_cursor(w, false); -} - -void qt_x11_wait_for_window_manager(QWidget *w, bool sendPostedEvents) -{ - if (!w || (!w->isWindow() && !w->internalWinId())) - return; - QApplication::flush(); - XEvent ev; - QElapsedTimer t; - t.start(); - static const int maximumWaitTime = 2000; - if (!w->testAttribute(Qt::WA_WState_Created)) - return; - - WId winid = w->internalWinId(); - - // first deliver events that are already in the local queue - if (sendPostedEvents) - QApplication::sendPostedEvents(); - - // the normal sequence is: - // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose - // with X11BypassWindowManagerHint: - // ConfigureNotify ... MapNotify ... Expose - - enum State { - Initial, Mapped - } state = Initial; - - do { - if (XEventsQueued(X11->display, QueuedAlready)) { - XNextEvent(X11->display, &ev); - qApp->x11ProcessEvent(&ev); - - switch (state) { - case Initial: - if (ev.type == MapNotify && ev.xany.window == winid) - state = Mapped; - break; - case Mapped: - if (ev.type == Expose && ev.xany.window == winid) - return; - break; - } - } else { - if (!XEventsQueued(X11->display, QueuedAfterFlush)) - qApp->syncX(); // non-busy wait - } - if (t.elapsed() > maximumWaitTime) - return; - } while(1); -} - -Q_WIDGETS_EXPORT void qt_x11_wait_for_window_manager(QWidget *w) -{ - qt_x11_wait_for_window_manager(w, true); -} - -void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0) -{ - if (!w->isVisible()) // not managed by the window manager - return; - - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = ATOM(_NET_WM_STATE); - e.xclient.display = X11->display; - e.xclient.window = w->internalWinId(); - e.xclient.format = 32; - e.xclient.data.l[0] = set ? 1 : 0; - e.xclient.data.l[1] = one; - e.xclient.data.l[2] = two; - e.xclient.data.l[3] = 0; - e.xclient.data.l[4] = 0; - XSendEvent(X11->display, RootWindow(X11->display, w->x11Info().screen()), - false, (SubstructureNotifyMask | SubstructureRedirectMask), &e); -} - -struct QX11WindowAttributes { - const XWindowAttributes *att; -}; - -void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const XWindowAttributes &a) -{ - QX11WindowAttributes att; - att.att = &a; - qt_x11_getX11InfoForWindow(xinfo,att); -} - - -static QVector<Atom> getNetWmState(QWidget *w) -{ - QVector<Atom> returnValue; - - // Don't read anything, just get the size of the property data - Atom actualType; - int actualFormat; - ulong propertyLength; - ulong bytesLeft; - uchar *propertyData = 0; - if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, 0, - False, XA_ATOM, &actualType, &actualFormat, - &propertyLength, &bytesLeft, &propertyData) == Success - && actualType == XA_ATOM && actualFormat == 32) { - returnValue.resize(bytesLeft / 4); - XFree((char*) propertyData); - propertyData = 0; - - // fetch all data - if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, - returnValue.size(), False, XA_ATOM, &actualType, &actualFormat, - &propertyLength, &bytesLeft, &propertyData) != Success) { - returnValue.clear(); - } else if (propertyLength != (ulong)returnValue.size()) { - returnValue.resize(propertyLength); - } - - // put it into netWmState - if (!returnValue.isEmpty()) { - memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom)); - } - if (propertyData) - XFree((char*) propertyData); - } - - return returnValue; -} - -void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) -{ - Q_Q(QWidget); - Qt::WindowType type = q->windowType(); - Qt::WindowFlags &flags = data.window_flags; - QWidget *parentWidget = q->parentWidget(); - - if (type == Qt::ToolTip) - flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; - if (type == Qt::Popup) - flags |= Qt::X11BypassWindowManagerHint; - - bool topLevel = (flags & Qt::Window); - bool popup = (type == Qt::Popup); - bool desktop = (type == Qt::Desktop); - bool tool = (type == Qt::Tool || type == Qt::SplashScreen - || type == Qt::ToolTip || type == Qt::Drawer); - -#ifdef ALIEN_DEBUG - qDebug() << "QWidgetPrivate::create_sys START:" << q << "topLevel?" << topLevel << "WId:" - << window << "initializeWindow:" << initializeWindow << "destroyOldWindow" << destroyOldWindow; -#endif - if (topLevel) { - if (parentWidget) { // if our parent stays on top, so must we - QWidget *ptl = parentWidget->window(); - if(ptl && (ptl->windowFlags() & Qt::WindowStaysOnTopHint)) - flags |= Qt::WindowStaysOnTopHint; - } - - if (type == Qt::SplashScreen) { - if (X11->isSupportedByWM(ATOM(_NET_WM_WINDOW_TYPE_SPLASH))) { - flags &= ~Qt::X11BypassWindowManagerHint; - } else { - flags |= Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint; - } - } - // All these buttons depend on the system menu, so we enable it - if (flags & (Qt::WindowMinimizeButtonHint - | Qt::WindowMaximizeButtonHint - | Qt::WindowContextHelpButtonHint)) - flags |= Qt::WindowSystemMenuHint; - } - - - Window parentw, destroyw = 0; - WId id = 0; - - // always initialize - if (!window) - initializeWindow = true; - - QX11Info *parentXinfo = parentWidget ? &parentWidget->d_func()->xinfo : 0; - - if (desktop && - qt_x11_create_desktop_on_screen >= 0 && - qt_x11_create_desktop_on_screen != xinfo.screen()) { - // desktop on a certain screen other than the default requested - QX11InfoData *xd = &X11->screens[qt_x11_create_desktop_on_screen]; - xinfo.setX11Data(xd); - } else if (parentXinfo && (parentXinfo->screen() != xinfo.screen() - || (parentXinfo->visual() != xinfo.visual() - && !q->inherits("QGLWidget")))) - { - // QGLWidgets have to be excluded here as they have a - // specially crafted QX11Info structure which can't be swapped - // out with the parent widgets QX11Info. The parent visual, - // for instance, might not even be GL capable. - xinfo = *parentXinfo; - } - - //get display, screen number, root window and desktop geometry for - //the current screen - Display *dpy = X11->display; - int scr = xinfo.screen(); - Window root_win = RootWindow(dpy, scr); - int sw = DisplayWidth(dpy,scr); - int sh = DisplayHeight(dpy,scr); - - if (desktop) { // desktop widget - popup = false; // force these flags off - data.crect.setRect(0, 0, sw, sh); - } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) { - QDesktopWidget *desktopWidget = qApp->desktop(); - if (desktopWidget->isVirtualDesktop()) { - QRect r = desktopWidget->screenGeometry(); - sw = r.width(); - sh = r.height(); - } - - int width = sw / 2; - int height = 4 * sh / 10; - if (extra) { - width = qMax(qMin(width, extra->maxw), extra->minw); - height = qMax(qMin(height, extra->maxh), extra->minh); - } - data.crect.setSize(QSize(width, height)); - } - - parentw = topLevel ? root_win : parentWidget->effectiveWinId(); - - XSetWindowAttributes wsa; - - if (window) { // override the old window - if (destroyOldWindow) { - if (topLevel) - X11->dndEnable(q, false); - destroyw = data.winid; - } - id = window; - setWinId(window); - XWindowAttributes a; - XGetWindowAttributes(dpy, window, &a); - data.crect.setRect(a.x, a.y, a.width, a.height); - - if (a.map_state == IsUnmapped) - q->setAttribute(Qt::WA_WState_Visible, false); - else - q->setAttribute(Qt::WA_WState_Visible); - - qt_x11_getX11InfoForWindow(&xinfo,a); - - } else if (desktop) { // desktop widget -#ifdef QWIDGET_EXTRA_DEBUG - qDebug() << "create desktop"; -#endif - id = (WId)parentw; // id = root window -// QWidget *otherDesktop = find(id); // is there another desktop? -// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) { -// otherDesktop->d->setWinId(0); // remove id from widget mapper -// d->setWinId(id); // make sure otherDesktop is -// otherDesktop->d->setWinId(id); // found first -// } else { - setWinId(id); -// } - } else if (topLevel || q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { -#ifdef QWIDGET_EXTRA_DEBUG - static int topLevels = 0; - static int children = 0; - if (parentw == root_win) - qDebug() << "create toplevel" << ++topLevels; - else - qDebug() << "create child" << ++children; -#endif - QRect safeRect = data.crect; //##### must handle huge sizes as well.... i.e. wrect - if (safeRect.width() < 1|| safeRect.height() < 1) { - if (topLevel) { - // top-levels must be at least 1x1 - safeRect.setSize(safeRect.size().expandedTo(QSize(1, 1))); - } else { - // create it way off screen, and rely on - // setWSGeometry() to do the right thing with it later - safeRect = QRect(-1000,-1000,1,1); - } - } -#ifndef QT_NO_XRENDER - int screen = xinfo.screen(); - if (topLevel && X11->use_xrender - && xinfo.depth() != 32 && X11->argbVisuals[screen] - && q->testAttribute(Qt::WA_TranslucentBackground)) - { - QX11InfoData *xd = xinfo.getX11Data(true); - - xd->screen = screen; - xd->visual = X11->argbVisuals[screen]; - xd->colormap = X11->argbColormaps[screen]; - xd->depth = 32; - xd->defaultVisual = false; - xd->defaultColormap = false; - xd->cells = xd->visual->map_entries; - xinfo.setX11Data(xd); - } -#endif - if (xinfo.defaultVisual() && xinfo.defaultColormap()) { - id = (WId)qt_XCreateSimpleWindow(q, dpy, parentw, - safeRect.left(), safeRect.top(), - safeRect.width(), safeRect.height(), - 0, - BlackPixel(dpy, xinfo.screen()), - WhitePixel(dpy, xinfo.screen())); - } else { - wsa.background_pixel = WhitePixel(dpy, xinfo.screen()); - wsa.border_pixel = BlackPixel(dpy, xinfo.screen()); - wsa.colormap = xinfo.colormap(); - id = (WId)qt_XCreateWindow(q, dpy, parentw, - safeRect.left(), safeRect.top(), - safeRect.width(), safeRect.height(), - 0, xinfo.depth(), InputOutput, - (Visual *) xinfo.visual(), - CWBackPixel|CWBorderPixel|CWColormap, - &wsa); - } - - setWinId(id); // set widget id/handle + hd - } - -#ifndef QT_NO_XRENDER - if (picture) { - XRenderFreePicture(X11->display, picture); - picture = 0; - } - - if (X11->use_xrender && !desktop && q->internalWinId()) { - XRenderPictFormat *format = XRenderFindVisualFormat(dpy, (Visual *) xinfo.visual()); - if (format) - picture = XRenderCreatePicture(dpy, id, format, 0, 0); - } -#endif // QT_NO_XRENDER - - QtMWMHints mwmhints; - mwmhints.flags = 0L; - mwmhints.functions = 0L; - mwmhints.decorations = 0; - mwmhints.input_mode = 0L; - mwmhints.status = 0L; - - if (topLevel) { - ulong wsa_mask = 0; - if (type != Qt::SplashScreen) { // && customize) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - - bool customize = flags & Qt::CustomizeWindowHint; - if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { - mwmhints.decorations |= MWM_DECOR_BORDER; - mwmhints.decorations |= MWM_DECOR_RESIZEH; - - if (flags & Qt::WindowTitleHint) - mwmhints.decorations |= MWM_DECOR_TITLE; - - if (flags & Qt::WindowSystemMenuHint) - mwmhints.decorations |= MWM_DECOR_MENU; - - if (flags & Qt::WindowMinimizeButtonHint) { - mwmhints.decorations |= MWM_DECOR_MINIMIZE; - mwmhints.functions |= MWM_FUNC_MINIMIZE; - } - - if (flags & Qt::WindowMaximizeButtonHint) { - mwmhints.decorations |= MWM_DECOR_MAXIMIZE; - mwmhints.functions |= MWM_FUNC_MAXIMIZE; - } - - if (flags & Qt::WindowCloseButtonHint) - mwmhints.functions |= MWM_FUNC_CLOSE; - } - } else { - // if type == Qt::SplashScreen - mwmhints.decorations = MWM_DECOR_ALL; - } - - if (tool) { - wsa.save_under = True; - wsa_mask |= CWSaveUnder; - } - - if (flags & Qt::X11BypassWindowManagerHint) { - wsa.override_redirect = True; - wsa_mask |= CWOverrideRedirect; - } - - if (wsa_mask && initializeWindow) { - Q_ASSERT(id); - XChangeWindowAttributes(dpy, id, wsa_mask, &wsa); - } - - if (mwmhints.functions != 0) { - mwmhints.flags |= MWM_HINTS_FUNCTIONS; - mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE; - } else { - mwmhints.functions = MWM_FUNC_ALL; - } - - if (!(flags & Qt::FramelessWindowHint) - && flags & Qt::CustomizeWindowHint - && flags & Qt::WindowTitleHint - && !(flags & - (Qt::WindowMinimizeButtonHint - | Qt::WindowMaximizeButtonHint - | Qt::WindowCloseButtonHint))) { - // a special case - only the titlebar without any button - mwmhints.flags = MWM_HINTS_FUNCTIONS; - mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE; - mwmhints.decorations = 0; - } - } - - if (!initializeWindow) { - // do no initialization - } else if (popup) { // popup widget - // set EWMH window types - setNetWmWindowTypes(); - - wsa.override_redirect = True; - wsa.save_under = True; - Q_ASSERT(id); - XChangeWindowAttributes(dpy, id, CWOverrideRedirect | CWSaveUnder, - &wsa); - } else if (topLevel && !desktop) { // top-level widget - if (!X11->wm_client_leader) - create_wm_client_leader(); - - // note: WM_TRANSIENT_FOR is set in QWidgetPrivate::show_sys() - - XSizeHints size_hints; - size_hints.flags = USSize | PSize | PWinGravity; - size_hints.x = data.crect.left(); - size_hints.y = data.crect.top(); - size_hints.width = data.crect.width(); - size_hints.height = data.crect.height(); - size_hints.win_gravity = - QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; - - XWMHints wm_hints; // window manager hints - memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy - wm_hints.flags = InputHint | StateHint | WindowGroupHint; - wm_hints.input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True; - wm_hints.initial_state = NormalState; - wm_hints.window_group = X11->wm_client_leader; - - XClassHint class_hint; - QByteArray appName = qAppName().toLatin1(); - class_hint.res_name = appName.data(); // application name - class_hint.res_class = const_cast<char *>(QX11Info::appClass()); // application class - - XSetWMProperties(dpy, id, 0, 0, - qApp->d_func()->argv, qApp->d_func()->argc, - &size_hints, &wm_hints, &class_hint); - - XResizeWindow(dpy, id, - qBound(1, data.crect.width(), XCOORD_MAX), - qBound(1, data.crect.height(), XCOORD_MAX)); - XStoreName(dpy, id, appName.data()); - Atom protocols[5]; - int n = 0; - protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol - protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol - protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol -#ifndef QT_NO_XSYNC - protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol -#endif // QT_NO_XSYNC - if (flags & Qt::WindowContextHelpButtonHint) - protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP); - XSetWMProtocols(dpy, id, protocols, n); - - // set mwm hints - SetMWMHints(dpy, id, mwmhints); - - // set EWMH window types - setNetWmWindowTypes(); - - // set _NET_WM_PID - long curr_pid = getpid(); - XChangeProperty(dpy, id, ATOM(_NET_WM_PID), XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &curr_pid, 1); - - // when we create a toplevel widget, the frame strut should be dirty - data.fstrut_dirty = 1; - - // declare the widget's window role - if (QTLWExtra *topData = maybeTopData()) { - if (!topData->role.isEmpty()) { - QByteArray windowRole = topData->role.toUtf8(); - XChangeProperty(dpy, id, - ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace, - (unsigned char *)windowRole.constData(), windowRole.length()); - } - } - - // set client leader property - XChangeProperty(dpy, id, ATOM(WM_CLIENT_LEADER), - XA_WINDOW, 32, PropModeReplace, - (unsigned char *)&X11->wm_client_leader, 1); - } else { - // non-toplevel widgets don't have a frame, so no need to - // update the strut - data.fstrut_dirty = 0; - } - - if (initializeWindow && q->internalWinId()) { - // don't erase when resizing - wsa.bit_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; - Q_ASSERT(id); - XChangeWindowAttributes(dpy, id, CWBitGravity, &wsa); - } - - // set X11 event mask - if (desktop) { -// QWidget* main_desktop = find(id); -// if (main_desktop->testWFlags(Qt::WPaintDesktop)) -// XSelectInput(dpy, id, stdDesktopEventMask | ExposureMask); -// else - XSelectInput(dpy, id, stdDesktopEventMask); - } else if (q->internalWinId()) { - XSelectInput(dpy, id, stdWidgetEventMask); -#if !defined (QT_NO_TABLET) - QTabletDeviceDataList *tablet_list = qt_tablet_devices(); - if (X11->ptrXSelectExtensionEvent) { - for (int i = 0; i < tablet_list->size(); ++i) { - QTabletDeviceData tablet = tablet_list->at(i); - X11->ptrXSelectExtensionEvent(dpy, id, reinterpret_cast<XEventClass*>(tablet.eventList), - tablet.eventCount); - } - } -#endif - } - - if (desktop) { - q->setAttribute(Qt::WA_WState_Visible); - } else if (topLevel) { // set X cursor - if (initializeWindow) { - qt_x11_enforce_cursor(q); - - if (QTLWExtra *topData = maybeTopData()) - if (!topData->caption.isEmpty()) - setWindowTitle_helper(topData->caption); - - //always enable dnd: it's not worth the effort to maintain the state - // NOTE: this always creates topData() - X11->dndEnable(q, true); - - if (maybeTopData() && maybeTopData()->opacity != 255) - q->setWindowOpacity(maybeTopData()->opacity/255.); - - } - } else if (q->internalWinId()) { - qt_x11_enforce_cursor(q); - if (QWidget *p = q->parentWidget()) // reset the cursor on the native parent - qt_x11_enforce_cursor(p); - } - - if (extra && !extra->mask.isEmpty() && q->internalWinId()) - XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0, - extra->mask.handle(), ShapeSet); - - if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) { - QInputContext *inputContext = q->inputContext(); - if (inputContext) - inputContext->setFocusWidget(q); - } - - if (destroyw) { - qt_XDestroyWindow(q, dpy, destroyw); - if (QTLWExtra *topData = maybeTopData()) { -#ifndef QT_NO_XSYNC - if (topData->syncUpdateCounter) - XSyncDestroyCounter(dpy, topData->syncUpdateCounter); -#endif - // we destroyed our old window - reset the top-level state - createTLSysExtra(); - } - } - - // newly created windows are positioned at the window system's - // (0,0) position. If the parent uses wrect mapping to expand the - // coordinate system, we must also adjust this widget's window - // system position - if (!topLevel && !parentWidget->data->wrect.topLeft().isNull()) - setWSGeometry(); - else if (topLevel && (data.crect.width() == 0 || data.crect.height() == 0)) - q->setAttribute(Qt::WA_OutsideWSRange, true); - - if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) { - Q_ASSERT(q->internalWinId()); - XMapWindow(X11->display, q->internalWinId()); - // Ensure that mapped alien widgets are flushed immediately when re-created as native widgets. - if (QWindowSurface *surface = q->windowSurface()) - surface->flush(q, q->rect(), q->mapTo(surface->window(), QPoint())); - } - -#ifdef ALIEN_DEBUG - qDebug() << "QWidgetPrivate::create_sys END:" << q; -#endif -} - -static void qt_x11_recreateWidget(QWidget *widget) -{ - if (widget->inherits("QGLWidget")) { - // We send QGLWidgets a ParentChange event which causes them to - // recreate their GL context, which in turn causes them to choose - // their visual again. Now that WA_TranslucentBackground is set, - // QGLContext::chooseVisual will select an ARGB visual. - - // QGLWidget expects a ParentAboutToChange to be sent first - QEvent aboutToChangeEvent(QEvent::ParentAboutToChange); - QApplication::sendEvent(widget, &aboutToChangeEvent); - - QEvent parentChangeEvent(QEvent::ParentChange); - QApplication::sendEvent(widget, &parentChangeEvent); - } else { - // For regular widgets, reparent them with their parent which - // also triggers a recreation of the native window - QPoint pos = widget->pos(); - bool visible = widget->isVisible(); - if (visible) - widget->hide(); - - widget->setParent(widget->parentWidget(), widget->windowFlags()); - widget->move(pos); - if (visible) - widget->show(); - } -} - -static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget) -{ - if (widget->internalWinId()) - qt_x11_recreateWidget(widget); - - const QObjectList &children = widget->children(); - for (int i = 0; i < children.size(); ++i) { - QWidget *child = qobject_cast<QWidget*>(children.at(i)); - if (child) - qt_x11_recreateNativeWidgetsRecursive(child); - } -} - -void QWidgetPrivate::x11UpdateIsOpaque() -{ -#ifndef QT_NO_XRENDER - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground)) - return; - - bool topLevel = (data.window_flags & Qt::Window); - int screen = xinfo.screen(); - if (topLevel && X11->use_xrender - && X11->argbVisuals[screen] && xinfo.depth() != 32) - { - qt_x11_recreateNativeWidgetsRecursive(q); - } -#endif -} - -/* - Returns true if the background is inherited; otherwise returns - false. - - Mainly used in the paintOnScreen case. -*/ -bool QWidgetPrivate::isBackgroundInherited() const -{ - Q_Q(const QWidget); - - // windows do not inherit their background - if (q->isWindow() || q->windowType() == Qt::SubWindow) - return false; - - if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent)) - return false; - - const QPalette &pal = q->palette(); - QPalette::ColorRole bg = q->backgroundRole(); - QBrush brush = pal.brush(bg); - - // non opaque brushes leaves us no choice, we must inherit - if (!q->autoFillBackground() || !brush.isOpaque()) - return true; - - if (brush.style() == Qt::SolidPattern) { - // the background is just a solid color. If there is no - // propagated contents, then we claim as performance - // optimization that it was not inheritet. This is the normal - // case in standard Windows or Motif style. - const QWidget *w = q->parentWidget(); - if (!w->d_func()->isBackgroundInherited()) - return false; - } - - return true; -} - -void QWidget::destroy(bool destroyWindow, bool destroySubWindows) -{ - Q_D(QWidget); - d->aboutToDestroy(); - if (!isWindow() && parentWidget()) - parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry())); - d->deactivateWidgetCleanup(); - if (testAttribute(Qt::WA_WState_Created)) { - setAttribute(Qt::WA_WState_Created, false); - QObjectList childList = children(); - for (int i = 0; i < childList.size(); ++i) { // destroy all widget children - register QObject *obj = childList.at(i); - if (obj->isWidgetType()) - static_cast<QWidget*>(obj)->destroy(destroySubWindows, - destroySubWindows); - } - if (QWidgetPrivate::mouseGrabber == this) - releaseMouse(); - if (QWidgetPrivate::keyboardGrabber == this) - releaseKeyboard(); - if (isWindow()) - X11->deferred_map.removeAll(this); - if (isModal()) { - // just be sure we leave modal - QApplicationPrivate::leaveModal(this); - } - else if ((windowType() == Qt::Popup)) - qApp->d_func()->closePopup(this); - -#ifndef QT_NO_XRENDER - if (d->picture) { - if (destroyWindow) - XRenderFreePicture(X11->display, d->picture); - d->picture = 0; - } -#endif // QT_NO_XRENDER - - // delete the _NET_WM_USER_TIME_WINDOW - qt_net_remove_user_time(this); - - if ((windowType() == Qt::Desktop)) { - if (acceptDrops()) - X11->dndEnable(this, false); - } else { - if (isWindow()) - X11->dndEnable(this, false); - if (destroyWindow) - qt_XDestroyWindow(this, X11->display, data->winid); - } - QT_TRY { - d->setWinId(0); - } QT_CATCH (const std::bad_alloc &) { - // swallow - destructors must not throw - } - - extern void qPRCleanup(QWidget *widget); // from qapplication_x11.cpp - if (testAttribute(Qt::WA_WState_Reparented)) - qPRCleanup(this); - - if(d->ic) { - delete d->ic; - } else { - // release previous focus information participating with - // preedit preservation of qic - QInputContext *qic = QApplicationPrivate::inputContext; - if (qic) - qic->widgetDestroyed(this); - } - } -} - -void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) -{ - Q_Q(QWidget); -#ifdef ALIEN_DEBUG - qDebug() << "QWidgetPrivate::setParent_sys START" << q << "parent:" << parent; -#endif - QX11Info old_xinfo = xinfo; - if (parent && parent->windowType() == Qt::Desktop) { - // make sure the widget is created on the same screen as the - // programmer specified desktop widget - xinfo = parent->d_func()->xinfo; - parent = 0; - } - - QTLWExtra *topData = maybeTopData(); - bool wasCreated = q->testAttribute(Qt::WA_WState_Created); - if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); - extern void qPRCreate(const QWidget *, Window); -#ifndef QT_NO_CURSOR - QCursor oldcurs; -#endif - - // dnd unregister (we will register again below) - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - q->setAttribute(Qt::WA_DropSiteRegistered, false); - - // if we are a top then remove our dnd prop for now - // it will get rest later - if (q->isWindow() && wasCreated) - X11->dndEnable(q, false); - - if (topData) - qt_net_remove_user_time(q); - -// QWidget *oldparent = q->parentWidget(); - WId old_winid = wasCreated ? data.winid : 0; - if ((q->windowType() == Qt::Desktop)) - old_winid = 0; - setWinId(0); - -#ifndef QT_NO_XRENDER - if (picture) { - XRenderFreePicture(X11->display, picture); - picture = 0; - } -#endif - - // hide and reparent our own window away. Otherwise we might get - // destroyed when emitting the child remove event below. See QWorkspace. - if (wasCreated && old_winid) { - XUnmapWindow(X11->display, old_winid); - if (!old_xinfo.screen() != xinfo.screen()) - XReparentWindow(X11->display, old_winid, RootWindow(X11->display, xinfo.screen()), 0, 0); - } - if (topData) { - topData->parentWinId = 0; - // zero the frame strut and mark it dirty - topData->frameStrut.setCoords(0, 0, 0, 0); - - // reparenting from top-level, make sure show() works again - topData->waitingForMapNotify = 0; - topData->validWMState = 0; - } - data.fstrut_dirty = (!parent || (f & Qt::Window)); // toplevels get a dirty framestrut - - QObjectPrivate::setParent_helper(parent); - bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); - - data.window_flags = f; - q->setAttribute(Qt::WA_WState_Created, false); - q->setAttribute(Qt::WA_WState_Visible, false); - q->setAttribute(Qt::WA_WState_Hidden, false); - adjustFlags(data.window_flags, q); - // keep compatibility with previous versions, we need to preserve the created state - // (but we recreate the winId for the widget being reparented, again for compatibility) - if (wasCreated) - createWinId(); - if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) - q->setAttribute(Qt::WA_WState_Hidden); - q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); - - if (wasCreated) { - QObjectList chlist = q->children(); - for (int i = 0; i < chlist.size(); ++i) { // reparent children - QObject *obj = chlist.at(i); - if (obj->isWidgetType()) { - QWidget *w = (QWidget *)obj; - if (!w->testAttribute(Qt::WA_WState_Created)) - continue; - if (xinfo.screen() != w->d_func()->xinfo.screen()) { - // ### force setParent() to not shortcut out (because - // ### we're setting the parent to the current parent) - // ### setParent will add child back to the list - // ### of children so we need to make sure the - // ### widget won't be added twice. - w->d_func()->parent = 0; - this->children.removeOne(w); - w->setParent(q); - } else if (!w->isWindow()) { - w->d_func()->invalidateBuffer(w->rect()); - if (w->internalWinId()) { - if (w->testAttribute(Qt::WA_NativeWindow)) { - QWidget *nativeParentWidget = w->nativeParentWidget(); - // Qt::WA_NativeWindow ensures that we always have a nativeParentWidget - Q_ASSERT(nativeParentWidget != 0); - QPoint p = w->mapTo(nativeParentWidget, QPoint()); - XReparentWindow(X11->display, - w->internalWinId(), - nativeParentWidget->internalWinId(), - p.x(), p.y()); - } else { - w->d_func()->setParent_sys(q, w->data->window_flags); - } - } - } else if (isTransient(w)) { - /* - when reparenting toplevel windows with toplevel-transient children, - we need to make sure that the window manager gets the updated - WM_TRANSIENT_FOR information... unfortunately, some window managers - don't handle changing WM_TRANSIENT_FOR before the toplevel window is - visible, so we unmap and remap all toplevel-transient children *after* - the toplevel parent has been mapped. thankfully, this is easy in Qt :) - - note that the WM_TRANSIENT_FOR hint is actually updated in - QWidgetPrivate::show_sys() - */ - if (w->internalWinId()) - XUnmapWindow(X11->display, w->internalWinId()); - QApplication::postEvent(w, new QEvent(QEvent::ShowWindowRequest)); - } - } - } - qPRCreate(q, old_winid); - updateSystemBackground(); - - if (old_winid) { - Window *cmwret; - int count; - if (XGetWMColormapWindows(X11->display, old_winid, &cmwret, &count)) { - Window *cmw; - int cmw_size = sizeof(Window)*count; - cmw = new Window[count]; - memcpy((char *)cmw, (char *)cmwret, cmw_size); - XFree((char *)cmwret); - int i; - for (i=0; i<count; i++) { - if (cmw[i] == old_winid) { - cmw[i] = q->internalWinId(); - break; - } - } - int top_count; - if (XGetWMColormapWindows(X11->display, q->window()->internalWinId(), - &cmwret, &top_count)) - { - Window *merged_cmw = new Window[count + top_count]; - memcpy((char *)merged_cmw, (char *)cmw, cmw_size); - memcpy((char *)merged_cmw + cmw_size, (char *)cmwret, sizeof(Window)*top_count); - delete [] cmw; - XFree((char *)cmwret); - cmw = merged_cmw; - count += top_count; - } - - XSetWMColormapWindows(X11->display, q->window()->internalWinId(), cmw, count); - delete [] cmw; - } - - qt_XDestroyWindow(q, X11->display, old_winid); - } - } - - // check if we need to register our dropsite - if (q->testAttribute(Qt::WA_AcceptDrops) - || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) { - q->setAttribute(Qt::WA_DropSiteRegistered, true); - } -#if !defined(QT_NO_IM) - ic = 0; -#endif - invalidateBuffer(q->rect()); -#ifdef ALIEN_DEBUG - qDebug() << "QWidgetPrivate::setParent_sys END" << q; -#endif -} - -QPoint QWidgetPrivate::mapToGlobal(const QPoint &pos) const -{ - Q_Q(const QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) { - QPoint p = pos + q->data->crect.topLeft(); - //cannot trust that !isWindow() implies parentWidget() before create - return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p); - } - int x, y; - Window child; - QPoint p = mapToWS(pos); - XTranslateCoordinates(X11->display, q->internalWinId(), - QApplication::desktop()->screen(xinfo.screen())->internalWinId(), - p.x(), p.y(), &x, &y, &child); - return QPoint(x, y); -} - -QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const -{ - Q_Q(const QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) { - //cannot trust that !isWindow() implies parentWidget() before create - QPoint p = (q->isWindow() || !q->parentWidget()) ? pos : q->parentWidget()->d_func()->mapFromGlobal(pos); - return p - q->data->crect.topLeft(); - } - int x, y; - Window child; - XTranslateCoordinates(X11->display, - QApplication::desktop()->screen(xinfo.screen())->internalWinId(), - q->internalWinId(), pos.x(), pos.y(), &x, &y, &child); - return mapFromWS(QPoint(x, y)); -} - -QPoint QWidget::mapToGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos + offset; - - return d->mapToGlobal(pos); -} - -QPoint QWidget::mapFromGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos - offset; - - return d->mapFromGlobal(pos); -} - -void QWidgetPrivate::updateSystemBackground() -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) - return; - QBrush brush = q->palette().brush(QPalette::Active, q->backgroundRole()); - Qt::WindowType type = q->windowType(); - if (brush.style() == Qt::NoBrush - || q->testAttribute(Qt::WA_NoSystemBackground) - || q->testAttribute(Qt::WA_UpdatesDisabled) - || type == Qt::Popup || type == Qt::ToolTip) { - if (QX11Info::isCompositingManagerRunning() - && q->testAttribute(Qt::WA_TranslucentBackground) - && !(q->parent())) - XSetWindowBackground(X11->display, q->internalWinId(), - QColormap::instance(xinfo.screen()).pixel(Qt::transparent)); - else - XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone); - } - else if (brush.style() == Qt::SolidPattern && brush.isOpaque()) - XSetWindowBackground(X11->display, q->internalWinId(), - QColormap::instance(xinfo.screen()).pixel(brush.color())); - else if (isBackgroundInherited()) - XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), ParentRelative); - else if (brush.style() == Qt::TexturePattern) { - extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); // qpixmap_x11.cpp - XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), - static_cast<QX11PlatformPixmap*>(qt_toX11Pixmap(brush.texture()).data.data())->x11ConvertToDefaultDepth()); - } else - XSetWindowBackground(X11->display, q->internalWinId(), - QColormap::instance(xinfo.screen()).pixel(brush.color())); -} - -#ifndef QT_NO_CURSOR -void QWidgetPrivate::setCursor_sys(const QCursor &) -{ - Q_Q(QWidget); - qt_x11_enforce_cursor(q); - XFlush(X11->display); -} - -void QWidgetPrivate::unsetCursor_sys() -{ - Q_Q(QWidget); - qt_x11_enforce_cursor(q); - XFlush(X11->display); -} -#endif - -static XTextProperty* -qstring_to_xtp(const QString& s) -{ - static XTextProperty tp = { 0, 0, 0, 0 }; - static bool free_prop = true; // we can't free tp.value in case it references - // the data of the static QCString below. - if (tp.value) { - if (free_prop) - XFree(tp.value); - tp.value = 0; - free_prop = true; - } - - static const QTextCodec* mapper = QTextCodec::codecForLocale(); - int errCode = 0; - if (mapper) { - QByteArray mapped = mapper->fromUnicode(s); - char* tl[2]; - tl[0] = mapped.data(); - tl[1] = 0; - errCode = XmbTextListToTextProperty(X11->display, tl, 1, XStdICCTextStyle, &tp); -#if defined(QT_DEBUG) - if (errCode < 0) - qDebug("qstring_to_xtp result code %d", errCode); -#endif - } - if (!mapper || errCode < 0) { - static QByteArray qcs; - qcs = s.toAscii(); - tp.value = (uchar*)qcs.data(); - tp.encoding = XA_STRING; - tp.format = 8; - tp.nitems = qcs.length(); - free_prop = false; - } - - // ### If we knew WM could understand unicode, we could use - // ### a much simpler, cheaper encoding... - /* - tp.value = (XChar2b*)s.unicode(); - tp.encoding = XA_UNICODE; // wish - tp.format = 16; - tp.nitems = s.length(); - */ - - return &tp; -} - -void QWidgetPrivate::setWindowTitle_sys(const QString &caption) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (!q->internalWinId()) - return; - XSetWMName(X11->display, q->internalWinId(), qstring_to_xtp(caption)); - - QByteArray net_wm_name = caption.toUtf8(); - XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_NAME), ATOM(UTF8_STRING), 8, - PropModeReplace, (unsigned char *)net_wm_name.data(), net_wm_name.size()); -} - -void QWidgetPrivate::setWindowIcon_sys(bool forceReset) -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - QTLWExtra *topData = this->topData(); - if (topData->iconPixmap && !forceReset) - // already been set - return; - - // preparing images to set the _NET_WM_ICON property - QIcon icon = q->windowIcon(); - QVector<long> icon_data; - Qt::HANDLE pixmap_handle = 0; - if (!icon.isNull()) { - QList<QSize> availableSizes = icon.availableSizes(); - if(availableSizes.isEmpty()) { - // try to use default sizes since the icon can be a scalable image like svg. - availableSizes.push_back(QSize(16,16)); - availableSizes.push_back(QSize(32,32)); - availableSizes.push_back(QSize(64,64)); - availableSizes.push_back(QSize(128,128)); - } - for(int i = 0; i < availableSizes.size(); ++i) { - QSize size = availableSizes.at(i); - QPixmap pixmap = icon.pixmap(size); - if (!pixmap.isNull()) { - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - int pos = icon_data.size(); - icon_data.resize(pos + 2 + image.width()*image.height()); - icon_data[pos++] = image.width(); - icon_data[pos++] = image.height(); - if (sizeof(long) == sizeof(quint32)) { - memcpy(icon_data.data() + pos, image.scanLine(0), image.byteCount()); - } else { - for (int y = 0; y < image.height(); ++y) { - uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y)); - for (int x = 0; x < image.width(); ++x) - icon_data[pos + y*image.width() + x] = scanLine[x]; - } - } - } - } - if (!icon_data.isEmpty()) { - extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap); - /* - if the app is running on an unknown desktop, or it is not - using the default visual, convert the icon to 1bpp as stated - in the ICCCM section 4.1.2.4; otherwise, create the icon pixmap - in the default depth (even though this violates the ICCCM) - */ - if (X11->desktopEnvironment == DE_UNKNOWN - || !QX11Info::appDefaultVisual(xinfo.screen()) - || !QX11Info::appDefaultColormap(xinfo.screen())) { - // unknown DE or non-default visual/colormap, use 1bpp bitmap - if (!forceReset || !topData->iconPixmap) - topData->iconPixmap = new QPixmap(qt_toX11Pixmap(QBitmap(icon.pixmap(QSize(64,64))))); - pixmap_handle = topData->iconPixmap->handle(); - } else { - // default depth, use a normal pixmap (even though this - // violates the ICCCM), since this works on all DEs known to Qt - if (!forceReset || !topData->iconPixmap) - topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64)))); - pixmap_handle = static_cast<QX11PlatformPixmap*>(topData->iconPixmap->data.data())->x11ConvertToDefaultDepth(); - } - } - } - - if (!q->internalWinId()) - return; - - if (!icon_data.isEmpty()) { - XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32, - PropModeReplace, (unsigned char *) icon_data.data(), - icon_data.size()); - } else { - XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON)); - } - - XWMHints *h = XGetWMHints(X11->display, q->internalWinId()); - XWMHints wm_hints; - if (!h) { - memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy - h = &wm_hints; - } - - if (pixmap_handle) { - h->icon_pixmap = pixmap_handle; - h->flags |= IconPixmapHint; - } else { - h->icon_pixmap = 0; - h->flags &= ~(IconPixmapHint | IconMaskHint); - } - - XSetWMHints(X11->display, q->internalWinId(), h); - if (h != &wm_hints) - XFree((char *)h); -} - -void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) -{ - Q_Q(QWidget); - if (!q->internalWinId()) - return; - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - XSetWMIconName(X11->display, q->internalWinId(), qstring_to_xtp(iconText)); - - QByteArray icon_name = iconText.toUtf8(); - XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON_NAME), ATOM(UTF8_STRING), 8, - PropModeReplace, (unsigned char *) icon_name.constData(), icon_name.size()); -} - - -void QWidget::grabMouse() -{ - if (isVisible() && !qt_nograb()) { - if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) - QWidgetPrivate::mouseGrabber->releaseMouse(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); -#ifndef QT_NO_DEBUG - int status = -#endif - XGrabPointer(X11->display, effectiveWinId(), False, - (uint)(ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | EnterWindowMask | - LeaveWindowMask), - GrabModeAsync, GrabModeAsync, - XNone, XNone, X11->time); -#ifndef QT_NO_DEBUG - if (status) { - const char *s = - status == GrabNotViewable ? "\"GrabNotViewable\"" : - status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" : - status == GrabFrozen ? "\"GrabFrozen\"" : - status == GrabInvalidTime ? "\"GrabInvalidTime\"" : - "<?>"; - qWarning("QWidget::grabMouse: Failed with %s", s); - } -#endif - QWidgetPrivate::mouseGrabber = this; - } -} - - -#ifndef QT_NO_CURSOR -void QWidget::grabMouse(const QCursor &cursor) -{ - if (!qt_nograb()) { - if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) - QWidgetPrivate::mouseGrabber->releaseMouse(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); -#ifndef QT_NO_DEBUG - int status = -#endif - XGrabPointer(X11->display, effectiveWinId(), False, - (uint)(ButtonPressMask | ButtonReleaseMask | - PointerMotionMask | EnterWindowMask | LeaveWindowMask), - GrabModeAsync, GrabModeAsync, - XNone, cursor.handle(), X11->time); -#ifndef QT_NO_DEBUG - if (status) { - const char *s = - status == GrabNotViewable ? "\"GrabNotViewable\"" : - status == AlreadyGrabbed ? "\"AlreadyGrabbed\"" : - status == GrabFrozen ? "\"GrabFrozen\"" : - status == GrabInvalidTime ? "\"GrabInvalidTime\"" : - "<?>"; - qWarning("QWidget::grabMouse: Failed with %s", s); - } -#endif - QWidgetPrivate::mouseGrabber = this; - } -} -#endif - - -void QWidget::releaseMouse() -{ - if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) { - XUngrabPointer(X11->display, X11->time); - XFlush(X11->display); - QWidgetPrivate::mouseGrabber = 0; - } -} - - -void QWidget::grabKeyboard() -{ - if (!qt_nograb()) { - if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this) - QWidgetPrivate::keyboardGrabber->releaseKeyboard(); - XGrabKeyboard(X11->display, effectiveWinId(), False, GrabModeAsync, GrabModeAsync, - X11->time); - QWidgetPrivate::keyboardGrabber = this; - } -} - - -void QWidget::releaseKeyboard() -{ - if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) { - XUngrabKeyboard(X11->display, X11->time); - QWidgetPrivate::keyboardGrabber = 0; - } -} - - -QWidget *QWidget::mouseGrabber() -{ - return QWidgetPrivate::mouseGrabber; -} - - -QWidget *QWidget::keyboardGrabber() -{ - return QWidgetPrivate::keyboardGrabber; -} - -void QWidget::activateWindow() -{ - QWidget *tlw = window(); - if (tlw->isVisible() && !tlw->d_func()->topData()->embedded && !X11->deferred_map.contains(tlw)) { - if (X11->userTime == 0) - X11->userTime = X11->time; - qt_net_update_user_time(tlw, X11->userTime); - - if (X11->isSupportedByWM(ATOM(_NET_ACTIVE_WINDOW)) - && !(tlw->windowFlags() & Qt::X11BypassWindowManagerHint)) { - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = ATOM(_NET_ACTIVE_WINDOW); - e.xclient.display = X11->display; - e.xclient.window = tlw->internalWinId(); - e.xclient.format = 32; - e.xclient.data.l[0] = 1; // 1 == application - e.xclient.data.l[1] = X11->userTime; - if (QWidget *aw = QApplication::activeWindow()) - e.xclient.data.l[2] = aw->internalWinId(); - else - e.xclient.data.l[2] = XNone; - e.xclient.data.l[3] = 0; - e.xclient.data.l[4] = 0; - XSendEvent(X11->display, RootWindow(X11->display, tlw->x11Info().screen()), - false, SubstructureNotifyMask | SubstructureRedirectMask, &e); - } else { - if (!qt_widget_private(tlw)->topData()->waitingForMapNotify) - XSetInputFocus(X11->display, tlw->internalWinId(), XRevertToParent, X11->time); - } - } -} - -void QWidget::setWindowState(Qt::WindowStates newstate) -{ - Q_D(QWidget); - bool needShow = false; - Qt::WindowStates oldstate = windowState(); - if (oldstate == newstate) - return; - if (isWindow()) { - // Ensure the initial size is valid, since we store it as normalGeometry below. - if (!testAttribute(Qt::WA_Resized) && !isVisible()) - adjustSize(); - - QTLWExtra *top = d->topData(); - - if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { - if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)) - && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) { - if ((newstate & Qt::WindowMaximized) && !(oldstate & Qt::WindowFullScreen)) - top->normalGeometry = geometry(); - qt_change_net_wm_state(this, (newstate & Qt::WindowMaximized), - ATOM(_NET_WM_STATE_MAXIMIZED_HORZ), - ATOM(_NET_WM_STATE_MAXIMIZED_VERT)); - } else if (! (newstate & Qt::WindowFullScreen)) { - if (newstate & Qt::WindowMaximized) { - // save original geometry - const QRect normalGeometry = geometry(); - - if (isVisible()) { - data->fstrut_dirty = true; - const QRect maxRect = QApplication::desktop()->availableGeometry(this); - const QRect r = top->normalGeometry; - const QRect fs = d->frameStrut(); - setGeometry(maxRect.x() + fs.left(), - maxRect.y() + fs.top(), - maxRect.width() - fs.left() - fs.right(), - maxRect.height() - fs.top() - fs.bottom()); - top->normalGeometry = r; - } - - if (top->normalGeometry.width() < 0) - top->normalGeometry = normalGeometry; - } else { - // restore original geometry - setGeometry(top->normalGeometry); - } - } - } - - if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { - if (X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) { - if (newstate & Qt::WindowFullScreen) { - top->normalGeometry = geometry(); - top->fullScreenOffset = d->frameStrut().topLeft(); - } - qt_change_net_wm_state(this, (newstate & Qt::WindowFullScreen), - ATOM(_NET_WM_STATE_FULLSCREEN)); - } else { - needShow = isVisible(); - - if (newstate & Qt::WindowFullScreen) { - data->fstrut_dirty = true; - const QRect normalGeometry = geometry(); - const QPoint fullScreenOffset = d->frameStrut().topLeft(); - - top->savedFlags = windowFlags(); - setParent(0, Qt::Window | Qt::FramelessWindowHint); - const QRect r = top->normalGeometry; - setGeometry(qApp->desktop()->screenGeometry(this)); - top->normalGeometry = r; - - if (top->normalGeometry.width() < 0) { - top->normalGeometry = normalGeometry; - top->fullScreenOffset = fullScreenOffset; - } - } else { - setParent(0, top->savedFlags); - - if (newstate & Qt::WindowMaximized) { - // from fullscreen to maximized - data->fstrut_dirty = true; - const QRect maxRect = QApplication::desktop()->availableGeometry(this); - const QRect r = top->normalGeometry; - const QRect fs = d->frameStrut(); - setGeometry(maxRect.x() + fs.left(), - maxRect.y() + fs.top(), - maxRect.width() - fs.left() - fs.right(), - maxRect.height() - fs.top() - fs.bottom()); - top->normalGeometry = r; - } else { - // restore original geometry - setGeometry(top->normalGeometry.adjusted(-top->fullScreenOffset.x(), - -top->fullScreenOffset.y(), - -top->fullScreenOffset.x(), - -top->fullScreenOffset.y())); - } - } - } - } - - createWinId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { - if (isVisible()) { - if (newstate & Qt::WindowMinimized) { - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = ATOM(WM_CHANGE_STATE); - e.xclient.display = X11->display; - e.xclient.window = data->winid; - e.xclient.format = 32; - e.xclient.data.l[0] = IconicState; - e.xclient.data.l[1] = 0; - e.xclient.data.l[2] = 0; - e.xclient.data.l[3] = 0; - e.xclient.data.l[4] = 0; - XSendEvent(X11->display, - RootWindow(X11->display,d->xinfo.screen()), - False, (SubstructureNotifyMask|SubstructureRedirectMask), &e); - } else { - setAttribute(Qt::WA_Mapped); - XMapWindow(X11->display, effectiveWinId()); - } - } - - needShow = false; - } - } - - data->window_state = newstate; - - if (needShow) - show(); - - if (newstate & Qt::WindowActive) - activateWindow(); - - QWindowStateChangeEvent e(oldstate); - QApplication::sendEvent(this, &e); -} - -/*! - \internal - Platform-specific part of QWidget::show(). -*/ - -void QWidgetPrivate::show_sys() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if (q->testAttribute(Qt::WA_DontShowOnScreen)) { - invalidateBuffer(q->rect()); - q->setAttribute(Qt::WA_Mapped); - if (QTLWExtra *tlwExtra = maybeTopData()) - tlwExtra->waitingForMapNotify = 0; - return; - } - - if (q->isWindow()) { - XWMHints *h = XGetWMHints(X11->display, q->internalWinId()); - XWMHints wm_hints; - bool got_hints = h != 0; - if (!got_hints) { - memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy - h = &wm_hints; - } - h->initial_state = q->isMinimized() ? IconicState : NormalState; - h->flags |= StateHint; - XSetWMHints(X11->display, q->internalWinId(), h); - if (got_hints) - XFree((char *)h); - - // update WM_NORMAL_HINTS - do_size_hints(q, extra); - - // udpate WM_TRANSIENT_FOR - if (isTransient(q)) { - QWidget *p = q->parentWidget(); - -#ifndef QT_NO_MENU - // hackish ... try to find the main window related to this QMenu - if (qobject_cast<QMenu *>(q)) { - p = static_cast<QMenuPrivate*>(this)->causedPopup.widget; - if (!p) - p = q->parentWidget(); - if (!p) - p = QApplication::widgetAt(q->pos()); - if (!p) - p = qApp->activeWindow(); - } -#endif - if (p) - p = p->window(); - if (p) { - // transient for window - XSetTransientForHint(X11->display, q->internalWinId(), p->internalWinId()); - } else { - // transient for group - XSetTransientForHint(X11->display, q->internalWinId(), X11->wm_client_leader); - } - } - - // update _MOTIF_WM_HINTS - QtMWMHints mwmhints = GetMWMHints(X11->display, q->internalWinId()); - - if (data.window_modality != Qt::NonModal) { - switch (data.window_modality) { - case Qt::WindowModal: - mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL; - break; - case Qt::ApplicationModal: - default: - mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL; - break; - } - mwmhints.flags |= MWM_HINTS_INPUT_MODE; - } else { - mwmhints.input_mode = MWM_INPUT_MODELESS; - mwmhints.flags &= ~MWM_HINTS_INPUT_MODE; - } - - if (q->minimumSize() == q->maximumSize()) { - // fixed size, remove the resize handle (since mwm/dtwm - // isn't smart enough to do it itself) - mwmhints.flags |= MWM_HINTS_FUNCTIONS; - if (mwmhints.functions == MWM_FUNC_ALL) { - mwmhints.functions = MWM_FUNC_MOVE; - } else { - mwmhints.functions &= ~MWM_FUNC_RESIZE; - } - - if (mwmhints.decorations == MWM_DECOR_ALL) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - mwmhints.decorations = (MWM_DECOR_BORDER - | MWM_DECOR_TITLE - | MWM_DECOR_MENU); - } else { - mwmhints.decorations &= ~MWM_DECOR_RESIZEH; - } - - if (q->windowFlags() & Qt::WindowMinimizeButtonHint) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - mwmhints.decorations |= MWM_DECOR_MINIMIZE; - mwmhints.functions |= MWM_FUNC_MINIMIZE; - } - if (q->windowFlags() & Qt::WindowMaximizeButtonHint) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - mwmhints.decorations |= MWM_DECOR_MAXIMIZE; - mwmhints.functions |= MWM_FUNC_MAXIMIZE; - } - if (q->windowFlags() & Qt::WindowCloseButtonHint) - mwmhints.functions |= MWM_FUNC_CLOSE; - } - - SetMWMHints(X11->display, q->internalWinId(), mwmhints); - - // update _NET_WM_STATE - QVector<Atom> netWmState = getNetWmState(q); - - Qt::WindowFlags flags = q->windowFlags(); - if (flags & Qt::WindowStaysOnTopHint) { - if (flags & Qt::WindowStaysOnBottomHint) - qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time"; - if (!netWmState.contains(ATOM(_NET_WM_STATE_ABOVE))) - netWmState.append(ATOM(_NET_WM_STATE_ABOVE)); - if (!netWmState.contains(ATOM(_NET_WM_STATE_STAYS_ON_TOP))) - netWmState.append(ATOM(_NET_WM_STATE_STAYS_ON_TOP)); - } else if (flags & Qt::WindowStaysOnBottomHint) { - if (!netWmState.contains(ATOM(_NET_WM_STATE_BELOW))) - netWmState.append(ATOM(_NET_WM_STATE_BELOW)); - } - if (q->isFullScreen()) { - if (!netWmState.contains(ATOM(_NET_WM_STATE_FULLSCREEN))) - netWmState.append(ATOM(_NET_WM_STATE_FULLSCREEN)); - } - if (q->isMaximized()) { - if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) - netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)); - if (!netWmState.contains(ATOM(_NET_WM_STATE_MAXIMIZED_VERT))) - netWmState.append(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)); - } - if (data.window_modality != Qt::NonModal) { - if (!netWmState.contains(ATOM(_NET_WM_STATE_MODAL))) - netWmState.append(ATOM(_NET_WM_STATE_MODAL)); - } - - if (!netWmState.isEmpty()) { - XChangeProperty(X11->display, q->internalWinId(), - ATOM(_NET_WM_STATE), XA_ATOM, 32, PropModeReplace, - (unsigned char *) netWmState.data(), netWmState.size()); - } else { - XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_STATE)); - } - - // set _NET_WM_USER_TIME - Time userTime = X11->userTime; - bool setUserTime = false; - if (q->testAttribute(Qt::WA_ShowWithoutActivating)) { - userTime = 0; - setUserTime = true; - } else if (userTime != CurrentTime) { - setUserTime = true; - } - if (setUserTime) - qt_net_update_user_time(q, userTime); - -#ifndef QT_NO_XSYNC - if (!topData()->syncUpdateCounter) { - XSyncValue value; - XSyncIntToValue(&value, 0); - topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value); - - XChangeProperty(X11->display, q->internalWinId(), - ATOM(_NET_WM_SYNC_REQUEST_COUNTER), - XA_CARDINAL, - 32, PropModeReplace, - (uchar *) &topData()->syncUpdateCounter, 1); - - topData()->newCounterValueHi = 0; - topData()->newCounterValueLo = 0; - } -#endif - - if (!topData()->embedded - && (topData()->validWMState || topData()->waitingForMapNotify) - && !q->isMinimized()) { - X11->deferred_map.append(q); - return; - } - - if (q->isMaximized() && !q->isFullScreen() - && !(X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ)) - && X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)))) { - XMapWindow(X11->display, q->internalWinId()); - data.fstrut_dirty = true; - qt_x11_wait_for_window_manager(q); - - // if the wm was not smart enough to adjust our size, do that manually - QRect maxRect = QApplication::desktop()->availableGeometry(q); - - QTLWExtra *top = topData(); - QRect normalRect = top->normalGeometry; - const QRect fs = frameStrut(); - - q->setGeometry(maxRect.x() + fs.left(), - maxRect.y() + fs.top(), - maxRect.width() - fs.left() - fs.right(), - maxRect.height() - fs.top() - fs.bottom()); - - // restore the original normalGeometry - top->normalGeometry = normalRect; - // internalSetGeometry() clears the maximized flag... make sure we set it back - data.window_state = data.window_state | Qt::WindowMaximized; - q->setAttribute(Qt::WA_Mapped); - return; - } - - if (q->isFullScreen() && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) { - XMapWindow(X11->display, q->internalWinId()); - qt_x11_wait_for_window_manager(q); - q->setAttribute(Qt::WA_Mapped); - return; - } - } - - invalidateBuffer(q->rect()); - - if (q->testAttribute(Qt::WA_OutsideWSRange)) - return; - q->setAttribute(Qt::WA_Mapped); - if (q->isWindow()) - topData()->waitingForMapNotify = 1; - - if (!q->isWindow() - && (!q->autoFillBackground() - || q->palette().brush(q->backgroundRole()).style() == Qt::LinearGradientPattern)) { - if (q->internalWinId()) { - XSetWindowBackgroundPixmap(X11->display, q->internalWinId(), XNone); - XMapWindow(X11->display, q->internalWinId()); - updateSystemBackground(); - } - return; - } - - if (q->internalWinId()) - XMapWindow(X11->display, q->internalWinId()); - - // Freedesktop.org Startup Notification - if (X11->startupId && q->isWindow()) { - QByteArray message("remove: ID="); - message.append(X11->startupId); - sendStartupMessage(message.constData()); - X11->startupId = 0; - } -} - -/*! - \internal - Platform-specific part of QWidget::show(). -*/ - -void QWidgetPrivate::sendStartupMessage(const char *message) const -{ - Q_Q(const QWidget); - - if (!message) - return; - - XEvent xevent; - xevent.xclient.type = ClientMessage; - xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO_BEGIN); - xevent.xclient.display = X11->display; - xevent.xclient.window = q->internalWinId(); - xevent.xclient.format = 8; - - Window rootWindow = RootWindow(X11->display, DefaultScreen(X11->display)); - uint sent = 0; - uint length = strlen(message) + 1; - do { - if (sent == 20) - xevent.xclient.message_type = ATOM(_NET_STARTUP_INFO); - - for (uint i = 0; i < 20 && i + sent <= length; i++) - xevent.xclient.data.b[i] = message[i + sent++]; - - XSendEvent(X11->display, rootWindow, false, PropertyChangeMask, &xevent); - } while (sent <= length); -} - -void QWidgetPrivate::setNetWmWindowTypes() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if (!q->isWindow()) { - if (q->internalWinId()) - XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_WINDOW_TYPE)); - return; - } - - QVector<long> windowTypes; - - // manual selection 1 (these are never set by Qt and take precedence) - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDesktop)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DESKTOP)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDock)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DOCK)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeNotification)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NOTIFICATION)); - - // manual selection 2 (Qt uses these during auto selection); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeUtility)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeSplash)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDialog)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolTip)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP)); - - // manual selection 3 (these can be set by Qt, but don't have a - // corresponding Qt::WindowType). note that order of the *MENU - // atoms is important - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeMenu)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_MENU)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDropDownMenu)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypePopupMenu)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeToolBar)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLBAR)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeCombo)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_COMBO)); - if (q->testAttribute(Qt::WA_X11NetWmWindowTypeDND)) - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DND)); - - // automatic selection - switch (q->windowType()) { - case Qt::Dialog: - case Qt::Sheet: - // dialog netwm type - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_DIALOG)); - break; - - case Qt::Tool: - case Qt::Drawer: - // utility netwm type - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_UTILITY)); - break; - - case Qt::ToolTip: - // tooltip netwm type - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_TOOLTIP)); - break; - - case Qt::SplashScreen: - // splash netwm type - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_SPLASH)); - break; - - default: - break; - } - - if (q->windowFlags() & Qt::FramelessWindowHint) { - // override netwm type - quick and easy for KDE noborder - windowTypes.append(ATOM(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE)); - } - - // normal netwm type - default - windowTypes.append(ATOM(_NET_WM_WINDOW_TYPE_NORMAL)); - - if (!windowTypes.isEmpty()) { - XChangeProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE), XA_ATOM, 32, - PropModeReplace, (unsigned char *) windowTypes.constData(), - windowTypes.count()); - } else { - XDeleteProperty(X11->display, q->winId(), ATOM(_NET_WM_WINDOW_TYPE)); - } -} - -/*! - \internal - Platform-specific part of QWidget::hide(). -*/ - -void QWidgetPrivate::hide_sys() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - deactivateWidgetCleanup(); - if (q->isWindow()) { - X11->deferred_map.removeAll(q); - if (q->internalWinId()) // in nsplugin, may be 0 - XWithdrawWindow(X11->display, q->internalWinId(), xinfo.screen()); - XFlush(X11->display); - } else { - invalidateBuffer(q->rect()); - if (q->internalWinId()) // in nsplugin, may be 0 - XUnmapWindow(X11->display, q->internalWinId()); - } - q->setAttribute(Qt::WA_Mapped, false); -} - -void QWidgetPrivate::setFocus_sys() -{ - -} - - -void QWidgetPrivate::raise_sys() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) - XRaiseWindow(X11->display, q->internalWinId()); -} - -void QWidgetPrivate::lower_sys() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) - XLowerWindow(X11->display, q->internalWinId()); - if(!q->isWindow()) - invalidateBuffer(q->rect()); -} - -void QWidgetPrivate::stackUnder_sys(QWidget* w) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId() && w->internalWinId()) { - Window stack[2]; - stack[0] = w->internalWinId();; - stack[1] = q->internalWinId(); - XRestackWindows(X11->display, stack, 2); - } - if(!q->isWindow() || !w->internalWinId()) - invalidateBuffer(q->rect()); -} - - -static void do_size_hints(QWidget* widget, QWExtra *x) -{ - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - XSizeHints s; - s.flags = 0; - if (x) { - QRect g = widget->geometry(); - s.x = g.x(); - s.y = g.y(); - s.width = g.width(); - s.height = g.height(); - if (x->minw > 0 || x->minh > 0) { - // add minimum size hints - s.flags |= PMinSize; - s.min_width = qMin(XCOORD_MAX, x->minw); - s.min_height = qMin(XCOORD_MAX, x->minh); - } - if (x->maxw < QWIDGETSIZE_MAX || x->maxh < QWIDGETSIZE_MAX) { - // add maximum size hints - s.flags |= PMaxSize; - s.max_width = qMin(XCOORD_MAX, x->maxw); - s.max_height = qMin(XCOORD_MAX, x->maxh); - } - if (x->topextra && - (x->topextra->incw > 0 || x->topextra->inch > 0)) { - // add resize increment hints - s.flags |= PResizeInc | PBaseSize; - s.width_inc = x->topextra->incw; - s.height_inc = x->topextra->inch; - s.base_width = x->topextra->basew; - s.base_height = x->topextra->baseh; - } - } - if (widget->testAttribute(Qt::WA_Moved)) { - // user (i.e. command-line) specified position - s.flags |= USPosition; - s.flags |= PPosition; - } - if (widget->testAttribute(Qt::WA_Resized)) { - // user (i.e. command-line) specified size - s.flags |= USSize; - s.flags |= PSize; - } - s.flags |= PWinGravity; - if (widget->testAttribute(Qt::WA_Moved) && x && x->topextra && !x->topextra->posFromMove) { - // position came from setGeometry(), tell the WM that we don't - // want our window gravity-shifted - s.win_gravity = StaticGravity; - } else { - // position came from move() - s.x = widget->x(); - s.y = widget->y(); - s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; - } - if (widget->internalWinId()) - XSetWMNormalHints(X11->display, widget->internalWinId(), &s); -} - - -/* - Helper function for non-toplevel widgets. Helps to map Qt's 32bit - coordinate system to X11's 16bit coordinate system. - - Sets the geometry of the widget to data.crect, but clipped to sizes - that X can handle. Unmaps widgets that are completely outside the - valid range. - - Maintains data.wrect, which is the geometry of the X widget, - measured in this widget's coordinate system. - - if the parent is not clipped, parentWRect is empty, otherwise - parentWRect is the geometry of the parent's X rect, measured in - parent's coord sys - */ -void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - /* - There are up to four different coordinate systems here: - Qt coordinate system for this widget. - X coordinate system for this widget (relative to wrect). - Qt coordinate system for parent - X coordinate system for parent (relative to parent's wrect). - */ - Display *dpy = xinfo.display(); - QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); - QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX); - QRect wrect; - //xrect is the X geometry of my X widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys) - QRect xrect = data.crect; - - const QWidget *const parent = q->parentWidget(); - QRect parentWRect = parent->data->wrect; - - if (parentWRect.isValid()) { - // parent is clipped, and we have to clip to the same limit as parent - if (!parentWRect.contains(xrect)) { - xrect &= parentWRect; - wrect = xrect; - //translate from parent's to my Qt coord sys - wrect.translate(-data.crect.topLeft()); - } - //translate from parent's Qt coords to parent's X coords - xrect.translate(-parentWRect.topLeft()); - - } else { - // parent is not clipped, we may or may not have to clip - - if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) { - // This is where the main optimization is: we are already - // clipped, and if our clip is still valid, we can just - // move our window, and do not need to move or clip - // children - - QRect vrect = xrect & parent->rect(); - vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords - if (data.wrect.contains(vrect)) { - xrect = data.wrect; - xrect.translate(data.crect.topLeft()); - if (data.winid) - XMoveWindow(dpy, data.winid, xrect.x(), xrect.y()); - return; - } - } - - if (!validRange.contains(xrect)) { - // we are too big, and must clip - xrect &=wrectRange; - wrect = xrect; - wrect.translate(-data.crect.topLeft()); - //parent's X coord system is equal to parent's Qt coord - //sys, so we don't need to map xrect. - } - - } - - // unmap if we are outside the valid window system coord system - bool outsideRange = !xrect.isValid(); - bool mapWindow = false; - if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) { - q->setAttribute(Qt::WA_OutsideWSRange, outsideRange); - if (outsideRange) { - if (data.winid) - XUnmapWindow(dpy, data.winid); - q->setAttribute(Qt::WA_Mapped, false); - } else if (!q->isHidden()) { - mapWindow = true; - } - } - - if (outsideRange) - return; - - bool jump = (data.wrect != wrect); - data.wrect = wrect; - - - // and now recursively for all children... - // ### can be optimized - for (int i = 0; i < children.size(); ++i) { - QObject *object = children.at(i); - if (object->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(object); - if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) - w->d_func()->setWSGeometry(jump); - } - } - - if (data.winid) { - // move ourselves to the new position and map (if necessary) after - // the movement. Rationale: moving unmapped windows is much faster - // than moving mapped windows - if (jump) //avoid flicker when jumping - XSetWindowBackgroundPixmap(dpy, data.winid, XNone); - if (!parent->internalWinId()) - xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0))); - XMoveResizeWindow(dpy, data.winid, xrect.x(), xrect.y(), xrect.width(), xrect.height()); - } - - //to avoid flicker, we have to show children after the helper widget has moved - if (jump) { - for (int i = 0; i < children.size(); ++i) { - QObject *object = children.at(i); - if (object->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(object); - if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) { - w->setAttribute(Qt::WA_Mapped); - if (w->internalWinId()) - XMapWindow(dpy, w->data->winid); - } - } - } - } - - - if (jump && data.winid) - XClearArea(dpy, data.winid, 0, 0, wrect.width(), wrect.height(), True); - - if (mapWindow && !dontShow) { - q->setAttribute(Qt::WA_Mapped); - if (data.winid) - XMapWindow(dpy, data.winid); - } -} - -void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - Display *dpy = X11->display; - - if ((q->windowType() == Qt::Desktop)) - return; - if (q->isWindow()) { - if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_VERT)) - && !X11->isSupportedByWM(ATOM(_NET_WM_STATE_MAXIMIZED_HORZ))) - data.window_state &= ~Qt::WindowMaximized; - if (!X11->isSupportedByWM(ATOM(_NET_WM_STATE_FULLSCREEN))) - data.window_state &= ~Qt::WindowFullScreen; - if (QTLWExtra *topData = maybeTopData()) - topData->normalGeometry = QRect(0,0,-1,-1); - } else { - uint s = data.window_state; - s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen); - data.window_state = s; - } - if (extra) { // any size restrictions? - w = qMin(w,extra->maxw); - h = qMin(h,extra->maxh); - w = qMax(w,extra->minw); - h = qMax(h,extra->minh); - } - QPoint oldPos(q->pos()); - QSize oldSize(q->size()); - QRect oldGeom(data.crect); - QRect r(x, y, w, h); - - // We only care about stuff that changes the geometry, or may - // cause the window manager to change its state - if (!q->isWindow() && oldGeom == r) - return; - - data.crect = r; - bool isResize = q->size() != oldSize; - - if (q->isWindow()) { - if (w == 0 || h == 0) { - q->setAttribute(Qt::WA_OutsideWSRange, true); - if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) - hide_sys(); - } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) { - q->setAttribute(Qt::WA_OutsideWSRange, false); - - // put the window in its place and show it - if (data.winid) - XMoveResizeWindow(dpy, data.winid, x, y, w, h); - topData()->posFromMove = false; // force StaticGravity - do_size_hints(q, extra); - show_sys(); - } else { - q->setAttribute(Qt::WA_OutsideWSRange, false); - if (!q->isVisible()) - do_size_hints(q, extra); - if (isMove) { - if ((data.window_flags & Qt::X11BypassWindowManagerHint) == Qt::X11BypassWindowManagerHint - // work around 4Dwm's incompliance with ICCCM 4.1.5 - || X11->desktopEnvironment == DE_4DWM) { - if (data.winid) - XMoveResizeWindow(dpy, data.winid, x, y, w, h); - } else if (q->isVisible() - && topData()->validWMState - && X11->isSupportedByWM(ATOM(_NET_MOVERESIZE_WINDOW))) { - XEvent e; - e.xclient.type = ClientMessage; - e.xclient.message_type = ATOM(_NET_MOVERESIZE_WINDOW); - e.xclient.display = X11->display; - e.xclient.window = q->internalWinId(); - e.xclient.format = 32; - e.xclient.data.l[0] = StaticGravity | 1<<8 | 1<<9 | 1<<10 | 1<<11 | 1<<12; - e.xclient.data.l[1] = x; - e.xclient.data.l[2] = y; - e.xclient.data.l[3] = w; - e.xclient.data.l[4] = h; - XSendEvent(X11->display, RootWindow(X11->display, q->x11Info().screen()), - false, (SubstructureNotifyMask | SubstructureRedirectMask), &e); - } else if (data.winid) { - // pos() is right according to ICCCM 4.1.5 - XMoveResizeWindow(dpy, data.winid, q->pos().x(), q->pos().y(), w, h); - } - } else if (isResize && data.winid) { - if (!q->isVisible() - && topData()->validWMState - && !q->testAttribute(Qt::WA_PendingMoveEvent)) { - /* - even though we've not visible, we could be in a - race w/ the window manager, and it may ignore - our ConfigureRequest. setting posFromMove to - false makes sure that doDeferredMap() in - qapplication_x11.cpp keeps the window in the - right place - */ - topData()->posFromMove = false; - } - XResizeWindow(dpy, data.winid, w, h); - } - } - if (isResize && !q->testAttribute(Qt::WA_DontShowOnScreen)) // set config pending only on resize, see qapplication_x11.cpp, translateConfigEvent() - q->setAttribute(Qt::WA_WState_ConfigPending); - - } else { - QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false; - const bool disableInTopLevelResize = inTopLevelResize && q->internalWinId(); - if (disableInTopLevelResize) { - // Top-level resize optimization does not work for native child widgets; - // disable it for this particular widget. - tlwExtra->inTopLevelResize = false; - } - - if (!isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) { - moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y()); - } - if (q->testAttribute(Qt::WA_WState_Created)) - setWSGeometry(); - - if (isResize && (!inTopLevelResize || disableInTopLevelResize) && q->isVisible()) - invalidateBuffer_resizeHelper(oldPos, oldSize); - - if (disableInTopLevelResize) - tlwExtra->inTopLevelResize = true; - } - - if (q->isVisible()) { - if (isMove && q->pos() != oldPos) { - if (X11->desktopEnvironment != DE_4DWM) { - // pos() is right according to ICCCM 4.1.5 - QMoveEvent e(q->pos(), oldPos); - QApplication::sendEvent(q, &e); - } else { - // work around 4Dwm's incompliance with ICCCM 4.1.5 - QMoveEvent e(data.crect.topLeft(), oldGeom.topLeft()); - QApplication::sendEvent(q, &e); - } - } - if (isResize) { - static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - // If we have a backing store with static contents, we have to disable the top-level - // resize optimization in order to get invalidated regions for resized widgets. - // The optimization discards all invalidateBuffer() calls since we're going to - // repaint everything anyways, but that's not the case with static contents. - const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra - && !extra->topextra->inTopLevelResize - && (!extra->topextra->backingStore - || !extra->topextra->backingStore->hasStaticContents()); - if (setTopLevelResize) - extra->topextra->inTopLevelResize = true; - QResizeEvent e(q->size(), oldSize); - QApplication::sendEvent(q, &e); - if (setTopLevelResize) - extra->topextra->inTopLevelResize = false; - } - } else { - if (isMove && q->pos() != oldPos) - q->setAttribute(Qt::WA_PendingMoveEvent, true); - if (isResize) - q->setAttribute(Qt::WA_PendingResizeEvent, true); - } -} - -void QWidgetPrivate::setConstraints_sys() -{ - Q_Q(QWidget); -#ifdef ALIEN_DEBUG - qDebug() << "QWidgetPrivate::setConstraints_sys START" << q; -#endif - if (q->testAttribute(Qt::WA_WState_Created)) - do_size_hints(q, extra); -#ifdef ALIEN_DEBUG - qDebug() << "QWidgetPrivate::setConstraints_sys END" << q; -#endif -} - -void QWidgetPrivate::scroll_sys(int dx, int dy) -{ - Q_Q(QWidget); - - scrollChildren(dx, dy); - if (!paintOnScreen()) { - scrollRect(q->rect(), dx, dy); - } else { - scroll_sys(dx, dy, QRect()); - } -} - -void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) -{ - Q_Q(QWidget); - - if (!paintOnScreen()) { - scrollRect(r, dx, dy); - return; - } - bool valid_rect = r.isValid(); - bool just_update = qAbs(dx) > q->width() || qAbs(dy) > q->height(); - QRect sr = valid_rect ? r : clipRect(); - if (just_update) - q->update(); - else if (!valid_rect) - dirty.translate(dx, dy); - - int x1, y1, x2, y2, w = sr.width(), h = sr.height(); - if (dx > 0) { - x1 = sr.x(); - x2 = x1+dx; - w -= dx; - } else { - x2 = sr.x(); - x1 = x2-dx; - w += dx; - } - if (dy > 0) { - y1 = sr.y(); - y2 = y1+dy; - h -= dy; - } else { - y2 = sr.y(); - y1 = y2-dy; - h += dy; - } - - if (dx == 0 && dy == 0) - return; - - Display *dpy = X11->display; - // Want expose events - if (w > 0 && h > 0 && !just_update && q->internalWinId()) { - GC gc = XCreateGC(dpy, q->internalWinId(), 0, 0); - XSetGraphicsExposures(dpy, gc, True); - XCopyArea(dpy, q->internalWinId(), q->internalWinId(), gc, x1, y1, w, h, x2, y2); - XFreeGC(dpy, gc); - } - - if (!valid_rect && !children.isEmpty()) { // scroll children - QPoint pd(dx, dy); - for (int i = 0; i < children.size(); ++i) { // move all children - register QObject *object = children.at(i); - if (object->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(object); - if (!w->isWindow()) - w->move(w->pos() + pd); - } - } - } - - if (just_update) - return; - - // Don't let the server be bogged-down with repaint events - bool repaint_immediately = (qt_sip_count(q) < 3 && !q->testAttribute(Qt::WA_WState_InPaintEvent)); - - if (dx) { - int x = x2 == sr.x() ? sr.x()+w : sr.x(); - if (repaint_immediately) - q->repaint(x, sr.y(), qAbs(dx), sr.height()); - else if (q->internalWinId()) - XClearArea(dpy, data.winid, x, sr.y(), qAbs(dx), sr.height(), True); - } - if (dy) { - int y = y2 == sr.y() ? sr.y()+h : sr.y(); - if (repaint_immediately) - q->repaint(sr.x(), y, sr.width(), qAbs(dy)); - else if (q->internalWinId()) - XClearArea(dpy, data.winid, sr.x(), y, sr.width(), qAbs(dy), True); - } - - qt_insert_sip(q, dx, dy); // #### ignores r -} - -int QWidget::metric(PaintDeviceMetric m) const -{ - Q_D(const QWidget); - int val; - if (m == PdmWidth) { - val = data->crect.width(); - } else if (m == PdmHeight) { - val = data->crect.height(); - } else { - Display *dpy = X11->display; - int scr = d->xinfo.screen(); - switch (m) { - case PdmDpiX: - case PdmPhysicalDpiX: - if (d->extra && d->extra->customDpiX) - val = d->extra->customDpiX; - else if (d->parent) - val = static_cast<QWidget *>(d->parent)->metric(m); - else - val = QX11Info::appDpiX(scr); - break; - case PdmDpiY: - case PdmPhysicalDpiY: - if (d->extra && d->extra->customDpiY) - val = d->extra->customDpiY; - else if (d->parent) - val = static_cast<QWidget *>(d->parent)->metric(m); - else - val = QX11Info::appDpiY(scr); - break; - case PdmWidthMM: - val = (DisplayWidthMM(dpy,scr)*data->crect.width())/ - DisplayWidth(dpy,scr); - break; - case PdmHeightMM: - val = (DisplayHeightMM(dpy,scr)*data->crect.height())/ - DisplayHeight(dpy,scr); - break; - case PdmNumColors: - val = d->xinfo.cells(); - break; - case PdmDepth: - val = d->xinfo.depth(); - break; - default: - val = 0; - qWarning("QWidget::metric: Invalid metric command"); - } - } - return val; -} - -void QWidgetPrivate::createSysExtra() -{ - extra->compress_events = true; - extra->xDndProxy = 0; -} - -void QWidgetPrivate::deleteSysExtra() -{ -} - -void QWidgetPrivate::createTLSysExtra() -{ - extra->topextra->spont_unmapped = 0; - extra->topextra->dnd = 0; - extra->topextra->validWMState = 0; - extra->topextra->waitingForMapNotify = 0; - extra->topextra->parentWinId = 0; - extra->topextra->userTimeWindow = 0; -#ifndef QT_NO_XSYNC - extra->topextra->syncUpdateCounter = 0; - extra->topextra->syncRequestTimestamp = 0; - extra->topextra->newCounterValueHi = 0; - extra->topextra->newCounterValueLo = 0; -#endif -} - -void QWidgetPrivate::deleteTLSysExtra() -{ - // don't destroy input context here. it will be destroyed in - // QWidget::destroy() destroyInputContext(); -} - -void QWidgetPrivate::registerDropSite(bool on) -{ - Q_UNUSED(on); -} - -void QWidgetPrivate::setMask_sys(const QRegion ®ion) -{ - Q_Q(QWidget); - if (!q->internalWinId()) - return; - - if (region.isEmpty()) { - XShapeCombineMask(X11->display, q->internalWinId(), ShapeBounding, 0, 0, - XNone, ShapeSet); - } else { - XShapeCombineRegion(X11->display, q->internalWinId(), ShapeBounding, 0, 0, - region.handle(), ShapeSet); - } -} - -/*! - \internal - - Computes the frame rectangle when needed. This is an internal function, you - should never call this. -*/ - -void QWidgetPrivate::updateFrameStrut() -{ - Q_Q(QWidget); - - QTLWExtra *top = topData(); - if (!top->validWMState) { - return; - } - if (!q->isWindow() && !q->internalWinId()) { - data.fstrut_dirty = false; - return; - } - - Atom type_ret; - Window l = q->effectiveWinId(), w = l, p, r; // target window, its parent, root - Window *c; - int i_unused; - unsigned int nc; - unsigned char *data_ret; - unsigned long l_unused; - - while (XQueryTree(X11->display, w, &r, &p, &c, &nc)) { - if (c && nc > 0) - XFree(c); - - if (! p) { - qWarning("QWidget::updateFrameStrut: No parent"); - return; - } - - // if the parent window is the root window, an Enlightenment virtual root or - // a NET WM virtual root window, stop here - data_ret = 0; - if (p == r || - (XGetWindowProperty(X11->display, p, - ATOM(ENLIGHTENMENT_DESKTOP), 0, 1, False, XA_CARDINAL, - &type_ret, &i_unused, &l_unused, &l_unused, - &data_ret) == Success && - type_ret == XA_CARDINAL)) { - if (data_ret) - XFree(data_ret); - - break; - } else if (X11->isSupportedByWM(ATOM(_NET_VIRTUAL_ROOTS)) && X11->net_virtual_root_list) { - int i = 0; - while (X11->net_virtual_root_list[i] != 0) { - if (X11->net_virtual_root_list[i++] == p) - break; - } - } - - l = w; - w = p; - } - - // we have our window - int transx, transy; - XWindowAttributes wattr; - if (XTranslateCoordinates(X11->display, l, w, - 0, 0, &transx, &transy, &p) && - XGetWindowAttributes(X11->display, w, &wattr)) { - top->frameStrut.setCoords(transx, - transy, - wattr.width - data.crect.width() - transx, - wattr.height - data.crect.height() - transy); - - // add the border_width for the window managers frame... some window managers - // do not use a border_width of zero for their frames, and if we the left and - // top strut, we ensure that pos() is absolutely correct. frameGeometry() - // will still be incorrect though... perhaps i should have foffset as well, to - // indicate the frame offset (equal to the border_width on X). - // - Brad - top->frameStrut.adjust(wattr.border_width, - wattr.border_width, - wattr.border_width, - wattr.border_width); - } - - data.fstrut_dirty = false; -} - -void QWidgetPrivate::setWindowOpacity_sys(qreal opacity) -{ - Q_Q(QWidget); - ulong value = ulong(opacity * 0xffffffff); - XChangeProperty(QX11Info::display(), q->internalWinId(), ATOM(_NET_WM_WINDOW_OPACITY), XA_CARDINAL, - 32, PropModeReplace, (uchar*)&value, 1); -} - -const QX11Info &QWidget::x11Info() const -{ - Q_D(const QWidget); - return d->xinfo; -} - -void QWidgetPrivate::setWindowRole() -{ - Q_Q(QWidget); - if (!q->internalWinId()) - return; - QByteArray windowRole = topData()->role.toUtf8(); - XChangeProperty(X11->display, q->internalWinId(), - ATOM(WM_WINDOW_ROLE), XA_STRING, 8, PropModeReplace, - (unsigned char *)windowRole.constData(), windowRole.length()); -} - -Q_GLOBAL_STATIC(QX11PaintEngine, qt_widget_paintengine) -QPaintEngine *QWidget::paintEngine() const -{ - Q_D(const QWidget); - if (qt_widget_paintengine()->isActive()) { - if (d->extraPaintEngine) - return d->extraPaintEngine; - QWidget *self = const_cast<QWidget *>(this); - self->d_func()->extraPaintEngine = new QX11PaintEngine(); - return d->extraPaintEngine; - } - return qt_widget_paintengine(); -} - -QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() -{ - return new QX11WindowSurface(q_func()); -} - -Qt::HANDLE QWidget::x11PictureHandle() const -{ -#ifndef QT_NO_XRENDER - Q_D(const QWidget); - if (!internalWinId() && testAttribute(Qt::WA_WState_Created)) - (void)winId(); // enforce native window - return d->picture; -#else - return 0; -#endif // QT_NO_XRENDER -} - -#ifndef QT_NO_XRENDER -XRenderColor QX11Data::preMultiply(const QColor &c) -{ - XRenderColor color; - const uint A = c.alpha(), - R = c.red(), - G = c.green(), - B = c.blue(); - color.alpha = (A | A << 8); - color.red = (R | R << 8) * color.alpha / 0x10000; - color.green = (G | G << 8) * color.alpha / 0x10000; - color.blue = (B | B << 8) * color.alpha / 0x10000; - return color; -} -Picture QX11Data::getSolidFill(int screen, const QColor &c) -{ - if (!X11->use_xrender) - return XNone; - - XRenderColor color = preMultiply(c); - for (int i = 0; i < X11->solid_fill_count; ++i) { - if (X11->solid_fills[i].screen == screen - && X11->solid_fills[i].color.alpha == color.alpha - && X11->solid_fills[i].color.red == color.red - && X11->solid_fills[i].color.green == color.green - && X11->solid_fills[i].color.blue == color.blue) - return X11->solid_fills[i].picture; - } - // none found, replace one - int i = qrand() % 16; - - if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) { - XRenderFreePicture (X11->display, X11->solid_fills[i].picture); - X11->solid_fills[i].picture = 0; - } - - if (!X11->solid_fills[i].picture) { - Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32); - XRenderPictureAttributes attrs; - attrs.repeat = True; - X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap, - XRenderFindStandardFormat(X11->display, PictStandardARGB32), - CPRepeat, &attrs); - XFreePixmap (X11->display, pixmap); - } - - X11->solid_fills[i].color = color; - X11->solid_fills[i].screen = screen; - XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1); - return X11->solid_fills[i].picture; -} -#endif - -void QWidgetPrivate::setModal_sys() -{ -} - -void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &att) -{ - QX11InfoData* xd = xinfo->getX11Data(true); - const XWindowAttributes &a = *(att.att); - // find which screen the window is on... - xd->screen = QX11Info::appScreen(); // by default, use the default :) - int i; - for (i = 0; i < ScreenCount(X11->display); i++) { - if (RootWindow(X11->display, i) == a.root) { - xd->screen = i; - break; - } - } - - xd->depth = a.depth; - xd->cells = DisplayCells(X11->display, xd->screen); - xd->visual = a.visual; - xd->defaultVisual = (XVisualIDFromVisual((Visual *) a.visual) == - XVisualIDFromVisual((Visual *) QX11Info::appVisual(xinfo->screen()))); - xd->colormap = a.colormap; - xd->defaultColormap = (a.colormap == QX11Info::appColormap(xinfo->screen())); - xinfo->setX11Data(xd); -} - -void QWidgetPrivate::updateX11AcceptFocus() -{ - Q_Q(QWidget); - if (!q->isWindow() || !q->internalWinId()) - return; - - XWMHints *h = XGetWMHints(X11->display, q->internalWinId()); - XWMHints wm_hints; - if (!h) { - memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy - h = &wm_hints; - } - h->flags |= InputHint; - h->input = q->testAttribute(Qt::WA_X11DoNotAcceptFocus) ? False : True; - - XSetWMHints(X11->display, q->internalWinId(), h); - if (h != &wm_hints) - XFree((char *)h); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qwidgetcreate_x11.cpp b/src/widgets/platforms/x11/qwidgetcreate_x11.cpp deleted file mode 100644 index 0a0656dd2b..0000000000 --- a/src/widgets/platforms/x11/qwidgetcreate_x11.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwidget.h" -#include "qt_x11_p.h" - -/* - Internal Qt functions to create X windows. We have put them in - separate functions to allow the programmer to reimplement them by - custom versions. -*/ - -QT_BEGIN_NAMESPACE - -Window qt_XCreateWindow(const QWidget *, Display *display, Window parent, - int x, int y, uint w, uint h, - int borderwidth, int depth, - uint windowclass, Visual *visual, - ulong valuemask, XSetWindowAttributes *attributes) -{ - return XCreateWindow(display, parent, x, y, w, h, borderwidth, depth, - windowclass, visual, valuemask, attributes); -} - - -Window qt_XCreateSimpleWindow(const QWidget *, Display *display, Window parent, - int x, int y, uint w, uint h, int borderwidth, - ulong border, ulong background) -{ - return XCreateSimpleWindow(display, parent, x, y, w, h, borderwidth, - border, background); -} - - -void qt_XDestroyWindow(const QWidget *, Display *display, Window window) -{ - if (window) - XDestroyWindow(display, window); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qx11embed_x11.cpp b/src/widgets/platforms/x11/qx11embed_x11.cpp deleted file mode 100644 index 3213b97629..0000000000 --- a/src/widgets/platforms/x11/qx11embed_x11.cpp +++ /dev/null @@ -1,1810 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" -#include "qx11embed_x11.h" -#include <qapplication.h> -#include <qevent.h> -#include <qpainter.h> -#include <qlayout.h> -#include <qstyle.h> -#include <qstyleoption.h> -#include <qelapsedtimer.h> -#include <qpointer.h> -#include <qdebug.h> -#include <qx11info_x11.h> -#include <private/qt_x11_p.h> -#include <private/qwidget_p.h> - -#define XK_MISCELLANY -#define XK_LATIN1 -#define None 0 -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/Xutil.h> -#include <X11/keysymdef.h> -#include <X11/X.h> - -#ifndef XK_ISO_Left_Tab -#define XK_ISO_Left_Tab 0xFE20 -#endif - -//#define QX11EMBED_DEBUG -#ifdef QX11EMBED_DEBUG -#include <qdebug.h> -#endif - -QT_BEGIN_NAMESPACE - -/*! - \class QX11EmbedWidget - \ingroup advanced - \inmodule QtWidgets - - \brief The QX11EmbedWidget class provides an XEmbed client widget. - - XEmbed is an X11 protocol that supports the embedding of a widget - from one application into another application. - - An XEmbed \e{client widget} is a window that is embedded into a - \e container. A container is the graphical location that embeds - (or \e swallows) an external application. - - QX11EmbedWidget is a widget used for writing XEmbed applets or - plugins. When it has been embedded and the container receives tab - focus, focus is passed on to the widget. When the widget reaches - the end of its focus chain, focus is passed back to the - container. Window activation, accelerator support, modality and - drag and drop (XDND) are also handled. - - The widget and container can both initiate the embedding. If the - widget is the initiator, the X11 window ID of the container that - it wants to embed itself into must be passed to embedInto(). - - If the container initiates the embedding, the window ID of the - embedded widget must be known. The container calls embed(), - passing the window ID. - - This example shows an application that embeds a QX11EmbedWidget - subclass into the window whose ID is passed as a command-line - argument: - - \snippet doc/src/snippets/qx11embedwidget/main.cpp 0 - - The problem of obtaining the window IDs is often solved by the - container invoking the application that provides the widget as a - separate process (as a panel invokes a docked applet), passing - its window ID to the new process as a command-line argument. The - new process can then call embedInto() with the container's window - ID, as shown in the example code above. Similarly, the new - process can report its window ID to the container through IPC, in - which case the container can embed the widget. - - When the widget has been embedded, it emits the signal - embedded(). If it is closed by the container, the widget emits - containerClosed(). If an error occurs when embedding, error() is - emitted. - - There are XEmbed widgets available for KDE and GTK+. The GTK+ - equivalent of QX11EmbedWidget is GtkPlug. The corresponding KDE 3 - widget is called QXEmbed. - - \sa QX11EmbedContainer, {XEmbed Specification} -*/ - -/*! - \class QX11EmbedContainer - \ingroup advanced - \inmodule QtWidgets - - \brief The QX11EmbedContainer class provides an XEmbed container - widget. - - XEmbed is an X11 protocol that supports the embedding of a widget - from one application into another application. - - An XEmbed \e container is the graphical location that embeds an - external \e {client widget}. A client widget is a window that is - embedded into a container. - - When a widget has been embedded and the container receives tab - focus, focus is passed on to the widget. When the widget reaches - the end of its focus chain, focus is passed back to the - container. Window activation, accelerator support, modality and - drag and drop (XDND) are also handled. - - QX11EmbedContainer is commonly used for writing panels or - toolbars that hold applets, or for \e swallowing X11 - applications. When writing a panel application, one container - widget is created on the toolbar, and it can then either swallow - another widget using embed(), or allow an XEmbed widget to be - embedded into itself. The container's X11 window ID, which is - retrieved with winId(), must then be known to the client widget. - After embedding, the client's window ID can be retrieved with - clientWinId(). - - In the following example, a container widget is created as the - main widget. It then invokes an application called "playmovie", - passing its window ID as a command line argument. The "playmovie" - program is an XEmbed client widget. The widget embeds itself into - the container using the container's window ID. - - \snippet doc/src/snippets/qx11embedcontainer/main.cpp 0 - - When the client widget is embedded, the container emits the - signal clientIsEmbedded(). The signal clientClosed() is emitted - when a widget is closed. - - It is possible for QX11EmbedContainer to embed XEmbed widgets - from toolkits other than Qt, such as GTK+. Arbitrary (non-XEmbed) - X11 widgets can also be embedded, but the XEmbed-specific - features such as window activation and focus handling are then - lost. - - The GTK+ equivalent of QX11EmbedContainer is GtkSocket. The - corresponding KDE 3 widget is called QXEmbed. - - \sa QX11EmbedWidget, {XEmbed Specification} -*/ - -/*! \fn void QX11EmbedWidget::embedded() - - This signal is emitted by the widget that has been embedded by an - XEmbed container. -*/ - -/*! \fn void QX11EmbedWidget::containerClosed() - - This signal is emitted by the client widget when the container - closes the widget. This can happen if the container itself - closes, or if the widget is rejected. - - The container can reject a widget for any reason, but the most - common cause of a rejection is when an attempt is made to embed a - widget into a container that already has an embedded widget. -*/ - -/*! \fn void QX11EmbedContainer::clientIsEmbedded() - - This signal is emitted by the container when a client widget has - been embedded. -*/ - -/*! \fn void QX11EmbedContainer::clientClosed() - - This signal is emitted by the container when the client widget - closes. -*/ - -/*! - \fn void QX11EmbedWidget::error(QX11EmbedWidget::Error error) - - This signal is emitted if an error occurred as a result of - embedding into or communicating with a container. The specified - \a error describes the problem that occurred. - - \sa QX11EmbedWidget::Error -*/ - -/*! - \fn QX11EmbedContainer::Error QX11EmbedContainer::error() const - - Returns the last error that occurred. -*/ - -/*! \fn void QX11EmbedContainer::error(QX11EmbedContainer::Error error) - - This signal is emitted if an error occurred when embedding or - communicating with a client. The specified \a error describes the - problem that occurred. - - \sa QX11EmbedContainer::Error -*/ - -/*! - \enum QX11EmbedWidget::Error - - \value Unknown An unrecognized error occurred. - - \value InvalidWindowID The X11 window ID of the container was - invalid. This error is usually triggered by passing an invalid - window ID to embedInto(). - - \omitvalue Internal -*/ - -/*! - \enum QX11EmbedContainer::Error - - \value Unknown An unrecognized error occurred. - - \value InvalidWindowID The X11 window ID of the container was - invalid. This error is usually triggered by passing an invalid - window ID to embed(). - - \omitvalue Internal -*/ - -const int XButtonPress = ButtonPress; -const int XButtonRelease = ButtonRelease; -#undef ButtonPress -#undef ButtonRelease - -// This is a hack to move topData() out from QWidgetPrivate to public. We -// need to to inspect window()'s embedded state. -class QHackWidget : public QWidget -{ - Q_DECLARE_PRIVATE(QWidget) -public: - QTLWExtra* topData() { return d_func()->topData(); } -}; - -static unsigned int XEMBED_VERSION = 0; - -enum QX11EmbedMessageType { - XEMBED_EMBEDDED_NOTIFY = 0, - XEMBED_WINDOW_ACTIVATE = 1, - XEMBED_WINDOW_DEACTIVATE = 2, - XEMBED_REQUEST_FOCUS = 3, - XEMBED_FOCUS_IN = 4, - XEMBED_FOCUS_OUT = 5, - XEMBED_FOCUS_NEXT = 6, - XEMBED_FOCUS_PREV = 7, - XEMBED_MODALITY_ON = 10, - XEMBED_MODALITY_OFF = 11, - XEMBED_REGISTER_ACCELERATOR = 12, - XEMBED_UNREGISTER_ACCELERATOR = 13, - XEMBED_ACTIVATE_ACCELERATOR = 14 -}; - -enum QX11EmbedFocusInDetail { - XEMBED_FOCUS_CURRENT = 0, - XEMBED_FOCUS_FIRST = 1, - XEMBED_FOCUS_LAST = 2 -}; - -enum QX11EmbedFocusInFlags { - XEMBED_FOCUS_OTHER = (0 << 0), - XEMBED_FOCUS_WRAPAROUND = (1 << 0) -}; - -enum QX11EmbedInfoFlags { - XEMBED_MAPPED = (1 << 0) -}; - -enum QX11EmbedAccelModifiers { - XEMBED_MODIFIER_SHIFT = (1 << 0), - XEMBED_MODIFIER_CONTROL = (1 << 1), - XEMBED_MODIFIER_ALT = (1 << 2), - XEMBED_MODIFIER_SUPER = (1 << 3), - XEMBED_MODIFIER_HYPER = (1 << 4) -}; - -enum QX11EmbedAccelFlags { - XEMBED_ACCELERATOR_OVERLOADED = (1 << 0) -}; - -// Silence the default X11 error handler. -static int x11ErrorHandler(Display *, XErrorEvent *) -{ - return 0; -} - -// Returns the X11 timestamp. Maintained mainly by qapplication -// internals, but also updated by the XEmbed widgets. -static Time x11Time() -{ - return qt_x11Data->time; -} - -// Gives the version and flags of the supported XEmbed protocol. -static unsigned int XEmbedVersion() -{ - return 0; -} - -// Sends an XEmbed message. -static void sendXEmbedMessage(WId window, Display *display, long message, - long detail = 0, long data1 = 0, long data2 = 0) -{ - XClientMessageEvent c; - memset(&c, 0, sizeof(c)); - c.type = ClientMessage; - c.message_type = ATOM(_XEMBED); - c.format = 32; - c.display = display; - c.window = window; - - c.data.l[0] = x11Time(); - c.data.l[1] = message; - c.data.l[2] = detail; - c.data.l[3] = data1; - c.data.l[4] = data2; - - XSendEvent(display, window, false, NoEventMask, (XEvent *) &c); -} - -// From qapplication_x11.cpp -static XKeyEvent lastKeyEvent; - -static QCoreApplication::EventFilter oldX11EventFilter; - -// The purpose of this global x11 filter is for one to capture the key -// events in their original state, but most importantly this is the -// only way to get the WM_TAKE_FOCUS message from WM_PROTOCOLS. -static bool x11EventFilter(void *message, long *result) -{ - XEvent *event = reinterpret_cast<XEvent *>(message); - if (event->type == XKeyPress || event->type == XKeyRelease) - lastKeyEvent = event->xkey; - - if (oldX11EventFilter && oldX11EventFilter != &x11EventFilter) - return oldX11EventFilter(message, result); - else - return false; -} - -// -struct functorData -{ - Window id, rootWindow; - bool clearedWmState; - bool reparentedToRoot; -}; - -static Bool functor(Display *display, XEvent *event, XPointer arg) -{ - functorData *data = (functorData *) arg; - - if (!data->reparentedToRoot && event->type == ReparentNotify - && event->xreparent.window == data->id - && event->xreparent.parent == data->rootWindow) { - data->reparentedToRoot = true; - return true; - } - - if (!data->clearedWmState - && event->type == PropertyNotify - && event->xproperty.window == data->id - && event->xproperty.atom == ATOM(WM_STATE)) { - if (event->xproperty.state == PropertyDelete) { - data->clearedWmState = true; - return true; - } - - Atom ret; - int format, status; - unsigned char *retval; - unsigned long nitems, after; - status = XGetWindowProperty(display, data->id, ATOM(WM_STATE), 0, 2, False, ATOM(WM_STATE), - &ret, &format, &nitems, &after, &retval ); - if (status == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) { - long state = *(long *)retval; - XFree(retval); - if (state == WithdrawnState) { - data->clearedWmState = true; - return true; - } - } - } - - return false; -} - -class QX11EmbedWidgetPrivate : public QWidgetPrivate -{ - Q_DECLARE_PUBLIC(QX11EmbedWidget) -public: - inline QX11EmbedWidgetPrivate() - { - lastError = QX11EmbedWidget::Unknown; - container = 0; - } - - void setEmbedded(); - - void emitError(QX11EmbedWidget::Error error) { - Q_Q(QX11EmbedWidget); - - lastError = error; - emit q->error(error); - } - - enum FocusWidgets { - FirstFocusWidget, - LastFocusWidget - }; - - int focusOriginator; - QWidget *getFocusWidget(FocusWidgets fw); - void checkActivateWindow(QObject *o); - QX11EmbedWidget *xEmbedWidget(QObject *o) const; - void clearFocus(); - - WId container; - QPointer<QWidget> currentFocus; - - QX11EmbedWidget::Error lastError; - -}; - -/*! - Constructs a QX11EmbedWidget object with the given \a parent. -*/ -QX11EmbedWidget::QX11EmbedWidget(QWidget *parent) - : QWidget(*new QX11EmbedWidgetPrivate, parent, 0) -{ - XSetErrorHandler(x11ErrorHandler); - - setAttribute(Qt::WA_NativeWindow); - setAttribute(Qt::WA_DontCreateNativeAncestors); - createWinId(); - XSelectInput(x11Info().display(), internalWinId(), - KeyPressMask | KeyReleaseMask | ButtonPressMask - | ButtonReleaseMask - | KeymapStateMask | ButtonMotionMask | PointerMotionMask - | FocusChangeMask - | ExposureMask | StructureNotifyMask - | SubstructureNotifyMask | PropertyChangeMask); - - long data[] = {XEMBED_VERSION, XEMBED_MAPPED}; - XChangeProperty(x11Info().display(), internalWinId(), ATOM(_XEMBED_INFO), - ATOM(_XEMBED_INFO), 32, PropModeReplace, - (unsigned char*) data, 2); - - setFocusPolicy(Qt::StrongFocus); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - QApplication::instance()->installEventFilter(this); - -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::QX11EmbedWidget: constructed client" - << (void *)this << "with winId" << winId(); -#endif -} - -/*! - Destructs the QX11EmbedWidget object. If the widget is embedded - when deleted, it is hidden and then detached from its container, - so that the container is free to embed a new widget. -*/ -QX11EmbedWidget::~QX11EmbedWidget() -{ - Q_D(QX11EmbedWidget); - if (d->container) { -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::~QX11EmbedWidget: unmapping" - << (void *)this << "with winId" << winId() - << "from container with winId" << d->container; -#endif - XUnmapWindow(x11Info().display(), internalWinId()); - XReparentWindow(x11Info().display(), internalWinId(), x11Info().appRootWindow(x11Info().screen()), 0, 0); - } - -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::~QX11EmbedWidget: destructed client" - << (void *)this << "with winId" << winId(); -#endif -} - -/*! - Returns the type of error that occurred last. This is the same error code - that is emitted by the error() signal. - - \sa Error -*/ -QX11EmbedWidget::Error QX11EmbedWidget::error() const -{ - return d_func()->lastError; -} - -/*! - When this function is called, the widget embeds itself into the - container whose window ID is \a id. - - If \a id is \e not the window ID of a container this function will - behave unpredictably. -*/ -void QX11EmbedWidget::embedInto(WId id) -{ - Q_D(QX11EmbedWidget); -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::embedInto: embedding client" - << (void *)this << "with winId" << winId() << "into container" - << id; -#endif - - d->container = id; - switch (XReparentWindow(x11Info().display(), internalWinId(), d->container, 0, 0)) { - case BadWindow: - d->emitError(InvalidWindowID); - break; - case BadMatch: - d->emitError(Internal); - break; - case Success: - default: - break; - } - QTLWExtra* x = d->extra ? d->extra->topextra : 0; - if (x) - x->frameStrut.setCoords(0, 0, 0, 0); - d->data.fstrut_dirty = false; -} - -/*! \internal - - Gets the first or last child widget that can get focus. -*/ -QWidget *QX11EmbedWidgetPrivate::getFocusWidget(FocusWidgets fw) -{ - Q_Q(QX11EmbedWidget); - QWidget *tlw = q; - QWidget *w = tlw->nextInFocusChain(); - - QWidget *last = tlw; - - extern bool qt_tab_all_widgets; - uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus; - - while (w != tlw) - { - if (((w->focusPolicy() & focus_flag) == focus_flag) - && w->isVisibleTo(q) && w->isEnabled()) - { - last = w; - if (fw == FirstFocusWidget) - break; - } - w = w->nextInFocusChain(); - } - - return last; -} - -/*! \internal - - Returns the xembed widget that the widget is a child of -*/ -QX11EmbedWidget *QX11EmbedWidgetPrivate::xEmbedWidget(QObject *o) const -{ - QX11EmbedWidget *xec = 0; - - // Check the widget itself, then its parents, and find the first - // QX11EmbedWidget. - do { - if ((xec = qobject_cast<QX11EmbedWidget *>(o))) - return xec; - } while ((o = o->parent())); - return 0; -} - -/*! \internal - - Checks the active window. -*/ -void QX11EmbedWidgetPrivate::checkActivateWindow(QObject *o) -{ - Q_Q(QX11EmbedWidget); - QX11EmbedWidget *xec = xEmbedWidget(o); - - // check if we are in the right xembed client - if (q != xec) - return; - - QWidget *w = qobject_cast<QWidget *>(o); - - // if it is no active window, then don't do the change - if (!(w && qApp->activeWindow())) - return; - - // if it already is the active window, don't do anything - if (w->window() != qApp->activeWindow()) - { - qApp->setActiveWindow(w->window()); - currentFocus = w; - - sendXEmbedMessage(xec->containerWinId(), q->x11Info().display(), XEMBED_REQUEST_FOCUS); - } -} - -/*! \internal - - Clears the focus -*/ -void QX11EmbedWidgetPrivate::clearFocus() -{ - Q_Q(QX11EmbedWidget); - // Setting focus on the client itself removes Qt's - // logical focus rectangle. We can't just do a - // clearFocus here, because when we send the synthetic - // FocusIn to ourselves on activation, Qt will set - // focus on focusWidget() again. This way, we "hide" - // focus rather than clearing it. - - if (!q->window()->hasFocus()) - q->window()->setFocus(Qt::OtherFocusReason); - - currentFocus = 0; -} - -/*! \internal - - Sets the embedded flag on the client. -*/ -void QX11EmbedWidgetPrivate::setEmbedded() -{ - Q_Q(QX11EmbedWidget); - ((QHackWidget *)q->window())->topData()->embedded = 1; -} - -/*! \internal - - Handles WindowActivate and FocusIn events for the client. -*/ -bool QX11EmbedWidget::eventFilter(QObject *o, QEvent *event) -{ - Q_D(QX11EmbedWidget); - switch (event->type()) { - case QEvent::FocusIn: - switch (((QFocusEvent *)event)->reason()) { - case Qt::MouseFocusReason: - // If the user clicks into one of the client widget's - // children and we didn't have focus already, we request - // focus from our container. - if (d->xEmbedWidget(o) == this) { - if (d->currentFocus.isNull()) - sendXEmbedMessage(d->container, x11Info().display(), XEMBED_REQUEST_FOCUS); - - d->currentFocus = qobject_cast<QWidget *>(o); - } - break; - case Qt::TabFocusReason: - // If the xembed client receives a focus event because of - // a Tab, then we are at the end of our focus chain and we - // ask the container to move to its next focus widget. - if (o == this) { - d->clearFocus(); - sendXEmbedMessage(d->container, x11Info().display(), XEMBED_FOCUS_NEXT); - return true; - } else { - // We're listening on events from qApp, so in order - // for us to know who to set focus on if we receive an - // activation event, we note the widget that got the - // focusin last. - if (d->xEmbedWidget(o) == this) - d->currentFocus = qobject_cast<QWidget *>(o); - } - break; - case Qt::BacktabFocusReason: - // If the window receives a focus event because of - // a Backtab, then we are at the start of our focus chain - // and we ask the container to move to its previous focus - // widget. - if (o == this) { - // See comment for Tab. - // If we receive a XEMBED_FOCUS_IN - // XEMBED_FOCUS_CURRENT, we will set focus in - // currentFocus. To avoid that in this case, we reset - // currentFocus. - d->clearFocus(); - sendXEmbedMessage(d->container, x11Info().display(), XEMBED_FOCUS_PREV); - return true; - } else { - if (d->xEmbedWidget(o) == this) - d->currentFocus = qobject_cast<QWidget *>(o); - } - break; - case Qt::ActiveWindowFocusReason: - if (isActiveWindow()) { - if (!d->currentFocus.isNull()) { - if (!d->currentFocus->hasFocus()) - d->currentFocus->setFocus(Qt::OtherFocusReason); - } else { - d->clearFocus(); - return true; - } - } - - break; - case Qt::PopupFocusReason: - case Qt::ShortcutFocusReason: - case Qt::OtherFocusReason: - // If focus is received to any child widget because of any - // other reason, remember the widget so that we can give - // it focus again if we're activated. - if (d->xEmbedWidget(o) == this) { - d->currentFocus = qobject_cast<QWidget *>(o); - } - break; - default: - break; - } - break; - case QEvent::MouseButtonPress: - // If we get a mouse button press event inside a embedded widget - // make sure this is the active window in qapp. - d->checkActivateWindow(o); - break; - default: - break; - } - - return QWidget::eventFilter(o, event); -} - -/*! \internal - - Handles some notification events and client messages. Client side - XEmbed message receiving is also handled here. -*/ -bool QX11EmbedWidget::x11Event(XEvent *event) -{ - Q_D(QX11EmbedWidget); - switch (event->type) { - case DestroyNotify: -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::x11Event: client" - << (void *)this << "with winId" << winId() - << "received a DestroyNotify"; -#endif - // If the container window is destroyed, we signal this to the user. - d->container = 0; - emit containerClosed(); - break; - case ReparentNotify: -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::x11Event: client" - << (void *)this << "with winId" << winId() - << "received a ReparentNotify to" - << ((event->xreparent.parent == x11Info().appRootWindow(x11Info().screen())) - ? QString::fromLatin1("root") : QString::number(event->xreparent.parent)); -#endif - // If the container shuts down, we will be reparented to the - // root window. We must also consider the case that we may be - // reparented from one container to another. - if (event->xreparent.parent == x11Info().appRootWindow(x11Info().screen())) { - if (((QHackWidget *)this)->topData()->embedded) { - d->container = 0; - emit containerClosed(); - } - return true; - } else { - d->container = event->xreparent.parent; - } - break; - case UnmapNotify: - // Mapping and unmapping are handled by changes to the - // _XEMBED_INFO property. Any default map/unmap requests are - // ignored. - return true; - case PropertyNotify: - // The container sends us map/unmap messages through the - // _XEMBED_INFO property. We adhere to the XEMBED_MAPPED bit in - // data2. - if (event->xproperty.atom == ATOM(_XEMBED_INFO)) { - Atom actual_type_return; - int actual_format_return; - unsigned long nitems_return; - unsigned long bytes_after_return; - unsigned char *prop_return = 0; - if (XGetWindowProperty(x11Info().display(), internalWinId(), ATOM(_XEMBED_INFO), 0, 2, - false, ATOM(_XEMBED_INFO), &actual_type_return, - &actual_format_return, &nitems_return, - &bytes_after_return, &prop_return) == Success) { - if (nitems_return > 1) { - if (((long * )prop_return)[1] & XEMBED_MAPPED) { - XMapWindow(x11Info().display(), internalWinId()); - } else { - XUnmapWindow(x11Info().display(), internalWinId()); - } - } - if (prop_return) - XFree(prop_return); - } - } - - break; - case ClientMessage: - // XEMBED messages have message_type _XEMBED - if (event->xclient.message_type == ATOM(_XEMBED)) { - // Discard XEMBED messages not to ourselves. (### dead code?) - if (event->xclient.window != internalWinId()) - break; - - // Update qt_x_time if necessary - Time msgtime = (Time) event->xclient.data.l[0]; - if (msgtime > X11->time) - X11->time = msgtime; - - switch (event->xclient.data.l[1]) { - case XEMBED_WINDOW_ACTIVATE: { - // When we receive an XEMBED_WINDOW_ACTIVATE, we simply send - // ourselves a WindowActivate event. Real activation happens - // when receive XEMBED_FOCUS_IN. - if (!isActiveWindow()) { - QEvent ev(QEvent::WindowActivate); - QApplication::sendEvent(this, &ev); - } - } - break; - case XEMBED_WINDOW_DEACTIVATE: { - // When we receive an XEMBED_WINDOW_DEACTIVATE, we simply send - // ourselves a WindowDeactivate event. Real activation happens - // when receive XEMBED_FOCUS_IN. - if (isActiveWindow()) { - if (!qApp->activePopupWidget()) - QApplication::setActiveWindow(0); - } else { - QEvent ev(QEvent::WindowDeactivate); - QApplication::sendEvent(this, &ev); - } - } - break; - case XEMBED_EMBEDDED_NOTIFY: { -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedWidget::x11Event: client" - << (void *)this << "with winId" << winId() - << "received an XEMBED EMBEDDED NOTIFY message"; -#endif - // In this message's l[2] we have the max version - // supported by both the client and the - // container. QX11EmbedWidget does not use this field. - - // We have been embedded, so we set our - // client's embedded flag. - d->setEmbedded(); - emit embedded(); - } - break; - case XEMBED_FOCUS_IN: - // don't set the focus if a modal dialog is open - if (qApp->activeModalWidget()) - break; - - // in case we embed more than one topLevel window inside the same - // host window. - if (window() != qApp->activeWindow()) - qApp->setActiveWindow(this); - - switch (event->xclient.data.l[2]) { - case XEMBED_FOCUS_CURRENT: - // The container sends us this message if it wants - // us to focus on the widget that last had focus. - // This is the reply when XEMBED_REQUEST_FOCUS is - // sent to the container. - if (!d->currentFocus.isNull()) { - if (!d->currentFocus->hasFocus()) - d->currentFocus->setFocus(Qt::OtherFocusReason); - } else { - // No widget currently has focus. We set focus - // on the first widget next to the - // client widget. Since the setFocus will not work - // if the window is disabled, set the currentFocus - // directly so that it's set on window activate. - d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::FirstFocusWidget); - d->currentFocus->setFocus(Qt::OtherFocusReason); - } - break; - case XEMBED_FOCUS_FIRST: - // The container sends this message when it wants - // us to focus on the first widget in our focus - // chain (typically because of a tab). - d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::FirstFocusWidget); - d->currentFocus->setFocus(Qt::TabFocusReason); - break; - case XEMBED_FOCUS_LAST: - // The container sends this message when it wants - // us to focus on the last widget in our focus - // chain (typically because of a backtab). - d->currentFocus = d->getFocusWidget(QX11EmbedWidgetPrivate::LastFocusWidget); - d->currentFocus->setFocus(Qt::BacktabFocusReason); - break; - default: - // Ignore any other XEMBED_FOCUS_IN details. - break; - } - break; - case XEMBED_FOCUS_OUT: - // The container sends us this message when it wants us - // to lose focus and forget about the widget that last - // had focus. Typically sent by the container when it - // loses focus because of mouse or tab activity. We do - // then not want to set focus on anything if we're - // activated. - if (isActiveWindow()) - d->clearFocus(); - - break; - default: - // Ignore any other XEMBED messages. - break; - }; - } else { - // Non-XEMBED client messages are not interesting. - } - - break; - default: - // Ignore all other x11 events. - break; - } - - // Allow default handling. - return QWidget::x11Event(event); -} - -/*! - \reimp -*/ -bool QX11EmbedWidget::event(QEvent *event) -{ - if (event->type() == QEvent::ParentChange) { - XSelectInput(x11Info().display(), internalWinId(), - KeyPressMask | KeyReleaseMask | ButtonPressMask - | ButtonReleaseMask - | KeymapStateMask | ButtonMotionMask | PointerMotionMask - | FocusChangeMask - | ExposureMask | StructureNotifyMask - | SubstructureNotifyMask | PropertyChangeMask); - } - return QWidget::event(event); -} - -/*! - \reimp -*/ -void QX11EmbedWidget::resizeEvent(QResizeEvent *event) -{ - if (layout()) - layout()->update(); - QWidget::resizeEvent(event); -} - -/*! - If the widget is embedded, returns the window ID of the - container; otherwize returns 0. -*/ -WId QX11EmbedWidget::containerWinId() const -{ - Q_D(const QX11EmbedWidget); - return d->container; -} - -class QX11EmbedContainerPrivate : public QWidgetPrivate -{ - Q_DECLARE_PUBLIC(QX11EmbedContainer) -public: - inline QX11EmbedContainerPrivate() - { - lastError = QX11EmbedContainer::Unknown; - client = 0; - focusProxy = 0; - clientIsXEmbed = false; - xgrab = false; - } - - bool isEmbedded() const; - void moveInputToProxy(); - - void acceptClient(WId window); - void rejectClient(WId window); - - void checkGrab(); - - WId topLevelParentWinId() const; - - void emitError(QX11EmbedContainer::Error error) { - Q_Q(QX11EmbedContainer); - lastError = error; - emit q->error(error); - } - - WId client; - QWidget *focusProxy; - bool clientIsXEmbed; - bool xgrab; - QRect clientOriginalRect; - QSize wmMinimumSizeHint; - - QX11EmbedContainer::Error lastError; - - static QX11EmbedContainer *activeContainer; -}; - -QX11EmbedContainer *QX11EmbedContainerPrivate::activeContainer = 0; - -/*! - Creates a QX11EmbedContainer object with the given \a parent. -*/ -QX11EmbedContainer::QX11EmbedContainer(QWidget *parent) - : QWidget(*new QX11EmbedContainerPrivate, parent, 0) -{ - Q_D(QX11EmbedContainer); - XSetErrorHandler(x11ErrorHandler); - - setAttribute(Qt::WA_NativeWindow); - setAttribute(Qt::WA_DontCreateNativeAncestors); - createWinId(); - - setFocusPolicy(Qt::StrongFocus); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - // ### PORT setKeyCompression(false); - setAcceptDrops(true); - setEnabled(false); - - // Everybody gets a focus proxy, but only one toplevel container's - // focus proxy is actually in use. - d->focusProxy = new QWidget(this); - d->focusProxy->setAttribute(Qt::WA_NativeWindow); - d->focusProxy->setAttribute(Qt::WA_DontCreateNativeAncestors); - d->focusProxy->createWinId(); - d->focusProxy->setGeometry(-1, -1, 1, 1); - - // We need events from the window (activation status) and - // from qApp (keypress/release). - qApp->installEventFilter(this); - - // Install X11 event filter. - if (!oldX11EventFilter) - oldX11EventFilter = QCoreApplication::instance()->setEventFilter(x11EventFilter); - - XSelectInput(x11Info().display(), internalWinId(), - KeyPressMask | KeyReleaseMask - | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask - | KeymapStateMask - | PointerMotionMask - | EnterWindowMask | LeaveWindowMask - | FocusChangeMask - | ExposureMask - | StructureNotifyMask - | SubstructureNotifyMask); - - // Make sure our new event mask takes effect as soon as possible. - XFlush(x11Info().display()); - - // Move input to our focusProxy if this widget is active, and not - // shaded by a modal dialog (in which case isActiveWindow() would - // still return true, but where we must not move input focus). - if (qApp->activeWindow() == window() && !d->isEmbedded()) - d->moveInputToProxy(); - -#ifdef QX11EMBED_DEBUG - qDebug() << "QX11EmbedContainer::QX11EmbedContainer: constructed container" - << (void *)this << "with winId" << winId(); -#endif -} - -/*! - Destructs a QX11EmbedContainer. -*/ -QX11EmbedContainer::~QX11EmbedContainer() -{ - Q_D(QX11EmbedContainer); - if (d->client) { - XUnmapWindow(x11Info().display(), d->client); - XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(x11Info().screen()), 0, 0); - } - - if (d->xgrab) - XUngrabButton(x11Info().display(), AnyButton, AnyModifier, internalWinId()); -} - - -QX11EmbedContainer::Error QX11EmbedContainer::error() const { - return d_func()->lastError; -} - - -/*! \reimp -*/ -void QX11EmbedContainer::paintEvent(QPaintEvent *) -{ -} - -/*! \internal - - Returns whether or not the windows' embedded flag is set. -*/ -bool QX11EmbedContainerPrivate::isEmbedded() const -{ - Q_Q(const QX11EmbedContainer); - return ((QHackWidget *)q->window())->topData()->embedded == 1; -} - -/*! \internal - - Returns the parentWinId of the window. -*/ -WId QX11EmbedContainerPrivate::topLevelParentWinId() const -{ - Q_Q(const QX11EmbedContainer); - return ((QHackWidget *)q->window())->topData()->parentWinId; -} - -/*! - If the container has an embedded widget, this function returns - the X11 window ID of the client; otherwise it returns 0. -*/ -WId QX11EmbedContainer::clientWinId() const -{ - Q_D(const QX11EmbedContainer); - return d->client; -} - -/*! - Instructs the container to embed the X11 window with window ID \a - id. The client widget will then move on top of the container - window and be resized to fit into the container. - - The \a id should be the ID of a window controlled by an XEmbed - enabled application, but this is not mandatory. If \a id does not - belong to an XEmbed client widget, then focus handling, - activation, accelerators and other features will not work - properly. -*/ -void QX11EmbedContainer::embedClient(WId id) -{ - Q_D(QX11EmbedContainer); - - if (id == 0) { - d->emitError(InvalidWindowID); - return; - } - - // Walk up the tree of parent windows to prevent embedding of ancestors. - WId thisId = internalWinId(); - Window rootReturn; - Window parentReturn; - Window *childrenReturn = 0; - unsigned int nchildrenReturn; - do { - if (XQueryTree(x11Info().display(), thisId, &rootReturn, - &parentReturn, &childrenReturn, &nchildrenReturn) == 0) { - d->emitError(InvalidWindowID); - return; - } - if (childrenReturn) { - XFree(childrenReturn); - childrenReturn = 0; - } - - thisId = parentReturn; - if (id == thisId) { - d->emitError(InvalidWindowID); - return; - } - } while (thisId != rootReturn); - - // watch for property notify events (see below) - XGrabServer(x11Info().display()); - XWindowAttributes attrib; - if (!XGetWindowAttributes(x11Info().display(), id, &attrib)) { - XUngrabServer(x11Info().display()); - d->emitError(InvalidWindowID); - return; - } - XSelectInput(x11Info().display(), id, attrib.your_event_mask | PropertyChangeMask | StructureNotifyMask); - XUngrabServer(x11Info().display()); - - // Put the window into WithdrawnState - XUnmapWindow(x11Info().display(), id); - XSync(x11Info().display(), False); // make sure the window is hidden - - /* - Wait for notification from the window manager that the window is - in withdrawn state. According to the ICCCM section 4.1.3.1, - we should wait for the WM_STATE property to either be deleted or - set to WithdrawnState. - - For safety, we will not wait more than 500 ms, so that we can - preemptively workaround buggy window managers. - */ - QElapsedTimer t; - t.start(); - - functorData data; - data.id = id; - data.rootWindow = attrib.root; - data.clearedWmState = false; - data.reparentedToRoot = false; - - do { - if (t.elapsed() > 500) // time-out after 500 ms - break; - - XEvent event; - if (!XCheckIfEvent(x11Info().display(), &event, functor, (XPointer) &data)) { - XSync(x11Info().display(), False); - usleep(50000); - continue; - } - - qApp->x11ProcessEvent(&event); - } while (!data.clearedWmState || !data.reparentedToRoot); - - // restore the event mask - XSelectInput(x11Info().display(), id, attrib.your_event_mask); - - switch (XReparentWindow(x11Info().display(), id, internalWinId(), 0, 0)) { - case BadWindow: - case BadMatch: - d->emitError(InvalidWindowID); - break; - default: - break; - } -} - -/*! \internal - - Handles key, activation and focus events for the container. -*/ -bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event) -{ - Q_D(QX11EmbedContainer); - switch (event->type()) { - case QEvent::KeyPress: - // Forward any keypresses to our client. - if (o == this && d->client) { - lastKeyEvent.window = d->client; - XSendEvent(x11Info().display(), d->client, false, KeyPressMask, (XEvent *) &lastKeyEvent); - return true; - } - break; - case QEvent::KeyRelease: - // Forward any keyreleases to our client. - if (o == this && d->client) { - lastKeyEvent.window = d->client; - XSendEvent(x11Info().display(), d->client, false, KeyReleaseMask, (XEvent *) &lastKeyEvent); - return true; - } - break; - - case QEvent::WindowActivate: - // When our container window is activated, we pass the - // activation message on to our client. Note that X input - // focus is set to our focus proxy. We want to intercept all - // keypresses. - if (o == window() && d->client) { - if (d->clientIsXEmbed) { - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_ACTIVATE); - } else { - d->checkGrab(); - if (hasFocus()) - XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time()); - } - if (!d->isEmbedded()) - d->moveInputToProxy(); - } - break; - case QEvent::WindowDeactivate: - // When our container window is deactivated, we pass the - // deactivation message to our client. - if (o == window() && d->client) { - if (d->clientIsXEmbed) - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_DEACTIVATE); - else - d->checkGrab(); - } - break; - case QEvent::FocusIn: - // When receiving FocusIn events generated by Tab or Backtab, - // we pass focus on to our client. Any mouse activity is sent - // directly to the client, and it will ask us for focus with - // XEMBED_REQUEST_FOCUS. - if (o == this && d->client) { - if (!d->isEmbedded()) - d->activeContainer = this; - - if (d->clientIsXEmbed) { - if (!d->isEmbedded()) - d->moveInputToProxy(); - - QFocusEvent *fe = (QFocusEvent *)event; - switch (fe->reason()) { - case Qt::TabFocusReason: - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_FIRST); - break; - case Qt::BacktabFocusReason: - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_LAST); - break; - default: - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT); - break; - } - } else { - d->checkGrab(); - XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time()); - } - } - - break; - case QEvent::FocusOut: { - // When receiving a FocusOut, we ask our client to remove its - // focus. - if (o == this && d->client) { - if (!d->isEmbedded()) { - d->activeContainer = 0; - if (isActiveWindow()) - d->moveInputToProxy(); - } - - if (d->clientIsXEmbed) { - QFocusEvent *fe = (QFocusEvent *)event; - if (o == this && d->client && fe->reason() != Qt::ActiveWindowFocusReason) - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_OUT); - } else { - d->checkGrab(); - } - } - } - break; - - case QEvent::Close: { - if (o == this && d->client) { - // Unmap the client and reparent it to the root window. - // Wait until the messages have been processed. Then ask - // the window manager to delete the window. - XUnmapWindow(x11Info().display(), d->client); - XReparentWindow(x11Info().display(), d->client, x11Info().appRootWindow(x11Info().screen()), 0, 0); - XSync(x11Info().display(), false); - - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = d->client; - ev.xclient.message_type = ATOM(WM_PROTOCOLS); - ev.xclient.format = 32; - ev.xclient.data.s[0] = ATOM(WM_DELETE_WINDOW); - XSendEvent(x11Info().display(), d->client, false, NoEventMask, &ev); - - XFlush(x11Info().display()); - d->client = 0; - d->clientIsXEmbed = false; - d->wmMinimumSizeHint = QSize(); - updateGeometry(); - setEnabled(false); - update(); - - emit clientClosed(); - } - } - default: - break; - } - - return QWidget::eventFilter(o, event); -} - -/*! \internal - - Handles X11 events for the container. -*/ -bool QX11EmbedContainer::x11Event(XEvent *event) -{ - Q_D(QX11EmbedContainer); - - switch (event->type) { - case CreateNotify: - // The client created an embedded window. - if (d->client) - d->rejectClient(event->xcreatewindow.window); - else - d->acceptClient(event->xcreatewindow.window); - break; - case DestroyNotify: - if (event->xdestroywindow.window == d->client) { - // The client died. - d->client = 0; - d->clientIsXEmbed = false; - d->wmMinimumSizeHint = QSize(); - updateGeometry(); - update(); - setEnabled(false); - emit clientClosed(); - } - break; - case ReparentNotify: - // The client sends us this if it reparents itself out of our - // widget. - if (event->xreparent.window == d->client && event->xreparent.parent != internalWinId()) { - d->client = 0; - d->clientIsXEmbed = false; - d->wmMinimumSizeHint = QSize(); - updateGeometry(); - update(); - setEnabled(false); - emit clientClosed(); - } else if (event->xreparent.parent == internalWinId()) { - // The client reparented itself into this window. - if (d->client) - d->rejectClient(event->xreparent.window); - else - d->acceptClient(event->xreparent.window); - } - break; - case ClientMessage: { - if (event->xclient.message_type == ATOM(_XEMBED)) { - // Ignore XEMBED messages not to ourselves - if (event->xclient.window != internalWinId()) - break; - - // Receiving an XEmbed message means the client - // is an XEmbed client. - d->clientIsXEmbed = true; - - Time msgtime = (Time) event->xclient.data.l[0]; - if (msgtime > X11->time) - X11->time = msgtime; - - switch (event->xclient.data.l[1]) { - case XEMBED_REQUEST_FOCUS: { - // This typically happens when the client gets focus - // because of a mouse click. - if (!hasFocus()) - setFocus(Qt::OtherFocusReason); - - // The message is passed along to the topmost container - // that eventually responds with a XEMBED_FOCUS_IN - // message. The focus in message is passed all the way - // back until it reaches the original focus - // requestor. In the end, not only the original client - // has focus, but also all its ancestor containers. - if (d->isEmbedded()) { - // If our window's embedded flag is set, then - // that suggests that we are part of a client. The - // parentWinId will then point to an container to whom - // we must pass this message. - sendXEmbedMessage(d->topLevelParentWinId(), x11Info().display(), XEMBED_REQUEST_FOCUS); - } else { - // Our window's embedded flag is not set, - // so we are the topmost container. We respond to - // the focus request message with a focus in - // message. This message will pass on from client - // to container to client until it reaches the - // originator of the XEMBED_REQUEST_FOCUS message. - sendXEmbedMessage(d->client, x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT); - } - - break; - } - case XEMBED_FOCUS_NEXT: - // Client sends this event when it received a tab - // forward and was at the end of its focus chain. If - // we are the only widget in the focus chain, we send - // ourselves a FocusIn event. - if (d->focus_next != this) { - focusNextPrevChild(true); - } else { - QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason); - qApp->sendEvent(this, &event); - } - - break; - case XEMBED_FOCUS_PREV: - // Client sends this event when it received a backtab - // and was at the start of its focus chain. If we are - // the only widget in the focus chain, we send - // ourselves a FocusIn event. - if (d->focus_next != this) { - focusNextPrevChild(false); - } else { - QFocusEvent event(QEvent::FocusIn, Qt::BacktabFocusReason); - qApp->sendEvent(this, &event); - } - - break; - default: - break; - } - } - } - break; - case XButtonPress: - if (!d->clientIsXEmbed) { - setFocus(Qt::MouseFocusReason); - XAllowEvents(x11Info().display(), ReplayPointer, CurrentTime); - return true; - } - break; - case XButtonRelease: - if (!d->clientIsXEmbed) - XAllowEvents(x11Info().display(), SyncPointer, CurrentTime); - break; - default: - break; - } - - return QWidget::x11Event(event); -} - -/*! \internal - - Whenever the container is resized, we need to resize our client. -*/ -void QX11EmbedContainer::resizeEvent(QResizeEvent *) -{ - Q_D(QX11EmbedContainer); - if (d->client) - XResizeWindow(x11Info().display(), d->client, width(), height()); -} - -/*! \internal - - We use the QShowEvent to signal to our client that we want it to - map itself. We do this by changing its window property - XEMBED_INFO. The client will get an X11 PropertyNotify. -*/ -void QX11EmbedContainer::showEvent(QShowEvent *) -{ - Q_D(QX11EmbedContainer); - if (d->client) { - long data[] = {XEMBED_VERSION, XEMBED_MAPPED}; - XChangeProperty(x11Info().display(), d->client, ATOM(_XEMBED_INFO), ATOM(_XEMBED_INFO), 32, - PropModeReplace, (unsigned char *) data, 2); - } -} - -/*! \internal - - We use the QHideEvent to signal to our client that we want it to - unmap itself. We do this by changing its window property - XEMBED_INFO. The client will get an X11 PropertyNotify. -*/ -void QX11EmbedContainer::hideEvent(QHideEvent *) -{ - Q_D(QX11EmbedContainer); - if (d->client) { - long data[] = {XEMBED_VERSION, XEMBED_MAPPED}; - XChangeProperty(x11Info().display(), d->client, ATOM(_XEMBED_INFO), ATOM(_XEMBED_INFO), 32, - PropModeReplace, (unsigned char *) data, 2); - } -} - -/*! - \reimp -*/ -bool QX11EmbedContainer::event(QEvent *event) -{ - if (event->type() == QEvent::ParentChange) { - XSelectInput(x11Info().display(), internalWinId(), - KeyPressMask | KeyReleaseMask - | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask - | KeymapStateMask - | PointerMotionMask - | EnterWindowMask | LeaveWindowMask - | FocusChangeMask - | ExposureMask - | StructureNotifyMask - | SubstructureNotifyMask); - } - return QWidget::event(event); -} - -/*! \internal - - Rejects a client window by reparenting it to the root window. The - client will receive a reparentnotify, and will most likely assume - that the container has shut down. The XEmbed protocol does not - define any way to reject a client window, but this is a clean way - to do it. -*/ -void QX11EmbedContainerPrivate::rejectClient(WId window) -{ - Q_Q(QX11EmbedContainer); - q->setEnabled(false); - XRemoveFromSaveSet(q->x11Info().display(), client); - XReparentWindow(q->x11Info().display(), window, q->x11Info().appRootWindow(q->x11Info().screen()), 0, 0); -} - -/*! \internal - - Accepts a client by mapping it, resizing it and optionally - activating and giving it logical focusing through XEMBED messages. -*/ -void QX11EmbedContainerPrivate::acceptClient(WId window) -{ - Q_Q(QX11EmbedContainer); - client = window; - q->setEnabled(true); - - // This tells Qt that we wish to forward DnD messages to - // our client. - if (!extra) - createExtra(); - extraData()->xDndProxy = client; - - unsigned int version = XEmbedVersion(); - - Atom actual_type_return; - int actual_format_return; - unsigned long nitems_return = 0; - unsigned long bytes_after_return; - unsigned char *prop_return = 0; - unsigned int clientversion = 0; - - // Add this client to our saveset, so if we crash, the client window - // doesn't get destroyed. This is useful for containers that restart - // automatically after a crash, because it can simply reembed its clients - // without having to restart them (KDE panel). - XAddToSaveSet(q->x11Info().display(), client); - - // XEmbed clients have an _XEMBED_INFO property in which we can - // fetch the version - if (XGetWindowProperty(q->x11Info().display(), client, ATOM(_XEMBED_INFO), 0, 2, false, - ATOM(_XEMBED_INFO), &actual_type_return, &actual_format_return, - &nitems_return, &bytes_after_return, &prop_return) == Success) { - - if (actual_type_return != None && actual_format_return != 0) { - // Clients with the _XEMBED_INFO property are XEMBED clients. - clientIsXEmbed = true; - - long *p = (long *)prop_return; - if (nitems_return >= 2) - clientversion = (unsigned int)p[0]; - } - - XFree(prop_return); - } - - // Store client window's original size and placement. - Window root; - int x_return, y_return; - unsigned int width_return, height_return, border_width_return, depth_return; - XGetGeometry(q->x11Info().display(), client, &root, &x_return, &y_return, - &width_return, &height_return, &border_width_return, &depth_return); - clientOriginalRect.setCoords(x_return, y_return, - x_return + width_return - 1, - y_return + height_return - 1); - - // Ask the client for its minimum size. - XSizeHints size; - long msize; - if (XGetWMNormalHints(q->x11Info().display(), client, &size, &msize) && (size.flags & PMinSize)) { - wmMinimumSizeHint = QSize(size.min_width, size.min_height); - q->updateGeometry(); - } - - // The container should set the data2 field to the lowest of its - // supported version number and that of the client (from - // _XEMBED_INFO property). - unsigned int minversion = version > clientversion ? clientversion : version; - sendXEmbedMessage(client, q->x11Info().display(), XEMBED_EMBEDDED_NOTIFY, q->internalWinId(), minversion); - XMapWindow(q->x11Info().display(), client); - - // Resize it, but no smaller than its minimum size hint. - XResizeWindow(q->x11Info().display(), - client, - qMax(q->width(), wmMinimumSizeHint.width()), - qMax(q->height(), wmMinimumSizeHint.height())); - q->update(); - - // Not mentioned in the protocol is that if the container - // is already active, the client must be activated to work - // properly. - if (q->window()->isActiveWindow()) - sendXEmbedMessage(client, q->x11Info().display(), XEMBED_WINDOW_ACTIVATE); - - // Also, if the container already has focus, then it must - // send a focus in message to its new client; otherwise we ask - // it to remove focus. - if (q->focusWidget() == q && q->hasFocus()) - sendXEmbedMessage(client, q->x11Info().display(), XEMBED_FOCUS_IN, XEMBED_FOCUS_FIRST); - else - sendXEmbedMessage(client, q->x11Info().display(), XEMBED_FOCUS_OUT); - - if (!clientIsXEmbed) { - checkGrab(); - if (q->hasFocus()) { - XSetInputFocus(q->x11Info().display(), client, XRevertToParent, x11Time()); - } - } else { - if (!isEmbedded()) - moveInputToProxy(); - } - - emit q->clientIsEmbedded(); -} - -/*! \internal - - Moves X11 keyboard input focus to the focusProxy, unless the focus - is there already. When X11 keyboard input focus is on the - focusProxy, which is a child of the container and a sibling of the - client, X11 keypresses and keyreleases will always go to the proxy - and not to the client. -*/ -void QX11EmbedContainerPrivate::moveInputToProxy() -{ - Q_Q(QX11EmbedContainer); - // Following Owen Taylor's advice from the XEmbed specification to - // always use CurrentTime when no explicit user action is involved. - XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, CurrentTime); -} - -/*! \internal - - Ask the window manager to give us a default minimum size. -*/ -QSize QX11EmbedContainer::minimumSizeHint() const -{ - Q_D(const QX11EmbedContainer); - if (!d->client || !d->wmMinimumSizeHint.isValid()) - return QWidget::minimumSizeHint(); - return d->wmMinimumSizeHint; -} - -/*! \internal - -*/ -void QX11EmbedContainerPrivate::checkGrab() -{ - Q_Q(QX11EmbedContainer); - if (!clientIsXEmbed && q->isActiveWindow() && !q->hasFocus()) { - if (!xgrab) { - XGrabButton(q->x11Info().display(), AnyButton, AnyModifier, q->internalWinId(), - true, ButtonPressMask, GrabModeSync, GrabModeAsync, - None, None); - } - xgrab = true; - } else { - if (xgrab) - XUngrabButton(q->x11Info().display(), AnyButton, AnyModifier, q->internalWinId()); - xgrab = false; - } -} - -/*! - Detaches the client from the embedder. The client will appear as a - standalone window on the desktop. -*/ -void QX11EmbedContainer::discardClient() -{ - Q_D(QX11EmbedContainer); - if (d->client) { - XResizeWindow(x11Info().display(), d->client, d->clientOriginalRect.width(), - d->clientOriginalRect.height()); - - d->rejectClient(d->client); - } -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qx11embed_x11.h b/src/widgets/platforms/x11/qx11embed_x11.h deleted file mode 100644 index fcf94b60a2..0000000000 --- a/src/widgets/platforms/x11/qx11embed_x11.h +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QX11EMBED_X11_H -#define QX11EMBED_X11_H - -#include <QtWidgets/qwidget.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QX11EmbedWidgetPrivate; -class Q_WIDGETS_EXPORT QX11EmbedWidget : public QWidget -{ - Q_OBJECT -public: - QX11EmbedWidget(QWidget *parent = 0); - ~QX11EmbedWidget(); - - void embedInto(WId id); - WId containerWinId() const; - - enum Error { - Unknown, - Internal, - InvalidWindowID - }; - Error error() const; - -Q_SIGNALS: - void embedded(); - void containerClosed(); - void error(QX11EmbedWidget::Error error); - -protected: - bool x11Event(XEvent *); - bool eventFilter(QObject *, QEvent *); - bool event(QEvent *); - void resizeEvent(QResizeEvent *); - -private: - Q_DECLARE_PRIVATE(QX11EmbedWidget) - Q_DISABLE_COPY(QX11EmbedWidget) -}; - -class QX11EmbedContainerPrivate; -class Q_WIDGETS_EXPORT QX11EmbedContainer : public QWidget -{ - Q_OBJECT -public: - QX11EmbedContainer(QWidget *parent = 0); - ~QX11EmbedContainer(); - - void embedClient(WId id); - void discardClient(); - - WId clientWinId() const; - - QSize minimumSizeHint() const; - - enum Error { - Unknown, - Internal, - InvalidWindowID - }; - Error error() const; - -Q_SIGNALS: - void clientIsEmbedded(); - void clientClosed(); - void error(QX11EmbedContainer::Error); - -protected: - bool x11Event(XEvent *); - bool eventFilter(QObject *, QEvent *); - void paintEvent(QPaintEvent *e); - void resizeEvent(QResizeEvent *); - void showEvent(QShowEvent *); - void hideEvent(QHideEvent *); - bool event(QEvent *); - -private: - Q_DECLARE_PRIVATE(QX11EmbedContainer) - Q_DISABLE_COPY(QX11EmbedContainer) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QX11EMBED_X11_H diff --git a/src/widgets/platforms/x11/qx11info_x11.cpp b/src/widgets/platforms/x11/qx11info_x11.cpp deleted file mode 100644 index 88092b3bac..0000000000 --- a/src/widgets/platforms/x11/qx11info_x11.cpp +++ /dev/null @@ -1,544 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwidget.h" -#include "qpixmap.h" -#include "qx11info_x11.h" -#include "qt_x11_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QX11Info - \brief The QX11Info class provides information about the X display - configuration. - - \ingroup shared - \inmodule QtWidgets - - The class provides two APIs: a set of non-static functions that - provide information about a specific widget or pixmap, and a set - of static functions that provide the default information for the - application. - - \warning This class is only available on X11. For querying - per-screen information in a portable way, use QDesktopWidget. - - \sa QWidget::x11Info(), QPixmap::x11Info(), QDesktopWidget -*/ - -/*! - Constructs an empty QX11Info object. -*/ -QX11Info::QX11Info() - : x11data(0) -{ -} - -/*! - Constructs a copy of \a other. -*/ -QX11Info::QX11Info(const QX11Info &other) -{ - x11data = other.x11data; - if (x11data) - ++x11data->ref; -} - -/*! - Assigns \a other to this object and returns a reference to this - object. -*/ -QX11Info &QX11Info::operator=(const QX11Info &other) -{ - if (other.x11data) - ++other.x11data->ref; - if (x11data && !--x11data->ref) - delete x11data; - x11data = other.x11data; - return *this; -} - -/*! - Destroys the QX11Info object. -*/ -QX11Info::~QX11Info() -{ - if (x11data && !--x11data->ref) - delete x11data; -} - -/*! - \internal - Makes a shallow copy of the X11-specific data of \a fromDevice, if it is not - null. Otherwise this function sets it to null. -*/ - -void QX11Info::copyX11Data(const QPaintDevice *fromDevice) -{ - QX11InfoData *xd = 0; - if (fromDevice) { - if (fromDevice->devType() == QInternal::Widget) - xd = static_cast<const QWidget *>(fromDevice)->x11Info().x11data; - else if (fromDevice->devType() == QInternal::Pixmap) - xd = static_cast<const QPixmap *>(fromDevice)->x11Info().x11data; - } - setX11Data(xd); -} - -/*! - \internal - Makes a deep copy of the X11-specific data of \a fromDevice, if it is not - null. Otherwise this function sets it to null. -*/ - -void QX11Info::cloneX11Data(const QPaintDevice *fromDevice) -{ - QX11InfoData *d = 0; - if (fromDevice) { - QX11InfoData *xd; - if (fromDevice->devType() == QInternal::Widget) { - xd = static_cast<const QWidget *>(fromDevice)->x11Info().x11data; - } else { - Q_ASSERT(fromDevice->devType() == QInternal::Pixmap); - xd = static_cast<const QPixmap *>(fromDevice)->x11Info().x11data; - } - d = new QX11InfoData(*xd); - d->ref = 0; - } - setX11Data(d); -} - -/*! - \internal - Makes a shallow copy of the X11-specific data \a d and assigns it to this - class. This function increments the reference code of \a d. -*/ - -void QX11Info::setX11Data(const QX11InfoData* d) -{ - if (x11data && !--x11data->ref) - delete x11data; - x11data = (QX11InfoData *)d; - if (x11data) - ++x11data->ref; -} - - -/*! - \internal - If \a def is false, returns a deep copy of the x11Data, or 0 if x11Data is 0. - If \a def is true, makes a QX11Data struct filled with the default - values. - - In either case the caller is responsible for deleting the returned - struct. But notice that the struct is a shared class, so other - classes might also have a reference to it. The reference count of - the returned QX11Data* is 0. -*/ - -QX11InfoData* QX11Info::getX11Data(bool def) const -{ - QX11InfoData* res = 0; - if (def) { - res = new QX11InfoData; - res->ref = 0; - res->screen = appScreen(); - res->depth = appDepth(); - res->cells = appCells(); - res->colormap = colormap(); - res->defaultColormap = appDefaultColormap(); - res->visual = (Visual*) appVisual(); - res->defaultVisual = appDefaultVisual(); - } else if (x11data) { - res = new QX11InfoData; - *res = *x11data; - res->ref = 0; - } - return res; -} - -/*! - Returns the horizontal resolution of the given \a screen in terms of the - number of dots per inch. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa setAppDpiX(), appDpiY() -*/ -int QX11Info::appDpiX(int screen) -{ - if (!X11) - return 75; - if (screen < 0) - screen = X11->defaultScreen; - if (screen > X11->screenCount) - return 0; - return X11->screens[screen].dpiX; -} - -/*! - Sets the horizontal resolution of the given \a screen to the number of - dots per inch specified by \a xdpi. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa appDpiX(), setAppDpiY() -*/ - -void QX11Info::setAppDpiX(int screen, int xdpi) -{ - if (!X11) - return; - if (screen < 0) - screen = X11->defaultScreen; - if (screen > X11->screenCount) - return; - X11->screens[screen].dpiX = xdpi; -} - -/*! - Returns the vertical resolution of the given \a screen in terms of the - number of dots per inch. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa setAppDpiY(), appDpiX() -*/ - -int QX11Info::appDpiY(int screen) -{ - if (!X11) - return 75; - if (screen < 0) - screen = X11->defaultScreen; - if (screen > X11->screenCount) - return 0; - return X11->screens[screen].dpiY; -} - -/*! - Sets the vertical resolution of the given \a screen to the number of - dots per inch specified by \a ydpi. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa appDpiY(), setAppDpiX() -*/ -void QX11Info::setAppDpiY(int screen, int ydpi) -{ - if (!X11) - return; - if (screen < 0) - screen = X11->defaultScreen; - if (screen > X11->screenCount) - return; - X11->screens[screen].dpiY = ydpi; -} - -/*! - Returns the X11 time. - - \sa setAppTime(), appUserTime() -*/ -unsigned long QX11Info::appTime() -{ - return X11 ? X11->time : 0; -} - -/*! - Sets the X11 time to the value specified by \a time. - - \sa appTime(), setAppUserTime() -*/ -void QX11Info::setAppTime(unsigned long time) -{ - if (X11) { - X11->time = time; - } -} - -/*! - Returns the X11 user time. - - \sa setAppUserTime(), appTime() -*/ -unsigned long QX11Info::appUserTime() -{ - return X11 ? X11->userTime : 0; -} - -/*! - Sets the X11 user time as specified by \a time. - - \sa appUserTime(), setAppTime() -*/ -void QX11Info::setAppUserTime(unsigned long time) -{ - if (X11) { - X11->userTime = time; - } -} - - -/*! - \fn const char *QX11Info::appClass() - - Returns the X11 application class. - - \sa display() -*/ - -/*! - Returns the default display for the application. - - \sa appScreen() -*/ - -Display *QX11Info::display() -{ - return X11 ? X11->display : 0; -} - -/*! - Returns the number of the screen where the application is being - displayed. - - \sa display(), screen() -*/ -int QX11Info::appScreen() -{ - return X11 ? X11->defaultScreen : 0; -} - -/*! - Returns a handle for the application's color map on the given \a screen. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa colormap(), defaultColormap() -*/ -Qt::HANDLE QX11Info::appColormap(int screen) -{ - return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].colormap : 0; -} - -/*! - Returns the current visual used by the application on the given - \a screen. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa visual(), defaultVisual() -*/ - -void *QX11Info::appVisual(int screen) -{ - return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].visual : 0; -} - -/*! - Returns a handle for the applications root window on the given \a screen. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa QApplication::desktop() -*/ -Qt::HANDLE QX11Info::appRootWindow(int screen) -{ - return X11 ? RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen) : 0; -} - -/*! - Returns the color depth (bits per pixel) used by the application on the - given \a screen. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa depth() -*/ - -int QX11Info::appDepth(int screen) -{ - return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].depth : 32; -} - -/*! - Returns the number of cells used by the application on the given \a screen. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa cells() -*/ - -int QX11Info::appCells(int screen) -{ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].cells : 0; } - -/*! - Returns true if the application has a default color map on the given - \a screen; otherwise returns false. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. -*/ -bool QX11Info::appDefaultColormap(int screen) -{ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultColormap : true; } - -/*! - Returns true if the application has a default visual on the given \a screen; - otherwise returns false. - - The \a screen argument is an X screen number. Be aware that if - the user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. -*/ -bool QX11Info::appDefaultVisual(int screen) -{ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultVisual : true; } - -/*! - Returns the number of the screen currently in use. - - The return value is an X screen number. Be aware that if the - user's system uses Xinerama (as opposed to traditional X11 - multiscreen), there is only one X screen. Use QDesktopWidget to - query for information about Xinerama screens. - - \sa appScreen() -*/ -int QX11Info::screen() const -{ return x11data ? x11data->screen : QX11Info::appScreen(); } - -/*! - Returns the color depth (bits per pixel) of the X display. - - \sa appDepth() -*/ - -int QX11Info::depth() const -{ return x11data ? x11data->depth : QX11Info::appDepth(); } - -/*! - Returns the number of cells. - - \sa appCells() -*/ - -int QX11Info::cells() const -{ return x11data ? x11data->cells : QX11Info::appCells(); } - -/*! - Returns a handle for the color map. - - \sa defaultColormap() -*/ - -Qt::HANDLE QX11Info::colormap() const -{ return x11data ? x11data->colormap : QX11Info::appColormap(); } - -/*! - Returns true if there is a default color map; otherwise returns false. - - \sa colormap() -*/ - -bool QX11Info::defaultColormap() const -{ return x11data ? x11data->defaultColormap : QX11Info::appDefaultColormap(); } - -/*! - Returns the current visual. - - \sa appVisual(), defaultVisual() -*/ - -void *QX11Info::visual() const -{ return x11data ? x11data->visual : QX11Info::appVisual(); } - -/*! - Returns true if there is a default visual; otherwise returns false. - - \sa visual(), appVisual() -*/ - -bool QX11Info::defaultVisual() const -{ return x11data ? x11data->defaultVisual : QX11Info::appDefaultVisual(); } - - -/*! - \since 4.4 - - Returns true if there is a compositing manager running. -*/ -bool QX11Info::isCompositingManagerRunning() -{ - return X11 ? X11->compositingManagerRunning : false; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/x11/qx11info_x11.h b/src/widgets/platforms/x11/qx11info_x11.h deleted file mode 100644 index 60cd0e9e92..0000000000 --- a/src/widgets/platforms/x11/qx11info_x11.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QX11INFO_X11_H -#define QX11INFO_X11_H - -#include <QtCore/qnamespace.h> - -typedef struct _XDisplay Display; - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -struct QX11InfoData; -class QX11Info; -class QPaintDevice; -class QApplicationPrivate; -class QX11InfoPrivate; -struct QX11WindowAttributes; - -void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &a); -class Q_WIDGETS_EXPORT QX11Info -{ -public: - QX11Info(); - ~QX11Info(); - QX11Info(const QX11Info &other); - QX11Info &operator=(const QX11Info &other); - - static Display *display(); - static const char *appClass(); - int screen() const; - int depth() const; - int cells() const; - Qt::HANDLE colormap() const; - bool defaultColormap() const; - void *visual() const; - bool defaultVisual() const; - - static int appScreen(); - static int appDepth(int screen = -1); - static int appCells(int screen = -1); - static Qt::HANDLE appColormap(int screen = -1); - static void *appVisual(int screen = -1); - static Qt::HANDLE appRootWindow(int screen = -1); - static bool appDefaultColormap(int screen = -1); - static bool appDefaultVisual(int screen = -1); - static int appDpiX(int screen = -1); - static int appDpiY(int screen = -1); - static void setAppDpiX(int screen, int dpi); - static void setAppDpiY(int screen, int dpi); - static unsigned long appTime(); - static unsigned long appUserTime(); - static void setAppTime(unsigned long time); - static void setAppUserTime(unsigned long time); - static bool isCompositingManagerRunning(); - -protected: - void copyX11Data(const QPaintDevice *); - void cloneX11Data(const QPaintDevice *); - void setX11Data(const QX11InfoData *); - QX11InfoData* getX11Data(bool def = false) const; - - QX11InfoData *x11data; - - friend class QX11PaintEngine; - friend class QPixmap; - friend class QX11PlatformPixmap; - friend class QWidget; - friend class QWidgetPrivate; - friend class QGLWidget; - friend void qt_init(QApplicationPrivate *priv, int, Display *display, Qt::HANDLE visual, - Qt::HANDLE colormap); - friend void qt_cleanup(); - friend void qt_x11_getX11InfoForWindow(QX11Info * xinfo, const QX11WindowAttributes &a); -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QX11INFO_X11_H diff --git a/src/widgets/platforms/x11/qximinputcontext_p.h b/src/widgets/platforms/x11/qximinputcontext_p.h deleted file mode 100644 index 47c6f78ff9..0000000000 --- a/src/widgets/platforms/x11/qximinputcontext_p.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Definition of QXIMInputContext class -** -** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved. -** -** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own -** license. You may use this file under your Qt license. Following -** description is copied from their original file headers. Contact -** immodule-qt@freedesktop.org if any conditions of this licensing are -** not clear to you. -** -****************************************************************************/ - -#ifndef QXIMINPUTCONTEXT_P_H -#define QXIMINPUTCONTEXT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#if !defined(Q_NO_IM) - -#include "QtCore/qglobal.h" -#include "QtWidgets/qinputcontext.h" -#include "QtGui/qfont.h" -#include "QtCore/qhash.h" -#ifdef Q_WS_X11 -#include "QtCore/qlist.h" -#include "QtCore/qbitarray.h" -#include "QtGui/qwindowdefs.h" -#include "private/qt_x11_p.h" -#endif - -QT_BEGIN_NAMESPACE - -class QKeyEvent; -class QWidget; -class QFont; -class QString; - -class QXIMInputContext : public QInputContext -{ - Q_OBJECT -public: - struct ICData { - XIC ic; - XFontSet fontset; - QWidget *widget; - QString text; - QBitArray selectedChars; - bool composing; - bool preeditEmpty; - void clear(); - }; - - QXIMInputContext(); - ~QXIMInputContext(); - - QString identifierName(); - QString language(); - - void reset(); - - void mouseHandler( int x, QMouseEvent *event); - bool isComposing() const; - - void setFocusWidget( QWidget *w ); - void widgetDestroyed(QWidget *w); - - void create_xim(); - void close_xim(); - - void update(); - - ICData *icData() const; -protected: - bool x11FilterEvent( QWidget *keywidget, XEvent *event ); - -private: - static XIMStyle xim_style; - - QString _language; - XIM xim; - QHash<WId, ICData *> ximData; - - ICData *createICData(QWidget *w); -}; - -QT_END_NAMESPACE - -#endif // Q_NO_IM - -#endif // QXIMINPUTCONTEXT_P_H diff --git a/src/widgets/platforms/x11/qximinputcontext_x11.cpp b/src/widgets/platforms/x11/qximinputcontext_x11.cpp deleted file mode 100644 index de1212c556..0000000000 --- a/src/widgets/platforms/x11/qximinputcontext_x11.cpp +++ /dev/null @@ -1,885 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** Implementation of QXIMInputContext class -** -** Copyright (C) 2003-2004 immodule for Qt Project. All rights reserved. -** -** This file is written to contribute to Nokia Corporation and/or its subsidiary(-ies) under their own -** license. You may use this file under your Qt license. Following -** description is copied from their original file headers. Contact -** immodule-qt@freedesktop.org if any conditions of this licensing are -** not clear to you. -** -****************************************************************************/ - -#include "qplatformdefs.h" -#include "qdebug.h" -#include "qximinputcontext_p.h" - -#if !defined(QT_NO_IM) - -QT_BEGIN_NAMESPACE - -#if !defined(QT_NO_XIM) - -QT_BEGIN_INCLUDE_NAMESPACE -#include "qplatformdefs.h" - -#include "qapplication.h" -#include "qwidget.h" -#include "qstring.h" -#include "qlist.h" -#include "qtextcodec.h" -#include "qevent.h" -#include "qtextformat.h" - -#include "qx11info_x11.h" - -#include <stdlib.h> -#include <limits.h> -QT_END_INCLUDE_NAMESPACE - -// #define QT_XIM_DEBUG -#ifdef QT_XIM_DEBUG -#define XIM_DEBUG qDebug -#else -#define XIM_DEBUG if (0) qDebug -#endif - -// from qapplication_x11.cpp -// #### move to X11 struct -extern XIMStyle qt_xim_preferred_style; -extern char *qt_ximServer; -extern int qt_ximComposingKeycode; -extern QTextCodec * qt_input_mapper; - -XIMStyle QXIMInputContext::xim_style = 0; -// moved from qapplication_x11.cpp -static const XIMStyle xim_default_style = XIMPreeditCallbacks | XIMStatusNothing; - - -extern "C" { -#ifdef USE_X11R6_XIM - static void xim_create_callback(XIM /*im*/, - XPointer client_data, - XPointer /*call_data*/) - { - QXIMInputContext *qic = reinterpret_cast<QXIMInputContext *>(client_data); - // qDebug("xim_create_callback"); - qic->create_xim(); - } - - static void xim_destroy_callback(XIM /*im*/, - XPointer client_data, - XPointer /*call_data*/) - { - QXIMInputContext *qic = reinterpret_cast<QXIMInputContext *>(client_data); - // qDebug("xim_destroy_callback"); - qic->close_xim(); - XRegisterIMInstantiateCallback(X11->display, 0, 0, 0, - (XIMProc) xim_create_callback, reinterpret_cast<char *>(qic)); - } -#endif // USE_X11R6_XIM - - static int xic_start_callback(XIC, XPointer client_data, XPointer) { - QXIMInputContext *qic = (QXIMInputContext *) client_data; - if (!qic) { - XIM_DEBUG("xic_start_callback: no qic"); - return 0; - } - QXIMInputContext::ICData *data = qic->icData(); - if (!data) { - XIM_DEBUG("xic_start_callback: no ic data"); - return 0; - } - XIM_DEBUG("xic_start_callback"); - - data->clear(); - data->composing = true; - - return 0; - } - - static int xic_draw_callback(XIC, XPointer client_data, XPointer call_data) { - QXIMInputContext *qic = (QXIMInputContext *) client_data; - if (!qic) { - XIM_DEBUG("xic_draw_callback: no qic"); - return 0; - } - QXIMInputContext::ICData *data = qic->icData(); - if (!data) { - XIM_DEBUG("xic_draw_callback: no ic data"); - return 0; - } - XIM_DEBUG("xic_draw_callback"); - - - if(!data->composing) { - data->clear(); - data->composing = true; - } - - XIMPreeditDrawCallbackStruct *drawstruct = (XIMPreeditDrawCallbackStruct *) call_data; - XIMText *text = (XIMText *) drawstruct->text; - int cursor = drawstruct->caret, sellen = 0, selstart = 0; - - if (!drawstruct->caret && !drawstruct->chg_first && !drawstruct->chg_length && !text) { - if(data->text.isEmpty()) { - XIM_DEBUG("compose emptied"); - // if the composition string has been emptied, we need - // to send an InputMethodEnd event - QInputMethodEvent e; - qic->sendEvent(e); - data->clear(); - - // if the commit string has coming after here, InputMethodStart - // will be sent dynamically - } - return 0; - } - - if (text) { - char *str = 0; - if (text->encoding_is_wchar) { - int l = wcstombs(NULL, text->string.wide_char, text->length); - if (l != -1) { - str = new char[l + 1]; - wcstombs(str, text->string.wide_char, l); - str[l] = 0; - } - } else - str = text->string.multi_byte; - - if (!str) - return 0; - - QString s = QString::fromLocal8Bit(str); - - if (text->encoding_is_wchar) - delete [] str; - - if (drawstruct->chg_length < 0) - data->text.replace(drawstruct->chg_first, INT_MAX, s); - else - data->text.replace(drawstruct->chg_first, drawstruct->chg_length, s); - - if (data->selectedChars.size() < data->text.length()) { - // expand the selectedChars array if the compose string is longer - int from = data->selectedChars.size(); - data->selectedChars.resize(data->text.length()); - for (int x = from; x < data->selectedChars.size(); ++x) - data->selectedChars.clearBit(x); - } - - // determine if the changed chars are selected based on text->feedback - for (int x = 0; x < text->length; ++x) - data->selectedChars.setBit(x + drawstruct->chg_first, - (text->feedback ? (text->feedback[x] & XIMReverse) : 0)); - - // figure out where the selection starts, and how long it is - bool started = false; - for (int x = 0; x < qMin(data->selectedChars.size(), data->text.length()); ++x) { - if (started) { - if (data->selectedChars.testBit(x)) ++sellen; - else break; - } else { - if (data->selectedChars.testBit(x)) { - selstart = x; - started = true; - sellen = 1; - } - } - } - } else { - if (drawstruct->chg_length == 0) - drawstruct->chg_length = -1; - - data->text.remove(drawstruct->chg_first, drawstruct->chg_length); - bool qt_compose_emptied = data->text.isEmpty(); - if (qt_compose_emptied) { - XIM_DEBUG("compose emptied 2 text=%s", data->text.toUtf8().constData()); - // if the composition string has been emptied, we need - // to send an InputMethodEnd event - QInputMethodEvent e; - qic->sendEvent(e); - data->clear(); - // if the commit string has coming after here, InputMethodStart - // will be sent dynamically - return 0; - } - } - - XIM_DEBUG("sending compose: '%s', cursor=%d, sellen=%d", - data->text.toUtf8().constData(), cursor, sellen); - QList<QInputMethodEvent::Attribute> attrs; - if (selstart > 0) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selstart, - qic->standardFormat(QInputContext::PreeditFormat)); - if (sellen) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selstart, sellen, - qic->standardFormat(QInputContext::SelectionFormat)); - if (selstart + sellen < data->text.length()) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, - selstart + sellen, data->text.length() - selstart - sellen, - qic->standardFormat(QInputContext::PreeditFormat)); - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, sellen ? 0 : 1, QVariant()); - QInputMethodEvent e(data->text, attrs); - data->preeditEmpty = data->text.isEmpty(); - qic->sendEvent(e); - - return 0; - } - - static int xic_done_callback(XIC, XPointer client_data, XPointer) { - QXIMInputContext *qic = (QXIMInputContext *) client_data; - if (!qic) - return 0; - - XIM_DEBUG("xic_done_callback"); - // Don't send InputMethodEnd here. QXIMInputContext::x11FilterEvent() - // handles InputMethodEnd with commit string. - return 0; - } -} - -void QXIMInputContext::ICData::clear() -{ - text = QString(); - selectedChars.clear(); - composing = false; - preeditEmpty = true; -} - -QXIMInputContext::ICData *QXIMInputContext::icData() const -{ - if (QWidget *w = focusWidget()) - return ximData.value(w->effectiveWinId()); - return 0; -} -/* The cache here is needed, as X11 leaks a few kb for every - XFreeFontSet call, so we avoid creating and deletion of fontsets as - much as possible -*/ -static XFontSet fontsetCache[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static int fontsetRefCount = 0; - -static const char * const fontsetnames[] = { - "-*-fixed-medium-r-*-*-16-*,-*-*-medium-r-*-*-16-*", - "-*-fixed-medium-i-*-*-16-*,-*-*-medium-i-*-*-16-*", - "-*-fixed-bold-r-*-*-16-*,-*-*-bold-r-*-*-16-*", - "-*-fixed-bold-i-*-*-16-*,-*-*-bold-i-*-*-16-*", - "-*-fixed-medium-r-*-*-24-*,-*-*-medium-r-*-*-24-*", - "-*-fixed-medium-i-*-*-24-*,-*-*-medium-i-*-*-24-*", - "-*-fixed-bold-r-*-*-24-*,-*-*-bold-r-*-*-24-*", - "-*-fixed-bold-i-*-*-24-*,-*-*-bold-i-*-*-24-*" -}; - -static XFontSet getFontSet(const QFont &f) -{ - int i = 0; - if (f.italic()) - i |= 1; - if (f.bold()) - i |= 2; - - if (f.pointSize() > 20) - i += 4; - - if (!fontsetCache[i]) { - Display* dpy = X11->display; - int missCount; - char** missList; - fontsetCache[i] = XCreateFontSet(dpy, fontsetnames[i], &missList, &missCount, 0); - if(missCount > 0) - XFreeStringList(missList); - if (!fontsetCache[i]) { - fontsetCache[i] = XCreateFontSet(dpy, "-*-fixed-*-*-*-*-16-*", &missList, &missCount, 0); - if(missCount > 0) - XFreeStringList(missList); - if (!fontsetCache[i]) - fontsetCache[i] = (XFontSet)-1; - } - } - return (fontsetCache[i] == (XFontSet)-1) ? 0 : fontsetCache[i]; -} - -extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp -#ifndef QT_NO_XKB -extern QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName); -#endif - -QXIMInputContext::QXIMInputContext() -{ - if (!qt_xim_preferred_style) // no configured input style, use the default - qt_xim_preferred_style = xim_default_style; - - xim = 0; - QByteArray ximServerName(qt_ximServer); - if (qt_ximServer) - ximServerName.prepend("@im="); - else - ximServerName = ""; - - if (!XSupportsLocale()) -#ifndef QT_NO_DEBUG - qWarning("Qt: Locale not supported on X server") -#endif - ; -#ifdef USE_X11R6_XIM - else if (XSetLocaleModifiers (ximServerName.constData()) == 0) - qWarning("Qt: Cannot set locale modifiers: %s", ximServerName.constData()); - else - XRegisterIMInstantiateCallback(X11->display, 0, 0, 0, - (XIMProc) xim_create_callback, reinterpret_cast<char *>(this)); -#else // !USE_X11R6_XIM - else if (XSetLocaleModifiers ("") == 0) - qWarning("Qt: Cannot set locale modifiers"); - else - QXIMInputContext::create_xim(); -#endif // USE_X11R6_XIM - -#ifndef QT_NO_XKB - if (X11->use_xkb) { - QByteArray layoutName; - QByteArray variantName; - - Atom type = XNone; - int format = 0; - ulong nitems = 0; - ulong bytesAfter = 0; - uchar *data = 0; - if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024, - false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success - && type == XA_STRING && format == 8 && nitems > 2) { - - char *names[5] = { 0, 0, 0, 0, 0 }; - char *p = reinterpret_cast<char *>(data), *end = p + nitems; - int i = 0; - do { - names[i++] = p; - p += qstrlen(p) + 1; - } while (p < end); - - QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(','); - QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(','); - for (int i = 0; i < qMin(layoutNames.count(), variantNames.count()); ++i ) { - QByteArray variantName = variantNames.at(i); - const int dashPos = variantName.indexOf("-"); - if (dashPos >= 0) - variantName.truncate(dashPos); - QLocale keyboardInputLocale = q_getKeyboardLocale(layoutNames.at(i), variantName); - if (keyboardInputLocale.textDirection() == Qt::RightToLeft) - qt_use_rtl_extensions = true; - } - } - - if (data) - XFree(data); - } -#endif // QT_NO_XKB - -} - - -/*!\internal - Creates the application input method. -*/ -void QXIMInputContext::create_xim() -{ - ++fontsetRefCount; -#ifndef QT_NO_XIM - xim = XOpenIM(X11->display, 0, 0, 0); - if (xim) { - -#ifdef USE_X11R6_XIM - XIMCallback destroy; - destroy.callback = (XIMProc) xim_destroy_callback; - destroy.client_data = XPointer(this); - if (XSetIMValues(xim, XNDestroyCallback, &destroy, (char *) 0) != 0) - qWarning("Xlib doesn't support destroy callback"); -#endif // USE_X11R6_XIM - - XIMStyles *styles = 0; - XGetIMValues(xim, XNQueryInputStyle, &styles, (char *) 0, (char *) 0); - if (styles) { - int i; - for (i = 0; !xim_style && i < styles->count_styles; i++) { - if (styles->supported_styles[i] == qt_xim_preferred_style) { - xim_style = qt_xim_preferred_style; - break; - } - } - // if the preferred input style couldn't be found, look for - // Nothing - for (i = 0; !xim_style && i < styles->count_styles; i++) { - if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) { - xim_style = XIMPreeditNothing | XIMStatusNothing; - break; - } - } - // ... and failing that, None. - for (i = 0; !xim_style && i < styles->count_styles; i++) { - if (styles->supported_styles[i] == (XIMPreeditNone | - XIMStatusNone)) { - xim_style = XIMPreeditNone | XIMStatusNone; - break; - } - } - - // qDebug("QApplication: using im style %lx", xim_style); - XFree((char *)styles); - } - - if (xim_style) { - -#ifdef USE_X11R6_XIM - XUnregisterIMInstantiateCallback(X11->display, 0, 0, 0, - (XIMProc) xim_create_callback, reinterpret_cast<char *>(this)); -#endif // USE_X11R6_XIM - - if (QWidget *focusWidget = QApplication::focusWidget()) { - // reinitialize input context after the input method - // server (like SCIM) has been launched without - // requiring the user to manually switch focus. - if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled) - && focusWidget->testAttribute(Qt::WA_WState_Created) - && focusWidget->isEnabled()) - setFocusWidget(focusWidget); - } - // following code fragment is not required for immodule - // version of XIM -#if 0 - QWidgetList list = qApp->topLevelWidgets(); - for (int i = 0; i < list.size(); ++i) { - QWidget *w = list.at(i); - w->d->createTLSysExtra(); - } -#endif - } else { - // Give up - qWarning("No supported input style found." - " See InputMethod documentation."); - close_xim(); - } - } -#endif // QT_NO_XIM -} - -/*!\internal - Closes the application input method. -*/ -void QXIMInputContext::close_xim() -{ - for(QHash<WId, ICData *>::const_iterator i = ximData.constBegin(), - e = ximData.constEnd(); i != e; ++i) { - ICData *data = i.value(); - if (data->ic) - XDestroyIC(data->ic); - delete data; - } - ximData.clear(); - - if ( --fontsetRefCount == 0 ) { - Display *dpy = X11->display; - for ( int i = 0; i < 8; i++ ) { - if ( fontsetCache[i] && fontsetCache[i] != (XFontSet)-1 ) { - XFreeFontSet(dpy, fontsetCache[i]); - fontsetCache[i] = 0; - } - } - } - - setFocusWidget(0); - xim = 0; -} - - - -QXIMInputContext::~QXIMInputContext() -{ - XIM old_xim = xim; // close_xim clears xim pointer. - close_xim(); - if (old_xim) - XCloseIM(old_xim); -} - - -QString QXIMInputContext::identifierName() -{ - // the name should be "xim" rather than "XIM" to be consistent - // with corresponding immodule of GTK+ - return QLatin1String("xim"); -} - - -QString QXIMInputContext::language() -{ - QString language; - if (xim) { - QByteArray locale(XLocaleOfIM(xim)); - - if (locale.startsWith("zh")) { - // Chinese language should be formed as "zh_CN", "zh_TW", "zh_HK" - language = QLatin1String(locale.left(5)); - } else { - // other languages should be two-letter ISO 639 language code - language = QLatin1String(locale.left(2)); - } - } - return language; -} - -void QXIMInputContext::reset() -{ - QWidget *w = focusWidget(); - if (!w) - return; - - ICData *data = ximData.value(w->effectiveWinId()); - if (!data) - return; - - if (data->ic) { - char *mb = XmbResetIC(data->ic); - QInputMethodEvent e; - if (mb) { - e.setCommitString(QString::fromLocal8Bit(mb)); - XFree(mb); - data->preeditEmpty = false; // force sending an event - } - if (!data->preeditEmpty) { - sendEvent(e); - update(); - } - } - data->clear(); -} - -void QXIMInputContext::widgetDestroyed(QWidget *w) -{ - QInputContext::widgetDestroyed(w); - ICData *data = ximData.take(w->effectiveWinId()); - if (!data) - return; - - data->clear(); - if (data->ic) - XDestroyIC(data->ic); - delete data; -} - -void QXIMInputContext::mouseHandler(int pos, QMouseEvent *e) -{ - if(e->type() != QEvent::MouseButtonPress) - return; - - XIM_DEBUG("QXIMInputContext::mouseHandler pos=%d", pos); - if (QWidget *w = focusWidget()) { - ICData *data = ximData.value(w->effectiveWinId()); - if (!data) - return; - if (pos < 0 || pos > data->text.length()) - reset(); - // ##### handle mouse position - } -} - -bool QXIMInputContext::isComposing() const -{ - QWidget *w = focusWidget(); - if (!w) - return false; - - ICData *data = ximData.value(w->effectiveWinId()); - if (!data) - return false; - return data->composing; -} - -void QXIMInputContext::setFocusWidget(QWidget *w) -{ - if (!xim) - return; - QWidget *oldFocus = focusWidget(); - if (oldFocus == w) - return; - - if (language() != QLatin1String("ja")) - reset(); - - if (oldFocus) { - ICData *data = ximData.value(oldFocus->effectiveWinId()); - if (data && data->ic) - XUnsetICFocus(data->ic); - } - - QInputContext::setFocusWidget(w); - - if (!w || w->inputMethodHints() & (Qt::ImhExclusiveInputMask | Qt::ImhHiddenText)) - return; - - ICData *data = ximData.value(w->effectiveWinId()); - if (!data) - data = createICData(w); - - if (data->ic) - XSetICFocus(data->ic); - - update(); -} - - -bool QXIMInputContext::x11FilterEvent(QWidget *keywidget, XEvent *event) -{ - int xkey_keycode = event->xkey.keycode; - if (!keywidget->testAttribute(Qt::WA_WState_Created)) - return false; - if (XFilterEvent(event, keywidget->effectiveWinId())) { - qt_ximComposingKeycode = xkey_keycode; // ### not documented in xlib - - update(); - - return true; - } - if (event->type != XKeyPress || event->xkey.keycode != 0) - return false; - - QWidget *w = focusWidget(); - if (keywidget != w) - return false; - ICData *data = ximData.value(w->effectiveWinId()); - if (!data) - return false; - - // input method has sent us a commit string - QByteArray string; - string.resize(513); - KeySym key; // unused - Status status; // unused - QString text; - int count = XmbLookupString(data->ic, &event->xkey, string.data(), string.size(), - &key, &status); - - if (status == XBufferOverflow) { - string.resize(count + 1); - count = XmbLookupString(data->ic, &event->xkey, string.data(), string.size(), - &key, &status); - } - if (count > 0) { - // XmbLookupString() gave us some text, convert it to unicode - text = qt_input_mapper->toUnicode(string.constData() , count); - if (text.isEmpty()) { - // codec couldn't convert to unicode? this can happen when running in the - // C locale (or with no LANG set). try converting from latin-1 - text = QString::fromLatin1(string.constData(), count); - } - } - -#if 0 - if (!(xim_style & XIMPreeditCallbacks) || !isComposing()) { - // ############### send a regular key event here! - ; - } -#endif - - QInputMethodEvent e; - e.setCommitString(text); - sendEvent(e); - data->clear(); - - update(); - - return true; -} - - -QXIMInputContext::ICData *QXIMInputContext::createICData(QWidget *w) -{ - ICData *data = new ICData; - data->widget = w; - data->preeditEmpty = true; - - XVaNestedList preedit_attr = 0; - XIMCallback startcallback, drawcallback, donecallback; - - QFont font = w->font(); - data->fontset = getFontSet(font); - - if (xim_style & XIMPreeditArea) { - XRectangle rect; - rect.x = 0; - rect.y = 0; - rect.width = w->width(); - rect.height = w->height(); - - preedit_attr = XVaCreateNestedList(0, - XNArea, &rect, - XNFontSet, data->fontset, - (char *) 0); - } else if (xim_style & XIMPreeditPosition) { - XPoint spot; - spot.x = 1; - spot.y = 1; - - preedit_attr = XVaCreateNestedList(0, - XNSpotLocation, &spot, - XNFontSet, data->fontset, - (char *) 0); - } else if (xim_style & XIMPreeditCallbacks) { - startcallback.client_data = (XPointer) this; - startcallback.callback = (XIMProc) xic_start_callback; - drawcallback.client_data = (XPointer) this; - drawcallback.callback = (XIMProc)xic_draw_callback; - donecallback.client_data = (XPointer) this; - donecallback.callback = (XIMProc) xic_done_callback; - - preedit_attr = XVaCreateNestedList(0, - XNPreeditStartCallback, &startcallback, - XNPreeditDrawCallback, &drawcallback, - XNPreeditDoneCallback, &donecallback, - (char *) 0); - } - - if (preedit_attr) { - data->ic = XCreateIC(xim, - XNInputStyle, xim_style, - XNClientWindow, w->effectiveWinId(), - XNPreeditAttributes, preedit_attr, - (char *) 0); - XFree(preedit_attr); - } else { - data->ic = XCreateIC(xim, - XNInputStyle, xim_style, - XNClientWindow, w->effectiveWinId(), - (char *) 0); - } - - if (data->ic) { - // when resetting the input context, preserve the input state - (void) XSetICValues(data->ic, XNResetState, XIMPreserveState, (char *) 0); - } else { - qWarning("Failed to create XIC"); - } - - ximData[w->effectiveWinId()] = data; - return data; -} - -void QXIMInputContext::update() -{ - QWidget *w = focusWidget(); - if (!w) - return; - - ICData *data = ximData.value(w->effectiveWinId()); - if (!data || !data->ic) - return; - - QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect(); - QPoint p; - if (w->nativeParentWidget()) - p = w->mapTo(w->nativeParentWidget(), QPoint((r.left() + r.right() + 1)/2, r.bottom())); - else - p = QPoint((r.left() + r.right() + 1)/2, r.bottom()); - XPoint spot; - spot.x = p.x(); - spot.y = p.y(); - - r = w->rect(); - XRectangle area; - area.x = r.x(); - area.y = r.y(); - area.width = r.width(); - area.height = r.height(); - - XFontSet fontset = getFontSet(qvariant_cast<QFont>(w->inputMethodQuery(Qt::ImFont))); - if (data->fontset == fontset) - fontset = 0; - else - data->fontset = fontset; - - XVaNestedList preedit_attr; - if (fontset) - preedit_attr = XVaCreateNestedList(0, - XNSpotLocation, &spot, - XNArea, &area, - XNFontSet, fontset, - (char *) 0); - else - preedit_attr = XVaCreateNestedList(0, - XNSpotLocation, &spot, - XNArea, &area, - (char *) 0); - - XSetICValues(data->ic, XNPreeditAttributes, preedit_attr, (char *) 0); - XFree(preedit_attr); -} - - -#else -/* - When QT_NO_XIM is defined, we provide a dummy implementation for - this class. The reason for this is that the header file is moc'ed - regardless of QT_NO_XIM. The best would be to remove the file - completely from the pri file is QT_NO_XIM was defined, or for moc - to understand this preprocessor directive. Since the header does - not declare this class when QT_NO_XIM is defined, this is dead - code. -*/ -bool QXIMInputContext::isComposing() const { return false; } -QString QXIMInputContext::identifierName() { return QString(); } -void QXIMInputContext::mouseHandler(int, QMouseEvent *) {} -void QXIMInputContext::setFocusWidget(QWidget *) {} -void QXIMInputContext::reset() {} -void QXIMInputContext::update() {} -QXIMInputContext::~QXIMInputContext() {} -void QXIMInputContext::widgetDestroyed(QWidget *) {} -QString QXIMInputContext::language() { return QString(); } -bool QXIMInputContext::x11FilterEvent(QWidget *, XEvent *) { return true; } - -#endif //QT_NO_XIM - -QT_END_NAMESPACE - -#endif //QT_NO_IM |