diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri index b13c43e371..59af997477 100644 --- a/src/gui/egl/egl.pri +++ b/src/gui/egl/egl.pri @@ -22,13 +22,7 @@ contains(QT_CONFIG, egl): { !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL } - wince*: SOURCES += egl/qegl_wince.cpp - - symbian { - SOURCES += egl/qegl_symbian.cpp - } else { - SOURCES += egl/qegl_qpa.cpp - } + SOURCES += egl/qegl_qpa.cpp } else:symbian: { DEFINES += QT_NO_EGL SOURCES += egl/qegl_stub.cpp diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp deleted file mode 100644 index f5ba4289f5..0000000000 --- a/src/gui/egl/qegl_symbian.cpp +++ /dev/null @@ -1,88 +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 -#include -#include -#include - -#include "qegl_p.h" -#include "qeglcontext_p.h" - -#include - -QT_BEGIN_NAMESPACE - -EGLNativeDisplayType QEgl::nativeDisplay() -{ - return EGL_DEFAULT_DISPLAY; -} - -EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) -{ - return (EGLNativeWindowType)(widget->winId()->DrawableWindow()); -} - -EGLNativePixmapType QEgl::nativePixmap(QPixmap*) -{ - qWarning("QEgl: EGL pixmap surfaces not implemented yet on Symbian"); - return (EGLNativePixmapType)0; -} - -// Set pixel format and other properties based on a paint device. -void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) -{ - if(!dev) - return; - - int devType = dev->devType(); - if (devType == QInternal::Image) { - setPixelFormat(static_cast(dev)->format()); - } else { - QImage::Format format = QImage::Format_RGB32; - if (QApplicationPrivate::instance() && QApplicationPrivate::instance()->useTranslucentEGLSurfaces) - format = QImage::Format_ARGB32_Premultiplied; - setPixelFormat(format); - } -} - - -QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp deleted file mode 100644 index 00d440b178..0000000000 --- a/src/gui/egl/qegl_wince.cpp +++ /dev/null @@ -1,85 +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 -#include -#include - -#include "qegl_p.h" -#include "qeglcontext_p.h" - -#include - - -QT_BEGIN_NAMESPACE - -EGLNativeDisplayType QEgl::nativeDisplay() -{ - HDC myDc = GetDC(0); - if (!myDc) { - qWarning("QEglContext::nativeDisplay(): WinCE display is not open"); - return EGL_DEFAULT_DISPLAY; - } - return EGLNativeDisplayType(myDc); -} - -EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) -{ - return (EGLNativeWindowType)(widget->winId()); -} - -EGLNativePixmapType QEgl::nativePixmap(QPixmap*) -{ - qWarning("QEgl: EGL pixmap surfaces not supported on WinCE"); - return (EGLNativePixmapType)0; -} - -// Set pixel format and other properties based on a paint device. -void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) -{ - int devType = dev->devType(); - if (devType == QInternal::Image) - setPixelFormat(static_cast(dev)->format()); - else - setPixelFormat(QImage::Format_RGB16); // XXX -} - -QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp deleted file mode 100644 index 4fd8a15157..0000000000 --- a/src/gui/egl/qegl_x11.cpp +++ /dev/null @@ -1,471 +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 - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "QtGui/private/qegl_p.h" -#include "QtGui/private/qeglcontext_p.h" - -QT_BEGIN_NAMESPACE - - -EGLNativeDisplayType QEgl::nativeDisplay() -{ - Display *xdpy = QX11Info::display(); - if (!xdpy) { - qWarning("QEglContext::getDisplay(): X11 display is not open"); - return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY); - } - return EGLNativeDisplayType(xdpy); -} - -EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) -{ - return (EGLNativeWindowType)(widget->winId()); -} - -EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap) -{ - return (EGLNativePixmapType)(pixmap->handle()); -} - -static int countBits(unsigned long mask) -{ - int count = 0; - while (mask != 0) { - if (mask & 1) - ++count; - mask >>= 1; - } - return count; -} - -// Set the pixel format parameters from the visual in "xinfo". -void QEglProperties::setVisualFormat(const QX11Info *xinfo) -{ - if (!xinfo) - return; - Visual *visual = (Visual*)xinfo->visual(); - if (!visual) - return; - if (visual->c_class != TrueColor && visual->c_class != DirectColor) - return; - setValue(EGL_RED_SIZE, countBits(visual->red_mask)); - setValue(EGL_GREEN_SIZE, countBits(visual->green_mask)); - setValue(EGL_BLUE_SIZE, countBits(visual->blue_mask)); - - EGLint alphaBits = 0; -#if !defined(QT_NO_XRENDER) - XRenderPictFormat *format; - format = XRenderFindVisualFormat(xinfo->display(), visual); - if (format && (format->type == PictTypeDirect) && format->direct.alphaMask) { - alphaBits = countBits(format->direct.alphaMask); - qDebug("QEglProperties::setVisualFormat() - visual's alphaMask is %d", alphaBits); - } -#endif - setValue(EGL_ALPHA_SIZE, alphaBits); -} - -extern const QX11Info *qt_x11Info(const QPaintDevice *pd); - -// Set pixel format and other properties based on a paint device. -void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) -{ - if (!dev) - return; - if (dev->devType() == QInternal::Image) - setPixelFormat(static_cast(dev)->format()); - else - setVisualFormat(qt_x11Info(dev)); -} - -//#define QT_DEBUG_X11_VISUAL_SELECTION 1 - -VisualID QEgl::getCompatibleVisualId(EGLConfig config) -{ - VisualID visualId = 0; - EGLint eglValue = 0; - - EGLint configRedSize = 0; - eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize); - - EGLint configGreenSize = 0; - eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize); - - EGLint configBlueSize = 0; - eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize); - - EGLint configAlphaSize = 0; - eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize); - - eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue); - int configId = eglValue; - - // See if EGL provided a valid VisualID: - eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue); - visualId = (VisualID)eglValue; - if (visualId) { - // EGL has suggested a visual id, so get the rest of the visual info for that id: - XVisualInfo visualInfoTemplate; - memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); - visualInfoTemplate.visualid = visualId; - - XVisualInfo *chosenVisualInfo; - int matchingCount = 0; - chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount); - if (chosenVisualInfo) { - // Skip size checks if implementation supports non-matching visual - // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). - if (QEgl::hasExtension("EGL_NV_post_convert_rounding")) { - XFree(chosenVisualInfo); - return visualId; - } - - int visualRedSize = countBits(chosenVisualInfo->red_mask); - int visualGreenSize = countBits(chosenVisualInfo->green_mask); - int visualBlueSize = countBits(chosenVisualInfo->blue_mask); - int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size - -#if !defined(QT_NO_XRENDER) - if (X11->use_xrender) { - // If we have XRender, actually check the visual supplied by EGL is ARGB - XRenderPictFormat *format; - format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual); - if (format && (format->type == PictTypeDirect)) - visualAlphaSize = countBits(format->direct.alphaMask); - } -#endif - - bool visualMatchesConfig = false; - if ( visualRedSize == configRedSize && - visualGreenSize == configGreenSize && - visualBlueSize == configBlueSize ) - { - // We need XRender to check the alpha channel size of the visual. If we don't have - // the alpha size, we don't check it against the EGL config's alpha size. - if (visualAlphaSize >= 0) - visualMatchesConfig = visualAlphaSize == configAlphaSize; - else - visualMatchesConfig = true; - } - - if (!visualMatchesConfig) { - if (visualAlphaSize >= 0) { - qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", - (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, - configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); - } else { - qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", - (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, - configId, configRedSize, configGreenSize, configBlueSize); - } - visualId = 0; - } - } else { - qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", - (int)visualId, configId); - visualId = 0; - } - XFree(chosenVisualInfo); - } -#ifdef QT_DEBUG_X11_VISUAL_SELECTION - else - qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); -#endif - - if (visualId) { -#ifdef QT_DEBUG_X11_VISUAL_SELECTION - if (configAlphaSize > 0) - qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); - else - qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); -#endif - return visualId; - } - - - // If EGL didn't give us a valid visual ID, try XRender -#if !defined(QT_NO_XRENDER) - if (!visualId && X11->use_xrender) { - XVisualInfo visualInfoTemplate; - memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); - - visualInfoTemplate.c_class = TrueColor; - - XVisualInfo *matchingVisuals; - int matchingCount = 0; - matchingVisuals = XGetVisualInfo(X11->display, - VisualClassMask, - &visualInfoTemplate, - &matchingCount); - - for (int i = 0; i < matchingCount; ++i) { - XRenderPictFormat *format; - format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual); - - // Check the format for the visual matches the EGL config - if ( (countBits(format->direct.redMask) == configRedSize) && - (countBits(format->direct.greenMask) == configGreenSize) && - (countBits(format->direct.blueMask) == configBlueSize) && - (countBits(format->direct.alphaMask) == configAlphaSize) ) - { - visualId = matchingVisuals[i].visualid; - break; - } - } - if (matchingVisuals) - XFree(matchingVisuals); - - } - if (visualId) { -# ifdef QT_DEBUG_X11_VISUAL_SELECTION - if (configAlphaSize > 0) - qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId); - else - qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId); -# endif // QT_DEBUG_X11_VISUAL_SELECTION - return visualId; - } -# ifdef QT_DEBUG_X11_VISUAL_SELECTION - else - qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId); -# endif // QT_DEBUG_X11_VISUAL_SELECTION - -#endif //!defined(QT_NO_XRENDER) - - - // Finally, if XRender also failed to find a visual (or isn't present), try to - // use XGetVisualInfo and only use the bit depths to match on: - if (!visualId) { - XVisualInfo visualInfoTemplate; - memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); - XVisualInfo *matchingVisuals; - int matchingCount = 0; - - visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; - matchingVisuals = XGetVisualInfo(X11->display, - VisualDepthMask, - &visualInfoTemplate, - &matchingCount); - if (!matchingVisuals) { - // Try again without taking the alpha channel into account: - visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; - matchingVisuals = XGetVisualInfo(X11->display, - VisualDepthMask, - &visualInfoTemplate, - &matchingCount); - } - - if (matchingVisuals) { - visualId = matchingVisuals[0].visualid; - XFree(matchingVisuals); - } - } - - if (visualId) { -#ifdef QT_DEBUG_X11_VISUAL_SELECTION - qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); -#endif - return visualId; - } - - qWarning("Unable to find an X11 visual which matches EGL config %d", configId); - return (VisualID)0; -} - -void qt_set_winid_on_widget(QWidget* w, Qt::HANDLE id) -{ - w->create(id); -} - - -// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't -// match the one for the passed in EGLConfig -EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *properties) -{ - int devType = device->devType(); - - if (devType == QInternal::Pbuffer) { - // TODO - return EGL_NO_SURFACE; - } - - QX11PlatformPixmap *x11PlatformPixmap = 0; - if (devType == QInternal::Pixmap) { - QPlatformPixmap *pmd = static_cast(device)->data_ptr().data(); - if (pmd->classId() == QPlatformPixmap::X11Class) - x11PlatformPixmap = static_cast(pmd); - else { - // TODO: Replace the pixmap's data with a new QX11PlatformPixmap - qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PlatformPixmap"); - return EGL_NO_SURFACE; - } - } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { - qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType); - return EGL_NO_SURFACE; - } - - VisualID visualId = QEgl::getCompatibleVisualId(config); - EGLint alphaSize; - eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize); - - if (devType == QInternal::Widget) { - QWidget *widget = static_cast(device); - - VisualID currentVisualId = 0; - if (widget->testAttribute(Qt::WA_WState_Created)) - currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual()); - - if (currentVisualId != visualId) { - // The window is either not created or has the wrong visual. Either way, we need - // to create a window with the correct visual and call create() on the widget: - - bool visible = widget->isVisible(); - if (visible) - widget->hide(); - - XVisualInfo visualInfo; - visualInfo.visualid = visualId; - { - XVisualInfo *visualInfoPtr; - int matchingCount = 0; - visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask, - &visualInfo, &matchingCount); - Q_ASSERT(visualInfoPtr); // visualId really should be valid! - visualInfo = *visualInfoPtr; - XFree(visualInfoPtr); - } - - Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen()); - if (widget->parentWidget()) - parentWindow = widget->parentWidget()->winId(); - - XSetWindowAttributes windowAttribs; - QColormap colmap = QColormap::instance(widget->x11Info().screen()); - windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole())); - windowAttribs.border_pixel = colmap.pixel(Qt::black); - - unsigned int valueMask = CWBackPixel|CWBorderPixel; - if (alphaSize > 0) { - windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow, - visualInfo.visual, AllocNone); - valueMask |= CWColormap; - } - - Window window = XCreateWindow(widget->x11Info().display(), parentWindow, - widget->x(), widget->y(), widget->width(), widget->height(), - 0, visualInfo.depth, InputOutput, visualInfo.visual, - valueMask, &windowAttribs); - - // This is a nasty hack to get round the fact that we can't be a friend of QWidget: - qt_set_winid_on_widget(widget, window); - - if (visible) - widget->show(); - } - - // At this point, the widget's window should be created and have the correct visual. Now we - // just need to create the EGL surface for it: - const int *props; - if (properties) - props = properties->properties(); - else - props = 0; - EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), props); - if (surf == EGL_NO_SURFACE) - qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - return surf; - } - - if (x11PlatformPixmap) { - // X11 Pixmaps are only created with a depth, so that's all we need to check - EGLint configDepth; - eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth); - if (x11PlatformPixmap->depth() != configDepth) { - // The bit depths are wrong which means the EGLConfig isn't compatable with - // this pixmap. So we need to replace the pixmap's existing data with a new - // one which is created with the correct depth: - -#ifndef QT_NO_XRENDER - if (configDepth == 32) { - qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32", - x11PlatformPixmap->depth()); - x11PlatformPixmap->convertToARGB32(true); - } else -#endif - { - qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)", - configDepth, x11PlatformPixmap->depth()); - } - } - - QEglProperties surfaceAttribs; - - // If the pixmap can't be bound to a texture, it's pretty useless - surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D); - if (alphaSize > 0) - surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA); - else - surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB); - - EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config, - (EGLNativePixmapType) x11PlatformPixmap->handle(), - surfaceAttribs.properties()); - x11PlatformPixmap->gl_surface = (void*)surf; - QImagePixmapCleanupHooks::enableCleanupHooks(x11PlatformPixmap); - return surf; - } - - return EGL_NO_SURFACE; -} - -QT_END_NAMESPACE diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h index 23f3000923..ec596200fb 100644 --- a/src/gui/egl/qeglproperties_p.h +++ b/src/gui/egl/qeglproperties_p.h @@ -60,7 +60,6 @@ QT_BEGIN_NAMESPACE -class QX11Info; class QPaintDevice; class Q_GUI_EXPORT QEglProperties diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index b67eb0fdb2..ea73119538 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -60,7 +60,6 @@ class QImageWriter; class QImageReader; class QColor; class QVariant; -class QX11Info; class QPlatformPixmap; class Q_GUI_EXPORT QPixmap : public QPaintDevice diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h index 565332049c..094dcd28e2 100644 --- a/src/tools/uic/qclass_lib_map.h +++ b/src/tools/uic/qclass_lib_map.h @@ -831,9 +831,6 @@ QT_CLASS_LIB(QWidgetList, QtWidgets, qwindowdefs.h) QT_CLASS_LIB(QWidgetMapper, QtWidgets, qwindowdefs.h) QT_CLASS_LIB(QWidgetSet, QtWidgets, qwindowdefs.h) QT_CLASS_LIB(QWindowSystemInterface, QtWidgets, qwindowsysteminterface_qpa.h) -QT_CLASS_LIB(QX11EmbedWidget, QtWidgets, qx11embed_x11.h) -QT_CLASS_LIB(QX11EmbedContainer, QtWidgets, qx11embed_x11.h) -QT_CLASS_LIB(QX11Info, QtWidgets, qx11info_x11.h) QT_CLASS_LIB(QGenericMatrix, QtGui, qgenericmatrix.h) QT_CLASS_LIB(QMatrix2x2, QtGui, qgenericmatrix.h) QT_CLASS_LIB(QMatrix2x3, QtGui, qgenericmatrix.h) diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc index 4d63e2f466..06a52af893 100644 --- a/src/widgets/kernel/qdesktopwidget.qdoc +++ b/src/widgets/kernel/qdesktopwidget.qdoc @@ -93,7 +93,7 @@ In the illustration above, Application One's primary screen is screen 0, and App Two's primary screen is screen 1. - \sa QApplication, QApplication::desktop(), QX11Info::appRootWindow() + \sa QApplication, QApplication::desktop() */ /*! diff --git a/src/widgets/kernel/qguieventdispatcher_glib.cpp b/src/widgets/kernel/qguieventdispatcher_glib.cpp deleted file mode 100644 index 6f9bb8f80d..0000000000 --- a/src/widgets/kernel/qguieventdispatcher_glib.cpp +++ /dev/null @@ -1,224 +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 "qguieventdispatcher_glib_p.h" - -#include "qapplication.h" -#include "qx11info_x11.h" - -#include "qt_x11_p.h" - -#include - -QT_BEGIN_NAMESPACE - -struct GX11EventSource -{ - GSource source; - GPollFD pollfd; - QEventLoop::ProcessEventsFlags flags; - QGuiEventDispatcherGlib *q; - QGuiEventDispatcherGlibPrivate *d; -}; - -class QGuiEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate -{ - Q_DECLARE_PUBLIC(QGuiEventDispatcherGlib) - -public: - QGuiEventDispatcherGlibPrivate(); - GX11EventSource *x11EventSource; - QList queuedUserInputEvents; -}; - -static gboolean x11EventSourcePrepare(GSource *s, gint *timeout) -{ - if (timeout) - *timeout = -1; - GX11EventSource *source = reinterpret_cast(s); - return (XEventsQueued(X11->display, QueuedAfterFlush) - || (!(source->flags & QEventLoop::ExcludeUserInputEvents) - && !source->d->queuedUserInputEvents.isEmpty())); -} - -static gboolean x11EventSourceCheck(GSource *s) -{ - GX11EventSource *source = reinterpret_cast(s); - return (XEventsQueued(X11->display, QueuedAfterFlush) - || (!(source->flags & QEventLoop::ExcludeUserInputEvents) - && !source->d->queuedUserInputEvents.isEmpty())); -} - -static gboolean x11EventSourceDispatch(GSource *s, GSourceFunc callback, gpointer user_data) -{ - GX11EventSource *source = reinterpret_cast(s); - - ulong marker = XNextRequest(X11->display); - do { - XEvent event; - if (!(source->flags & QEventLoop::ExcludeUserInputEvents) - && !source->d->queuedUserInputEvents.isEmpty()) { - // process a pending user input event - event = source->d->queuedUserInputEvents.takeFirst(); - } else if (XEventsQueued(X11->display, QueuedAlready)) { - // process events from the X server - XNextEvent(X11->display, &event); - - if (source->flags & QEventLoop::ExcludeUserInputEvents) { - // queue user input events - switch (event.type) { - case ButtonPress: - case ButtonRelease: - case MotionNotify: - case XKeyPress: - case XKeyRelease: - case EnterNotify: - case LeaveNotify: - source->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; - } - } - source->d->queuedUserInputEvents.append(event); - continue; - - default: - break; - } - } - } else { - // no event to process - break; - } - - // send through event filter - if (source->q->filterEvent(&event)) - continue; - - if (qApp->x11ProcessEvent(&event) == 1) - return true; - - if (event.xany.serial >= marker) - goto out; - } while (XEventsQueued(X11->display, QueuedAfterFlush)); - - out: - - source->d->runTimersOnceWithNormalPriority(); - - if (callback) - callback(user_data); - return true; -} - -static GSourceFuncs x11EventSourceFuncs = { - x11EventSourcePrepare, - x11EventSourceCheck, - x11EventSourceDispatch, - NULL, - NULL, - NULL -}; - -QGuiEventDispatcherGlibPrivate::QGuiEventDispatcherGlibPrivate() -{ - x11EventSource = reinterpret_cast(g_source_new(&x11EventSourceFuncs, - sizeof(GX11EventSource))); - g_source_set_can_recurse(&x11EventSource->source, true); - - memset(&x11EventSource->pollfd, 0, sizeof(GPollFD)); - x11EventSource->flags = QEventLoop::AllEvents; - x11EventSource->q = 0; - x11EventSource->d = 0; - - g_source_attach(&x11EventSource->source, mainContext); -} - -QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(QObject *parent) - : QEventDispatcherGlib(*new QGuiEventDispatcherGlibPrivate, parent) -{ -} - -QGuiEventDispatcherGlib::~QGuiEventDispatcherGlib() -{ - Q_D(QGuiEventDispatcherGlib); - - g_source_remove_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd); - g_source_destroy(&d->x11EventSource->source); - d->x11EventSource = 0; -} - -bool QGuiEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) -{ - Q_D(QGuiEventDispatcherGlib); - QEventLoop::ProcessEventsFlags saved_flags = d->x11EventSource->flags; - d->x11EventSource->flags = flags; - bool returnValue = QEventDispatcherGlib::processEvents(flags); - d->x11EventSource->flags = saved_flags; - return returnValue; -} - -void QGuiEventDispatcherGlib::startingUp() -{ - Q_D(QGuiEventDispatcherGlib); - d->x11EventSource->pollfd.fd = XConnectionNumber(X11->display); - d->x11EventSource->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; - d->x11EventSource->q = this; - d->x11EventSource->d = d; - g_source_add_poll(&d->x11EventSource->source, &d->x11EventSource->pollfd); -} - -void QGuiEventDispatcherGlib::flush() -{ - XFlush(X11->display); -} - -QT_END_NAMESPACE diff --git a/src/widgets/kernel/qguieventdispatcher_glib_p.h b/src/widgets/kernel/qguieventdispatcher_glib_p.h deleted file mode 100644 index ff210b5ca4..0000000000 --- a/src/widgets/kernel/qguieventdispatcher_glib_p.h +++ /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$ -** -****************************************************************************/ - -#ifndef QGUIEVENTDISPATCHER_GLIB_P_H -#define QGUIEVENTDISPATCHER_GLIB_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QGuiEventDispatcherGlibPrivate; - -class QGuiEventDispatcherGlib : public QEventDispatcherGlib -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QGuiEventDispatcherGlib) - -public: - explicit QGuiEventDispatcherGlib(QObject *parent = 0); - ~QGuiEventDispatcherGlib(); - - bool processEvents(QEventLoop::ProcessEventsFlags flags); - - void startingUp(); - void flush(); -}; - -QT_END_NAMESPACE - -#endif // QGUIEVENTDISPATCHER_GLIB_P_H diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp index 11b4f0cd84..7a53dc3415 100644 --- a/src/widgets/kernel/qwhatsthis.cpp +++ b/src/widgets/kernel/qwhatsthis.cpp @@ -65,10 +65,6 @@ #define SPI_GETDROPSHADOW 0x1024 #endif #endif -#if defined(Q_WS_X11) -#include "qx11info_x11.h" -#include -#endif QT_BEGIN_NAMESPACE diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index ec3523d9b3..c419856838 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -11953,13 +11953,6 @@ void QWidget::clearMask() setMask(QRegion()); } -/*! \fn const QX11Info &QWidget::x11Info() const - Returns information about the configuration of the X display used to display - the widget. - - \warning This function is only available on X11. -*/ - /*! \fn Qt::HANDLE QWidget::x11PictureHandle() const Returns the X11 Picture handle of the widget for XRender support. Use of this function is not portable. This function will diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index d3d7c12a44..f97b343463 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -101,9 +101,6 @@ class QGraphicsEffect; class QRasterWindowSurface; class QUnifiedToolbarSurface; class QPixmap; -#if defined(Q_WS_X11) -class QX11Info; -#endif class QWidgetData { diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 84c1c0b58b..c890dfe70c 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -677,7 +677,6 @@ public: // *************************** Platform specific ************************************ #if defined(Q_WS_X11) // <----------------------------------------------------------- X11 - QX11Info xinfo; Qt::HANDLE picture; static QWidget *mouseGrabber; static QWidget *keyboardGrabber; diff --git a/src/widgets/platforms/win/qapplication_win.cpp b/src/widgets/platforms/win/qapplication_win.cpp deleted file mode 100644 index 725c46d55e..0000000000 --- a/src/widgets/platforms/win/qapplication_win.cpp +++ /dev/null @@ -1,4239 +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$ -** -****************************************************************************/ - -#ifdef Q_WS_WINCE -#include "qguifunctions_wince.h" -#include "qmenubar.h" -extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp -extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp -extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp -extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp -extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.cpp -#endif -#ifdef Q_WS_WINCE_WM -#include -#include -#ifdef QT_WINCE_GESTURES -#ifndef QT_NO_GESTURES -#include -#endif -#endif -#endif - -#include "qapplication.h" -#include "qdesktopwidget.h" -#include "qevent.h" -#include "private/qeventdispatcher_win_p.h" -#include "qeventloop.h" -#include "qclipboard.h" -#include "qcursor.h" -#include "qdatetime.h" -#include "qpointer.h" -#include "qhash.h" -#include "qmetaobject.h" -#include "qmime.h" -#include "qpainter.h" -#include "qpixmapcache.h" -#include "qsessionmanager.h" -#include "qstyle.h" -#include "qwhatsthis.h" // ######## dependency -#include "qwidget.h" -#include "qcolormap.h" -#include "qlayout.h" -#include "qtooltip.h" -#include "qt_windows.h" -#include "qscrollbar.h" -#if defined(QT_NON_COMMERCIAL) -#include "qnc_win.h" -#endif -#include "private/qwininputcontext_p.h" -#include "private/qcursor_p.h" -#include "private/qmath_p.h" -#include "private/qapplication_p.h" -#include "private/qbackingstore_p.h" -#include "private/qwindowsurface_raster_p.h" -#include "qdebug.h" -#include -#include -#include -#include "qevent_p.h" - -//#define ALIEN_DEBUG - -#ifndef QT_NO_THREAD -#include "qmutex.h" -#endif - -#ifndef QT_NO_ACCESSIBILITY -#include "qaccessible.h" - -#include -#ifndef WM_GETOBJECT -#define WM_GETOBJECT 0x003D -#endif -#endif // QT_NO_ACCESSIBILITY - -#if !defined(WINABLEAPI) -# if defined(Q_WS_WINCE) -# include -# endif -# if !defined(Q_WS_WINCE) -# include -# endif -#endif - -#ifndef QT_NO_GESTURES -# ifndef GID_ZOOM -# define GID_ZOOM 3 -# define GID_TWOFINGERTAP 6 -# define GID_PRESSANDTAP 7 -# define GID_ROLLOVER GID_PRESSANDTAP -# endif -#endif - -#ifndef WM_TOUCH -# define WM_TOUCH 0x0240 -#endif - -#ifndef TOUCHEVENTF_MOVE -# define TOUCHEVENTF_MOVE 0x0001 -# define TOUCHEVENTF_DOWN 0x0002 -# define TOUCHEVENTF_UP 0x0004 -# define TOUCHEVENTF_INRANGE 0x0008 -# define TOUCHEVENTF_PRIMARY 0x0010 -# define TOUCHEVENTF_NOCOALESCE 0x0020 -# define TOUCHEVENTF_PEN 0x0040 -# define TOUCHEVENTF_PALM 0x0080 - -# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001 -# define TOUCHINPUTMASKF_EXTRAINFO 0x0002 -# define TOUCHINPUTMASKF_CONTACTAREA 0x0004 - -typedef struct tagTOUCHINPUT -{ - LONG x; - LONG y; - HANDLE hSource; - DWORD dwID; - DWORD dwFlags; - DWORD dwMask; - DWORD dwTime; - ULONG_PTR dwExtraInfo; - DWORD cxContact; - DWORD cyContact; -} TOUCHINPUT, *PTOUCHINPUT; - -#endif - -#include -#include -#include -#include -#include -#include - -#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \ - | PK_ORIENTATION | PK_CURSOR | PK_Z) -#define PACKETMODE 0 - -#include -#ifndef CSR_TYPE -#define CSR_TYPE 20 // Some old Wacom wintab.h may not provide this constant. -#endif -#include - -#if defined(__CYGWIN32__) -#define __INSIDE_CYGWIN32__ -#include -#endif - -#ifndef IMR_RECONVERTSTRING -#define IMR_RECONVERTSTRING 4 -#endif - -#ifndef IMR_CONFIRMRECONVERTSTRING -#define IMR_CONFIRMRECONVERTSTRING 0x0005 -#endif -QT_BEGIN_NAMESPACE - -#ifdef Q_WS_WINCE -#ifndef SHRG_RETURNCMD -struct SHRGINFO { - DWORD cbSize; - HWND hwndClient; - POINT ptDown; - DWORD dwFlags; -}; -#define GN_CONTEXTMENU 1000 -#define SHRG_RETURNCMD 0x00000001 -#define SHRG_NOANIMATION 0x00000010 -#endif - -#ifndef SPI_SETSIPINFO -#define SPI_SETSIPINFO 224 -#endif - -#ifndef QT_NO_GESTURES -typedef DWORD (API *AygRecognizeGesture)(SHRGINFO*); -static AygRecognizeGesture ptrRecognizeGesture = 0; -static bool aygResolved = false; -static void resolveAygLibs() -{ - if (!aygResolved) { - aygResolved = true; - QSystemLibrary ayglib(QLatin1String("aygshell")); - ptrRecognizeGesture = (AygRecognizeGesture) ayglib.resolve("SHRecognizeGesture"); - } -} -#endif // QT_NO_GESTURES - -#endif - -#ifndef SPI_SETFONTSMOOTHINGTYPE -# define SPI_SETFONTSMOOTHINGTYPE 0x200B -#endif -#ifndef SPI_GETFONTSMOOTHINGTYPE -# define SPI_GETFONTSMOOTHINGTYPE 0x200A -#endif -#ifndef FE_FONTSMOOTHINGCLEARTYPE -# define FE_FONTSMOOTHINGCLEARTYPE 0x0002 -#endif - -Q_WIDGETS_EXPORT qreal qt_fontsmoothing_gamma; -Q_WIDGETS_EXPORT bool qt_cleartype_enabled; -Q_WIDGETS_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default - -typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL); -typedef BOOL (API *PtrWTClose)(HCTX); -typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID); -typedef BOOL (API *PtrWTEnable)(HCTX, BOOL); -typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL); -typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID); -typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT); -typedef int (API *PtrWTQueueSizeGet)(HCTX); -typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int); - -static PtrWTInfo ptrWTInfo = 0; -static PtrWTEnable ptrWTEnable = 0; -static PtrWTOverlap ptrWTOverlap = 0; -static PtrWTPacketsGet ptrWTPacketsGet = 0; -static PtrWTGet ptrWTGet = 0; - -static PACKET localPacketBuf[QT_TABLET_NPACKETQSIZE]; // our own tablet packet queue. -HCTX qt_tablet_context; // the hardware context for the tablet (like a window handle) -bool qt_tablet_tilt_support; - -#ifndef QT_NO_TABLETEVENT -static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab); -static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor); -static void initWinTabFunctions(); // resolve the WINTAB api functions -#endif // QT_NO_TABLETEVENT - - -#ifndef QT_NO_ACCESSIBILITY -extern IAccessible *qt_createWindowsAccessible(QAccessibleInterface *object); -#endif // QT_NO_ACCESSIBILITY - -extern bool qt_tabletChokeMouse; -extern QWidget* qt_get_tablet_widget(); -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); -extern QRegion qt_dirtyRegion(QWidget *); - -typedef QHash QTabletCursorInfo; -Q_GLOBAL_STATIC(QTabletCursorInfo, tCursorInfo) -QTabletDeviceData currentTabletPointer; - -// from qregion_win.cpp -extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom); - -// support for on-the-fly changes of the XP theme engine -#ifndef WM_THEMECHANGED -#define WM_THEMECHANGED 0x031A -#endif -#ifndef COLOR_MENUHILIGHT -#define COLOR_MENUHILIGHT 29 -#define COLOR_MENUBAR 30 -#endif - -// support for xbuttons -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define WM_XBUTTONDBLCLK 0x020D -#endif -#ifndef GET_KEYSTATE_WPARAM -#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam)) -#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam)) -#define XBUTTON1 0x0001 -#define XBUTTON2 0x0002 -#endif -#ifndef MK_XBUTTON1 -#define MK_XBUTTON1 0x0020 -#define MK_XBUTTON2 0x0040 -#endif - -// support for multi-media-keys -#ifndef WM_APPCOMMAND -#define WM_APPCOMMAND 0x0319 -#endif - -#ifndef FAPPCOMMAND_MOUSE -#define FAPPCOMMAND_MOUSE 0x8000 -#define FAPPCOMMAND_KEY 0 -#define FAPPCOMMAND_OEM 0x1000 -#define FAPPCOMMAND_MASK 0xF000 -#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK)) -#define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK)) -#define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM -#define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam)) -#define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam) - -#define APPCOMMAND_BROWSER_BACKWARD 1 -#define APPCOMMAND_BROWSER_FORWARD 2 -#define APPCOMMAND_BROWSER_REFRESH 3 -#define APPCOMMAND_BROWSER_STOP 4 -#define APPCOMMAND_BROWSER_SEARCH 5 -#define APPCOMMAND_BROWSER_FAVORITES 6 -#define APPCOMMAND_BROWSER_HOME 7 -#define APPCOMMAND_VOLUME_MUTE 8 -#define APPCOMMAND_VOLUME_DOWN 9 -#define APPCOMMAND_VOLUME_UP 10 -#define APPCOMMAND_MEDIA_NEXTTRACK 11 -#define APPCOMMAND_MEDIA_PREVIOUSTRACK 12 -#define APPCOMMAND_MEDIA_STOP 13 -#define APPCOMMAND_MEDIA_PLAY_PAUSE 14 -#define APPCOMMAND_LAUNCH_MAIL 15 -#define APPCOMMAND_LAUNCH_MEDIA_SELECT 16 -#define APPCOMMAND_LAUNCH_APP1 17 -#define APPCOMMAND_LAUNCH_APP2 18 -#define APPCOMMAND_BASS_DOWN 19 -#define APPCOMMAND_BASS_BOOST 20 -#define APPCOMMAND_BASS_UP 21 -#define APPCOMMAND_TREBLE_DOWN 22 -#define APPCOMMAND_TREBLE_UP 23 -#endif // FAPPCOMMAND_MOUSE - -// New commands from Windows XP (some even Sp1) -#ifndef APPCOMMAND_MICROPHONE_VOLUME_MUTE -#define APPCOMMAND_MICROPHONE_VOLUME_MUTE 24 -#define APPCOMMAND_MICROPHONE_VOLUME_DOWN 25 -#define APPCOMMAND_MICROPHONE_VOLUME_UP 26 -#define APPCOMMAND_HELP 27 -#define APPCOMMAND_FIND 28 -#define APPCOMMAND_NEW 29 -#define APPCOMMAND_OPEN 30 -#define APPCOMMAND_CLOSE 31 -#define APPCOMMAND_SAVE 32 -#define APPCOMMAND_PRINT 33 -#define APPCOMMAND_UNDO 34 -#define APPCOMMAND_REDO 35 -#define APPCOMMAND_COPY 36 -#define APPCOMMAND_CUT 37 -#define APPCOMMAND_PASTE 38 -#define APPCOMMAND_REPLY_TO_MAIL 39 -#define APPCOMMAND_FORWARD_MAIL 40 -#define APPCOMMAND_SEND_MAIL 41 -#define APPCOMMAND_SPELL_CHECK 42 -#define APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE 43 -#define APPCOMMAND_MIC_ON_OFF_TOGGLE 44 -#define APPCOMMAND_CORRECTION_LIST 45 -#define APPCOMMAND_MEDIA_PLAY 46 -#define APPCOMMAND_MEDIA_PAUSE 47 -#define APPCOMMAND_MEDIA_RECORD 48 -#define APPCOMMAND_MEDIA_FAST_FORWARD 49 -#define APPCOMMAND_MEDIA_REWIND 50 -#define APPCOMMAND_MEDIA_CHANNEL_UP 51 -#define APPCOMMAND_MEDIA_CHANNEL_DOWN 52 -#endif // APPCOMMAND_MICROPHONE_VOLUME_MUTE - -#if (_WIN32_WINNT < 0x0400) -// This struct is defined in winuser.h if the _WIN32_WINNT >= 0x0400 -- in the -// other cases we have to define it on our own. -typedef struct tagTRACKMOUSEEVENT { - DWORD cbSize; - DWORD dwFlags; - HWND hwndTrack; - DWORD dwHoverTime; -} TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT; -#endif -#ifndef WM_MOUSELEAVE -#define WM_MOUSELEAVE 0x02A3 -#endif - -QT_BEGIN_INCLUDE_NAMESPACE -#include "private/qwidget_p.h" -QT_END_INCLUDE_NAMESPACE - -static int translateButtonState(int s, int type, int button); - -// ##### get rid of this! -QRgb qt_colorref2qrgb(COLORREF col) -{ - return qRgb(GetRValue(col),GetGValue(col),GetBValue(col)); -} - - -/***************************************************************************** - Internal variables and functions - *****************************************************************************/ - -static HWND curWin = 0; // current window -static HDC displayDC = 0; // display device context - -// Session management -static bool sm_blockUserInput = false; -static bool sm_smActive = false; -extern QSessionManager* qt_session_manager_self; -static bool sm_cancel; - -static bool replayPopupMouseEvent = false; // replay handling when popups close - -// ignore the next release event if return from a modal widget -Q_WIDGETS_EXPORT bool qt_win_ignoreNextMouseReleaseEvent = false; - - -#if defined(QT_DEBUG) -static bool appNoGrab = false; // mouse/keyboard grabbing -#endif - -static bool app_do_modal = false; // modal mode -extern QWidgetList *qt_modal_stack; -extern QDesktopWidget *qt_desktopWidget; -static QPointer popupButtonFocus; -static bool qt_try_modal(QWidget *, MSG *, int& ret); - -QWidget *qt_button_down = 0; // widget got last button-down -QPointer qt_last_mouse_receiver = 0; - -static HWND autoCaptureWnd = 0; -static HWND imeParentWnd = 0; -static void setAutoCapture(HWND); // automatic capture -static void releaseAutoCapture(); - -static void unregWinClasses(); - -extern QCursor *qt_grab_cursor(); - -#if defined(Q_WS_WIN) -#define __export -#endif - -extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); - -class QETWidget : public QWidget // event translator widget -{ -public: - QWExtra *xtra() { return d_func()->extraData(); } - QTLWExtra *topData() { return d_func()->topData(); } - QTLWExtra *maybeTopData() { return d_func()->maybeTopData(); } - void syncBackingStore(const QRegion &rgn) { d_func()->syncBackingStore(rgn); } - void syncBackingStore() { d_func()->syncBackingStore(); } - QWidgetData *dataPtr() { return data; } - QWidgetPrivate *dptr() { return d_func(); } - QRect frameStrut() const { return d_func()->frameStrut(); } - bool winEvent(MSG *m, long *r) { return QWidget::winEvent(m, r); } - void markFrameStrutDirty() { data->fstrut_dirty = 1; } - bool translateMouseEvent(const MSG &msg); - bool translateWheelEvent(const MSG &msg); - bool translatePaintEvent(const MSG &msg); - bool translateConfigEvent(const MSG &msg); - bool translateCloseEvent(const MSG &msg); - bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets); -#ifndef QT_NO_GESTURES - bool translateGestureEvent(const MSG &msg, const GESTUREINFO &gi); -#endif - void repolishStyle(QStyle &style); - inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); } - inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); } - inline uint testWindowState(uint teststate){ return dataPtr()->window_state & teststate; } - inline void setWindowTitle_helper(const QString &title) { d_func()->setWindowTitle_helper(title); } - inline void forceUpdate() { - QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); - if (tlwExtra && tlwExtra->backingStore) - tlwExtra->backingStore->markDirty(rect(), this, true, true); - } -}; - -// need to get default font? -extern bool qt_app_has_font; - -extern QFont qt_LOGFONTtoQFont(LOGFONT& lf,bool scale); - -static void qt_set_windows_color_resources() -{ - // Do the color settings - QPalette pal; - pal.setColor(QPalette::WindowText, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOWTEXT)))); - pal.setColor(QPalette::Button, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNFACE)))); - pal.setColor(QPalette::Light, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNHIGHLIGHT)))); - pal.setColor(QPalette::Dark, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNSHADOW)))); - pal.setColor(QPalette::Mid, pal.button().color().darker(150)); - pal.setColor(QPalette::Text, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOWTEXT)))); - pal.setColor(QPalette::BrightText, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNHIGHLIGHT)))); - pal.setColor(QPalette::Base, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_WINDOW)))); - pal.setColor(QPalette::Window, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNFACE)))); - pal.setColor(QPalette::ButtonText, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_BTNTEXT)))); - pal.setColor(QPalette::Midlight, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_3DLIGHT)))); - pal.setColor(QPalette::Shadow, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_3DDKSHADOW)))); - pal.setColor(QPalette::Highlight, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHT)))); - pal.setColor(QPalette::HighlightedText, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT)))); - -#if defined(Q_WS_WINCE) - // ### hardcoded until I find out how to get it from the system settings. - pal.setColor(QPalette::LinkVisited, pal.highlight().color().dark(150)); - pal.setColor(QPalette::Link, pal.highlight().color().light(130)); - // Background == Base on Windows CE - if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc()) - pal.setColor(QPalette::Background, pal.base().color()); -#else - pal.setColor(QPalette::Link, Qt::blue); - pal.setColor(QPalette::LinkVisited, Qt::magenta); -#endif - - - - pal.setColor(QPalette::Inactive, QPalette::Button, pal.button().color()); - pal.setColor(QPalette::Inactive, QPalette::Window, pal.background().color()); - pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color()); - pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color()); - - if (pal.midlight() == pal.button()) - pal.setColor(QPalette::Midlight, pal.button().color().lighter(110)); - if (pal.background() != pal.base()) { - pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window)); - pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text)); - } - - const QColor bg = pal.background().color(); - const QColor fg = pal.foreground().color(), btn = pal.button().color(); - QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2, - (fg.blue()+btn.blue())/2); - pal.setColorGroup(QPalette::Disabled, pal.foreground(), pal.button(), pal.light(), - pal.dark(), pal.mid(), pal.text(), pal.brightText(), pal.base(), pal.background() ); - pal.setColor(QPalette::Disabled, QPalette::WindowText, disabled); - pal.setColor(QPalette::Disabled, QPalette::Text, disabled); - pal.setColor(QPalette::Disabled, QPalette::ButtonText, disabled); - pal.setColor(QPalette::Disabled, QPalette::Highlight, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHT)))); - pal.setColor(QPalette::Disabled, QPalette::HighlightedText, - QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT)))); - pal.setColor(QPalette::Disabled, QPalette::Base, bg); - - QApplicationPrivate::setSystemPalette(pal); - - QApplicationPrivate::initializeWidgetPaletteHash(); - - QColor ttip(qt_colorref2qrgb(GetSysColor(COLOR_INFOBK))); - - QColor ttipText(qt_colorref2qrgb(GetSysColor(COLOR_INFOTEXT))); - { -#ifndef QT_NO_TOOLTIP - QPalette tiplabel(pal); - tiplabel.setColor(QPalette::All, QPalette::Button, ttip); - tiplabel.setColor(QPalette::All, QPalette::Window, ttip); - tiplabel.setColor(QPalette::All, QPalette::Text, ttipText); - tiplabel.setColor(QPalette::All, QPalette::WindowText, ttipText); - tiplabel.setColor(QPalette::All, QPalette::ButtonText, ttipText); - tiplabel.setColor(QPalette::All, QPalette::Button, ttip); - tiplabel.setColor(QPalette::All, QPalette::Window, ttip); - tiplabel.setColor(QPalette::All, QPalette::Text, ttipText); - tiplabel.setColor(QPalette::All, QPalette::WindowText, ttipText); - tiplabel.setColor(QPalette::All, QPalette::ButtonText, ttipText); - const QColor fg = tiplabel.foreground().color(), btn = tiplabel.button().color(); - QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2, - (fg.blue()+btn.blue())/2); - tiplabel.setColor(QPalette::Disabled, QPalette::WindowText, disabled); - tiplabel.setColor(QPalette::Disabled, QPalette::Text, disabled); - tiplabel.setColor(QPalette::Disabled, QPalette::Base, Qt::white); - tiplabel.setColor(QPalette::Disabled, QPalette::BrightText, Qt::white); - QToolTip::setPalette(tiplabel); -#endif //QT_NO_TOOLTIP - } -} - -static void qt_set_windows_font_resources() -{ -#ifndef Q_WS_WINCE - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - - QFont menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont, true); - QFont messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont, true); - QFont statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont, true); - QFont titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont, true); - - LOGFONT lfIconTitleFont; - SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - QFont iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont, true); - - QApplication::setFont(menuFont, "QMenu"); - QApplication::setFont(menuFont, "QMenuBar"); - QApplication::setFont(messageFont, "QMessageBox"); - QApplication::setFont(statusFont, "QTipLabel"); - QApplication::setFont(statusFont, "QStatusBar"); - QApplication::setFont(titleFont, "Q3TitleBar"); - QApplication::setFont(titleFont, "QWorkspaceTitleBar"); - QApplication::setFont(iconTitleFont, "QAbstractItemView"); - QApplication::setFont(iconTitleFont, "QDockWidgetTitle"); - -#else - LOGFONT lf; - HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); - GetObject(stockFont, sizeof(lf), &lf); - QFont systemFont = qt_LOGFONTtoQFont(lf, true); - QApplicationPrivate::setSystemFont(systemFont); - QFont smallerFont = systemFont; - if (qt_wince_is_mobile()) { - smallerFont.setPointSize(systemFont.pointSize()-1); - QApplication::setFont(smallerFont, "QTabBar"); - smallerFont.setBold(true); - QApplication::setFont(smallerFont, "QAbstractButton"); - } -#endif// Q_WS_WINCE -} - -static void qt_win_read_cleartype_settings() -{ - UINT result = 0; -#ifdef Q_OS_WINCE - if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0)) - qt_cleartype_enabled = result; -#else - if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0)) - qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); -#endif - - int winSmooth; - if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) { - qt_fontsmoothing_gamma = winSmooth / qreal(1000.0); - } else { - qt_fontsmoothing_gamma = 1.0; - } - - // Safeguard ourselves against corrupt registry values... - if (qt_fontsmoothing_gamma > 5 || qt_fontsmoothing_gamma < 1) - qt_fontsmoothing_gamma = qreal(1.4); -} - -static void qt_set_windows_resources() -{ - if (QApplication::type() != QApplication::Tty) - (void) QApplication::style(); // trigger creation of application style - qt_set_windows_font_resources(); - qt_set_windows_color_resources(); -} - -void QApplicationPrivate::initializeWidgetPaletteHash() -{ - QPalette pal = *QApplicationPrivate::sys_pal; - QColor menuCol(qt_colorref2qrgb(GetSysColor(COLOR_MENU))); - QColor menuText(qt_colorref2qrgb(GetSysColor(COLOR_MENUTEXT))); - BOOL isFlat = false; - if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlat, 0); - QPalette menu(pal); - // we might need a special color group for the menu. - menu.setColor(QPalette::Active, QPalette::Button, menuCol); - menu.setColor(QPalette::Active, QPalette::Text, menuText); - menu.setColor(QPalette::Active, QPalette::WindowText, menuText); - menu.setColor(QPalette::Active, QPalette::ButtonText, menuText); - const QColor fg = menu.foreground().color(), btn = menu.button().color(); - QColor disabled(qt_colorref2qrgb(GetSysColor(COLOR_GRAYTEXT))); - menu.setColor(QPalette::Disabled, QPalette::WindowText, disabled); - menu.setColor(QPalette::Disabled, QPalette::Text, disabled); - menu.setColor(QPalette::Disabled, QPalette::Highlight, - QColor(qt_colorref2qrgb(GetSysColor( - (QSysInfo::WindowsVersion >= QSysInfo::WV_XP - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) - && isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)))); - menu.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); - menu.setColor(QPalette::Disabled, QPalette::Button, - menu.color(QPalette::Active, QPalette::Button)); - menu.setColor(QPalette::Inactive, QPalette::Button, - menu.color(QPalette::Active, QPalette::Button)); - menu.setColor(QPalette::Inactive, QPalette::Text, - menu.color(QPalette::Active, QPalette::Text)); - menu.setColor(QPalette::Inactive, QPalette::WindowText, - menu.color(QPalette::Active, QPalette::WindowText)); - menu.setColor(QPalette::Inactive, QPalette::ButtonText, - menu.color(QPalette::Active, QPalette::ButtonText)); - menu.setColor(QPalette::Inactive, QPalette::Highlight, - menu.color(QPalette::Active, QPalette::Highlight)); - menu.setColor(QPalette::Inactive, QPalette::HighlightedText, - menu.color(QPalette::Active, QPalette::HighlightedText)); - menu.setColor(QPalette::Inactive, QPalette::ButtonText, - pal.color(QPalette::Inactive, QPalette::Dark)); - QApplication::setPalette(menu, "QMenu"); - - if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) && isFlat) { - QColor menubar(qt_colorref2qrgb(GetSysColor(COLOR_MENUBAR))); - menu.setColor(QPalette::Active, QPalette::Button, menubar); - menu.setColor(QPalette::Disabled, QPalette::Button, menubar); - menu.setColor(QPalette::Inactive, QPalette::Button, menubar); - } - QApplication::setPalette(menu, "QMenuBar"); -} - -static void qt_set_windows_updateScrollBar(QWidget *widget) -{ - QList children = widget->children(); - for (int i = 0; i < children.size(); ++i) { - QObject *o = children.at(i); - if(!o->isWidgetType()) - continue; - if (QWidget *w = static_cast(o)) - qt_set_windows_updateScrollBar(w); - } -#ifndef QT_NO_SCROLLBAR - if (qobject_cast(widget)) - widget->updateGeometry(); -#endif -} - - -/***************************************************************************** - qt_init() - initializes Qt for Windows - *****************************************************************************/ - -typedef BOOL (WINAPI *PtrSetProcessDPIAware) (VOID); -static PtrSetProcessDPIAware ptrSetProcessDPIAware = 0; -PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0; -PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect = 0; -static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info) -{ - return (*ptrUpdateLayeredWindow)(hwnd, info->hdcDst, info->pptDst, info->psize, info->hdcSrc, - info->pptSrc, info->crKey, info->pblend, info->dwFlags); -} - -void qt_init(QApplicationPrivate *priv, int) -{ - - int argc = priv->argc; - char **argv = priv->argv; - int i, j; - - // Get command line params - - j = argc ? 1 : 0; - for (i=1; iargc) { - priv->argv[j] = 0; - priv->argc = j; - } - -#ifndef Q_WS_WINCE - // No message boxes but important ones - SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); -#endif - -#ifndef Q_WS_WINCE - // Initialize OLE/COM - // S_OK means success and S_FALSE means that it has already - // been initialized - HRESULT r; - r = OleInitialize(0); - if (r != S_OK && r != S_FALSE) { - qWarning("Qt: Could not initialize OLE (error %x)", (unsigned int)r); - } -#endif - - // Misc. initialization -#if defined(QT_DEBUG) && !defined(Q_WS_WINCE) - GdiSetBatchLimit(1); -#endif - - // initialize key mapper - QKeyMapper::changeKeyboard(); - - QColormap::initialize(); - QFont::initialize(); -#ifndef QT_NO_CURSOR - QCursorData::initialize(); -#endif - qApp->setObjectName(priv->appName()); - - // default font -#ifndef Q_WS_WINCE - HGDIOBJ stockFont = GetStockObject(DEFAULT_GUI_FONT); -#else - HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); -#endif - - LOGFONT lf; - GetObject(stockFont, sizeof(lf), &lf); - QFont systemFont = qt_LOGFONTtoQFont(lf, true); - -#ifndef Q_WS_WINCE - if (systemFont.family() == QLatin1String("MS Shell Dlg")) { - systemFont.setFamily(QLatin1String("MS Shell Dlg 2")); - } -#endif - - QApplicationPrivate::setSystemFont(systemFont); - - // QFont::locale_init(); ### Uncomment when it does something on Windows - - if (QApplication::desktopSettingsAware()) - qt_set_windows_resources(); - -#ifndef QT_NO_TABLETEVENT - initWinTabFunctions(); -#endif // QT_NO_TABLETEVENT - QApplicationPrivate::inputContext = new QWinInputContext(0); - - // Read the initial cleartype settings... - qt_win_read_cleartype_settings(); - qt_win_owndc_required = false; - - extern void qt_win_initialize_directdraw(); - qt_win_initialize_directdraw(); - -#ifndef Q_OS_WINCE - ptrUpdateLayeredWindowIndirect = - (PtrUpdateLayeredWindowIndirect) QSystemLibrary::resolve(QLatin1String("user32"), - "UpdateLayeredWindowIndirect"); - ptrUpdateLayeredWindow = - (PtrUpdateLayeredWindow) QSystemLibrary::resolve(QLatin1String("user32"), - "UpdateLayeredWindow"); - - if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect) - ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect; - - // Notify Vista and Windows 7 that we support highter DPI settings - ptrSetProcessDPIAware = (PtrSetProcessDPIAware) - QSystemLibrary::resolve(QLatin1String("user32"), "SetProcessDPIAware"); - if (ptrSetProcessDPIAware) - ptrSetProcessDPIAware(); -#endif - -#ifndef QT_NO_GESTURES - priv->GetGestureInfo = 0; - priv->GetGestureExtraArgs = 0; - priv->CloseGestureInfoHandle = 0; - priv->SetGestureConfig = 0; - priv->GetGestureConfig = 0; - priv->BeginPanningFeedback = 0; - priv->UpdatePanningFeedback = 0; - priv->EndPanningFeedback = 0; - -#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) - priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo; - priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments; -#elif !defined(Q_WS_WINCE) - #if !defined(QT_NO_NATIVE_GESTURES) - priv->GetGestureInfo = - (PtrGetGestureInfo)QSystemLibrary::resolve(QLatin1String("user32"), - "GetGestureInfo"); - priv->GetGestureExtraArgs = - (PtrGetGestureExtraArgs)QSystemLibrary::resolve(QLatin1String("user32"), - "GetGestureExtraArgs"); - priv->CloseGestureInfoHandle = - (PtrCloseGestureInfoHandle)QSystemLibrary::resolve(QLatin1String("user32"), - "CloseGestureInfoHandle"); - priv->SetGestureConfig = - (PtrSetGestureConfig)QSystemLibrary::resolve(QLatin1String("user32"), - "SetGestureConfig"); - priv->GetGestureConfig = - (PtrGetGestureConfig)QSystemLibrary::resolve(QLatin1String("user32"), - "GetGestureConfig"); - #endif // QT_NO_NATIVE_GESTURES - QSystemLibrary libTheme(QLatin1String("uxtheme")); - priv->BeginPanningFeedback = - (PtrBeginPanningFeedback)libTheme.resolve("BeginPanningFeedback"); - priv->UpdatePanningFeedback = - (PtrUpdatePanningFeedback)libTheme.resolve("UpdatePanningFeedback"); - priv->EndPanningFeedback = - (PtrEndPanningFeedback)libTheme.resolve("EndPanningFeedback"); -#endif -#endif // QT_NO_GESTURES -} - -/***************************************************************************** - qt_cleanup() - cleans up when the application is finished - *****************************************************************************/ - -void qt_cleanup() -{ - unregWinClasses(); - QPixmapCache::clear(); - -#ifndef QT_NO_CURSOR - QCursorData::cleanup(); -#endif - QFont::cleanup(); - QColormap::cleanup(); - if (displayDC) { - ReleaseDC(0, displayDC); - displayDC = 0; - } - - delete QApplicationPrivate::inputContext; - QApplicationPrivate::inputContext = 0; - -#ifndef Q_WS_WINCE - // Deinitialize OLE/COM - OleUninitialize(); -#endif -} - - -/***************************************************************************** - Platform specific global and internal functions - *****************************************************************************/ - -Q_WIDGETS_EXPORT HDC qt_win_display_dc() // get display DC -{ - Q_ASSERT(qApp && qApp->thread() == QThread::currentThread()); - if (!displayDC) - displayDC = GetDC(0); - return displayDC; -} - -bool qt_nograb() // application no-grab option -{ -#if defined(QT_DEBUG) - return appNoGrab; -#else - return false; -#endif -} - -typedef QHash WinClassNameHash; -Q_GLOBAL_STATIC(WinClassNameHash, winclassNames) - -// -// If 0 is passed as the widget pointer, register a window class -// for QWidget as default. This is used in QGLTemporaryContext -// during GL initialization, where we don't want to use temporary -// QWidgets or QGLWidgets, neither do we want to have separate code -// to register window classes. -// -const QString qt_reg_winclass(QWidget *w) // register window class -{ - Qt::WindowFlags flags = w ? w->windowFlags() : (Qt::WindowFlags)0; - Qt::WindowFlags type = flags & Qt::WindowType_Mask; - - uint style; - bool icon; - QString cname; - if (w && qt_widget_private(w)->isGLWidget) { - cname = QLatin1String("QGLWidget"); - style = CS_DBLCLKS; -#ifndef Q_WS_WINCE - style |= CS_OWNDC; -#endif - icon = true; - } else if (w && (flags & Qt::MSWindowsOwnDC)) { - cname = QLatin1String("QWidgetOwnDC"); - style = CS_DBLCLKS; -#ifndef Q_WS_WINCE - style |= CS_OWNDC; -#endif - icon = true; - } else if (w && (type == Qt::Tool || type == Qt::ToolTip)) { - style = CS_DBLCLKS; - if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) { - if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { - style |= CS_DROPSHADOW; - } - cname = QLatin1String("QToolTip"); - } else { - cname = QLatin1String("QTool"); - } -#ifndef Q_WS_WINCE - style |= CS_SAVEBITS; -#endif - icon = false; - } else if (w && (type == Qt::Popup)) { - cname = QLatin1String("QPopup"); - style = CS_DBLCLKS; -#ifndef Q_WS_WINCE - style |= CS_SAVEBITS; -#endif - if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP - && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - style |= CS_DROPSHADOW; - icon = false; - } else { - cname = QLatin1String("QWidget"); - style = CS_DBLCLKS; - icon = true; - } - -#ifndef Q_WS_WINCE - // force CS_OWNDC when the GL graphics system is - // used as the default renderer - if (qt_win_owndc_required) - style |= CS_OWNDC; -#endif - -#ifdef Q_OS_WINCE - // We need to register the classes with the - // unique ID on WinCE to make sure we can - // move the windows to the front when starting - // a second instance. - wchar_t uniqueAppID[MAX_PATH]; - GetModuleFileName(0, uniqueAppID, MAX_PATH); - cname = QString::number(RegisterWindowMessage( - (const wchar_t *) QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1Char('\\'), - QLatin1Char('_')).utf16())); -#endif - - // since multiple Qt versions can be used in one process - // each one has to have window class names with a unique name - // The first instance gets the unmodified name; if the class - // has already been registered by another instance of Qt then - // add an instance-specific ID, the address of the window proc. - static int classExists = -1; - - if (classExists == -1) { - WNDCLASS wcinfo; - classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (wchar_t*)cname.utf16(), &wcinfo); - classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; - } - - if (classExists) - cname += QString::number((quintptr)QtWndProc); - - if (winclassNames()->contains(cname)) // already registered in our list - return cname; - -#ifndef Q_WS_WINCE - WNDCLASSEX wc; - wc.cbSize = sizeof(WNDCLASSEX); -#else - WNDCLASS wc; -#endif - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = qWinAppInst(); - if (icon) { - wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); -#ifndef Q_WS_WINCE - if (wc.hIcon) { - int sw = GetSystemMetrics(SM_CXSMICON); - int sh = GetSystemMetrics(SM_CYSMICON); - wc.hIconSm = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, sw, sh, 0); - } else { - wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - wc.hIconSm = 0; - } -#endif - } else { - wc.hIcon = 0; -#ifndef Q_WS_WINCE - wc.hIconSm = 0; -#endif - } - wc.hCursor = 0; -#ifndef Q_WS_WINCE - HBRUSH brush = 0; - if (w && !qt_widget_private(w)->isGLWidget) - brush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); - wc.hbrBackground = brush; -#else - wc.hbrBackground = 0; -#endif - wc.lpszMenuName = 0; - wc.lpszClassName = (wchar_t*)cname.utf16(); - -#ifndef Q_WS_WINCE - ATOM atom = RegisterClassEx(&wc); -#else - ATOM atom = RegisterClass(&wc); -#endif - -#ifndef QT_NO_DEBUG - if (!atom) - qErrnoWarning("QApplication::regClass: Registering window class failed."); -#else - Q_UNUSED(atom); -#endif - - winclassNames()->insert(cname, 1); - return cname; -} - -Q_WIDGETS_EXPORT const QString qt_getRegisteredWndClass() -{ - return qt_reg_winclass(0); -} - -static void unregWinClasses() -{ - WinClassNameHash *hash = winclassNames(); - QHash::ConstIterator it = hash->constBegin(); - while (it != hash->constEnd()) { - UnregisterClass((wchar_t*)it.key().utf16(), qWinAppInst()); - ++it; - } - hash->clear(); -} - - -/***************************************************************************** - Safe configuration (move,resize,setGeometry) mechanism to avoid - recursion when processing messages. - *****************************************************************************/ - -struct QWinConfigRequest { - WId id; // widget to be configured - int req; // 0=move, 1=resize, 2=setGeo - int x, y, w, h; // request parameters -}; - -static QList *configRequests = 0; - -void qWinRequestConfig(WId id, int req, int x, int y, int w, int h) -{ - if (!configRequests) // create queue - configRequests = new QList; - QWinConfigRequest *r = new QWinConfigRequest; - r->id = id; // create new request - r->req = req; - r->x = x; - r->y = y; - r->w = w; - r->h = h; - configRequests->append(r); // store request in queue -} - -static void qWinProcessConfigRequests() // perform requests in queue -{ - if (!configRequests) - return; - QWinConfigRequest *r; - for (;;) { - if (configRequests->isEmpty()) - break; - r = configRequests->takeLast(); - QWidget *w = QWidget::find(r->id); - QRect rect(r->x, r->y, r->w, r->h); - int req = r->req; - delete r; - - if ( w ) { // widget exists - if (w->testAttribute(Qt::WA_WState_ConfigPending)) - return; // biting our tail - if (req == 0) - w->move(rect.topLeft()); - else if (req == 1) - w->resize(rect.size()); - else - w->setGeometry(rect); - } - } - delete configRequests; - configRequests = 0; -} - - -/***************************************************************************** - GUI event dispatcher - *****************************************************************************/ - -class QGuiEventDispatcherWin32 : public QEventDispatcherWin32 -{ - Q_DECLARE_PRIVATE(QEventDispatcherWin32) -public: - QGuiEventDispatcherWin32(QObject *parent = 0); - bool processEvents(QEventLoop::ProcessEventsFlags flags); -}; - -QGuiEventDispatcherWin32::QGuiEventDispatcherWin32(QObject *parent) - : QEventDispatcherWin32(parent) -{ - createInternalHwnd(); -} - -bool QGuiEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) -{ - if (!QEventDispatcherWin32::processEvents(flags)) - return false; - - if (configRequests) // any pending configs? - qWinProcessConfigRequests(); - - return true; -} - -void QApplicationPrivate::createEventDispatcher() -{ - Q_Q(QApplication); - if (q->type() != QApplication::Tty) - eventDispatcher = new QGuiEventDispatcherWin32(q); - else - eventDispatcher = new QEventDispatcherWin32(q); -} - -/***************************************************************************** - Platform specific QApplication members - *****************************************************************************/ - - -#ifndef QT_NO_CURSOR - -/***************************************************************************** - QApplication cursor stack - *****************************************************************************/ - -void QApplication::setOverrideCursor(const QCursor &cursor) -{ - qApp->d_func()->cursor_list.prepend(cursor); - SetCursor(qApp->d_func()->cursor_list.first().handle()); -} - -void QApplication::restoreOverrideCursor() -{ - if (qApp->d_func()->cursor_list.isEmpty()) - return; - qApp->d_func()->cursor_list.removeFirst(); - - if (!qApp->d_func()->cursor_list.isEmpty()) { - SetCursor(qApp->d_func()->cursor_list.first().handle()); - } else { - QWidget *w = QWidget::find(curWin); - if (w) - SetCursor(w->cursor().handle()); - else - SetCursor(QCursor(Qt::ArrowCursor).handle()); - } -} - -#endif - -/* - Internal function called from QWidget::setCursor() - force is true if this function is called from dispatchEnterLeave, it means that the - mouse is actually directly under this widget. -*/ - -#ifndef QT_NO_CURSOR -void qt_win_set_cursor(QWidget *w, bool force) -{ - static QPointer lastUnderMouse = 0; - if (force) { - lastUnderMouse = w; - } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse - && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) { - w = lastUnderMouse; - } - - if (!curWin && w && w->internalWinId()) - return; - QWidget* cW = w && !w->internalWinId() ? w : QWidget::find(curWin); - if (!cW || cW->window() != w->window() || - !cW->isVisible() || !cW->underMouse() || QApplication::overrideCursor()) - return; - - SetCursor(cW->cursor().handle()); -} -#endif // QT_NO_CURSOR - -Qt::KeyboardModifiers qt_win_getKeyboardModifiers() -{ - Qt::KeyboardModifiers modifiers = Qt::NoModifier; - if (GetKeyState(VK_SHIFT) < 0) - modifiers |= Qt::ShiftModifier; - if (GetKeyState(VK_CONTROL) < 0) - modifiers |= Qt::ControlModifier; - if (GetKeyState(VK_MENU) < 0) - modifiers |= Qt::AltModifier; - return modifiers; -} - -/***************************************************************************** - Routines to find a Qt widget from a screen position - *****************************************************************************/ - -QWidget *QApplication::topLevelAt(const QPoint &pos) -{ - POINT p; - HWND win; - QWidget *w; - p.x = pos.x(); - p.y = pos.y(); - win = WindowFromPoint(p); - if (!win) - return 0; - - w = QWidget::find(win); - while (!w && win) { - win = GetParent(win); - w = QWidget::find(win); - } - return w ? w->window() : 0; -} - -void QApplication::beep() -{ - MessageBeep(MB_OK); -} - -static void alert_widget(QWidget *widget, int duration) -{ -#ifdef Q_OS_WINCE - Q_UNUSED(widget); - Q_UNUSED(duration); -#else - bool stopFlash = duration < 0; - - if (widget && (!widget->isActiveWindow() || stopFlash)) { - DWORD timeOut = GetCaretBlinkTime(); - if (timeOut <= 0) - timeOut = 250; - - UINT flashCount; - if (duration == 0) - flashCount = 10; - else - flashCount = duration/timeOut; - - FLASHWINFO info; - info.cbSize = sizeof(info); - info.hwnd = widget->window()->winId(); - info.dwFlags = stopFlash ? FLASHW_STOP : FLASHW_TRAY; - info.dwTimeout = stopFlash ? 0 : timeOut; - info.uCount = stopFlash ? 0 : flashCount; - - FlashWindowEx(&info); - } -#endif -} - -void QApplication::alert(QWidget *widget, int duration) -{ - if (!QApplicationPrivate::checkInstance("alert")) - return; - - if (widget) { - alert_widget(widget, duration); - } else { - const QWidgetList toplevels(topLevelWidgets()); - for (int i = 0; i < toplevels.count(); ++i) { - QWidget *topLevel = toplevels.at(i); - alert_widget(topLevel, duration); - } - } -} - -QString QApplicationPrivate::appName() const -{ - return QCoreApplicationPrivate::appName(); -} - - -/***************************************************************************** - Main event loop - *****************************************************************************/ - -extern uint qGlobalPostedEventsCount(); - -void QApplication::winFocus(QWidget *widget, bool gotFocus) -{ - if (d_func()->inPopupMode()) // some delayed focus event to ignore - return; - if (gotFocus) { - setActiveWindow(widget); - if (QApplicationPrivate::active_window - && (QApplicationPrivate::active_window->windowType() == Qt::Dialog)) { - // raise the entire application, not just the dialog - QWidget* mw = QApplicationPrivate::active_window; -#ifndef Q_WS_WINCE - while(mw->parentWidget() && (mw->windowType() == Qt::Dialog)) - mw = mw->parentWidget()->window(); - if (mw->testAttribute(Qt::WA_WState_Created) && mw != QApplicationPrivate::active_window) - SetWindowPos(mw->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -#else - // On Desktop Windows, we set the first parent of the dialog on top - // Child windows will be automatically set above again. - // On Windows CE we pass no parent in CreateWindowEx as otherwise - // dialogs get embedded into the parent window. Thus we need to - // manually iterate and reactivate all windows from bottom up. - QList raiseList; - raiseList.push_back(mw); - while(mw->parentWidget() && (mw->windowType() == Qt::Dialog)) { - mw = mw->parentWidget()->window(); - raiseList.push_back(mw); - } - while(!raiseList.isEmpty()) { - mw = raiseList.takeLast(); - if (mw->testAttribute(Qt::WA_WState_Created)) { - HWND state = HWND_TOP; - if (mw->windowFlags() & Qt::WindowStaysOnBottomHint) - state = HWND_BOTTOM; - else if (mw->windowFlags() & Qt::WindowStaysOnTopHint) - state = HWND_TOPMOST; - SetWindowPos(mw->internalWinId(), state, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - } - } -#endif - } - } else { - setActiveWindow(0); - } -} - - -// -// QtWndProc() receives all messages from the main event loop -// - -static bool inLoop = false; -static int inputcharset = CP_ACP; - -#define RETURN(x) { inLoop=false;return x; } - -static bool qt_is_translatable_mouse_event(UINT message) -{ - return (((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) || - (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK)) - && message != WM_MOUSEWHEEL - && message != WM_MOUSEHWHEEL) - -#ifndef Q_WS_WINCE - || (message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK) -#endif - ; -} - -extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - bool result = true; - QEvent::Type evt_type = QEvent::None; - QETWidget *widget = 0; - - // there is no need to process pakcets from tablet unless - // it is actually on the tablet, a flag to let us know... - int nPackets; // the number of packets we get from the queue - - long res = 0; - if (!qApp) // unstable app state - RETURN(QWinInputContext::DefWindowProc(hwnd,message,wParam,lParam)) - - QScopedLoopLevelCounter loopLevelCounter(QThreadData::get2(qApp->thread())); - -#if 0 - // make sure we update widgets also when the user resizes - if (inLoop && qApp->loopLevel()) - qApp->sendPostedEvents(0, QEvent::Paint); -#endif - - inLoop = true; - - MSG msg; - msg.hwnd = hwnd; // create MSG structure - msg.message = message; // time and pt fields ignored - msg.wParam = wParam; - msg.lParam = lParam; - msg.pt.x = GET_X_LPARAM(lParam); - msg.pt.y = GET_Y_LPARAM(lParam); - // If it's a non-client-area message the coords are screen coords, otherwise they are - // client coords. -#ifndef Q_WS_WINCE - if (message < WM_NCMOUSEMOVE || message > WM_NCMBUTTONDBLCLK) -#endif - ClientToScreen(msg.hwnd, &msg.pt); - - /* - // sometimes the autograb is not released, so the clickevent is sent - // to the wrong window. We ignore this for now, because it doesn't - // cause any problems. - if (msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN) { - HWND handle = WindowFromPoint(msg.pt); - if (msg.hwnd != handle) { - msg.hwnd = handle; - hwnd = handle; - } - } - */ - -#if defined(QT_NON_COMMERCIAL) - QT_NC_WNDPROC -#endif - - // send through app filter - if (qApp->filterEvent(&msg, &res)) - return res; - - // close any opened ime candidate window (enabled only on a popup widget) - if (imeParentWnd && QApplication::activePopupWidget() - && (message == WM_MBUTTONDOWN || message == WM_XBUTTONDOWN - || message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN -#ifndef Q_WS_WINCE - || message == WM_NCMBUTTONDOWN || message == WM_NCLBUTTONDOWN - || message == WM_NCRBUTTONDOWN)) { -#else - )) { -#endif - ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0); - } - - switch (message) { -#ifndef Q_WS_WINCE -#ifndef QT_NO_SESSIONMANAGER - case WM_QUERYENDSESSION: { - if (sm_smActive) // bogus message from windows - RETURN(true); - - sm_smActive = true; - sm_blockUserInput = true; // prevent user-interaction outside interaction windows - sm_cancel = false; - if (qt_session_manager_self) - qApp->commitData(*qt_session_manager_self); - if (lParam & ENDSESSION_LOGOFF) { - _flushall(); - } - RETURN(!sm_cancel); - } - case WM_ENDSESSION: { - sm_smActive = false; - sm_blockUserInput = false; - bool endsession = (bool) wParam; - - // we receive the message for each toplevel window included internal hidden ones, - // but the aboutToQuit signal should be emitted only once. - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - if (endsession && !qAppPriv->aboutToQuitEmitted) { - qAppPriv->aboutToQuitEmitted = true; - int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()"); - qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0); - // since the process will be killed immediately quit() has no real effect - QApplication::quit(); - } - - RETURN(0); - } -#endif - case WM_DISPLAYCHANGE: - if (QApplication::type() == QApplication::Tty) - break; - if (qt_desktopWidget) { - qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77)); - QSize sz(GetSystemMetrics(78), GetSystemMetrics(79)); - if (sz == qt_desktopWidget->size()) { - // a screen resized without changing size of the virtual desktop - QResizeEvent rs(sz, qt_desktopWidget->size()); - QApplication::sendEvent(qt_desktopWidget, &rs); - } else { - qt_desktopWidget->resize(sz); - } - } - break; -#endif - - case WM_SETTINGCHANGE: -#ifdef Q_WS_WINCE - // CE SIP hide/show - if (qt_desktopWidget && wParam == SPI_SETSIPINFO) { - QResizeEvent re(QSize(0, 0), QSize(0, 0)); // Calculated by QDesktopWidget - QApplication::sendEvent(qt_desktopWidget, &re); - break; - } -#endif - // ignore spurious XP message when user logs in again after locking - if (QApplication::type() == QApplication::Tty) - break; - if (QApplication::desktopSettingsAware() && wParam != SPI_SETWORKAREA) { - widget = (QETWidget*)QWidget::find(hwnd); - if (widget) { - if (wParam == SPI_SETNONCLIENTMETRICS) - widget->markFrameStrutDirty(); - } - } - else if (qt_desktopWidget && wParam == SPI_SETWORKAREA) { - qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77)); - QSize sz(GetSystemMetrics(78), GetSystemMetrics(79)); - if (sz == qt_desktopWidget->size()) { - // a screen resized without changing size of the virtual desktop - QResizeEvent rs(sz, qt_desktopWidget->size()); - QApplication::sendEvent(qt_desktopWidget, &rs); - } else { - qt_desktopWidget->resize(sz); - } - } - - if (wParam == SPI_SETFONTSMOOTHINGTYPE) { - qt_win_read_cleartype_settings(); - foreach (QWidget *w, QApplication::topLevelWidgets()) { - if (!w->isVisible()) - continue; - ((QETWidget *) w)->forceUpdate(); - } - } - - break; - case WM_SYSCOLORCHANGE: - if (QApplication::type() == QApplication::Tty) - break; - if (QApplication::desktopSettingsAware()) { - widget = (QETWidget*)QWidget::find(hwnd); - if (widget && !widget->parentWidget()) - qt_set_windows_color_resources(); - } - break; - - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_XBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: - if (qt_win_ignoreNextMouseReleaseEvent) - qt_win_ignoreNextMouseReleaseEvent = false; - break; - - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_XBUTTONUP: - if (qt_win_ignoreNextMouseReleaseEvent) { - qt_win_ignoreNextMouseReleaseEvent = false; - if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) { - releaseAutoCapture(); - qt_button_down = 0; - } - - RETURN(0); - } - break; - - default: - break; - } - - if (!widget) - widget = (QETWidget*)QWidget::find(hwnd); - if (!widget) // don't know this widget - goto do_default; - - if (app_do_modal) { // modal event handling - int ret = 0; - if (!qt_try_modal(widget, &msg, ret)) - RETURN(ret); - } - - res = 0; - if (widget->winEvent(&msg, &res)) // send through widget filter - RETURN(res); - - if (qt_is_translatable_mouse_event(message)) { - if (QApplication::activePopupWidget() != 0) { // in popup mode - POINT curPos = msg.pt; - QWidget* w = QApplication::widgetAt(curPos.x, curPos.y); - if (w) - widget = (QETWidget*)w; - } - - if (!qt_tabletChokeMouse) { - result = widget->translateMouseEvent(msg); // mouse event -#if defined(Q_WS_WINCE) && !defined(QT_NO_CONTEXTMENU) - if (message == WM_LBUTTONDOWN && widget != QApplication::activePopupWidget()) { - QWidget* alienWidget = widget; - if ((alienWidget != QApplication::activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) { - QPoint pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); - QPoint globalPos(msg.pt.x, msg.pt.y); - // In case we are using Alien, then the widget to - // send the context menu event is a different one - if (!alienWidget->testAttribute(Qt::WA_NativeWindow) && !alienWidget->testAttribute(Qt::WA_PaintOnScreen)) { - alienWidget = QApplication::widgetAt(globalPos); - if (alienWidget) - pos = alienWidget->mapFromGlobal(globalPos); - } - if (alienWidget) { - SHRGINFO shrg; - shrg.cbSize = sizeof(shrg); - shrg.hwndClient = hwnd; - shrg.ptDown.x = GET_X_LPARAM(lParam); - shrg.ptDown.y = GET_Y_LPARAM(lParam); - shrg.dwFlags = SHRG_RETURNCMD | SHRG_NOANIMATION; - resolveAygLibs(); -#ifndef QT_NO_GESTURES - if (ptrRecognizeGesture && (ptrRecognizeGesture(&shrg) == GN_CONTEXTMENU)) { - if (QApplication::activePopupWidget()) - QApplication::activePopupWidget()->close(); - QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos); - result = qt_sendSpontaneousEvent(alienWidget, &e); - } -#endif // QT_NO_GESTURES - } - } - } -#endif - } else { - // Sometimes we only get a WM_MOUSEMOVE message - // and sometimes we get both a WM_MOUSEMOVE and - // a WM_LBUTTONDOWN/UP, this creates a spurious mouse - // press/release event, using the PeekMessage - // will help us fix this. This leaves us with a - // question: - // This effectively kills using the mouse AND the - // tablet simultaneously, well creates wacky input. - // Is this going to be a problem? (probably not) - bool next_is_button = false; - bool is_mouse_move = (message == WM_MOUSEMOVE); - if (is_mouse_move) { - MSG msg1; - if (PeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST, - WM_MOUSELAST, PM_NOREMOVE)) - next_is_button = (msg1.message == WM_LBUTTONUP - || msg1.message == WM_LBUTTONDOWN); - } - if (!is_mouse_move || (is_mouse_move && !next_is_button)) - qt_tabletChokeMouse = false; - } - } else { - switch (message) { - case WM_TOUCH: - result = QApplicationPrivate::instance()->translateTouchEvent(msg); - break; - case WM_KEYDOWN: // keyboard event - case WM_SYSKEYDOWN: - qt_keymapper_private()->updateKeyMap(msg); - // fall-through intended - case WM_KEYUP: - case WM_SYSKEYUP: -#if Q_OS_WINCE_WM - case WM_HOTKEY: - if(HIWORD(msg.lParam) == VK_TBACK) { - const bool hotKeyDown = !(LOWORD(msg.lParam) & MOD_KEYUP); - msg.lParam = 0x69 << 16; - msg.wParam = VK_BACK; - if (hotKeyDown) { - msg.message = WM_KEYDOWN; - qt_keymapper_private()->updateKeyMap(msg); - } else { - msg.message = WM_KEYUP; - } - } - // fall-through intended -#endif - case WM_IME_CHAR: - case WM_IME_KEYDOWN: - case WM_CHAR: { - MSG msg1; - bool anyMsg = PeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE); - if (anyMsg && msg1.message == WM_DEADCHAR) { - result = true; // consume event since there is a dead char next - break; - } - QWidget *g = QWidget::keyboardGrabber(); - if (g && qt_get_tablet_widget() && hwnd == qt_get_tablet_widget()->winId()) { - // if we get an event for the internal tablet widget, - // then don't send it to the keyboard grabber, but - // send it to the widget itself (we don't use it right - // now, just in case). - g = 0; - } - if (g) - widget = (QETWidget*)g; - else if (QApplication::activePopupWidget()) - widget = (QETWidget*)QApplication::activePopupWidget()->focusWidget() - ? (QETWidget*)QApplication::activePopupWidget()->focusWidget() - : (QETWidget*)QApplication::activePopupWidget(); - else if (QApplication::focusWidget()) - widget = (QETWidget*)QApplication::focusWidget(); - else if (!widget || widget->internalWinId() == GetFocus()) // We faked the message to go to exactly that widget. - widget = (QETWidget*)widget->window(); - if (widget->isEnabled()) - result = sm_blockUserInput - ? true - : qt_keymapper_private()->translateKeyEvent(widget, msg, g != 0); - break; - } - case WM_SYSCHAR: - result = true; // consume event - break; - - case WM_MOUSEWHEEL: - case WM_MOUSEHWHEEL: - result = widget->translateWheelEvent(msg); - break; - - case WM_APPCOMMAND: - { - uint cmd = GET_APPCOMMAND_LPARAM(lParam); - uint uDevice = GET_DEVICE_LPARAM(lParam); - uint dwKeys = GET_KEYSTATE_LPARAM(lParam); - - int state = translateButtonState(dwKeys, QEvent::KeyPress, 0); - - switch (uDevice) { - case FAPPCOMMAND_KEY: - { - int key = 0; - - switch(cmd) { - case APPCOMMAND_BASS_BOOST: - key = Qt::Key_BassBoost; - break; - case APPCOMMAND_BASS_DOWN: - key = Qt::Key_BassDown; - break; - case APPCOMMAND_BASS_UP: - key = Qt::Key_BassUp; - break; - case APPCOMMAND_TREBLE_DOWN: - key = Qt::Key_TrebleDown; - break; - case APPCOMMAND_TREBLE_UP: - key = Qt::Key_TrebleUp; - break; - case APPCOMMAND_HELP: - key = Qt::Key_Help; - break; - case APPCOMMAND_FIND: - key = Qt::Key_Search; - break; - default: - break; - } - if (key) { - bool res = false; - QWidget *g = QWidget::keyboardGrabber(); - if (g) - widget = (QETWidget*)g; - else if (QApplication::focusWidget()) - widget = (QETWidget*)QApplication::focusWidget(); - else - widget = (QETWidget*)widget->window(); - if (widget->isEnabled()) { - res = QKeyMapper::sendKeyEvent(widget, g != 0, QEvent::KeyPress, key, - Qt::KeyboardModifier(state), - QString(), false, 0, 0, 0, 0); - } - if (res) - return true; - } - } - break; - - default: - break; - } - - result = false; - } - break; - -#ifndef Q_WS_WINCE - case WM_NCHITTEST: - if (widget->isWindow()) { - QPoint pos = widget->mapFromGlobal(QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); - // don't show resize-cursors for fixed-size widgets - QRect fs = widget->frameStrut(); - if (!widget->isMinimized()) { - if (widget->minimumHeight() == widget->maximumHeight()) { - if (pos.y() < -(fs.top() - fs.left())) - return HTCAPTION; - if (pos.y() >= widget->height()) - return HTBORDER; - } - if (widget->minimumWidth() == widget->maximumWidth() && (pos.x() < 0 || pos.x() >= widget->width())) - return HTBORDER; - } - } - - result = false; - break; -#endif - - case WM_SYSCOMMAND: { -#ifndef Q_WS_WINCE - bool window_state_change = false; - Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state); - // MSDN:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are - // used internally by the system. To obtain the correct result when testing the value of - // wParam, an application must combine the value 0xFFF0 with the wParam value by using - // the bitwise AND operator. - switch(0xfff0 & wParam) { - case SC_CONTEXTHELP: -#ifndef QT_NO_WHATSTHIS - QWhatsThis::enterWhatsThisMode(); -#endif - DefWindowProc(hwnd, WM_NCPAINT, 1, 0); - break; -#if defined(QT_NON_COMMERCIAL) - QT_NC_SYSCOMMAND -#endif - case SC_MINIMIZE: - window_state_change = true; - widget->dataPtr()->window_state |= Qt::WindowMinimized; - if (widget->isVisible()) { - QHideEvent e; - qt_sendSpontaneousEvent(widget, &e); - widget->hideChildren(true); - const QString title = widget->windowIconText(); - if (!title.isEmpty()) - widget->setWindowTitle_helper(title); - } - result = false; - break; - case SC_MAXIMIZE: - if(widget->isWindow()) - widget->topData()->normalGeometry = widget->geometry(); - case SC_RESTORE: - window_state_change = true; - if ((0xfff0 & wParam) == SC_MAXIMIZE) - widget->dataPtr()->window_state |= Qt::WindowMaximized; - else if (!widget->isMinimized()) - widget->dataPtr()->window_state &= ~Qt::WindowMaximized; - - if (widget->isMinimized()) { - widget->dataPtr()->window_state &= ~Qt::WindowMinimized; - widget->showChildren(true); - QShowEvent e; - qt_sendSpontaneousEvent(widget, &e); - const QString title = widget->windowTitle(); - if (!title.isEmpty()) - widget->setWindowTitle_helper(title); - } - result = false; - break; - default: - result = false; - break; - } - - if (window_state_change) { - QWindowStateChangeEvent e(oldstate); - qt_sendSpontaneousEvent(widget, &e); - } -#endif // #ifndef Q_OS_WINCE - - break; - } - - case WM_SETTINGCHANGE: - if ( QApplication::type() == QApplication::Tty ) - break; - - if (!msg.wParam) { -#ifdef Q_WS_WINCE - // On Windows CE, lParam parameter is a constant, not a char pointer. - if (msg.lParam == INI_INTL) { -#else - QString area = QString::fromWCharArray((wchar_t*)msg.lParam); - if (area == QLatin1String("intl")) { -#endif - QLocalePrivate::updateSystemPrivate(); - if (!widget->testAttribute(Qt::WA_SetLocale)) - widget->dptr()->setLocale_helper(QLocale(), true); - QEvent e(QEvent::LocaleChange); - QApplication::sendEvent(qApp, &e); - } - } - else if (msg.wParam == SPI_SETICONTITLELOGFONT) { - if (QApplication::desktopSettingsAware()) { - widget = (QETWidget*)QWidget::find(hwnd); - if (widget && !widget->parentWidget()) { - qt_set_windows_font_resources(); - } - } - } - else if (msg.wParam == SPI_SETNONCLIENTMETRICS) { - widget = (QETWidget*)QWidget::find(hwnd); - if (widget && !widget->parentWidget()) { - qt_set_windows_updateScrollBar(widget); - QEvent e(QEvent::LayoutRequest); - QApplication::sendEvent(widget, &e); - } - } - - break; - - case WM_PAINT: // paint event - case WM_ERASEBKGND: // erase window background - result = widget->translatePaintEvent(msg); - break; - -#ifndef Q_WS_WINCE - case WM_ENTERSIZEMOVE: - autoCaptureWnd = hwnd; - break; - case WM_EXITSIZEMOVE: - autoCaptureWnd = 0; - break; -#endif - case WM_MOVE: // move window - case WM_SIZE: // resize window - result = widget->translateConfigEvent(msg); - break; - - case WM_ACTIVATEAPP: - if (wParam == FALSE) { - QApplication::setActiveWindow(0); - // Another application was activated while our popups are open, - // then close all popups. In case some popup refuses to close, - // we give up after 1024 attempts (to avoid an infinite loop). - int maxiter = 1024; - QWidget *popup; - while ((popup=QApplication::activePopupWidget()) && maxiter--) - popup->close(); - } - break; - - case WM_ACTIVATE: - if ( QApplication::type() == QApplication::Tty ) - break; - - if (ptrWTOverlap && ptrWTEnable) { - // cooperate with other tablet applications, but when - // we get focus, I want to use the tablet... - if (qt_tablet_context && GET_WM_ACTIVATE_STATE(wParam, lParam)) { - if (ptrWTEnable(qt_tablet_context, true)) - ptrWTOverlap(qt_tablet_context, true); - } - } - if (QApplication::activePopupWidget() && LOWORD(wParam) == WA_INACTIVE && - QWidget::find((HWND)lParam) == 0) { - // Another application was activated while our popups are open, - // then close all popups. In case some popup refuses to close, - // we give up after 1024 attempts (to avoid an infinite loop). - int maxiter = 1024; - QWidget *popup; - while ((popup=QApplication::activePopupWidget()) && maxiter--) - popup->close(); - } - - if (LOWORD(wParam) != WA_INACTIVE) { - // WM_ACTIVATEAPP handles the "true" false case, as this is only when the application - // loses focus. Doing it here would result in the widget getting focus to not know - // where it got it from; it would simply get a 0 value as the old focus widget. -#ifdef Q_WS_WINCE - { -#ifdef Q_WS_WINCE_WM - // On Windows mobile we do not receive WM_SYSCOMMAND / SC_MINIMIZE messages. - // Thus we have to unset the minimized state explicitly. We must do this for all - // top-level widgets, because we get the HWND of a random widget here. - foreach (QWidget* tlw, QApplication::topLevelWidgets()) { - if (tlw->isMinimized()) - tlw->setWindowState(tlw->windowState() & ~Qt::WindowMinimized); - } -#else - // On Windows CE we do not receive WM_SYSCOMMAND / SC_MINIMIZE messages. - // Thus we have to unset the minimized state explicitly. - if (widget->windowState() & Qt::WindowMinimized) - widget->setWindowState(widget->windowState() & ~Qt::WindowMinimized); -#endif // Q_WS_WINCE_WM - -#else - if (!(widget->windowState() & Qt::WindowMinimized)) { -#endif - // Ignore the activate message send by WindowsXP to a minimized window -#ifdef Q_WS_WINCE_WM - if (widget->windowState() & Qt::WindowFullScreen) - qt_wince_hide_taskbar(widget->winId()); -#endif - qApp->winFocus(widget, true); - // reset any window alert flashes - alert_widget(widget, -1); - } - } - - // Windows tries to activate a modally blocked window. - // This happens when restoring an application after "Show Desktop" - if (app_do_modal && LOWORD(wParam) == WA_ACTIVE) { - QWidget *top = 0; - if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && widget != top) { - if (top->isVisible()) { - top->activateWindow(); - } else { - // This is the case when native file dialogs are shown - QWidget *p = (top->parentWidget() ? top->parentWidget()->window() : 0); - if (p && p->isVisible()) - p->activateWindow(); - } - } - } - break; - -#ifndef Q_WS_WINCE - case WM_MOUSEACTIVATE: - if (widget->window()->windowType() == Qt::Tool) { - QWidget *w = widget; - if (!w->window()->focusWidget()) { - while (w && (w->focusPolicy() & Qt::ClickFocus) == 0) { - if (w->isWindow()) { - QWidget *fw = w; - while ((fw = fw->nextInFocusChain()) != w && fw->focusPolicy() == Qt::NoFocus) - ; - if (fw != w) - break; - QWidget *pw = w->parentWidget(); - while (pw) { - pw = pw->window(); - if (pw && pw->isVisible() && pw->focusWidget()) { - Q_ASSERT(pw->testAttribute(Qt::WA_WState_Created)); - SetWindowPos(pw->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); - break; - } - pw = pw->parentWidget(); - } - RETURN(MA_NOACTIVATE); - } - w = w->parentWidget(); - } - } - } - RETURN(MA_ACTIVATE); - break; -#endif - case WM_SHOWWINDOW: - if (lParam == SW_PARENTOPENING) { - if (widget->testAttribute(Qt::WA_WState_Hidden)) - RETURN(0); - } - if (widget->isWindow() && widget->testAttribute(Qt::WA_WState_Visible) - && !widget->testWindowState(Qt::WindowMinimized)) { - if (lParam == SW_PARENTOPENING) { - QShowEvent e; - qt_sendSpontaneousEvent(widget, &e); - widget->showChildren(true); - } else if (lParam == SW_PARENTCLOSING) { - QHideEvent e; - qt_sendSpontaneousEvent(widget, &e); - widget->hideChildren(true); - } - } - if (!wParam && autoCaptureWnd == widget->internalWinId()) - releaseAutoCapture(); - result = false; - break; - - case WM_PALETTECHANGED: // our window changed palette - if (QColormap::hPal() && (WId)wParam == widget->internalWinId()) - RETURN(0); // otherwise: FALL THROUGH! - // FALL THROUGH - case WM_QUERYNEWPALETTE: // realize own palette - if (QColormap::hPal()) { - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - HDC hdc = GetDC(widget->internalWinId()); - HPALETTE hpalOld = SelectPalette(hdc, QColormap::hPal(), FALSE); - uint n = RealizePalette(hdc); - if (n) - InvalidateRect(widget->internalWinId(), 0, TRUE); - SelectPalette(hdc, hpalOld, TRUE); - RealizePalette(hdc); - ReleaseDC(widget->internalWinId(), hdc); - RETURN(n); - } - break; - case WM_CLOSE: // close window - widget->translateCloseEvent(msg); - RETURN(0); // always handled - - case WM_DESTROY: // destroy window - if (hwnd == curWin) { - QWidget *enter = QWidget::mouseGrabber(); - if (enter == widget) - enter = 0; - QApplicationPrivate::dispatchEnterLeave(enter, widget); - curWin = enter ? enter->effectiveWinId() : 0; - qt_last_mouse_receiver = enter; - } - if (widget == popupButtonFocus) - popupButtonFocus = 0; - result = false; - break; - -#ifndef Q_WS_WINCE - case WM_WINDOWPOSCHANGING: - { - result = false; - if (widget->isWindow()) { - WINDOWPOS *winPos = (WINDOWPOS *)lParam; - if (widget->layout() && widget->layout()->hasHeightForWidth() - && !(winPos->flags & (SWP_NOCOPYBITS | SWP_NOSIZE))) { - QRect fs = widget->frameStrut(); - QRect rect = widget->geometry(); - QRect newRect = QRect(winPos->x + fs.left(), - winPos->y + fs.top(), - winPos->cx - fs.left() - fs.right(), - winPos->cy - fs.top() - fs.bottom()); - - QSize newSize = QLayout::closestAcceptableSize(widget, newRect.size()); - - int dh = newSize.height() - newRect.height(); - int dw = newSize.width() - newRect.width(); - if (!dw && ! dh) - break; // Size OK - - if (rect.y() != newRect.y()) { - newRect.setTop(newRect.top() - dh); - } else { - newRect.setBottom(newRect.bottom() + dh); - } - - if (rect.x() != newRect.x()) { - newRect.setLeft(newRect.left() - dw); - } else { - newRect.setRight(newRect.right() + dw); - } - - winPos->x = newRect.x() - fs.left(); - winPos->y = newRect.y() - fs.top(); - winPos->cx = newRect.width() + fs.left() + fs.right(); - winPos->cy = newRect.height() + fs.top() + fs.bottom(); - - RETURN(0); - } - if (widget->windowFlags() & Qt::WindowStaysOnBottomHint) { - winPos->hwndInsertAfter = HWND_BOTTOM; - } - } - } - break; - - case WM_GETMINMAXINFO: - if (widget->xtra()) { - MINMAXINFO *mmi = (MINMAXINFO *)lParam; - QWExtra *x = widget->xtra(); - QRect fs = widget->frameStrut(); - if ( x->minw > 0 ) - mmi->ptMinTrackSize.x = x->minw + fs.right() + fs.left(); - if ( x->minh > 0 ) - mmi->ptMinTrackSize.y = x->minh + fs.top() + fs.bottom(); - qint32 maxw = (x->maxw >= x->minw) ? x->maxw : x->minw; - qint32 maxh = (x->maxh >= x->minh) ? x->maxh : x->minh; - if ( maxw < QWIDGETSIZE_MAX ) { - mmi->ptMaxTrackSize.x = maxw + fs.right() + fs.left(); - // windows with title bar have an implicit size limit of 112 pixels - if (widget->windowFlags() & Qt::WindowTitleHint) - mmi->ptMaxTrackSize.x = qMax(mmi->ptMaxTrackSize.x, 112); - } - if ( maxh < QWIDGETSIZE_MAX ) - mmi->ptMaxTrackSize.y = maxh + fs.top() + fs.bottom(); - RETURN(0); - } - break; - -#ifndef QT_NO_CONTEXTMENU - case WM_CONTEXTMENU: - { - // it's not VK_APPS or Shift+F10, but a click in the NC area - if (lParam != (int)0xffffffff) { - result = false; - break; - } - - QWidget *fw = QWidget::keyboardGrabber(); - if (!fw) { - if (QApplication::activePopupWidget()) - fw = (QApplication::activePopupWidget()->focusWidget() - ? QApplication::activePopupWidget()->focusWidget() - : QApplication::activePopupWidget()); - else if (QApplication::focusWidget()) - fw = QApplication::focusWidget(); - else if (widget) - fw = widget->window(); - } - if (fw && fw->isEnabled()) { - QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center(); - QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos), - qt_win_getKeyboardModifiers()); - result = qt_sendSpontaneousEvent(fw, &e); - } - } - break; -#endif -#endif - - case WM_IME_STARTCOMPOSITION: - case WM_IME_ENDCOMPOSITION: - case WM_IME_COMPOSITION: { - QWidget *fw = QApplication::focusWidget(); - QWinInputContext *im = fw ? qobject_cast(fw->inputContext()) : 0; - if (fw && im) { - if(message == WM_IME_STARTCOMPOSITION) - result = im->startComposition(); - else if (message == WM_IME_ENDCOMPOSITION) - result = im->endComposition(); - else if (message == WM_IME_COMPOSITION) - result = im->composition(lParam); - } - break; - } - case WM_IME_REQUEST: { - QWidget *fw = QApplication::focusWidget(); - QWinInputContext *im = fw ? qobject_cast(fw->inputContext()) : 0; - if (fw && im) { - if(wParam == IMR_RECONVERTSTRING) { - int ret = im->reconvertString((RECONVERTSTRING *)lParam); - if (ret == -1) { - result = false; - } else { - return ret; - } - } else if (wParam == IMR_CONFIRMRECONVERTSTRING) { - RETURN(TRUE); - } else { - // in all other cases, call DefWindowProc() - result = false; - } - } - break; - } -#ifndef Q_WS_WINCE - case WM_CHANGECBCHAIN: - case WM_DRAWCLIPBOARD: -#endif - case WM_RENDERFORMAT: - case WM_RENDERALLFORMATS: -#ifndef QT_NO_CLIPBOARD - case WM_DESTROYCLIPBOARD: - if (qt_clipboard) { - QClipboardEvent e(reinterpret_cast(&msg)); - qt_sendSpontaneousEvent(qt_clipboard, &e); - RETURN(0); - } - result = false; - break; -#endif //QT_NO_CLIPBOARD -#ifndef QT_NO_ACCESSIBILITY - case WM_GETOBJECT: - { - /* On Win64, lParam can be 0x00000000fffffffc or 0xfffffffffffffffc (!), - but MSDN says that lParam should be converted to a DWORD - before its compared against OBJID_CLIENT - */ - const DWORD dwObjId = (DWORD)lParam; - // Ignoring all requests while starting up - if (QApplication::startingUp() || QApplication::closingDown() || dwObjId != OBJID_CLIENT) { - result = false; - break; - } - - typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN); - static PtrLresultFromObject ptrLresultFromObject = 0; - static bool oleaccChecked = false; - - if (!oleaccChecked) { - oleaccChecked = true; -#if !defined(Q_OS_WINCE) - ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); -#endif - } - if (ptrLresultFromObject) { - QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(widget); - if (!acc) { - result = false; - break; - } - - // and get an instance of the IAccessibile implementation - IAccessible *iface = qt_createWindowsAccessible(acc); - res = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2 - iface->Release(); // the client will release the object again, and then it will destroy itself - - if (res > 0) - RETURN(res); - } - } - result = false; - break; - case WM_GETTEXT: - if (!widget->isWindow()) { - int ret = 0; - QAccessibleInterface *acc = QAccessible::queryAccessibleInterface(widget); - if (acc) { - QString text = acc->text(QAccessible::Name, 0); - if (text.isEmpty()) - text = widget->objectName(); - ret = qMin(wParam - 1, text.size()); - text.resize(ret); - memcpy((void *)lParam, text.utf16(), (text.size() + 1) * sizeof(ushort)); - delete acc; - } - if (!ret) { - result = false; - break; - } - RETURN(ret); - } - result = false; - break; -#endif - case WT_PACKET: - if (ptrWTPacketsGet) { - if ((nPackets = ptrWTPacketsGet(qt_tablet_context, QT_TABLET_NPACKETQSIZE, &localPacketBuf))) { - result = widget->translateTabletEvent(msg, localPacketBuf, nPackets); - } - } - break; - case WT_PROXIMITY: - - #ifndef QT_NO_TABLETEVENT - if (ptrWTPacketsGet && ptrWTInfo) { - const bool enteredProximity = LOWORD(lParam) != 0; - PACKET proximityBuffer[1]; // we are only interested in the first packet in this case - const int totalPacks = ptrWTPacketsGet(qt_tablet_context, 1, proximityBuffer); - if (totalPacks > 0) { - const UINT currentCursor = proximityBuffer[0].pkCursor; - - UINT csr_physid; - ptrWTInfo(WTI_CURSORS + currentCursor, CSR_PHYSID, &csr_physid); - UINT csr_type; - ptrWTInfo(WTI_CURSORS + currentCursor, CSR_TYPE, &csr_type); - const UINT deviceIdMask = 0xFF6; // device type mask && device color mask - quint64 uniqueId = (csr_type & deviceIdMask); - uniqueId = (uniqueId << 32) | csr_physid; - - // initialising and updating the cursor should be done in response to - // WT_CSRCHANGE. We do it in WT_PROXIMITY because some wintab never send - // the event WT_CSRCHANGE even if asked with CXO_CSRMESSAGES - const QTabletCursorInfo *const globalCursorInfo = tCursorInfo(); - if (!globalCursorInfo->contains(uniqueId)) - tabletInit(uniqueId, csr_type, qt_tablet_context); - - currentTabletPointer = globalCursorInfo->value(uniqueId); - tabletUpdateCursor(currentTabletPointer, currentCursor); - } - qt_tabletChokeMouse = false; - - QTabletEvent tabletProximity(enteredProximity ? QEvent::TabletEnterProximity - : QEvent::TabletLeaveProximity, - QPoint(), QPoint(), QPointF(), currentTabletPointer.currentDevice, currentTabletPointer.currentPointerType, 0, 0, - 0, 0, 0, 0, 0, currentTabletPointer.llId); - QApplication::sendEvent(qApp, &tabletProximity); - } - #endif // QT_NO_TABLETEVENT - - break; -#ifdef Q_WS_WINCE_WM - case WM_SETFOCUS: { - HIMC hC; - hC = ImmGetContext(hwnd); - ImmSetOpenStatus(hC, TRUE); - ImmEscape(NULL, hC, IME_ESC_SET_MODE, (LPVOID)IM_SPELL); - result = false; - } - break; -#endif - case WM_KILLFOCUS: - if (!QWidget::find((HWND)wParam)) { // we don't get focus, so unset it now - if (!widget->hasFocus()) // work around Windows bug after minimizing/restoring - widget = (QETWidget*)QApplication::focusWidget(); - HWND focus = ::GetFocus(); - //if there is a current widget and the new widget belongs to the same toplevel window - //or if the current widget was embedded into non-qt window (i.e. we won't get WM_ACTIVATEAPP) - //then we clear the focus on the widget - //in case the new widget belongs to a different widget hierarchy, clearing the focus - //will be handled because the active window will change - const bool embedded = widget && ((QETWidget*)widget->window())->topData()->embedded; - if (widget && (embedded || ::IsChild(widget->window()->internalWinId(), focus))) { - widget->clearFocus(); - result = true; - } else { - result = false; - } - } else { - result = false; - } - break; - case WM_THEMECHANGED: - if ((widget->windowType() == Qt::Desktop) || !qApp || QApplication::closingDown() - || QApplication::type() == QApplication::Tty) - break; - - if (widget->testAttribute(Qt::WA_WState_Polished)) - QApplication::style()->unpolish(widget); - - if (widget->testAttribute(Qt::WA_WState_Polished)) - QApplication::style()->polish(widget); - widget->repolishStyle(*QApplication::style()); - if (widget->isVisible()) - widget->update(); - break; - -#ifndef Q_WS_WINCE - case WM_INPUTLANGCHANGE: { - wchar_t info[7]; - if (!GetLocaleInfo(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) { - inputcharset = CP_ACP; - } else { - inputcharset = QString::fromWCharArray(info).toInt(); - } - QKeyMapper::changeKeyboard(); - break; - } -#else - case WM_COMMAND: { - bool OkCommand = (LOWORD(wParam) == 0x1); - bool CancelCommand = (LOWORD(wParam) == 0x2); - if (OkCommand) - QApplication::postEvent(widget, new QEvent(QEvent::OkRequest)); - if (CancelCommand) - widget->showMinimized(); - else -#ifndef QT_NO_MENUBAR - QMenuBar::wceCommands(LOWORD(wParam)); -#endif - result = true; - } - break; - case WM_HELP: - QApplication::postEvent(widget, new QEvent(QEvent::HelpRequest)); - result = true; - break; -#endif - - case WM_MOUSELEAVE: - // We receive a mouse leave for curWin, meaning - // the mouse was moved outside our widgets - if (widget->internalWinId() == curWin) { - bool dispatch = !widget->underMouse(); - // hasMouse is updated when dispatching enter/leave, - // so test if it is actually up-to-date - if (!dispatch) { - QRect geom = widget->geometry(); - if (widget->parentWidget() && !widget->isWindow()) { - QPoint gp = widget->parentWidget()->mapToGlobal(widget->pos()); - geom.setX(gp.x()); - geom.setY(gp.y()); - } - QPoint cpos = QCursor::pos(); - dispatch = !geom.contains(cpos); - if ( !dispatch && !QWidget::mouseGrabber()) { - QWidget *hittest = QApplication::widgetAt(cpos); - dispatch = !hittest || hittest->internalWinId() != curWin; - } - if (!dispatch) { - HRGN hrgn = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0); - if (GetWindowRgn(curWin, hrgn) != ERROR) { - QPoint lcpos = widget->mapFromGlobal(cpos); - dispatch = !PtInRegion(hrgn, lcpos.x(), lcpos.y()); - } - DeleteObject(hrgn); - } - } - if (dispatch) { - if (qt_last_mouse_receiver && !qt_last_mouse_receiver->internalWinId()) - QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver); - else - QApplicationPrivate::dispatchEnterLeave(0, QWidget::find((WId)curWin)); - curWin = 0; - qt_last_mouse_receiver = 0; - } - } - break; - - case WM_CANCELMODE: - { - // this goes through QMenuBar's event filter - QEvent e(QEvent::ActivationChange); - QApplication::sendEvent(qApp, &e); - } - break; - - case WM_IME_NOTIFY: - // special handling for ime, only for widgets in a popup - if (wParam == IMN_OPENCANDIDATE) { - imeParentWnd = hwnd; - if (QApplication::activePopupWidget()) { - // temporarily disable the mouse grab to allow mouse input in - // the ime candidate window. The actual handle is untouched - if (autoCaptureWnd) - ReleaseCapture(); - } - } else if (wParam == IMN_CLOSECANDIDATE) { - imeParentWnd = 0; - if (QApplication::activePopupWidget()) { - // undo the action above, when candidate window is closed - if (autoCaptureWnd) - SetCapture(autoCaptureWnd); - } - } - result = false; - break; -#ifndef QT_NO_GESTURES -#if !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES) - case WM_GESTURE: { - GESTUREINFO gi; - memset(&gi, 0, sizeof(GESTUREINFO)); - gi.cbSize = sizeof(GESTUREINFO); - - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - BOOL bResult = false; - if (qAppPriv->GetGestureInfo) - bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); - if (bResult) { - if (gi.dwID == GID_BEGIN) { - // find the alien widget for the gesture position. - // This might not be accurate as the position is the center - // point of two fingers for multi-finger gestures. - QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y); - QWidget *w = widget->childAt(widget->mapFromGlobal(pt)); - qAppPriv->gestureWidget = w ? w : widget; - } - if (qAppPriv->gestureWidget) - static_cast(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi); - if (qAppPriv->CloseGestureInfoHandle) - qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); - if (gi.dwID == GID_END) - qAppPriv->gestureWidget = 0; - } else { - DWORD dwErr = GetLastError(); - if (dwErr > 0) - qWarning() << "translateGestureEvent: error = " << dwErr; - } - result = true; - break; - } -#endif // !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES) -#endif // QT_NO_GESTURES -#ifndef QT_NO_CURSOR - case WM_SETCURSOR: { - QCursor *ovr = QApplication::overrideCursor(); - if (ovr) { - SetCursor(ovr->handle()); - RETURN(TRUE); - } - result = false; - break; - } -#endif - default: - result = false; // event was not processed - break; - } - } - - if (evt_type != QEvent::None) { // simple event - QEvent e(evt_type); - result = qt_sendSpontaneousEvent(widget, &e); - } - - if (result) - RETURN(false); - -do_default: - RETURN(QWinInputContext::DefWindowProc(hwnd,message,wParam,lParam)) -} - - -/***************************************************************************** - Modal widgets; We have implemented our own modal widget mechanism - to get total control. - 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; - - releaseAutoCapture(); - ClipCursor(0); - 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; - qt_win_ignoreNextMouseReleaseEvent = false; -} - -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()); - app_do_modal = false; // necessary, we may get recursively into qt_try_modal below - 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; - } - qt_win_ignoreNextMouseReleaseEvent = true; - } - app_do_modal = qt_modal_stack != 0; -} - -bool qt_try_modal(QWidget *widget, MSG *msg, int& ret) -{ -#if defined(Q_OS_WINCE) - Q_UNUSED(ret); -#endif - QWidget * top = 0; - - if (QApplicationPrivate::tryModalHelper(widget, &top)) - return true; - - int type = msg->message; - - bool block_event = false; -#ifndef Q_WS_WINCE - if (type != WM_NCHITTEST) { -#endif - if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) || - type == WM_MOUSEWHEEL || type == WM_MOUSEHWHEEL || - type == WM_MOUSELEAVE || - (type >= WM_KEYFIRST && type <= WM_KEYLAST) -#ifndef Q_WS_WINCE - || type == WM_NCMOUSEMOVE -#endif - ) { - if (type == WM_MOUSEMOVE -#ifndef Q_WS_WINCE - || type == WM_NCMOUSEMOVE -#endif - ) { -#ifndef QT_NO_CURSOR - QCursor *c = qt_grab_cursor(); - if (!c) - c = QApplication::overrideCursor(); - if (c) // application cursor defined - SetCursor(c->handle()); - else - SetCursor(QCursor(Qt::ArrowCursor).handle()); -#endif // QT_NO_CURSOR - } - block_event = true; - } else if (type == WM_CLOSE) { - block_event = true; - } -#ifndef Q_WS_WINCE - else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){ - if (!top->isActiveWindow()) { - top->activateWindow(); - } else { - QApplication::beep(); - } - block_event = true; - ret = MA_NOACTIVATEANDEAT; - } else if (type == WM_SYSCOMMAND) { - if (!(msg->wParam == SC_RESTORE && widget->isMinimized())) - block_event = true; - } - } -#endif - - return !block_event; -} - - -/***************************************************************************** - 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 - *****************************************************************************/ - -void QApplicationPrivate::openPopup(QWidget *popup) -{ - if (!QApplicationPrivate::popupWidgets) - QApplicationPrivate::popupWidgets = new QWidgetList; - QApplicationPrivate::popupWidgets->append(popup); - if (!popup->isEnabled()) - return; - - // close any opened 'ime candidate window' - if (imeParentWnd) - ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0); - - if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()) { - Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created)); - setAutoCapture(popup->internalWinId()); // grab mouse/keyboard - } - // 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); - QApplication::sendEvent(fw, &e); - } - } -} - -void QApplicationPrivate::closePopup(QWidget *popup) -{ - if (!QApplicationPrivate::popupWidgets) - return; - QApplicationPrivate::popupWidgets->removeAll(popup); - POINT curPos; - GetCursorPos(&curPos); - - // close any opened 'ime candidate window' - if (imeParentWnd) - ::SendMessage(imeParentWnd, WM_IME_ENDCOMPOSITION, 0, 0); - - if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup - delete QApplicationPrivate::popupWidgets; - QApplicationPrivate::popupWidgets = 0; - replayPopupMouseEvent = (!popup->geometry().contains(QPoint(curPos.x, curPos.y)) - && !popup->testAttribute(Qt::WA_NoMouseReplay)); - if (!popup->isEnabled()) - return; - if (!qt_nograb()) // grabbing not disabled - releaseAutoCapture(); - QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget() - : QApplication::focusWidget(); - if (fw) { - if (fw != QApplication::focusWidget()) { - fw->setFocus(Qt::PopupFocusReason); - } else { - QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); - QApplication::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 (QApplicationPrivate::popupWidgets->count() == 1) { - Q_ASSERT(aw->testAttribute(Qt::WA_WState_Created)); - setAutoCapture(aw->internalWinId()); - } - if (QWidget *fw = aw->focusWidget()) - fw->setFocus(Qt::PopupFocusReason); - } -} - - - - -/***************************************************************************** - Event translation; translates Windows events to Qt events - *****************************************************************************/ - -// -// Auto-capturing for mouse press and mouse release -// - -static void setAutoCapture(HWND h) -{ - if (autoCaptureWnd) - releaseAutoCapture(); - autoCaptureWnd = h; - SetCapture(h); -} - -static void releaseAutoCapture() -{ - if (autoCaptureWnd) { - ReleaseCapture(); - autoCaptureWnd = 0; - } -} - - -// -// Mouse event translation -// -// Non-client mouse messages are not translated -// - -static const ushort mouseTbl[] = { - WM_MOUSEMOVE, QEvent::MouseMove, 0, - WM_LBUTTONDOWN, QEvent::MouseButtonPress, Qt::LeftButton, - WM_LBUTTONUP, QEvent::MouseButtonRelease, Qt::LeftButton, - WM_LBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton, - WM_RBUTTONDOWN, QEvent::MouseButtonPress, Qt::RightButton, - WM_RBUTTONUP, QEvent::MouseButtonRelease, Qt::RightButton, - WM_RBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton, - WM_MBUTTONDOWN, QEvent::MouseButtonPress, Qt::MidButton, - WM_MBUTTONUP, QEvent::MouseButtonRelease, Qt::MidButton, - WM_MBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton, - // use XButton1 for now, the real X button is decided later - WM_XBUTTONDOWN, QEvent::MouseButtonPress, Qt::XButton1, - WM_XBUTTONUP, QEvent::MouseButtonRelease, Qt::XButton1, - WM_XBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::XButton1, - -#ifndef Q_WS_WINCE - WM_NCMOUSEMOVE, QEvent::NonClientAreaMouseMove, 0, - WM_NCLBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton, - WM_NCLBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton, - WM_NCLBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::LeftButton, - WM_NCRBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::RightButton, - WM_NCRBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton, - WM_NCRBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::RightButton, - WM_NCMBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::MidButton, - WM_NCMBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton, - WM_NCMBUTTONDBLCLK, QEvent::NonClientAreaMouseButtonDblClick, Qt::MidButton, -#endif - - 0, 0, 0 -}; - -static int translateButtonState(int s, int type, int button) -{ - Q_UNUSED(type); - Q_UNUSED(button); - int bst = 0; - if (s & MK_LBUTTON) - bst |= Qt::LeftButton; - if (s & MK_MBUTTON) - bst |= Qt::MidButton; - if (s & MK_RBUTTON) - bst |= Qt::RightButton; - if (s & MK_SHIFT) - bst |= Qt::ShiftModifier; - if (s & MK_CONTROL) - bst |= Qt::ControlModifier; - - if (s & MK_XBUTTON1) - bst |= Qt::XButton1; - if (s & MK_XBUTTON2) - bst |= Qt::XButton2; - - if (GetKeyState(VK_MENU) < 0) - bst |= Qt::AltModifier; - - if ((GetKeyState(VK_LWIN) < 0) || - (GetKeyState(VK_RWIN) < 0)) - bst |= Qt::MetaModifier; - - return bst; -} - -void qt_win_eatMouseMove() -{ - // after closing a windows dialog with a double click (i.e. open a file) - // the message queue still contains a dubious WM_MOUSEMOVE message where - // the left button is reported to be down (wParam != 0). - // remove all those messages (usually 1) and post the last one with a - // reset button state - - MSG msg = {0, 0, 0, 0, 0, {0, 0} }; - while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - ; - if (msg.message == WM_MOUSEMOVE) - PostMessage(msg.hwnd, msg.message, 0, msg.lParam); -} - -// In DnD, the mouse release event never appears, so the -// mouse button state machine must be manually reset -void QApplication::winMouseButtonUp() -{ - qt_button_down = 0; - releaseAutoCapture(); -} - -void QETWidget::repolishStyle(QStyle &) -{ - QEvent e(QEvent::StyleChange); - QApplication::sendEvent(this, &e); -} - -bool QETWidget::translateMouseEvent(const MSG &msg) -{ - if (!isWindow() && testAttribute(Qt::WA_NativeWindow)) - Q_ASSERT(internalWinId()); - - static QPoint pos; - static POINT gpos={-1,-1}; - QEvent::Type type; // event parameters - int button; - int state; - int i; - - if (sm_blockUserInput) //block user interaction during session management - return true; - - // Compress mouse move events - if (msg.message == WM_MOUSEMOVE) { - MSG mouseMsg; - while (PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST, - WM_MOUSELAST, PM_NOREMOVE)) { - if (mouseMsg.message == WM_MOUSEMOVE) { -#define PEEKMESSAGE_IS_BROKEN 1 -#ifdef PEEKMESSAGE_IS_BROKEN - // Since the Windows PeekMessage() function doesn't - // correctly return the wParam for WM_MOUSEMOVE events - // if there is a key release event in the queue - // _before_ the mouse event, we have to also consider - // key release events (kls 2003-05-13): - MSG keyMsg; - bool done = false; - while (PeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST, - PM_NOREMOVE)) { - if (keyMsg.time < mouseMsg.time) { - if ((keyMsg.lParam & 0xC0000000) == 0x40000000) { - PeekMessage(&keyMsg, 0, keyMsg.message, - keyMsg.message, PM_REMOVE); - } else { - done = true; - break; - } - } else { - break; // no key event before the WM_MOUSEMOVE event - } - } - if (done) - break; -#else - // Actually the following 'if' should work instead of - // the above key event checking, but apparently - // PeekMessage() is broken :-( - if (mouseMsg.wParam != msg.wParam) - break; // leave the message in the queue because - // the key state has changed -#endif - MSG *msgPtr = (MSG *)(&msg); - // Update the passed in MSG structure with the - // most recent one. - msgPtr->lParam = mouseMsg.lParam; - msgPtr->wParam = mouseMsg.wParam; - // Extract the x,y coordinates from the lParam as we do in the WndProc - msgPtr->pt.x = GET_X_LPARAM(mouseMsg.lParam); - msgPtr->pt.y = GET_Y_LPARAM(mouseMsg.lParam); - ClientToScreen(msg.hwnd, &(msgPtr->pt)); - // Remove the mouse move message - PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE, - WM_MOUSEMOVE, PM_REMOVE); - } else { - break; // there was no more WM_MOUSEMOVE event - } - } - } - - for (i=0; (UINT)mouseTbl[i] != msg.message && mouseTbl[i]; i += 3) - ; - if (!mouseTbl[i]) - return false; - type = (QEvent::Type)mouseTbl[++i]; // event type - button = mouseTbl[++i]; // which button - if (button == Qt::XButton1) { - switch(GET_XBUTTON_WPARAM(msg.wParam)) { - case XBUTTON1: - button = Qt::XButton1; - break; - case XBUTTON2: - button = Qt::XButton2; - break; - } - } -#ifndef Q_OS_WINCE - static bool trackMouseEventLookup = false; - typedef BOOL (WINAPI *PtrTrackMouseEvent)(LPTRACKMOUSEEVENT); - static PtrTrackMouseEvent ptrTrackMouseEvent = 0; -#endif - state = translateButtonState(msg.wParam, type, button); // button state - const QPoint widgetPos = mapFromGlobal(QPoint(msg.pt.x, msg.pt.y)); - QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); - if (alienWidget && alienWidget->internalWinId()) - alienWidget = 0; - - if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove - || type == QEvent::TabletMove) { - - if (!(state & Qt::MouseButtonMask)) - qt_button_down = 0; -#ifndef QT_NO_CURSOR - QCursor *c = qt_grab_cursor(); - if (!c) - c = QApplication::overrideCursor(); - if (c) // application cursor defined - SetCursor(c->handle()); - else if (type != QEvent::NonClientAreaMouseMove && !qt_button_down) { - // use widget cursor if widget is enabled - QWidget *w = alienWidget ? alienWidget : this; - while (!w->isWindow() && !w->isEnabled()) - w = w->parentWidget(); - SetCursor(w->cursor().handle()); - } -#endif // QT_NO_CURSOR - - HWND id = effectiveWinId(); - QWidget *mouseGrabber = QWidget::mouseGrabber(); - QWidget *activePopupWidget = QApplication::activePopupWidget(); - if (mouseGrabber) { - if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos))) - id = mouseGrabber->effectiveWinId(); - } else if (type == QEvent::NonClientAreaMouseMove) { - id = 0; - } - - if (curWin != id) { // new current window - if (id == 0) { - QWidget *leave = qt_last_mouse_receiver; - if (!leave) - leave = QWidget::find(curWin); - QApplicationPrivate::dispatchEnterLeave(0, leave); - qt_last_mouse_receiver = 0; - curWin = 0; - } else { - QWidget *leave = 0; - if (curWin && qt_last_mouse_receiver) - leave = qt_last_mouse_receiver; - else - leave = QWidget::find(curWin); - QWidget *enter = alienWidget ? alienWidget : this; - if (mouseGrabber && activePopupWidget) { - if (leave != mouseGrabber) - enter = mouseGrabber; - else - enter = activePopupWidget == this ? this : mouseGrabber; - } - QApplicationPrivate::dispatchEnterLeave(enter, leave); - qt_last_mouse_receiver = enter; - curWin = enter ? enter->effectiveWinId() : 0; - } -#ifndef Q_OS_WINCE - - if (curWin != 0) { - if (!trackMouseEventLookup) { - trackMouseEventLookup = true; - ptrTrackMouseEvent = (PtrTrackMouseEvent)QSystemLibrary::resolve(QLatin1String("comctl32"), "_TrackMouseEvent"); - } - if (ptrTrackMouseEvent && !qApp->d_func()->inPopupMode()) { - // We always have to set the tracking, since - // Windows detects more leaves than we do.. - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = 0x00000002; // TME_LEAVE - tme.hwndTrack = curWin; // Track on window receiving msgs - tme.dwHoverTime = (DWORD)-1; // HOVER_DEFAULT - ptrTrackMouseEvent(&tme); - } - } -#endif // Q_OS_WINCE - } - - POINT curPos = msg.pt; - if (curPos.x == gpos.x && curPos.y == gpos.y) - return true; // same global position - gpos = curPos; - - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - ScreenToClient(internalWinId(), &curPos); - - pos.rx() = curPos.x; - pos.ry() = curPos.y; - pos = d_func()->mapFromWS(pos); - } else { - gpos = msg.pt; - pos = mapFromGlobal(QPoint(gpos.x, gpos.y)); - - // mouse button pressed - if (!qt_button_down && (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)) { - QWidget *tlw = window(); - if (QWidget *child = tlw->childAt(mapTo(tlw, pos))) - qt_button_down = child; - else - qt_button_down = this; - } - } - - bool res = false; - - bool nonClientAreaEvent = type >= QEvent::NonClientAreaMouseMove - && type <= QEvent::NonClientAreaMouseButtonDblClick; - - if (qApp->d_func()->inPopupMode()) { // in popup mode - - if (nonClientAreaEvent) - return false; - - replayPopupMouseEvent = false; - QWidget* activePopupWidget = QApplication::activePopupWidget(); - QWidget *target = activePopupWidget; - const QPoint globalPos(gpos.x, gpos.y); - - if (target != this) { - if ((windowType() == Qt::Popup) && rect().contains(pos) && 0) - target = this; - else // send to last popup - pos = target->mapFromGlobal(globalPos); - } - QWidget *popupChild = target->childAt(pos); - bool releaseAfter = false; - switch (type) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - popupButtonFocus = popupChild; - break; - case QEvent::MouseButtonRelease: - case QEvent::TabletRelease: - - releaseAfter = true; - break; - default: - break; // nothing for mouse move - } - - if (target->isEnabled()) { - if (popupButtonFocus) { - target = popupButtonFocus; - } else if (popupChild) { - target = popupChild; - } - - pos = target->mapFromGlobal(globalPos); - QMouseEvent e(type, pos, globalPos, - Qt::MouseButton(button), - Qt::MouseButtons(state & Qt::MouseButtonMask), - Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask)); - res = QApplicationPrivate::sendMouseEvent(target, &e, alienWidget, this, &qt_button_down, - qt_last_mouse_receiver); - res = res && e.isAccepted(); - } else { - // close disabled popups when a mouse button is pressed or released - switch (type) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonRelease: - target->close(); - break; - default: - break; - } - } - - if (releaseAfter) { - popupButtonFocus = 0; - qt_button_down = 0; - } - -#ifndef Q_OS_WINCE - if (type == QEvent::MouseButtonPress - && QApplication::activePopupWidget() != activePopupWidget - && ptrTrackMouseEvent - && curWin) { - // Since curWin is already the window we clicked on, - // we have to setup the mouse tracking here. - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = 0x00000002; // TME_LEAVE - tme.hwndTrack = curWin; // Track on window receiving msgs - tme.dwHoverTime = (DWORD)-1; // HOVER_DEFAULT - ptrTrackMouseEvent(&tme); - } -#endif - if (type == QEvent::MouseButtonPress - && QApplication::activePopupWidget() != activePopupWidget - && replayPopupMouseEvent) { - // the popup disappeared. Replay the event - QWidget* w = QApplication::widgetAt(gpos.x, gpos.y); - if (w && !QApplicationPrivate::isBlockedByModal(w)) { - Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); - HWND hwndTarget = w->effectiveWinId(); - if (QWidget::mouseGrabber() == 0) - setAutoCapture(hwndTarget); - if (!w->isActiveWindow()) - w->activateWindow(); - POINT widgetpt = gpos; - ScreenToClient(hwndTarget, &widgetpt); - LPARAM lParam = MAKELPARAM(widgetpt.x, widgetpt.y); - PostMessage(hwndTarget, msg.message, msg.wParam, lParam); - } - } else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton - && QApplication::activePopupWidget() == activePopupWidget) { - // popup still alive and received right-button-release -#if !defined(QT_NO_CONTEXTMENU) - QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos, - qt_win_getKeyboardModifiers()); - bool res2 = QApplication::sendSpontaneousEvent( target, &e2 ); - if (!res) // RMB not accepted - res = res2 && e2.isAccepted(); -#endif - } - } else { // not popup mode - int bs = state & Qt::MouseButtonMask; - if ((type == QEvent::MouseButtonPress || - type == QEvent::MouseButtonDblClick) && bs == button) { - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - if (QWidget::mouseGrabber() == 0) - setAutoCapture(internalWinId()); - } else if (type == QEvent::MouseButtonRelease && bs == 0) { - if (QWidget::mouseGrabber() == 0) - releaseAutoCapture(); - } - - const QPoint globalPos(gpos.x,gpos.y); - QWidget *widget = QApplicationPrivate::pickMouseReceiver(this, globalPos, pos, type, - Qt::MouseButtons(bs), - qt_button_down, alienWidget); - if (!widget) - return false; // don't send event - - QMouseEvent e(type, pos, globalPos, Qt::MouseButton(button), - Qt::MouseButtons(state & Qt::MouseButtonMask), - Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask)); - - res = QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, - qt_last_mouse_receiver); - - // non client area events are only informational, you cannot "handle" them - res = res && e.isAccepted() && !nonClientAreaEvent; -#if !defined(QT_NO_CONTEXTMENU) - if (type == QEvent::MouseButtonRelease && button == Qt::RightButton) { - QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos, - qt_win_getKeyboardModifiers()); - bool res2 = QApplication::sendSpontaneousEvent(widget, &e2); - if (!res) - res = res2 && e2.isAccepted(); - } -#endif - - if (type != QEvent::MouseMove) - pos.rx() = pos.ry() = -9999; // init for move compression - } - return res; -} - -bool QETWidget::translateWheelEvent(const MSG &msg) -{ - int state = 0; - - if (sm_blockUserInput) // block user interaction during session management - return true; - - state = translateButtonState(GET_KEYSTATE_WPARAM(msg.wParam), 0, 0); - - int delta; - if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL) - delta = (short) HIWORD (msg.wParam); - else - delta = (int) msg.wParam; - - Qt::Orientation orient = (msg.message == WM_MOUSEHWHEEL || state&Qt::AltModifier -#if 0 - // disabled for now - Trenton's one-wheel mouse makes trouble... - // "delta" for usual wheels is +-120. +-240 seems to indicate - // the second wheel see more recent MSDN for WM_MOUSEWHEEL - - ( // <- parantheses added to make update happy, remove if the - // #if 0 is removed - || delta == 240 || delta == -240)?Qt::Horizontal:Vertical; - if (delta == 240 || delta == -240) - delta /= 2; -#endif - ) ? Qt::Horizontal : Qt::Vertical; - - // according to the MSDN documentation on WM_MOUSEHWHEEL: - // a positive value indicates that the wheel was rotated to the right; - // a negative value indicates that the wheel was rotated to the left. - // Qt defines this value as the exact opposite, so we have to flip the value! - if (msg.message == WM_MOUSEHWHEEL) - delta = -delta; - - QPoint globalPos; - - globalPos.rx() = (short)LOWORD (msg.lParam); - globalPos.ry() = (short)HIWORD (msg.lParam); - - - // if there is a widget under the mouse and it is not shadowed - // by modality, we send the event to it first - int ret = 0; - QWidget* w = QApplication::widgetAt(globalPos); - if (!w || !qt_try_modal(w, (MSG*)&msg, ret)) { - //synaptics touchpad shows its own widget at this position - //so widgetAt() will fail with that HWND, try child of this widget - w = this->childAt(this->mapFromGlobal(globalPos)); - if (!w) - w = this; - } - - // send the event to the widget or its ancestors - { - QWidget* popup = QApplication::activePopupWidget(); - if (popup && w->window() != popup) - popup->close(); -#ifndef QT_NO_WHEELEVENT - QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta, - Qt::MouseButtons(state & Qt::MouseButtonMask), - Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient); - - if (QApplication::sendSpontaneousEvent(w, &e)) -#else - Q_UNUSED(orient); -#endif //QT_NO_WHEELEVENT - return true; - } - - // send the event to the widget that has the focus or its ancestors, if different - if (w != QApplication::focusWidget() && (w = QApplication::focusWidget())) { - QWidget* popup = QApplication::activePopupWidget(); - if (popup && w->window() != popup) - popup->close(); -#ifndef QT_NO_WHEELEVENT - QWheelEvent e(w->mapFromGlobal(globalPos), globalPos, delta, - Qt::MouseButtons(state & Qt::MouseButtonMask), - Qt::KeyboardModifier(state & Qt::KeyboardModifierMask), orient); - if (QApplication::sendSpontaneousEvent(w, &e)) -#endif //QT_NO_WHEELEVENT - return true; - } - return false; -} - - -// -// Windows Wintab to QTabletEvent translation -// - -// the following is adapted from the wintab syspress example (public domain) -/* -------------------------------------------------------------------------- */ -// Initialize the "static" information of a cursor device (pen, airbrush, etc). -// The QTabletDeviceData is initialized with the data that do not change in time -// (number of button, type of device, etc) but do not initialize the variable data -// (e.g.: pen or eraser) -#ifndef QT_NO_TABLETEVENT - -static void tabletInit(const quint64 uniqueId, const UINT csr_type, HCTX hTab) -{ - Q_ASSERT(ptrWTInfo); - Q_ASSERT(ptrWTGet); - - Q_ASSERT(!tCursorInfo()->contains(uniqueId)); - - /* browse WinTab's many info items to discover pressure handling. */ - AXIS np; - LOGCONTEXT lc; - - /* get the current context for its device variable. */ - ptrWTGet(hTab, &lc); - - /* get the size of the pressure axis. */ - QTabletDeviceData tdd; - tdd.llId = uniqueId; - - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_NPRESSURE, &np); - tdd.minPressure = int(np.axMin); - tdd.maxPressure = int(np.axMax); - - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_TPRESSURE, &np); - tdd.minTanPressure = int(np.axMin); - tdd.maxTanPressure = int(np.axMax); - - LOGCONTEXT lcMine; - - /* get default region */ - ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); - - tdd.minX = 0; - tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); - - tdd.minY = 0; - tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); - - tdd.minZ = 0; - tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); - - const uint cursorTypeBitMask = 0x0F06; // bitmask to find the specific cursor type (see Wacom FAQ) - if (((csr_type & 0x0006) == 0x0002) && ((csr_type & cursorTypeBitMask) != 0x0902)) { - tdd.currentDevice = QTabletEvent::Stylus; - } else { - switch (csr_type & cursorTypeBitMask) { - case 0x0802: - tdd.currentDevice = QTabletEvent::Stylus; - break; - case 0x0902: - tdd.currentDevice = QTabletEvent::Airbrush; - break; - case 0x0004: - tdd.currentDevice = QTabletEvent::FourDMouse; - break; - case 0x0006: - tdd.currentDevice = QTabletEvent::Puck; - break; - case 0x0804: - tdd.currentDevice = QTabletEvent::RotationStylus; - break; - default: - tdd.currentDevice = QTabletEvent::NoDevice; - } - } - tCursorInfo()->insert(uniqueId, tdd); -} -#endif // QT_NO_TABLETEVENT - -// Update the "dynamic" information of a cursor device (pen, airbrush, etc). -// The dynamic information is the information of QTabletDeviceData that can change -// in time (eraser or pen if a device is turned around). -#ifndef QT_NO_TABLETEVENT - -static void tabletUpdateCursor(QTabletDeviceData &tdd, const UINT currentCursor) -{ - switch (currentCursor % 3) { // %3 for dual track - case 0: - tdd.currentPointerType = QTabletEvent::Cursor; - break; - case 1: - tdd.currentPointerType = QTabletEvent::Pen; - break; - case 2: - tdd.currentPointerType = QTabletEvent::Eraser; - break; - default: - tdd.currentPointerType = QTabletEvent::UnknownPointer; - } -} -#endif // QT_NO_TABLETEVENT - -bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, - int numPackets) -{ - Q_UNUSED(msg); - POINT ptNew; - static DWORD btnNew, btnOld, btnChange; - qreal prsNew; - ORIENTATION ort; - static bool button_pressed = false; - int i, - tiltX, - tiltY; - bool sendEvent = false; - QEvent::Type t; - int z = 0; - qreal rotation = 0.0; - qreal tangentialPressure; - - // the most common event that we get... - t = QEvent::TabletMove; - for (i = 0; i < numPackets; i++) { - // get the unique ID of the device... - btnOld = btnNew; - btnNew = localPacketBuf[i].pkButtons; - btnChange = btnOld ^ btnNew; - - if (btnNew & btnChange) { - button_pressed = true; - t = QEvent::TabletPress; - } - ptNew.x = UINT(localPacketBuf[i].pkX); - ptNew.y = UINT(localPacketBuf[i].pkY); -#ifndef QT_NO_TABLETEVENT - z = (currentTabletPointer.currentDevice == QTabletEvent::FourDMouse) ? UINT(localPacketBuf[i].pkZ) : 0; -#else - Q_UNUSED(z); -#endif // QT_NO_TABLETEVENT - prsNew = 0.0; - QRect desktopArea = QApplication::desktop()->geometry(); - QPointF hiResGlobal = currentTabletPointer.scaleCoord(ptNew.x, ptNew.y, desktopArea.left(), - desktopArea.width(), desktopArea.top(), - desktopArea.height()); - - if (btnNew) { -#ifndef QT_NO_TABLETEVENT - if (currentTabletPointer.currentPointerType == QTabletEvent::Pen || currentTabletPointer.currentPointerType == QTabletEvent::Eraser) - prsNew = localPacketBuf[i].pkNormalPressure - / qreal(currentTabletPointer.maxPressure - - currentTabletPointer.minPressure); - else -#endif // QT_NO_TABLETEVENT - prsNew = 0; - } else if (button_pressed) { - // One button press, should only give one button release - t = QEvent::TabletRelease; - button_pressed = false; - } - QPoint globalPos(qRound(hiResGlobal.x()), qRound(hiResGlobal.y())); - - if (t == QEvent::TabletPress) - { - qt_button_down = QApplication::widgetAt(globalPos); - } - - // make sure the tablet event get's sent to the proper widget... - QWidget *w = 0; - - if (qt_button_down) - w = qt_button_down; // Pass it to the thing that's grabbed it. - else - w = QApplication::widgetAt(globalPos); - - if (!w) - w = this; - - if (t == QEvent::TabletRelease) - { - if (qt_win_ignoreNextMouseReleaseEvent) { - qt_win_ignoreNextMouseReleaseEvent = false; - if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) { - releaseAutoCapture(); - qt_button_down = 0; - } - } - - } - - QPoint localPos = w->mapFromGlobal(globalPos); -#ifndef QT_NO_TABLETEVENT - if (currentTabletPointer.currentDevice == QTabletEvent::Airbrush) { - tangentialPressure = localPacketBuf[i].pkTangentPressure - / qreal(currentTabletPointer.maxTanPressure - - currentTabletPointer.minTanPressure); - } else { - tangentialPressure = 0.0; - } -#else - tangentialPressure = 0.0; -#endif // QT_NO_TABLETEVENT - - if (!qt_tablet_tilt_support) { - tiltX = tiltY = 0; - rotation = 0.0; - } else { - ort = localPacketBuf[i].pkOrientation; - // convert from azimuth and altitude to x tilt and y tilt - // what follows is the optimized version. Here are the equations - // I used to get to this point (in case things change :) - // X = sin(azimuth) * cos(altitude) - // Y = cos(azimuth) * cos(altitude) - // Z = sin(altitude) - // X Tilt = arctan(X / Z) - // Y Tilt = arctan(Y / Z) - double radAzim = (ort.orAzimuth / 10) * (Q_PI / 180); - //double radAlt = abs(ort.orAltitude / 10) * (Q_PI / 180); - double tanAlt = tan((abs(ort.orAltitude / 10)) * (Q_PI / 180)); - - double degX = atan(sin(radAzim) / tanAlt); - double degY = atan(cos(radAzim) / tanAlt); - tiltX = int(degX * (180 / Q_PI)); - tiltY = int(-degY * (180 / Q_PI)); - rotation = ort.orTwist; - } -#ifndef QT_NO_TABLETEVENT - QTabletEvent e(t, localPos, globalPos, hiResGlobal, currentTabletPointer.currentDevice, - currentTabletPointer.currentPointerType, prsNew, tiltX, tiltY, - tangentialPressure, rotation, z, QApplication::keyboardModifiers(), currentTabletPointer.llId); - sendEvent = QApplication::sendSpontaneousEvent(w, &e); -#endif // QT_NO_TABLETEVENT - } - return sendEvent; -} - -extern bool qt_is_gui_used; - - -#ifndef QT_NO_TABLETEVENT - -static void initWinTabFunctions() -{ -#if defined(Q_OS_WINCE) - return; -#else - if (!qt_is_gui_used) - return; - - QSystemLibrary library(QLatin1String("wintab32")); - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); - ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); - ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); -#endif // Q_OS_WINCE -} -#endif // QT_NO_TABLETEVENT - - -// -// Paint event translation -// -bool QETWidget::translatePaintEvent(const MSG &msg) -{ - if (!isWindow() && testAttribute(Qt::WA_NativeWindow)) - Q_ASSERT(internalWinId()); - - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - if (!GetUpdateRect(internalWinId(), 0, FALSE)) { // The update bounding rect is invalid - d_func()->hd = 0; - setAttribute(Qt::WA_PendingUpdate, false); - return false; - } - - if (msg.message == WM_ERASEBKGND) - return true; - - setAttribute(Qt::WA_PendingUpdate, false); - - if (d_func()->isGLWidget) { - if (d_func()->usesDoubleBufferedGLContext) - InvalidateRect(internalWinId(), 0, false); - } else { - const QRegion dirtyInBackingStore(qt_dirtyRegion(this)); - // Make sure the invalidated region contains the region we're about to repaint. - // BeginPaint will set the clip to the invalidated region and it is impossible - // to enlarge it afterwards (only shrink it). Using GetDCEx is not suffient - // as it may return an invalid context (especially on Windows Vista). - if (!dirtyInBackingStore.isEmpty()) - InvalidateRgn(internalWinId(), dirtyInBackingStore.handle(), false); - } - PAINTSTRUCT ps; - d_func()->hd = BeginPaint(internalWinId(), &ps); - - const QRect updateRect(QPoint(ps.rcPaint.left, ps.rcPaint.top), - QPoint(ps.rcPaint.right, ps.rcPaint.bottom)); - - // Mapping region from system to qt (32 bit) coordinate system. - d_func()->syncBackingStore(updateRect.translated(data->wrect.topLeft())); - - d_func()->hd = 0; - EndPaint(internalWinId(), &ps); - - return true; -} - -// -// Window move and resize (configure) events -// - -bool QETWidget::translateConfigEvent(const MSG &msg) -{ - if (!testAttribute(Qt::WA_WState_Created)) // in QWidget::create() - return true; - if (testAttribute(Qt::WA_WState_ConfigPending)) - return true; - if (testAttribute(Qt::WA_DontShowOnScreen)) - return true; - if (!isWindow()) - return true; - setAttribute(Qt::WA_WState_ConfigPending); // set config flag - QRect cr = geometry(); - if (msg.message == WM_SIZE) { // resize event - WORD a = LOWORD(msg.lParam); - WORD b = HIWORD(msg.lParam); - QSize oldSize = size(); - QSize newSize(a, b); -#ifdef Q_WS_WINCE_WM - if (isFullScreen() && (oldSize.width() == newSize.height()) && (oldSize.height() == newSize.width())) - qt_wince_hide_taskbar(internalWinId()); -#endif - cr.setSize(newSize); - if (msg.wParam != SIZE_MINIMIZED) - data->crect = cr; - if (isWindow()) { // update title/icon text - d_func()->createTLExtra(); - // Capture SIZE_MINIMIZED without preceding WM_SYSCOMMAND - // (like Windows+M) - if (msg.wParam == SIZE_MINIMIZED && !isMinimized()) { -#ifndef Q_WS_WINCE - const QString title = windowIconText(); - if (!title.isEmpty()) - d_func()->setWindowTitle_helper(title); -#endif - data->window_state |= Qt::WindowMinimized; - if (isVisible()) { - QHideEvent e; - QApplication::sendSpontaneousEvent(this, &e); - hideChildren(true); - } - } else if (msg.wParam != SIZE_MINIMIZED) { - bool window_state_changed = false; - Qt::WindowStates oldstate = Qt::WindowStates(dataPtr()->window_state); - if (isMinimized()) { -#ifndef Q_WS_WINCE - const QString title = windowTitle(); - if (!title.isEmpty()) - d_func()->setWindowTitle_helper(title); -#endif - data->window_state &= ~Qt::WindowMinimized; - showChildren(true); - QShowEvent e; - QApplication::sendSpontaneousEvent(this, &e); - // Capture SIZE_MAXIMIZED and SIZE_RESTORED without preceding WM_SYSCOMMAND - // (Aero Snap on Win7) - } else if (msg.wParam == SIZE_MAXIMIZED && !isMaximized()) { - data->window_state |= Qt::WindowMaximized; - window_state_changed = true; - } else if (msg.wParam == SIZE_RESTORED && isMaximized()) { - data->window_state &= ~(Qt::WindowMaximized); - window_state_changed = true; - } - if (window_state_changed) { - QWindowStateChangeEvent e(oldstate); - QApplication::sendSpontaneousEvent(this, &e); - } - } - } - if (msg.wParam != SIZE_MINIMIZED && oldSize != newSize) { - if (isVisible()) { - QTLWExtra *tlwExtra = maybeTopData(); - static bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt(); - const bool hasStaticContents = tlwExtra && tlwExtra->backingStore - && tlwExtra->backingStore->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 (!slowResize && tlwExtra && !hasStaticContents) - tlwExtra->inTopLevelResize = true; - QResizeEvent e(newSize, oldSize); - QApplication::sendSpontaneousEvent(this, &e); - if (d_func()->paintOnScreen()) { - QRegion updateRegion(rect()); - if (testAttribute(Qt::WA_StaticContents)) - updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); - d_func()->syncBackingStore(updateRegion); - } else { - d_func()->syncBackingStore(); - } - if (!slowResize && tlwExtra) - tlwExtra->inTopLevelResize = false; - } else { - QResizeEvent *e = new QResizeEvent(newSize, oldSize); - QApplication::postEvent(this, e); - } - } - } else if (msg.message == WM_MOVE) { // move event - int a = (int) (short) LOWORD(msg.lParam); - int b = (int) (short) HIWORD(msg.lParam); - QPoint oldPos = geometry().topLeft(); - QPoint newCPos(a, b); - // Ignore silly Windows move event to wild pos after iconify. -#if !defined(Q_WS_WINCE) - if (!IsIconic(internalWinId()) && newCPos != oldPos) { -#endif - cr.moveTopLeft(newCPos); - data->crect = cr; - if (isVisible()) { - QMoveEvent e(newCPos, oldPos); // cpos (client position) - QApplication::sendSpontaneousEvent(this, &e); - } else { - QMoveEvent * e = new QMoveEvent(newCPos, oldPos); - QApplication::postEvent(this, e); - } -#if !defined(Q_WS_WINCE) - } -#endif - } - setAttribute(Qt::WA_WState_ConfigPending, false); // clear config flag - return true; -} - - -// -// Close window event translation. -// -// This class is a friend of QApplication because it needs to emit the -// lastWindowClosed() signal when the last top level widget is closed. -// - -bool QETWidget::translateCloseEvent(const MSG &) -{ - return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); -} - -#ifndef QT_NO_GESTURES -bool QETWidget::translateGestureEvent(const MSG &, const GESTUREINFO &gi) -{ - const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); - QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); - if (alienWidget && alienWidget->internalWinId()) - alienWidget = 0; - QWidget *widget = alienWidget ? alienWidget : this; - - QNativeGestureEvent event; - event.sequenceId = gi.dwSequenceID; - event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); - event.argument = gi.ullArguments; - - switch (gi.dwID) { - case GID_BEGIN: - event.gestureType = QNativeGestureEvent::GestureBegin; - break; - case GID_END: - event.gestureType = QNativeGestureEvent::GestureEnd; - break; - case GID_ZOOM: - event.gestureType = QNativeGestureEvent::Zoom; - break; - case GID_PAN: - event.gestureType = QNativeGestureEvent::Pan; - break; - case GID_ROTATE: - event.gestureType = QNativeGestureEvent::Rotate; - break; - case GID_TWOFINGERTAP: - case GID_ROLLOVER: - default: - break; - } - if (event.gestureType != QNativeGestureEvent::None) - qt_sendSpontaneousEvent(widget, &event); - return true; -} -#endif // QT_NO_GESTURES - -void QApplication::setCursorFlashTime(int msecs) -{ - SetCaretBlinkTime(msecs / 2); - QApplicationPrivate::cursor_flash_time = msecs; -} - - -int QApplication::cursorFlashTime() -{ - int blink = (int)GetCaretBlinkTime(); - if (!blink) - return QApplicationPrivate::cursor_flash_time; - if (blink > 0) - return 2*blink; - return 0; -} - - -void QApplication::setDoubleClickInterval(int ms) -{ -#ifndef Q_WS_WINCE - SetDoubleClickTime(ms); -#endif - QApplicationPrivate::mouse_double_click_time = ms; -} - -int QApplication::doubleClickInterval() -{ - int ms = GetDoubleClickTime(); - if (ms != 0) - return ms; - return QApplicationPrivate::mouse_double_click_time; -} - - -void QApplication::setKeyboardInputInterval(int ms) -{ - QApplicationPrivate::keyboard_input_time = ms; -} - -int QApplication::keyboardInputInterval() -{ - // FIXME: get from the system - return QApplicationPrivate::keyboard_input_time; -} - -#ifndef QT_NO_WHEELEVENT -void QApplication::setWheelScrollLines(int n) -{ -#ifdef SPI_SETWHEELSCROLLLINES - if (n < 0) - n = 0; - SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); -#else - QApplicationPrivate::wheel_scroll_lines = n; -#endif -} - -int QApplication::wheelScrollLines() -{ -#ifdef SPI_GETWHEELSCROLLLINES - uint i = 3; - SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); - if (i > INT_MAX) - i = INT_MAX; - return i; -#else - return QApplicationPrivate::wheel_scroll_lines; -#endif -} -#endif //QT_NO_WHEELEVENT - -static bool effect_override = false; - -void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) -{ - effect_override = true; - switch (effect) { - case Qt::UI_AnimateMenu: - QApplicationPrivate::animate_menu = enable; - break; - case Qt::UI_FadeMenu: - QApplicationPrivate::fade_menu = enable; - break; - case Qt::UI_AnimateCombo: - QApplicationPrivate::animate_combo = enable; - break; - case Qt::UI_AnimateTooltip: - QApplicationPrivate::animate_tooltip = enable; - break; - case Qt::UI_FadeTooltip: - 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) - return false; - - if (!effect_override && desktopSettingsAware()) { - // we know that they can be used when we are here - BOOL enabled = false; - UINT api; - switch (effect) { - case Qt::UI_AnimateMenu: - api = SPI_GETMENUANIMATION; - break; - case Qt::UI_FadeMenu: - api = SPI_GETMENUFADE; - break; - case Qt::UI_AnimateCombo: - api = SPI_GETCOMBOBOXANIMATION; - break; - case Qt::UI_AnimateTooltip: - api = SPI_GETTOOLTIPANIMATION; - break; - case Qt::UI_FadeTooltip: - api = SPI_GETTOOLTIPFADE; - break; - default: - api = SPI_GETUIEFFECTS; - break; - } - SystemParametersInfo(api, 0, &enabled, 0); - return enabled; - } - - 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; - } -} - -#ifndef QT_NO_SESSIONMANAGER - -bool QSessionManager::allowsInteraction() -{ - sm_blockUserInput = false; - return true; -} - -bool QSessionManager::allowsErrorInteraction() -{ - sm_blockUserInput = false; - return true; -} - -void QSessionManager::release() -{ - if (sm_smActive) - sm_blockUserInput = true; -} - -void QSessionManager::cancel() -{ - sm_cancel = true; -} - -#endif //QT_NO_SESSIONMANAGER - - -bool QApplicationPrivate::HasTouchSupport = false; -PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0; -PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0; -PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0; - -void QApplicationPrivate::initializeMultitouch_sys() -{ - if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { - static const int QT_SM_DIGITIZER = 94; - int value = GetSystemMetrics(QT_SM_DIGITIZER); - static const int QT_NID_INTEGRATED_TOUCH = 0x01; - static const int QT_NID_EXTERNAL_TOUCH = 0x02; - static const int QT_NID_MULTI_INPUT = 0x40; - QApplicationPrivate::HasTouchSupport = - value & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH | QT_NID_MULTI_INPUT); - } - - QSystemLibrary library(QLatin1String("user32")); - // MinGW (g++ 3.4.5) accepts only C casts. - RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow")); - GetTouchInputInfo = (PtrGetTouchInputInfo)(library.resolve("GetTouchInputInfo")); - CloseTouchInputHandle = (PtrCloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); - - touchInputIDToTouchPointID.clear(); -} - -void QApplicationPrivate::cleanupMultitouch_sys() -{ - touchInputIDToTouchPointID.clear(); -} - -bool QApplicationPrivate::translateTouchEvent(const MSG &msg) -{ - QWidget *widgetForHwnd = QWidget::find(msg.hwnd); - if (!widgetForHwnd) - return false; - - QRect screenGeometry = QApplication::desktop()->screenGeometry(widgetForHwnd); - - QList touchPoints; - - QVector winTouchInputs(msg.wParam); - memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); - Qt::TouchPointStates allStates = 0; - QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); - for (int i = 0; i < winTouchInputs.count(); ++i) { - const TOUCHINPUT &touchInput = winTouchInputs.at(i); - - int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1); - if (touchPointID == -1) { - touchPointID = touchInputIDToTouchPointID.count(); - touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID); - } - - QTouchEvent::TouchPoint touchPoint(touchPointID); - - // update state - QPointF screenPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); - QRectF screenRect; - if (touchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA) - screenRect.setSize(QSizeF(qreal(touchInput.cxContact) / qreal(100.), - qreal(touchInput.cyContact) / qreal(100.))); - screenRect.moveCenter(screenPos); - - Qt::TouchPointStates state; - if (touchInput.dwFlags & TOUCHEVENTF_DOWN) { - state = Qt::TouchPointPressed; - } else if (touchInput.dwFlags & TOUCHEVENTF_UP) { - state = Qt::TouchPointReleased; - } else { - state = (screenPos == touchPoint.screenPos() - ? Qt::TouchPointStationary - : Qt::TouchPointMoved); - } - if (touchInput.dwFlags & TOUCHEVENTF_PRIMARY) - state |= Qt::TouchPointPrimary; - touchPoint.setState(state); - touchPoint.setScreenRect(screenRect); - touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(), - screenPos.y() / screenGeometry.height())); - - allStates |= state; - - touchPoints.append(touchPoint); - } - QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); - - if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) { - // all touch points released, forget the ids we've seen, they may not be reused - touchInputIDToTouchPointID.clear(); - } - - translateRawTouchEvent(widgetForHwnd, QTouchEvent::TouchScreen, touchPoints); - return true; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qclipboard_win.cpp b/src/widgets/platforms/win/qclipboard_win.cpp deleted file mode 100644 index 841eea1e34..0000000000 --- a/src/widgets/platforms/win/qclipboard_win.cpp +++ /dev/null @@ -1,398 +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 "qclipboard.h" - -#ifndef QT_NO_CLIPBOARD - -#include "qapplication.h" -#include "qapplication_p.h" -#include "qeventloop.h" -#include "qwidget.h" -#include "qevent.h" -#include "qmime.h" -#include "qt_windows.h" -#include "qdnd_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -#if defined(Q_OS_WINCE) -QT_BEGIN_INCLUDE_NAMESPACE -#include "qguifunctions_wince.h" -QT_END_INCLUDE_NAMESPACE - -HRESULT QtCeGetClipboard(IDataObject** obj); -HRESULT QtCeSetClipboard(IDataObject* obj); -void QtCeFlushClipboard(); - -#define OleGetClipboard QtCeGetClipboard -#define OleSetClipboard QtCeSetClipboard -#define OleFlushClipboard QtCeFlushClipboard - -#endif - -typedef BOOL (WINAPI *PtrIsHungAppWindow)(HWND); - -static PtrIsHungAppWindow ptrIsHungAppWindow = 0; - -class QClipboardWatcher : public QInternalMimeData { -public: - QClipboardWatcher() - : QInternalMimeData() - { - } - - bool hasFormat_sys(const QString &mimetype) const; - QStringList formats_sys() const; - QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const; -}; - - -bool QClipboardWatcher::hasFormat_sys(const QString &mime) const -{ - IDataObject * pDataObj = 0; - - if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity - return false; - - bool has = QWindowsMime::converterToMime(mime, pDataObj) != 0; - - pDataObj->Release(); - - return has; -} - -QStringList QClipboardWatcher::formats_sys() const -{ - QStringList fmts; - IDataObject * pDataObj = 0; - - if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity - return QStringList(); - - fmts = QWindowsMime::allMimesForFormats(pDataObj); - - pDataObj->Release(); - - return fmts; -} - -QVariant QClipboardWatcher::retrieveData_sys(const QString &mimeType, QVariant::Type type) const -{ - QVariant result; - IDataObject * pDataObj = 0; - - if (OleGetClipboard(&pDataObj) != S_OK && !pDataObj) // Sanity - return result; - - QWindowsMime *converter = QWindowsMime::converterToMime(mimeType, pDataObj); - - if (converter) - result = converter->convertToMime(mimeType, pDataObj, type); - - pDataObj->Release(); - - return result; -} - -class QClipboardData -{ -public: - QClipboardData() - : iData(0) - , nextClipboardViewer(0) - { - clipBoardViewer = new QWidget(); - clipBoardViewer->createWinId(); - clipBoardViewer->setObjectName(QLatin1String("internal clipboard owner")); - // We don't need this internal widget to appear in QApplication::topLevelWidgets() - if (QWidgetPrivate::allWidgets) - QWidgetPrivate::allWidgets->remove(clipBoardViewer); - } - - ~QClipboardData() - { - Q_ASSERT(clipBoardViewer->testAttribute(Qt::WA_WState_Created)); - ChangeClipboardChain(clipBoardViewer->internalWinId(), nextClipboardViewer); - delete clipBoardViewer; - releaseIData(); - } - - void releaseIData() - { - if (iData) { - delete iData->mimeData(); - iData->releaseQt(); - iData->Release(); - iData = 0; - } - } - - QOleDataObject * iData; - QWidget *clipBoardViewer; - HWND nextClipboardViewer; - QClipboardWatcher watcher; -}; - -static QClipboardData *ptrClipboardData = 0; - -static QClipboardData *clipboardData() -{ - if (ptrClipboardData == 0) { - ptrClipboardData = new QClipboardData; - // this needs to be done here to avoid recursion - Q_ASSERT(ptrClipboardData->clipBoardViewer->testAttribute(Qt::WA_WState_Created)); - ptrClipboardData->nextClipboardViewer = SetClipboardViewer(ptrClipboardData->clipBoardViewer->internalWinId()); - } - return ptrClipboardData; -} - -static void cleanupClipboardData() -{ - delete ptrClipboardData; - ptrClipboardData = 0; -} - -#if defined(Q_OS_WINCE) -HRESULT QtCeGetClipboard(IDataObject** obj) -{ - HWND owner = ptrClipboardData->clipBoardViewer->internalWinId(); - if (!OpenClipboard(owner)) - return !S_OK; - - if (!IsClipboardFormatAvailable(CF_TEXT) && !IsClipboardFormatAvailable(CF_UNICODETEXT)) - return !S_OK; - - HANDLE clipData = GetClipboardData(CF_TEXT); - QString clipText; - if (clipData == 0) { - clipData = GetClipboardData(CF_UNICODETEXT); - if (clipData != 0) - clipText = QString::fromWCharArray((wchar_t *)clipData); - } else { - clipText = QString::fromLatin1((const char*)clipData); - } - - QMimeData *mimeData = new QMimeData(); - mimeData->setText(clipText); - QOleDataObject* data = new QOleDataObject(mimeData); - *obj = data; - CloseClipboard(); - return S_OK; -} - -HRESULT QtCeSetClipboard(IDataObject* obj) -{ - HWND owner = ptrClipboardData->clipBoardViewer->internalWinId(); - if (!OpenClipboard(owner)) - return !S_OK; - - bool result = false; - if (obj == 0) { - result = true; - EmptyClipboard(); - CloseClipboard(); - } else { - QOleDataObject* qobj = static_cast(obj); - - const QMimeData* data = qobj->mimeData(); - if (data->hasText()) { - EmptyClipboard(); - result = SetClipboardData(CF_UNICODETEXT, wcsdup(reinterpret_cast (data->text().utf16()))) != NULL; - CloseClipboard(); - result = true; - } - } - return result ? S_OK : !S_OK; -} - -void QtCeFlushClipboard() { } -#endif - - - -QClipboard::~QClipboard() -{ - cleanupClipboardData(); -} - -void QClipboard::setMimeData(QMimeData *src, Mode mode) -{ - if (mode != Clipboard) - return; - QClipboardData *d = clipboardData(); - - if (!(d->iData && d->iData->mimeData() == src)) { - d->releaseIData(); - d->iData = new QOleDataObject(src); - } - - if (OleSetClipboard(d->iData) != S_OK) { - d->releaseIData(); - qErrnoWarning("QClipboard::setMimeData: Failed to set data on clipboard"); - return; - } -#if defined(Q_OS_WINCE) - // As WinCE does not support notifications we send the signal here - // We will get no event when the clipboard changes outside... - emit dataChanged(); - emit changed(Clipboard); -#endif -} - -void QClipboard::clear(Mode mode) -{ - if (mode != Clipboard) return; - - QClipboardData *d = clipboardData(); - - d->releaseIData(); - - if (OleSetClipboard(0) != S_OK) { - qErrnoWarning("QClipboard::clear: Failed to clear data on clipboard"); - return; - } -#if defined(Q_OS_WINCE) - // As WinCE does not support notifications we send the signal here - // We will get no event when the clipboard changes outside... - emit dataChanged(); - emit changed(Clipboard); -#endif -} - -bool QClipboard::event(QEvent *e) -{ - if (e->type() != QEvent::Clipboard) - return QObject::event(e); - - QClipboardData *d = clipboardData(); - - MSG *m = (MSG *)((QClipboardEvent*)e)->data(); - if (!m) { - // this is sent to render all formats at app shut down - if (ownsClipboard()) { - OleFlushClipboard(); - d->releaseIData(); - } - return true; - } - - bool propagate = false; - - if (m->message == WM_CHANGECBCHAIN) { - if ((HWND)m->wParam == d->nextClipboardViewer) - d->nextClipboardViewer = (HWND)m->lParam; - else - propagate = true; - } else if (m->message == WM_DRAWCLIPBOARD) { - emitChanged(QClipboard::Clipboard); - if (!ownsClipboard() && d->iData) - // clean up the clipboard object if we no longer own the clipboard - d->releaseIData(); - propagate = true; - } - if (propagate && d->nextClipboardViewer) { - if (ptrIsHungAppWindow == 0) { - QSystemLibrary library(QLatin1String("User32")); - ptrIsHungAppWindow = (PtrIsHungAppWindow)library.resolve("IsHungAppWindow"); - } - if (ptrIsHungAppWindow && ptrIsHungAppWindow(d->nextClipboardViewer)) { - qWarning("%s: Cowardly refusing to send clipboard message to hung application...", Q_FUNC_INFO); - } else { - SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); - } - } - - return true; -} - -void QClipboard::connectNotify(const char *signal) -{ - if (qstrcmp(signal,SIGNAL(dataChanged())) == 0) { - // ensure we are up and running but block signals so the dataChange signal - // is not emitted while being connected to. - bool blocked = blockSignals(true); - QClipboardData *d = clipboardData(); - blockSignals(blocked); - Q_UNUSED(d); - } -} - -const QMimeData *QClipboard::mimeData(Mode mode) const -{ - if (mode != Clipboard) - return 0; - - QClipboardData *data = clipboardData(); - // sort cut for local copy / paste - if (ownsClipboard() && data->iData->mimeData()) - return data->iData->mimeData(); - return &data->watcher; -} - -bool QClipboard::supportsMode(Mode mode) const -{ - return (mode == Clipboard); -} - -bool QClipboard::ownsMode(Mode mode) const -{ - if (mode == Clipboard) { - QClipboardData *d = clipboardData(); -#if !defined(Q_OS_WINCE) - return d->iData && OleIsCurrentClipboard(d->iData) == S_OK; -#else - return d->iData && GetClipboardOwner() == d->clipBoardViewer->internalWinId(); -#endif - } else { - return false; - } -} - -void QClipboard::ownerDestroyed() -{ -} - -QT_END_NAMESPACE - -#endif // QT_NO_CLIPBOARD diff --git a/src/widgets/platforms/win/qcolormap_win.cpp b/src/widgets/platforms/win/qcolormap_win.cpp deleted file mode 100644 index 4a95977438..0000000000 --- a/src/widgets/platforms/win/qcolormap_win.cpp +++ /dev/null @@ -1,201 +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 "qcolor.h" -#include "qcolormap.h" -#include "qvector.h" -#include "qt_windows.h" - -#if defined(Q_WS_WINCE) -#include "qguifunctions_wince.h" -#endif - -QT_BEGIN_NAMESPACE - -class QColormapPrivate -{ -public: - inline QColormapPrivate() - : ref(1), mode(QColormap::Direct), depth(0), hpal(0) - { } - - QAtomicInt ref; - - QColormap::Mode mode; - int depth; - int numcolors; - - HPALETTE hpal; - QVector palette; -}; - -static QColormapPrivate *screenMap = 0; - -void QColormap::initialize() -{ - HDC dc = qt_win_display_dc(); - - screenMap = new QColormapPrivate; - screenMap->depth = GetDeviceCaps(dc, BITSPIXEL); - - screenMap->numcolors = -1; - if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) - screenMap->numcolors = GetDeviceCaps(dc, SIZEPALETTE); - - if (screenMap->numcolors <= 16 || screenMap->numcolors > 256) // no need to create palette - return; - - LOGPALETTE* pal = 0; - int numPalEntries = 6*6*6; // color cube - - pal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + numPalEntries * sizeof(PALETTEENTRY)); - // Make 6x6x6 color cube - int idx = 0; - for(int ir = 0x0; ir <= 0xff; ir+=0x33) { - for(int ig = 0x0; ig <= 0xff; ig+=0x33) { - for(int ib = 0x0; ib <= 0xff; ib+=0x33) { - pal->palPalEntry[idx].peRed = ir; - pal->palPalEntry[idx].peGreen = ig; - pal->palPalEntry[idx].peBlue = ib; - pal->palPalEntry[idx].peFlags = 0; - idx++; - } - } - } - - pal->palVersion = 0x300; - pal->palNumEntries = numPalEntries; - - screenMap->hpal = CreatePalette(pal); - if (!screenMap->hpal) - qErrnoWarning("QColor::initialize: Failed to create logical palette"); - free (pal); - - SelectPalette(dc, screenMap->hpal, FALSE); - RealizePalette(dc); - - PALETTEENTRY paletteEntries[256]; - screenMap->numcolors = GetPaletteEntries(screenMap->hpal, 0, 255, paletteEntries); - - screenMap->palette.resize(screenMap->numcolors); - for (int i = 0; i < screenMap->numcolors; i++) { - screenMap->palette[i] = qRgb(paletteEntries[i].peRed, - paletteEntries[i].peGreen, - paletteEntries[i].peBlue); - } -} - -void QColormap::cleanup() -{ - if (!screenMap) - return; - - if (screenMap->hpal) { // delete application global - DeleteObject(screenMap->hpal); // palette - screenMap->hpal = 0; - } - - delete screenMap; - screenMap = 0; -} - -QColormap QColormap::instance(int) -{ - Q_ASSERT_X(screenMap, "QColormap", - "A QApplication object needs to be constructed before QColormap is used."); - return QColormap(); -} - -QColormap::QColormap() - : d(screenMap) -{ d->ref.ref(); } - -QColormap::QColormap(const QColormap &colormap) - :d (colormap.d) -{ d->ref.ref(); } - -QColormap::~QColormap() -{ - if (!d->ref.deref()) - delete d; -} - -QColormap::Mode QColormap::mode() const -{ return d->mode; } - -int QColormap::depth() const -{ return d->depth; } - -int QColormap::size() const -{ return d->numcolors; } - -uint QColormap::pixel(const QColor &color) const -{ - const QColor c = color.toRgb(); - COLORREF rgb = RGB(c.red(), c.green(), c.blue()); - if (d->hpal) - return PALETTEINDEX(GetNearestPaletteIndex(d->hpal, rgb)); - return rgb; -} - -const QColor QColormap::colorAt(uint pixel) const -{ - if (d->hpal) { - if (pixel < uint(d->numcolors)) - return d->palette.at(pixel); - return QColor(); - } - return QColor(GetRValue(pixel), GetGValue(pixel), GetBValue(pixel)); -} - - -HPALETTE QColormap::hPal() -{ return screenMap ? screenMap->hpal : 0; } - - -const QVector QColormap::colormap() const -{ return d->palette; } - -QColormap &QColormap::operator=(const QColormap &colormap) -{ qAtomicAssign(d, colormap.d); return *this; } - - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qcursor_win.cpp b/src/widgets/platforms/win/qcursor_win.cpp deleted file mode 100644 index cef83f5a1b..0000000000 --- a/src/widgets/platforms/win/qcursor_win.cpp +++ /dev/null @@ -1,493 +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 -#include -#include - -#ifndef QT_NO_CURSOR - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - Internal QCursorData class - *****************************************************************************/ - -QCursorData::QCursorData(Qt::CursorShape s) - : cshape(s), bm(0), bmm(0), hx(0), hy(0), hcurs(0) -{ - ref = 1; -} - -QCursorData::~QCursorData() -{ - delete bm; - delete bmm; -#if !defined(Q_WS_WINCE) || defined(GWES_ICONCURS) - if (hcurs) - DestroyCursor(hcurs); -#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->bm = new QBitmap(bitmap); - d->bmm = new QBitmap(mask); - d->hcurs = 0; - d->cshape = Qt::BitmapCursor; - d->hx = hotX >= 0 ? hotX : bitmap.width()/2; - d->hy = hotY >= 0 ? hotY : bitmap.height()/2; - return d; -} - -HCURSOR QCursor::handle() const -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (!d->hcurs) - d->update(); - return d->hcurs; -} - -QCursor::QCursor(HCURSOR handle) -{ - d = new QCursorData(Qt::CustomCursor); - d->hcurs = handle; -} - -#endif //QT_NO_CURSOR - -QPoint QCursor::pos() -{ - POINT p; - GetCursorPos(&p); - return QPoint(p.x, p.y); -} - -void QCursor::setPos(int x, int y) -{ - SetCursorPos(x, y); -} - -#ifndef QT_NO_CURSOR - -extern HBITMAP qt_createIconMask(const QBitmap &bitmap); - -static HCURSOR create32BitCursor(const QPixmap &pixmap, int hx, int hy) -{ - HCURSOR cur = 0; -#if !defined(Q_WS_WINCE) - QBitmap mask = pixmap.mask(); - if (mask.isNull()) { - mask = QBitmap(pixmap.size()); - mask.fill(Qt::color1); - } - - HBITMAP ic = pixmap.toWinHBITMAP(QPixmap::Alpha); - HBITMAP im = qt_createIconMask(mask); - - ICONINFO ii; - ii.fIcon = 0; - ii.xHotspot = hx; - ii.yHotspot = hy; - ii.hbmMask = im; - ii.hbmColor = ic; - - cur = CreateIconIndirect(&ii); - - DeleteObject(ic); - DeleteObject(im); -#elif defined(GWES_ICONCURS) - QImage bbits, mbits; - bool invb, invm; - bbits = pixmap.toImage().convertToFormat(QImage::Format_Mono); - mbits = pixmap.toImage().convertToFormat(QImage::Format_Mono); - invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); - invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); - - int sysW = GetSystemMetrics(SM_CXCURSOR); - int sysH = GetSystemMetrics(SM_CYCURSOR); - int sysN = qMax(1, sysW / 8); - int n = qMax(1, bbits.width() / 8); - int h = bbits.height(); - - uchar* xBits = new uchar[sysH * sysN]; - uchar* xMask = new uchar[sysH * sysN]; - int x = 0; - for (int i = 0; i < sysH; ++i) { - if (i >= h) { - memset(&xBits[x] , 255, sysN); - memset(&xMask[x] , 0, sysN); - x += sysN; - } else { - int fillWidth = n > sysN ? sysN : n; - uchar *bits = bbits.scanLine(i); - uchar *mask = mbits.scanLine(i); - for (int j = 0; j < fillWidth; ++j) { - uchar b = bits[j]; - uchar m = mask[j]; - if (invb) - b ^= 0xFF; - if (invm) - m ^= 0xFF; - xBits[x] = ~m; - xMask[x] = b ^ m; - ++x; - } - for (int j = fillWidth; j < sysN; ++j ) { - xBits[x] = 255; - xMask[x] = 0; - ++x; - } - } - } - - cur = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH, - xBits, xMask); -#else - Q_UNUSED(pixmap); - Q_UNUSED(hx); - Q_UNUSED(hy); -#endif - return cur; -} - -void QCursorData::update() -{ - if (!QCursorData::initialized) - QCursorData::initialize(); - if (hcurs) - return; - - if (cshape == Qt::BitmapCursor && !pixmap.isNull()) { - hcurs = create32BitCursor(pixmap, hx, hy); - if (hcurs) - return; - } - - - // Non-standard Windows cursors are created from bitmaps - - 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 phand_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, - 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, - 0x80, 0x1c, 0x00, 0x00, 0x80, 0xe4, 0x00, 0x00, 0x80, 0x24, 0x03, 0x00, - 0x80, 0x24, 0x05, 0x00, 0xb8, 0x24, 0x09, 0x00, 0xc8, 0x00, 0x09, 0x00, - 0x88, 0x00, 0x08, 0x00, 0x90, 0x00, 0x08, 0x00, 0xa0, 0x00, 0x08, 0x00, - 0x20, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x04, 0x00, - 0x80, 0x00, 0x04, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x01, 0x02, 0x00, - 0x00, 0x01, 0x02, 0x00, 0x00, 0xff, 0x03, 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 phandm_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, - 0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, - 0x80, 0x1f, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x80, 0xff, 0x03, 0x00, - 0x80, 0xff, 0x07, 0x00, 0xb8, 0xff, 0x0f, 0x00, 0xf8, 0xff, 0x0f, 0x00, - 0xf8, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xe0, 0xff, 0x0f, 0x00, - 0xe0, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x07, 0x00, - 0x80, 0xff, 0x07, 0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0xff, 0x03, 0x00, - 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x03, 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 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_bits32[] = { - vsplit_bits, vsplitm_bits, hsplit_bits, hsplitm_bits, - phand_bits, phandm_bits - }; - - wchar_t *sh = 0; - switch (cshape) { // map to windows cursor - case Qt::ArrowCursor: - sh = IDC_ARROW; - break; - case Qt::UpArrowCursor: - sh = IDC_UPARROW; - break; - case Qt::CrossCursor: - sh = IDC_CROSS; - break; - case Qt::WaitCursor: - sh = IDC_WAIT; - break; - case Qt::IBeamCursor: - sh = IDC_IBEAM; - break; - case Qt::SizeVerCursor: - sh = IDC_SIZENS; - break; - case Qt::SizeHorCursor: - sh = IDC_SIZEWE; - break; - case Qt::SizeBDiagCursor: - sh = IDC_SIZENESW; - break; - case Qt::SizeFDiagCursor: - sh = IDC_SIZENWSE; - break; - case Qt::SizeAllCursor: - sh = IDC_SIZEALL; - break; - case Qt::ForbiddenCursor: - sh = IDC_NO; - break; - case Qt::WhatsThisCursor: - sh = IDC_HELP; - break; - case Qt::BusyCursor: - sh = IDC_APPSTARTING; - break; - case Qt::PointingHandCursor: - sh = IDC_HAND; - break; - case Qt::BlankCursor: - case Qt::SplitVCursor: - case Qt::SplitHCursor: - case Qt::OpenHandCursor: - case Qt::ClosedHandCursor: - case Qt::BitmapCursor: { - QImage bbits, mbits; - bool invb, invm; - if (cshape == Qt::BlankCursor) { - bbits = QImage(32, 32, QImage::Format_Mono); - bbits.fill(0); // ignore color table - mbits = bbits.copy(); - hx = hy = 16; - invb = invm = false; - } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) { - bool open = cshape == Qt::OpenHandCursor; - QBitmap cb = QBitmap::fromData(QSize(16, 16), open ? openhand_bits : closedhand_bits); - QBitmap cm = QBitmap::fromData(QSize(16, 16), open ? openhandm_bits : closedhandm_bits); - bbits = cb.toImage().convertToFormat(QImage::Format_Mono); - mbits = cm.toImage().convertToFormat(QImage::Format_Mono); - hx = hy = 8; - invb = invm = false; - } else if (cshape != Qt::BitmapCursor) { - int i = cshape - Qt::SplitVCursor; - QBitmap cb = QBitmap::fromData(QSize(32, 32), cursor_bits32[i * 2]); - QBitmap cm = QBitmap::fromData(QSize(32, 32), cursor_bits32[i * 2 + 1]); - bbits = cb.toImage().convertToFormat(QImage::Format_Mono); - mbits = cm.toImage().convertToFormat(QImage::Format_Mono); - if (cshape == Qt::PointingHandCursor) { - hx = 7; - hy = 0; - } else - hx = hy = 16; - invb = invm = false; - } else { - bbits = bm->toImage().convertToFormat(QImage::Format_Mono); - mbits = bmm->toImage().convertToFormat(QImage::Format_Mono); - invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); - invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); - } - int n = qMax(1, bbits.width() / 8); - int h = bbits.height(); -#if !defined(Q_WS_WINCE) - uchar* xBits = new uchar[h * n]; - uchar* xMask = new uchar[h * n]; - int x = 0; - for (int i = 0; i < h; ++i) { - uchar *bits = bbits.scanLine(i); - uchar *mask = mbits.scanLine(i); - for (int j = 0; j < n; ++j) { - uchar b = bits[j]; - uchar m = mask[j]; - if (invb) - b ^= 0xff; - if (invm) - m ^= 0xff; - xBits[x] = ~m; - xMask[x] = b ^ m; - ++x; - } - } - hcurs = CreateCursor(qWinAppInst(), hx, hy, bbits.width(), bbits.height(), - xBits, xMask); - delete [] xBits; - delete [] xMask; -#elif defined(GWES_ICONCURS) // Q_WS_WINCE - // Windows CE only supports fixed cursor size. - int sysW = GetSystemMetrics(SM_CXCURSOR); - int sysH = GetSystemMetrics(SM_CYCURSOR); - int sysN = qMax(1, sysW / 8); - uchar* xBits = new uchar[sysH * sysN]; - uchar* xMask = new uchar[sysH * sysN]; - int x = 0; - for (int i = 0; i < sysH; ++i) { - if (i >= h) { - memset(&xBits[x] , 255, sysN); - memset(&xMask[x] , 0, sysN); - x += sysN; - } else { - int fillWidth = n > sysN ? sysN : n; - uchar *bits = bbits.scanLine(i); - uchar *mask = mbits.scanLine(i); - for (int j = 0; j < fillWidth; ++j) { - uchar b = bits[j]; - uchar m = mask[j]; - if (invb) - b ^= 0xFF; - if (invm) - m ^= 0xFF; - xBits[x] = ~m; - xMask[x] = b ^ m; - ++x; - } - for (int j = fillWidth; j < sysN; ++j ) { - xBits[x] = 255; - xMask[x] = 0; - ++x; - } - } - } - - hcurs = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH, - xBits, xMask); - delete [] xBits; - delete [] xMask; -#else - Q_UNUSED(n); - Q_UNUSED(h); -#endif - return; - } - case Qt::DragCopyCursor: - case Qt::DragMoveCursor: - case Qt::DragLinkCursor: { - QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape); - hcurs = create32BitCursor(pixmap, hx, hy); - } - break; - default: - qWarning("QCursor::update: Invalid cursor shape %d", cshape); - return; - } -#ifdef Q_WS_WINCE - hcurs = LoadCursor(0, sh); -#else - hcurs = (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); -#endif -} - -QT_END_NAMESPACE -#endif // QT_NO_CURSOR diff --git a/src/widgets/platforms/win/qdesktopwidget_win.cpp b/src/widgets/platforms/win/qdesktopwidget_win.cpp deleted file mode 100644 index f77cc1f847..0000000000 --- a/src/widgets/platforms/win/qdesktopwidget_win.cpp +++ /dev/null @@ -1,387 +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 "qdesktopwidget.h" -#include "qt_windows.h" -#include "qapplication_p.h" -#include -#include -#include -#ifdef Q_WS_WINCE -#include -#endif -#include "qwidget_p.h" -#include "qdebug.h" - -QT_BEGIN_NAMESPACE - -class QDesktopWidgetPrivate : public QWidgetPrivate -{ -public: - QDesktopWidgetPrivate(); - ~QDesktopWidgetPrivate(); - - static void init(QDesktopWidget *that); - static void cleanup(); - static int screenCount; - static int primaryScreen; - - static QVector *rects; - static QVector *workrects; - - struct MONITORINFO - { - DWORD cbSize; - RECT rcMonitor; - RECT rcWork; - DWORD dwFlags; - }; - - typedef BOOL (WINAPI *InfoFunc)(HMONITOR, MONITORINFO*); - typedef BOOL (QT_WIN_CALLBACK *EnumProc)(HMONITOR, HDC, LPRECT, LPARAM); - typedef BOOL (WINAPI *EnumFunc)(HDC, LPCRECT, EnumProc, LPARAM); - - static EnumFunc enumDisplayMonitors; - static InfoFunc getMonitorInfo; - static int refcount; -}; - -int QDesktopWidgetPrivate::screenCount = 1; -int QDesktopWidgetPrivate::primaryScreen = 0; -QDesktopWidgetPrivate::EnumFunc QDesktopWidgetPrivate::enumDisplayMonitors = 0; -QDesktopWidgetPrivate::InfoFunc QDesktopWidgetPrivate::getMonitorInfo = 0; -QVector *QDesktopWidgetPrivate::rects = 0; -QVector *QDesktopWidgetPrivate::workrects = 0; -static int screen_number = 0; -int QDesktopWidgetPrivate::refcount = 0; -#ifdef Q_WS_WINCE_WM -// Use SIP information, if available -// SipGetInfo is not supported by SSDK (no definition!). -static inline void qt_get_sip_info(QRect &rect) -{ - SIPINFO sip; - memset(&sip, 0, sizeof(SIPINFO)); - sip.cbSize = sizeof(SIPINFO); - if (SipGetInfo(&sip)) - rect = QRect(QPoint(sip.rcVisibleDesktop.left, sip.rcVisibleDesktop.top), - QPoint(sip.rcVisibleDesktop.right - 1, sip.rcVisibleDesktop.bottom - 1)); -} -#endif - - -BOOL QT_WIN_CALLBACK enumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM) -{ - QDesktopWidgetPrivate::screenCount++; - QDesktopWidgetPrivate::rects->resize(QDesktopWidgetPrivate::screenCount); - QDesktopWidgetPrivate::workrects->resize(QDesktopWidgetPrivate::screenCount); - // Get the MONITORINFO block - QDesktopWidgetPrivate::MONITORINFO info; - memset(&info, 0, sizeof(QDesktopWidgetPrivate::MONITORINFO)); - info.cbSize = sizeof(QDesktopWidgetPrivate::MONITORINFO); - BOOL res = QDesktopWidgetPrivate::getMonitorInfo(hMonitor, &info); - if (!res) { - (*QDesktopWidgetPrivate::rects)[screen_number] = QRect(); - (*QDesktopWidgetPrivate::workrects)[screen_number] = QRect(); - return true; - } - - // Fill list of rects - RECT r = info.rcMonitor; - QRect qr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1)); - (*QDesktopWidgetPrivate::rects)[screen_number] = qr; - - r = info.rcWork; - qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1)); - (*QDesktopWidgetPrivate::workrects)[screen_number] = qr; - - if (info.dwFlags & 0x00000001) //MONITORINFOF_PRIMARY - QDesktopWidgetPrivate::primaryScreen = screen_number; - - ++screen_number; - // Stop the enumeration if we have them all - return true; -} - -QDesktopWidgetPrivate::QDesktopWidgetPrivate() -{ - ++refcount; -} - -void QDesktopWidgetPrivate::init(QDesktopWidget *that) -{ - if (rects) - return; - - rects = new QVector(); - workrects = new QVector(); - screenCount = 0; - -#ifndef Q_OS_WINCE - QSystemLibrary user32Lib(QLatin1String("user32")); - enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - - if (!enumDisplayMonitors || !getMonitorInfo) { - screenCount = GetSystemMetrics(80); // SM_CMONITORS - rects->resize(screenCount); - for (int i = 0; i < screenCount; ++i) - rects->replace(i, that->rect()); - return; - } - // Calls enumCallback - enumDisplayMonitors(0, 0, enumCallback, 0); - enumDisplayMonitors = 0; - getMonitorInfo = 0; -#else - QSystemLibrary coreLib(QLatin1String("coredll")); - // CE >= 4.0 case - enumDisplayMonitors = (EnumFunc)coreLib.resolve("EnumDisplayMonitors"); - getMonitorInfo = (InfoFunc)coreLib.resolve("GetMonitorInfo"); - - if ((!enumDisplayMonitors || !getMonitorInfo)) { - screenCount = GetSystemMetrics(SM_CMONITORS); - return; - } - - if (!coreLib.isLoaded() || !enumDisplayMonitors || !getMonitorInfo) { - rects->resize(screenCount); - for (int i = 0; i < screenCount; ++i) - (*rects)[i] = that->rect(); - - RECT r; - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1)); - -#if defined(Q_WS_WINCE_WM) - qt_get_sip_info(qr); -#endif - - workrects->resize(screenCount); - for (int j = 0; j < screenCount; ++j) - (*workrects)[j] = qr; - return; - } - - // Calls enumCallback - enumDisplayMonitors(0, 0, enumCallback, 0); - enumDisplayMonitors = 0; - getMonitorInfo = 0; -#endif // Q_WS_WINCE -} - -QDesktopWidgetPrivate::~QDesktopWidgetPrivate() -{ - if (!--refcount) - cleanup(); -} - -void QDesktopWidgetPrivate::cleanup() -{ - screen_number = 0; - screenCount = 1; - primaryScreen = 0; - enumDisplayMonitors = 0; - getMonitorInfo = 0; - delete rects; - rects = 0; - delete workrects; - workrects = 0; -} - -/* - \omit - Function is commented out in header - \fn void *QDesktopWidget::handle(int screen) const - - Returns the window system handle of the display device with the - index \a screen, for low-level access. Using this function is not - portable. - - The return type varies with platform; see qwindowdefs.h for details. - - \sa x11Display(), QPaintDevice::handle() - \endomit -*/ - -QDesktopWidget::QDesktopWidget() - : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) -{ - setObjectName(QLatin1String("desktop")); - QDesktopWidgetPrivate::init(this); -} - -QDesktopWidget::~QDesktopWidget() -{ -} - -bool QDesktopWidget::isVirtualDesktop() const -{ - return true; -} - -int QDesktopWidget::primaryScreen() const -{ - return d_func()->primaryScreen; -} - -int QDesktopWidget::numScreens() const -{ - return d_func()->screenCount; -} - -QWidget *QDesktopWidget::screen(int /* screen */) -{ - // It seems that a Qt::WType_Desktop cannot be moved? - return this; -} - -// -// MSVC 7.10 warns that d (the result of the expanded Q_D macro) as a local variable that is not referenced. -// Therefore, we ignore that warning with the following pragmas -// I've also tried to eliminate the macro, but to no use... -// We pop it further down -#ifdef Q_CC_MSVC -# pragma warning(push) -# pragma warning(disable : 4189) -#endif -const QRect QDesktopWidget::availableGeometry(int screen) const -{ - Q_D(const QDesktopWidget); -#ifdef Q_WS_WINCE_WM - for(int i=0; i < d->workrects->size(); ++i) - qt_get_sip_info((*d->workrects)[i]); -#endif - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; - - return d->workrects->at(screen); -} - -const QRect QDesktopWidget::screenGeometry(int screen) const -{ - const QDesktopWidgetPrivate *d = d_func(); - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; - - return d->rects->at(screen); -} - -int QDesktopWidget::screenNumber(const QWidget *widget) const -{ - Q_D(const QDesktopWidget); - if (!widget) - return d->primaryScreen; - - 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->at(i).intersected(frame); - int size = sect.width() * sect.height(); - if (size > maxSize && sect.width() > 0 && sect.height() > 0) { - maxSize = size; - maxScreen = i; - } - } - - return maxScreen; -} - -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->at(i)); - if (thisDistance < shortestDistance) { - shortestDistance = thisDistance; - closestScreen = i; - } - } - - return closestScreen; -} - -void QDesktopWidget::resizeEvent(QResizeEvent *) -{ - Q_D(QDesktopWidget); - const QVector oldrects(*d->rects); - const QVector oldworkrects(*d->workrects); - int oldscreencount = d->screenCount; - - QDesktopWidgetPrivate::cleanup(); - QDesktopWidgetPrivate::init(this); -#ifdef Q_WS_WINCE_WM - for(int i=0; i < d->workrects->size(); ++i) - qt_get_sip_info((*d->workrects)[i]); -#endif - - for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) { - const QRect oldrect = oldrects[i]; - const QRect newrect = d->rects->at(i); - if (oldrect != newrect) - emit resized(i); - } - - for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) { - const QRect oldrect = oldworkrects[j]; - const QRect newrect = d->workrects->at(j); - if (oldrect != newrect) - emit workAreaResized(j); - } - - if (oldscreencount != d->screenCount) { - emit screenCountChanged(d->screenCount); - } -} - -#ifdef Q_CC_MSVC -# pragma warning(pop) -#endif - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qdnd_win.cpp b/src/widgets/platforms/win/qdnd_win.cpp deleted file mode 100644 index 073937fc45..0000000000 --- a/src/widgets/platforms/win/qdnd_win.cpp +++ /dev/null @@ -1,1027 +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 "qapplication_p.h" -#include "qevent.h" -#include "qpainter.h" -#include "qwidget.h" -#include "qbuffer.h" -#include "qdatastream.h" -#include "qcursor.h" -#include "qt_windows.h" -#include -#ifndef QT_NO_ACCESSIBILITY -#include "qaccessible.h" -#endif -#include "qdnd_p.h" -#include "qdebug.h" - -#if defined(Q_OS_WINCE) -#include "qguifunctions_wince.h" -#endif - -// support for xbuttons -#ifndef MK_XBUTTON1 -#define MK_XBUTTON1 0x0020 -#define MK_XBUTTON2 0x0040 -#endif - -QT_BEGIN_NAMESPACE - -#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD)) - -//--------------------------------------------------------------------- -// QOleDataObject Constructor -//--------------------------------------------------------------------- - -QOleDataObject::QOleDataObject(QMimeData *mimeData) -{ - m_refs = 1; - data = mimeData; - CF_PERFORMEDDROPEFFECT = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); - performedEffect = DROPEFFECT_NONE; -} - -QOleDataObject::~QOleDataObject() -{ -} - -void QOleDataObject::releaseQt() -{ - data = 0; -} - -const QMimeData *QOleDataObject::mimeData() const -{ - return data; -} - -DWORD QOleDataObject::reportedPerformedEffect() const -{ - return performedEffect; -} - -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - -STDMETHODIMP -QOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if (iid == IID_IUnknown || iid == IID_IDataObject) { - *ppv = this; - AddRef(); - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QOleDataObject::AddRef(void) -{ - return ++m_refs; -} - -STDMETHODIMP_(ULONG) -QOleDataObject::Release(void) -{ - if (--m_refs == 0) { - releaseQt(); - delete this; - return 0; - } - return m_refs; -} - -//--------------------------------------------------------------------- -// IDataObject Methods -// -// The following methods are NOT supported for data transfer using the -// clipboard or drag-drop: -// -// IDataObject::SetData -- return E_NOTIMPL -// IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED -// ::DUnadvise -// ::EnumDAdvise -// IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL -// (NOTE: must set pformatetcOut->ptd = NULL) -//--------------------------------------------------------------------- - -STDMETHODIMP -QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) -{ -#ifdef QDND_DEBUG - qDebug("QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)"); -#ifndef Q_OS_WINCE - wchar_t buf[256] = {0}; - GetClipboardFormatName(pformatetc->cfFormat, buf, 255); - qDebug("CF = %d : %s", pformatetc->cfFormat, QString::fromWCharArray(buf)); -#endif -#endif - - if (!data) - return ResultFromScode(DATA_E_FORMATETC); - - QWindowsMime *converter = QWindowsMime::converterFromMime(*pformatetc, data); - - if (converter && converter->convertFromMime(*pformatetc, data, pmedium)) - return ResultFromScode(S_OK); - else - return ResultFromScode(DATA_E_FORMATETC); -} - -STDMETHODIMP -QOleDataObject::GetDataHere(LPFORMATETC, LPSTGMEDIUM) -{ - return ResultFromScode(DATA_E_FORMATETC); -} - -STDMETHODIMP -QOleDataObject::QueryGetData(LPFORMATETC pformatetc) -{ -#ifdef QDND_DEBUG - qDebug("QOleDataObject::QueryGetData(LPFORMATETC pformatetc)"); -#endif - - if (!data) - return ResultFromScode(DATA_E_FORMATETC); - - if (QWindowsMime::converterFromMime(*pformatetc, data)) - return ResultFromScode(S_OK); - return ResultFromScode(S_FALSE); -} - -STDMETHODIMP -QOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut) -{ - pformatetcOut->ptd = NULL; - return ResultFromScode(E_NOTIMPL); -} - -STDMETHODIMP -QOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL fRelease) -{ - if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) { - DWORD * val = (DWORD*)GlobalLock(pMedium->hGlobal); - performedEffect = *val; - GlobalUnlock(pMedium->hGlobal); - if (fRelease) - ReleaseStgMedium(pMedium); - return ResultFromScode(S_OK); - } - return ResultFromScode(E_NOTIMPL); -} - - -STDMETHODIMP -QOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) -{ -#ifdef QDND_DEBUG - qDebug("QOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)"); -#endif - - if (!data) - return ResultFromScode(DATA_E_FORMATETC); - - SCODE sc = S_OK; - - QVector fmtetcs; - if (dwDirection == DATADIR_GET) { - fmtetcs = QWindowsMime::allFormatsForMime(data); - } else { - FORMATETC formatetc; - formatetc.cfFormat = CF_PERFORMEDDROPEFFECT; - formatetc.dwAspect = DVASPECT_CONTENT; - formatetc.lindex = -1; - formatetc.ptd = NULL; - formatetc.tymed = TYMED_HGLOBAL; - fmtetcs.append(formatetc); - } - - QOleEnumFmtEtc *enumFmtEtc = new QOleEnumFmtEtc(fmtetcs); - *ppenumFormatEtc = enumFmtEtc; - if (enumFmtEtc->isNull()) { - delete enumFmtEtc; - *ppenumFormatEtc = NULL; - sc = E_OUTOFMEMORY; - } - - return ResultFromScode(sc); -} - -STDMETHODIMP -QOleDataObject::DAdvise(FORMATETC FAR*, DWORD, - LPADVISESINK, DWORD FAR*) -{ - return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); -} - - -STDMETHODIMP -QOleDataObject::DUnadvise(DWORD) -{ - return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); -} - -STDMETHODIMP -QOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) -{ - return ResultFromScode(OLE_E_ADVISENOTSUPPORTED); -} - -#endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD - -#ifndef QT_NO_DRAGANDDROP - -//#define QDND_DEBUG - -#ifdef QDND_DEBUG -extern QString dragActionsToString(Qt::DropActions actions); -#endif - -Qt::DropActions translateToQDragDropActions(DWORD pdwEffects) -{ - Qt::DropActions actions = Qt::IgnoreAction; - if (pdwEffects & DROPEFFECT_LINK) - actions |= Qt::LinkAction; - if (pdwEffects & DROPEFFECT_COPY) - actions |= Qt::CopyAction; - if (pdwEffects & DROPEFFECT_MOVE) - actions |= Qt::MoveAction; - return actions; -} - -Qt::DropAction translateToQDragDropAction(DWORD pdwEffect) -{ - if (pdwEffect & DROPEFFECT_LINK) - return Qt::LinkAction; - if (pdwEffect & DROPEFFECT_COPY) - return Qt::CopyAction; - if (pdwEffect & DROPEFFECT_MOVE) - return Qt::MoveAction; - return Qt::IgnoreAction; -} - -DWORD translateToWinDragEffects(Qt::DropActions action) -{ - DWORD effect = DROPEFFECT_NONE; - if (action & Qt::LinkAction) - effect |= DROPEFFECT_LINK; - if (action & Qt::CopyAction) - effect |= DROPEFFECT_COPY; - if (action & Qt::MoveAction) - effect |= DROPEFFECT_MOVE; - return effect; -} - -Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState) -{ - Qt::KeyboardModifiers modifiers = Qt::NoModifier; - - if (keyState & MK_SHIFT) - modifiers |= Qt::ShiftModifier; - if (keyState & MK_CONTROL) - modifiers |= Qt::ControlModifier; - if (keyState & MK_ALT) - modifiers |= Qt::AltModifier; - - return modifiers; -} - -Qt::MouseButtons toQtMouseButtons(DWORD keyState) -{ - Qt::MouseButtons buttons = Qt::NoButton; - - if (keyState & MK_LBUTTON) - buttons |= Qt::LeftButton; - if (keyState & MK_RBUTTON) - buttons |= Qt::RightButton; - if (keyState & MK_MBUTTON) - buttons |= Qt::MidButton; - - return buttons; -} - -class QOleDropSource : public IDropSource -{ -public: - QOleDropSource(); - virtual ~QOleDropSource(); - - void createCursors(); - - // IUnknown methods - STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj); - STDMETHOD_(ULONG,AddRef)(void); - STDMETHOD_(ULONG,Release)(void); - - // IDropSource methods - STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState); - STDMETHOD(GiveFeedback)(DWORD dwEffect); - -private: - Qt::MouseButtons currentButtons; - Qt::DropAction currentAction; - QMap cursors; - - ULONG m_refs; -}; - - -QOleDropSource::QOleDropSource() -{ - currentButtons = Qt::NoButton; - m_refs = 1; - currentAction = Qt::IgnoreAction; -} - -QOleDropSource::~QOleDropSource() -{ -} - -void QOleDropSource::createCursors() -{ - QDragManager *manager = QDragManager::self(); - if (manager && manager->object - && (!manager->object->pixmap().isNull() - || manager->hasCustomDragCursors())) { - QPixmap pm = manager->object->pixmap(); - QList actions; - actions << Qt::MoveAction << Qt::CopyAction << Qt::LinkAction; - if (!manager->object->pixmap().isNull()) - actions << Qt::IgnoreAction; - QPoint hotSpot = manager->object->hotSpot(); - for (int cnum = 0; cnum < actions.size(); ++cnum) { - QPixmap cpm = manager->dragCursor(actions.at(cnum)); - int w = cpm.width(); - int h = cpm.height(); - - if (!pm.isNull()) { - int x1 = qMin(-hotSpot.x(), 0); - int x2 = qMax(pm.width() - hotSpot.x(), cpm.width()); - int y1 = qMin(-hotSpot.y(), 0); - int y2 = qMax(pm.height() - hotSpot.y(), cpm.height()); - - w = x2 - x1 + 1; - h = y2 - y1 + 1; - } - - QRect srcRect = pm.rect(); - QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y())); - QPoint newHotSpot = hotSpot; - -#if defined(Q_OS_WINCE) - // Limited cursor size - int reqw = GetSystemMetrics(SM_CXCURSOR); - int reqh = GetSystemMetrics(SM_CYCURSOR); - - QPoint hotspotInPM = newHotSpot - pmDest; - if (reqw < w) { - // Not wide enough - move objectpm right - qreal r = qreal(newHotSpot.x()) / w; - newHotSpot = QPoint(int(r * reqw), newHotSpot.y()); - if (newHotSpot.x() + cpm.width() > reqw) - newHotSpot.setX(reqw - cpm.width()); - - srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height())); - } - if (reqh < h) { - qreal r = qreal(newHotSpot.y()) / h; - newHotSpot = QPoint(newHotSpot.x(), int(r * reqh)); - if (newHotSpot.y() + cpm.height() > reqh) - newHotSpot.setY(reqh - cpm.height()); - - srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh)); - } - // Always use system cursor size - w = reqw; - h = reqh; -#endif - - QPixmap newCursor(w, h); - if (!pm.isNull()) { - newCursor.fill(QColor(0, 0, 0, 0)); - QPainter p(&newCursor); - p.drawPixmap(pmDest, pm, srcRect); - p.drawPixmap(qMax(0,newHotSpot.x()),qMax(0,newHotSpot.y()),cpm); - } else { - newCursor = cpm; - } - -#ifndef QT_NO_CURSOR - cursors[actions.at(cnum)] = QCursor(newCursor, pm.isNull() ? 0 : qMax(0,newHotSpot.x()), - pm.isNull() ? 0 : qMax(0,newHotSpot.y())); -#endif - } - } -} - - - -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - - -STDMETHODIMP -QOleDropSource::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if(iid == IID_IUnknown || iid == IID_IDropSource) - { - *ppv = this; - ++m_refs; - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - - -STDMETHODIMP_(ULONG) -QOleDropSource::AddRef(void) -{ - return ++m_refs; -} - - -STDMETHODIMP_(ULONG) -QOleDropSource::Release(void) -{ - if(--m_refs == 0) - { - delete this; - return 0; - } - return m_refs; -} - -static inline Qt::MouseButtons keystate_to_mousebutton(DWORD grfKeyState) -{ - Qt::MouseButtons result; - if (grfKeyState & MK_LBUTTON) - result |= Qt::LeftButton; - if (grfKeyState & MK_MBUTTON) - result |= Qt::MidButton; - if (grfKeyState & MK_RBUTTON) - result |= Qt::RightButton; - if (grfKeyState & MK_XBUTTON1) - result |= Qt::XButton1; - if (grfKeyState & MK_XBUTTON2) - result |= Qt::XButton2; - return result; -} - -//--------------------------------------------------------------------- -// IDropSource Methods -//--------------------------------------------------------------------- -QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP -QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) -{ -#ifdef QDND_DEBUG - qDebug("QOleDropSource::QueryContinueDrag(fEscapePressed %d, grfKeyState %d)", fEscapePressed, grfKeyState); -#endif - - if (fEscapePressed) { - return ResultFromScode(DRAGDROP_S_CANCEL); - } else if ((GetAsyncKeyState(VK_LBUTTON) == 0) - && (GetAsyncKeyState(VK_MBUTTON) == 0) - && (GetAsyncKeyState(VK_RBUTTON) == 0)) { - // grfKeyState is broken on CE & some Windows XP versions, - // therefore we need to check the state manually - return ResultFromScode(DRAGDROP_S_DROP); - } else { -#if !defined(Q_OS_WINCE) - if (currentButtons == Qt::NoButton) { - currentButtons = keystate_to_mousebutton(grfKeyState); - } else { - Qt::MouseButtons buttons = keystate_to_mousebutton(grfKeyState); - if (!(currentButtons & buttons)) - return ResultFromScode(DRAGDROP_S_DROP); - } -#endif - QApplication::processEvents(); - return NOERROR; - } -} - -QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP -QOleDropSource::GiveFeedback(DWORD dwEffect) -{ - Qt::DropAction action = translateToQDragDropAction(dwEffect); - -#ifdef QDND_DEBUG - qDebug("QOleDropSource::GiveFeedback(DWORD dwEffect)"); - qDebug("dwEffect = %s", dragActionsToString(action).toLatin1().data()); -#endif - - if (currentAction != action) { - currentAction = action; - QDragManager::self()->emitActionChanged(currentAction); - } - - if (cursors.contains(currentAction)) { -#ifndef QT_NO_CURSOR - SetCursor(cursors[currentAction].handle()); -#endif - return ResultFromScode(S_OK); - } - - return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS); -} - -//--------------------------------------------------------------------- -// QOleDropTarget -//--------------------------------------------------------------------- - -QOleDropTarget::QOleDropTarget(QWidget* w) -: widget(w) -{ - m_refs = 1; -} - -void QOleDropTarget::releaseQt() -{ - widget = 0; -} - -//--------------------------------------------------------------------- -// IUnknown Methods -//--------------------------------------------------------------------- - - -STDMETHODIMP -QOleDropTarget::QueryInterface(REFIID iid, void FAR* FAR* ppv) -{ - if(iid == IID_IUnknown || iid == IID_IDropTarget) - { - *ppv = this; - AddRef(); - return NOERROR; - } - *ppv = NULL; - return ResultFromScode(E_NOINTERFACE); -} - - -STDMETHODIMP_(ULONG) -QOleDropTarget::AddRef(void) -{ - return ++m_refs; -} - - -STDMETHODIMP_(ULONG) -QOleDropTarget::Release(void) -{ - if(--m_refs == 0) - { - delete this; - return 0; - } - return m_refs; -} - -//--------------------------------------------------------------------- -// IDropTarget Methods -//--------------------------------------------------------------------- - -QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP -QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) -{ -#ifdef QDND_DEBUG - qDebug("QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)"); -#endif - - if (!QApplicationPrivate::tryModalHelper(widget)) { - *pdwEffect = DROPEFFECT_NONE; - return NOERROR; - } - - QDragManager *manager = QDragManager::self(); - manager->dropData->currentDataObject = pDataObj; - manager->dropData->currentDataObject->AddRef(); - sendDragEnterEvent(widget, grfKeyState, pt, pdwEffect); - *pdwEffect = chosenEffect; - - return NOERROR; -} - -void QOleDropTarget::sendDragEnterEvent(QWidget *dragEnterWidget, DWORD grfKeyState, - POINTL pt, LPDWORD pdwEffect) -{ - Q_ASSERT(dragEnterWidget); - lastPoint = dragEnterWidget->mapFromGlobal(QPoint(pt.x,pt.y)); - lastKeyState = grfKeyState; - - chosenEffect = DROPEFFECT_NONE; - currentWidget = dragEnterWidget; - - QDragManager *manager = QDragManager::self(); - QMimeData * md = manager->source() ? manager->dragPrivate()->data : manager->dropData; - QDragEnterEvent enterEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md, - toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState)); - QApplication::sendEvent(dragEnterWidget, &enterEvent); - answerRect = enterEvent.answerRect(); - - if (enterEvent.isAccepted()) { - chosenEffect = translateToWinDragEffects(enterEvent.dropAction()); - } - - // Documentation states that a drag move event is sendt immidiatly after - // a drag enter event. This will honor widgets overriding dragMoveEvent only: - if (enterEvent.isAccepted()) { - QDragMoveEvent moveEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md, - toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState)); - answerRect = enterEvent.answerRect(); - moveEvent.setDropAction(enterEvent.dropAction()); - moveEvent.accept(); // accept by default, since enter event was accepted. - - QApplication::sendEvent(dragEnterWidget, &moveEvent); - if (moveEvent.isAccepted()) { - answerRect = moveEvent.answerRect(); - chosenEffect = translateToWinDragEffects(moveEvent.dropAction()); - } else { - chosenEffect = DROPEFFECT_NONE; - } - } - -} - -QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP -QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) -{ -#ifdef QDND_DEBUG - qDebug("QOleDropTarget::DragOver(grfKeyState %d, pt (%d,%d), pdwEffect %d)", grfKeyState, pt.x, pt.y, pdwEffect); -#endif - - QWidget *dragOverWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y))); - if (!dragOverWidget) - dragOverWidget = widget; - - - if (!QApplicationPrivate::tryModalHelper(dragOverWidget) - || !dragOverWidget->testAttribute(Qt::WA_DropSiteRegistered)) { - *pdwEffect = DROPEFFECT_NONE; - return NOERROR; - } - - QPoint tmpPoint = dragOverWidget->mapFromGlobal(QPoint(pt.x, pt.y)); - // see if we should compress this event - if ((tmpPoint == lastPoint || answerRect.contains(tmpPoint)) && lastKeyState == grfKeyState) { - *pdwEffect = chosenEffect; - return NOERROR; - } - - if (!dragOverWidget->internalWinId() && dragOverWidget != currentWidget) { - QPointer dragOverWidgetGuard(dragOverWidget); - // Send drag leave event to the previous drag widget. - QDragLeaveEvent dragLeave; - if (currentWidget) - QApplication::sendEvent(currentWidget, &dragLeave); - if (!dragOverWidgetGuard) { - dragOverWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y))); - if (!dragOverWidget) - dragOverWidget = widget; - } - // Send drag enter event to the current drag widget. - sendDragEnterEvent(dragOverWidget, grfKeyState, pt, pdwEffect); - } - - QDragManager *manager = QDragManager::self(); - QMimeData *md = manager->source() ? manager->dragPrivate()->data : manager->dropData; - - QDragMoveEvent oldEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md, - toQtMouseButtons(lastKeyState), toQtKeyboardModifiers(lastKeyState)); - - - lastPoint = tmpPoint; - lastKeyState = grfKeyState; - - QDragMoveEvent e(lastPoint, translateToQDragDropActions(*pdwEffect), md, - toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState)); - if (chosenEffect != DROPEFFECT_NONE) { - if (oldEvent.dropAction() == e.dropAction() && - oldEvent.keyboardModifiers() == e.keyboardModifiers()) - e.setDropAction(translateToQDragDropAction(chosenEffect)); - e.accept(); - } - QApplication::sendEvent(dragOverWidget, &e); - - answerRect = e.answerRect(); - if (e.isAccepted()) - chosenEffect = translateToWinDragEffects(e.dropAction()); - else - chosenEffect = DROPEFFECT_NONE; - *pdwEffect = chosenEffect; - - return NOERROR; -} - -QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP -QOleDropTarget::DragLeave() -{ -#ifdef QDND_DEBUG - qDebug("QOleDropTarget::DragLeave()"); -#endif - - if (!QApplicationPrivate::tryModalHelper(widget)) { - return NOERROR; - } - - currentWidget = 0; - QDragLeaveEvent e; - QApplication::sendEvent(widget, &e); - - QDragManager *manager = QDragManager::self(); - - if (manager->dropData->currentDataObject) { // Sanity - manager->dropData->currentDataObject->Release(); - manager->dropData->currentDataObject = 0; - } - - return NOERROR; -} - -#define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) - -QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP -QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) -{ -#ifdef QDND_DEBUG - qDebug("QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, grfKeyState %d, POINTL pt, LPDWORD pdwEffect)", grfKeyState); -#endif - - QWidget *dropWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y))); - if (!dropWidget) - dropWidget = widget; - - if (!QApplicationPrivate::tryModalHelper(dropWidget) - || !dropWidget->testAttribute(Qt::WA_DropSiteRegistered)) { - *pdwEffect = DROPEFFECT_NONE; - return NOERROR; - } - - lastPoint = dropWidget->mapFromGlobal(QPoint(pt.x,pt.y)); - // grfKeyState does not all ways contain button state in the drop so if - // it doesn't then use the last known button state; - if ((grfKeyState & KEY_STATE_BUTTON_MASK) == 0) - grfKeyState |= lastKeyState & KEY_STATE_BUTTON_MASK; - lastKeyState = grfKeyState; - - QDragManager *manager = QDragManager::self(); - QMimeData *md = manager->source() ? manager->dragPrivate()->data : manager->dropData; - QDropEvent e(lastPoint, translateToQDragDropActions(*pdwEffect), md, - toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState)); - if (chosenEffect != DROPEFFECT_NONE) { - e.setDropAction(translateToQDragDropAction(chosenEffect)); - } - QApplication::sendEvent(dropWidget, &e); - - if (chosenEffect != DROPEFFECT_NONE) { - e.accept(); - } - - - if (e.isAccepted()) { - if (e.dropAction() == Qt::MoveAction || e.dropAction() == Qt::TargetMoveAction) { - if (e.dropAction() == Qt::MoveAction) - chosenEffect = DROPEFFECT_MOVE; - else - chosenEffect = DROPEFFECT_COPY; - HGLOBAL hData = GlobalAlloc(0, sizeof(DWORD)); - if (hData) { - DWORD *moveEffect = (DWORD *)GlobalLock(hData);; - *moveEffect = DROPEFFECT_MOVE; - GlobalUnlock(hData); - STGMEDIUM medium; - memset(&medium, 0, sizeof(STGMEDIUM)); - medium.tymed = TYMED_HGLOBAL; - medium.hGlobal = hData; - FORMATETC format; - format.cfFormat = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT); - format.tymed = TYMED_HGLOBAL; - format.ptd = 0; - format.dwAspect = 1; - format.lindex = -1; - manager->dropData->currentDataObject->SetData(&format, &medium, true); - } - } else { - chosenEffect = translateToWinDragEffects(e.dropAction()); - } - } else { - chosenEffect = DROPEFFECT_NONE; - } - *pdwEffect = chosenEffect; - - - if (manager->dropData->currentDataObject) { - manager->dropData->currentDataObject->Release(); - manager->dropData->currentDataObject = 0; - } - - return NOERROR; - - // We won't get any mouserelease-event, so manually adjust qApp state: -///### test this QApplication::winMouseButtonUp(); -} - -//--------------------------------------------------------------------- -// QDropData -//--------------------------------------------------------------------- - -bool QDropData::hasFormat_sys(const QString &mimeType) const -{ - if (!currentDataObject) // Sanity - return false; - - return QWindowsMime::converterToMime(mimeType, currentDataObject) != 0; -} - -QStringList QDropData::formats_sys() const -{ - QStringList fmts; - if (!currentDataObject) // Sanity - return fmts; - - fmts = QWindowsMime::allMimesForFormats(currentDataObject); - - return fmts; -} - -QVariant QDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const -{ - QVariant result; - - if (!currentDataObject) // Sanity - return result; - - QWindowsMime *converter = QWindowsMime::converterToMime(mimeType, currentDataObject); - - if (converter) - result = converter->convertToMime(mimeType, currentDataObject, type); - - return result; -} - -Qt::DropAction QDragManager::drag(QDrag *o) - -{ -#ifdef QDND_DEBUG - qDebug("QDragManager::drag(QDrag *drag)"); -#endif - - if (object == o || !o || !o->d_func()->source) - return Qt::IgnoreAction; - - if (object) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - } - - object = o; - -#ifdef QDND_DEBUG - qDebug("actions = %s", dragActionsToString(dragPrivate()->possible_actions).toLatin1().data()); -#endif - - dragPrivate()->target = 0; - -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart); -#endif - - DWORD resultEffect; - QOleDropSource *src = new QOleDropSource(); - src->createCursors(); - QOleDataObject *obj = new QOleDataObject(o->mimeData()); - DWORD allowedEffects = translateToWinDragEffects(dragPrivate()->possible_actions); - -#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS) - HRESULT r = DoDragDrop(obj, src, allowedEffects, &resultEffect); -#else - HRESULT r = DRAGDROP_S_CANCEL; - resultEffect = DROPEFFECT_MOVE; -#endif - - Qt::DropAction ret = Qt::IgnoreAction; - if (r == DRAGDROP_S_DROP) { - if (obj->reportedPerformedEffect() == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) { - ret = Qt::TargetMoveAction; - resultEffect = DROPEFFECT_MOVE; - } else { - ret = translateToQDragDropAction(resultEffect); - } - // Force it to be a copy if an unsupported operation occurred. - // This indicates a bug in the drop target. - if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects)) - ret = Qt::CopyAction; - } else { - dragPrivate()->target = 0; - } - - // clean up - obj->releaseQt(); - obj->Release(); // Will delete obj if refcount becomes 0 - src->Release(); // Will delete src if refcount becomes 0 - object = 0; - o->setMimeData(0); - o->deleteLater(); - -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd); -#endif - - return ret; -} - -void QDragManager::cancel(bool /* deleteSource */) -{ - if (object) { - beingCancelled = true; - object = 0; - } - -#ifndef QT_NO_CURSOR - // insert cancel code here ######## todo - - if (restoreCursor) { - QApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif -#ifndef QT_NO_ACCESSIBILITY - QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd); -#endif -} - -void QDragManager::updatePixmap() -{ - // not used in windows implementation -} - -bool QDragManager::eventFilter(QObject *, QEvent *) -{ - // not used in windows implementation - return false; -} - -void QDragManager::timerEvent(QTimerEvent*) -{ - // not used in windows implementation -} - -void QDragManager::move(const QPoint &) -{ - // not used in windows implementation -} - -void QDragManager::drop() -{ - // not used in windows implementation -} - -QT_END_NAMESPACE - -#endif // QT_NO_DRAGANDDROP diff --git a/src/widgets/platforms/win/qfont_win.cpp b/src/widgets/platforms/win/qfont_win.cpp deleted file mode 100644 index 7a0f234ca6..0000000000 --- a/src/widgets/platforms/win/qfont_win.cpp +++ /dev/null @@ -1,166 +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 "qfont.h" -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qtextengine_p.h" -#include "qfontmetrics.h" -#include "qfontinfo.h" - -#include "qwidget.h" -#include "qpainter.h" -#include -#include "qt_windows.h" -#include -#include "qapplication.h" -#include -#include - -QT_BEGIN_NAMESPACE - -extern HDC shared_dc(); // common dc for all fonts -extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp - -// ### maybe move to qapplication_win -QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/) -{ - QString family = QString::fromWCharArray(lf.lfFaceName); - QFont qf(family); - qf.setItalic(lf.lfItalic); - if (lf.lfWeight != FW_DONTCARE) - qf.setWeight(weightFromInteger(lf.lfWeight)); - int lfh = qAbs(lf.lfHeight); - qf.setPointSizeF(lfh * 72.0 / GetDeviceCaps(shared_dc(),LOGPIXELSY)); - qf.setUnderline(false); - qf.setOverline(false); - qf.setStrikeOut(false); - return qf; -} - - -static inline float pixelSize(const QFontDef &request, int dpi) -{ - float pSize; - if (request.pointSize != -1) - pSize = request.pointSize * dpi/ 72.; - else - pSize = request.pixelSize; - return pSize; -} - -static inline float pointSize(const QFontDef &fd, int dpi) -{ - float pSize; - if (fd.pointSize < 0) - pSize = fd.pixelSize * 72. / ((float)dpi); - else - pSize = fd.pointSize; - return pSize; -} - -/***************************************************************************** - QFont member functions - *****************************************************************************/ - -void QFont::initialize() -{ -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - -HFONT QFont::handle() const -{ - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - Q_ASSERT(engine != 0); - if (engine->type() == QFontEngine::Multi) - engine = static_cast(engine)->engine(0); - if (engine->type() == QFontEngine::Win) - return static_cast(engine)->hfont; - return 0; -} - -QString QFont::rawName() const -{ - return family(); -} - -void QFont::setRawName(const QString &name) -{ - setFamily(name); -} - -QString QFont::defaultFamily() const -{ - switch(d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("Times New Roman"); - case QFont::Courier: - case QFont::Monospace: - return QString::fromLatin1("Courier New"); - case QFont::Decorative: - return QString::fromLatin1("Bookman Old Style"); - case QFont::Cursive: - return QString::fromLatin1("Comic Sans MS"); - case QFont::Fantasy: - return QString::fromLatin1("Impact"); - case QFont::Helvetica: - return QString::fromLatin1("Arial"); - case QFont::System: - default: - return QString::fromLatin1("MS Sans Serif"); - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("helvetica"); -} - -QString QFont::lastResortFont() const -{ - return QString::fromLatin1("arial"); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qfontdatabase_win.cpp b/src/widgets/platforms/win/qfontdatabase_win.cpp deleted file mode 100644 index 788eb307c3..0000000000 --- a/src/widgets/platforms/win/qfontdatabase_win.cpp +++ /dev/null @@ -1,1348 +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 "qt_windows.h" -#include -#include -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qpaintdevice.h" -#include -#include "qabstractfileengine.h" -#include "qendian.h" - -#if !defined(QT_NO_DIRECTWRITE) -# include "qsettings.h" -# include "qfontenginedirectwrite_p.h" -#endif - -#ifdef Q_OS_WINCE -# include -#endif - -QT_BEGIN_NAMESPACE - -extern HDC shared_dc(); // common dc for all fonts - -#ifdef MAKE_TAG -#undef MAKE_TAG -#endif -// GetFontData expects the tags in little endian ;( -#define MAKE_TAG(ch1, ch2, ch3, ch4) (\ - (((quint32)(ch4)) << 24) | \ - (((quint32)(ch3)) << 16) | \ - (((quint32)(ch2)) << 8) | \ - ((quint32)(ch1)) \ - ) - -static HFONT stock_sysfont = 0; - -static bool localizedName(const QString &name) -{ - const QChar *c = name.unicode(); - for(int i = 0; i < name.length(); ++i) { - if(c[i].unicode() >= 0x100) - return true; - } - return false; -} - -static inline quint16 getUShort(const unsigned char *p) -{ - quint16 val; - val = *p++ << 8; - val |= *p; - - return val; -} - -static QString getEnglishName(const uchar *table, quint32 bytes) -{ - QString i18n_name; - enum { - NameRecordSize = 12, - FamilyId = 1, - MS_LangIdEnglish = 0x009 - }; - - // get the name table - quint16 count; - quint16 string_offset; - const unsigned char *names; - - int microsoft_id = -1; - int apple_id = -1; - int unicode_id = -1; - - if(getUShort(table) != 0) - goto error; - - count = getUShort(table+2); - string_offset = getUShort(table+4); - names = table + 6; - - if(string_offset >= bytes || 6 + count*NameRecordSize > string_offset) - goto error; - - for(int i = 0; i < count; ++i) { - // search for the correct name entry - - quint16 platform_id = getUShort(names + i*NameRecordSize); - quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize); - quint16 language_id = getUShort(names + 4 + i*NameRecordSize); - quint16 name_id = getUShort(names + 6 + i*NameRecordSize); - - if(name_id != FamilyId) - continue; - - enum { - PlatformId_Unicode = 0, - PlatformId_Apple = 1, - PlatformId_Microsoft = 3 - }; - - quint16 length = getUShort(names + 8 + i*NameRecordSize); - quint16 offset = getUShort(names + 10 + i*NameRecordSize); - if(DWORD(string_offset + offset + length) >= bytes) - continue; - - if ((platform_id == PlatformId_Microsoft - && (encoding_id == 0 || encoding_id == 1)) - && (language_id & 0x3ff) == MS_LangIdEnglish - && microsoft_id == -1) - microsoft_id = i; - // not sure if encoding id 4 for Unicode is utf16 or ucs4... - else if(platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1) - unicode_id = i; - else if(platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0) - apple_id = i; - } - { - bool unicode = false; - int id = -1; - if(microsoft_id != -1) { - id = microsoft_id; - unicode = true; - } else if(apple_id != -1) { - id = apple_id; - unicode = false; - } else if (unicode_id != -1) { - id = unicode_id; - unicode = true; - } - if(id != -1) { - quint16 length = getUShort(names + 8 + id*NameRecordSize); - quint16 offset = getUShort(names + 10 + id*NameRecordSize); - if(unicode) { - // utf16 - - length /= 2; - i18n_name.resize(length); - QChar *uc = (QChar *) i18n_name.unicode(); - const unsigned char *string = table + string_offset + offset; - for(int i = 0; i < length; ++i) - uc[i] = getUShort(string + 2*i); - } else { - // Apple Roman - - i18n_name.resize(length); - QChar *uc = (QChar *) i18n_name.unicode(); - const unsigned char *string = table + string_offset + offset; - for(int i = 0; i < length; ++i) - uc[i] = QLatin1Char(string[i]); - } - } - } - error: - //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); - return i18n_name; -} - -static QString getEnglishName(const QString &familyName) -{ - QString i18n_name; - - HDC hdc = GetDC( 0 ); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); - lf.lfCharSet = DEFAULT_CHARSET; - HFONT hfont = CreateFontIndirect(&lf); - - if(!hfont) { - ReleaseDC(0, hdc); - return QString(); - } - - HGDIOBJ oldobj = SelectObject( hdc, hfont ); - - const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' ); - - // get the name table - unsigned char *table = 0; - - DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 ); - if ( bytes == GDI_ERROR ) { - // ### Unused variable - /* int err = GetLastError(); */ - goto error; - } - - table = new unsigned char[bytes]; - GetFontData(hdc, name_tag, 0, table, bytes); - if ( bytes == GDI_ERROR ) - goto error; - - i18n_name = getEnglishName(table, bytes); -error: - delete [] table; - SelectObject( hdc, oldobj ); - DeleteObject( hfont ); - ReleaseDC( 0, hdc ); - - //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); - return i18n_name; -} - -extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp - -static -void addFontToDatabase(QString familyName, const QString &scriptName, - TEXTMETRIC *textmetric, - const FONTSIGNATURE *signature, - int type) -{ - const int script = -1; - const QString foundryName; - Q_UNUSED(script); - - bool italic = false; - int weight; - bool fixed; - bool ttf; - bool scalable; - int size; - -// QString escript = QString::fromWCharArray(f->elfScript); -// qDebug("script=%s", escript.latin1()); - - NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; - fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); - ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); - scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; - italic = tm->tmItalic; - weight = tm->tmWeight; - - // the "@family" fonts are just the same as "family". Ignore them. - if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) { - QtFontStyle::Key styleKey; - styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal; - styleKey.weight = weightFromInteger(weight); - - QtFontFamily *family = privateDb()->family(familyName, true); - - if(ttf && localizedName(familyName) && family->english_name.isEmpty()) - family->english_name = getEnglishName(familyName); - - QtFontFoundry *foundry = family->foundry(foundryName, true); - QtFontStyle *style = foundry->style(styleKey, QString(), true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - - // add fonts windows can generate for us: - if (styleKey.weight <= QFont::DemiBold) { - QtFontStyle::Key key(styleKey); - key.weight = QFont::Bold; - QtFontStyle *style = foundry->style(key, QString(), true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - } - if (styleKey.style != QFont::StyleItalic) { - QtFontStyle::Key key(styleKey); - key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, QString(), true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - } - if (styleKey.weight <= QFont::DemiBold && styleKey.style != QFont::StyleItalic) { - QtFontStyle::Key key(styleKey); - key.weight = QFont::Bold; - key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, QString(), true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - } - - family->fixedPitch = fixed; - - if (!family->writingSystemCheck && type & TRUETYPE_FONTTYPE) { - quint32 unicodeRange[4] = { - signature->fsUsb[0], signature->fsUsb[1], - signature->fsUsb[2], signature->fsUsb[3] - }; -#ifdef Q_WS_WINCE - if (signature->fsUsb[0] == 0) { - // If the unicode ranges bit mask is zero then - // EnumFontFamiliesEx failed to determine it properly. - // In this case we just pretend that the font supports all languages. - unicodeRange[0] = 0xbfffffff; // second most significant bit must be zero - unicodeRange[1] = 0xffffffff; - unicodeRange[2] = 0xffffffff; - unicodeRange[3] = 0xffffffff; - } -#endif - quint32 codePageRange[2] = { - signature->fsCsb[0], signature->fsCsb[1] - }; - QList systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); - - for (int i = 0; i < systems.count(); ++i) { - QFontDatabase::WritingSystem writingSystem = systems.at(i); - - // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains - // the symbol for Baht, and Windows thus reports that it supports the Thai script. - // Since it's the default UI font on this platform, most widgets will be unable to - // display Thai text by default. As a temporary work around, we special case Segoe UI - // and remove the Thai script from its list of supported writing systems. - if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI")) - family->writingSystems[writingSystem] = QtFontFamily::Supported; - } - } else if (!family->writingSystemCheck) { - //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1()); - if (scriptName == QLatin1String("Western") - || scriptName == QLatin1String("Baltic") - || scriptName == QLatin1String("Central European") - || scriptName == QLatin1String("Turkish") - || scriptName == QLatin1String("Vietnamese")) - family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Thai")) - family->writingSystems[QFontDatabase::Thai] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Symbol") - || scriptName == QLatin1String("Other")) - family->writingSystems[QFontDatabase::Symbol] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("OEM/Dos")) - family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("CHINESE_GB2312")) - family->writingSystems[QFontDatabase::SimplifiedChinese] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("CHINESE_BIG5")) - family->writingSystems[QFontDatabase::TraditionalChinese] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Cyrillic")) - family->writingSystems[QFontDatabase::Cyrillic] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Hangul")) - family->writingSystems[QFontDatabase::Korean] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Hebrew")) - family->writingSystems[QFontDatabase::Hebrew] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Greek")) - family->writingSystems[QFontDatabase::Greek] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Japanese")) - family->writingSystems[QFontDatabase::Japanese] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Arabic")) - family->writingSystems[QFontDatabase::Arabic] = QtFontFamily::Supported; - } - } -} - -static -int CALLBACK -storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, int type, LPARAM /*p*/) -{ - QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); - QString script = QString::fromWCharArray(f->elfScript); - - FONTSIGNATURE signature = textmetric->ntmFontSig; - - // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is - // identical to a TEXTMETRIC except for the last four members, which we don't use - // anyway - addFontToDatabase(familyName, script, (TEXTMETRIC *)textmetric, &signature, type); - // keep on enumerating - return 1; -} - -static -void populate_database(const QString& fam) -{ - QFontDatabasePrivate *d = privateDb(); - if (!d) - return; - - QtFontFamily *family = 0; - if(!fam.isEmpty()) { - family = d->family(fam); - if(family && family->loaded) - return; - } else if (d->count) { - return; - } - - HDC dummy = GetDC(0); - - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - if (fam.isNull()) { - lf.lfFaceName[0] = 0; - } else { - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded - } - lf.lfPitchAndFamily = 0; - - EnumFontFamiliesEx(dummy, &lf, - (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0); - - ReleaseDC(0, dummy); - - for (int i = 0; i < d->applicationFonts.count(); ++i) { - QFontDatabasePrivate::ApplicationFont fnt = d->applicationFonts.at(i); - if (!fnt.memoryFont) - continue; - for (int j = 0; j < fnt.families.count(); ++j) { - const QString familyName = fnt.families.at(j); - HDC hdc = GetDC(0); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size())); - lf.lfCharSet = DEFAULT_CHARSET; - HFONT hfont = CreateFontIndirect(&lf); - HGDIOBJ oldobj = SelectObject(hdc, hfont); - - TEXTMETRIC textMetrics; - GetTextMetrics(hdc, &textMetrics); - - addFontToDatabase(familyName, QString(), - &textMetrics, - &fnt.signatures.at(j), - TRUETYPE_FONTTYPE); - - SelectObject(hdc, oldobj); - DeleteObject(hfont); - ReleaseDC(0, hdc); - } - } - - if(!fam.isEmpty()) { - family = d->family(fam); - if(family) { - if(!family->writingSystemCheck) { - } - family->loaded = true; - } - } -} - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db || db->count) - return; - - populate_database(QString()); - -#ifdef QFONTDATABASE_DEBUG - // print the database - for (int f = 0; f < db->count; f++) { - QtFontFamily *family = db->families[f]; - qDebug(" %s: %p", qPrintable(family->name), family); - populate_database(family->name); - -#if 0 - qDebug(" scripts supported:"); - for (int i = 0; i < QUnicodeTables::ScriptCount; i++) - if(family->writingSystems[i] & QtFontFamily::Supported) - qDebug(" %d", i); - for (int fd = 0; fd < family->count; fd++) { - QtFontFoundry *foundry = family->foundries[fd]; - qDebug(" %s", foundry->name.latin1()); - for (int s = 0; s < foundry->count; s++) { - QtFontStyle *style = foundry->styles[s]; - qDebug(" style: style=%d weight=%d smooth=%d", style->key.style, - style->key.weight, style->smoothScalable ); - if(!style->smoothScalable) { - for(int i = 0; i < style->count; ++i) { - qDebug(" %d", style->pixelSizes[i].pixelSize); - } - } - } - } -#endif - } -#endif // QFONTDATABASE_DEBUG - -} - -static inline void load(const QString &family = QString(), int = -1) -{ - populate_database(family); -} - - - - - -// -------------------------------------------------------------------------------------- -// font loader -// -------------------------------------------------------------------------------------- - - - -static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, HDC fontHdc, int dpi) -{ - fe->fontDef = request; // most settings are equal - - HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fontHdc) ? fontHdc : shared_dc(); - SelectObject(dc, fe->hfont); - wchar_t n[64]; - GetTextFace(dc, 64, n); - fe->fontDef.family = QString::fromWCharArray(n); - fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - if (fe->fontDef.pointSize < 0) { - fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi; - } else if (fe->fontDef.pixelSize == -1) { - fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.); - } -} - -#if !defined(QT_NO_DIRECTWRITE) -static void initFontInfo(QFontEngineDirectWrite *fe, const QFontDef &request, - int dpi, IDWriteFont *font) -{ - fe->fontDef = request; - - IDWriteFontFamily *fontFamily = NULL; - HRESULT hr = font->GetFontFamily(&fontFamily); - - IDWriteLocalizedStrings *familyNames = NULL; - if (SUCCEEDED(hr)) - hr = fontFamily->GetFamilyNames(&familyNames); - - UINT32 index = 0; - BOOL exists = false; - - wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; - - if (SUCCEEDED(hr)) { - int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); - - if (defaultLocaleSuccess) - hr = familyNames->FindLocaleName(localeName, &index, &exists); - - if (SUCCEEDED(hr) && !exists) - hr = familyNames->FindLocaleName(L"en-us", &index, &exists); - } - - if (!exists) - index = 0; - - UINT32 length = 0; - if (SUCCEEDED(hr)) - hr = familyNames->GetStringLength(index, &length); - - wchar_t *name = new (std::nothrow) wchar_t[length+1]; - if (name == NULL) - hr = E_OUTOFMEMORY; - - // Get the family name. - if (SUCCEEDED(hr)) - hr = familyNames->GetString(index, name, length + 1); - - if (SUCCEEDED(hr)) - fe->fontDef.family = QString::fromWCharArray(name); - - delete[] name; - if (familyNames != NULL) - familyNames->Release(); - - if (FAILED(hr)) - qErrnoWarning(hr, "initFontInfo: Failed to get family name"); - - if (fe->fontDef.pointSize < 0) - fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi; - else if (fe->fontDef.pixelSize == -1) - fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.); -} -#endif - -static const char *other_tryFonts[] = { - "Arial", - "MS UI Gothic", - "Gulim", - "SimSun", - "PMingLiU", - "Arial Unicode MS", - 0 -}; - -static const char *jp_tryFonts [] = { - "MS UI Gothic", - "Arial", - "Gulim", - "SimSun", - "PMingLiU", - "Arial Unicode MS", - 0 -}; - -static const char *ch_CN_tryFonts [] = { - "SimSun", - "Arial", - "PMingLiU", - "Gulim", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char *ch_TW_tryFonts [] = { - "PMingLiU", - "Arial", - "SimSun", - "Gulim", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char *kr_tryFonts[] = { - "Gulim", - "Arial", - "PMingLiU", - "SimSun", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char **tryFonts = 0; - -#if !defined(QT_NO_DIRECTWRITE) -static QString fontNameSubstitute(const QString &familyName) -{ - QLatin1String key("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\" - "FontSubstitutes"); - return QSettings(key, QSettings::NativeFormat).value(familyName, familyName).toString(); -} -#endif - -static inline HFONT systemFont() -{ - if (stock_sysfont == 0) - stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT); - return stock_sysfont; -} - -#if !defined(DEFAULT_GUI_FONT) -#define DEFAULT_GUI_FONT 17 -#endif - -static QFontEngine *loadEngine(int script, const QFontDef &request, - HDC fontHdc, int dpi, bool rawMode, - const QtFontDesc *desc, - const QStringList &family_list) -{ - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - - bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc; - - HDC hdc = shared_dc(); - QString font_name = desc != 0 ? desc->family->name : request.family; - - if (useDevice) { - hdc = fontHdc; - font_name = request.family; - } - - bool stockFont = false; - bool preferClearTypeAA = false; - - HFONT hfont = 0; - - -#if !defined(QT_NO_DIRECTWRITE) - bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) - || (request.hintingPreference == QFont::PreferVerticalHinting); - IDWriteFont *directWriteFont = 0; -#else - bool useDirectWrite = false; -#endif - - if (rawMode) { // will choose a stock font - int f, deffnt = SYSTEM_FONT; - QString fam = desc != 0 ? desc->family->name.toLower() : request.family.toLower(); - if (fam == QLatin1String("default")) - f = deffnt; - else if (fam == QLatin1String("system")) - f = SYSTEM_FONT; -#ifndef Q_WS_WINCE - else if (fam == QLatin1String("system_fixed")) - f = SYSTEM_FIXED_FONT; - else if (fam == QLatin1String("ansi_fixed")) - f = ANSI_FIXED_FONT; - else if (fam == QLatin1String("ansi_var")) - f = ANSI_VAR_FONT; - else if (fam == QLatin1String("device_default")) - f = DEVICE_DEFAULT_FONT; - else if (fam == QLatin1String("oem_fixed")) - f = OEM_FIXED_FONT; -#endif - else if (fam[0] == QLatin1Char('#')) - f = fam.right(fam.length()-1).toInt(); - else - f = deffnt; - hfont = (HFONT)GetStockObject(f); - if (!hfont) { - qErrnoWarning("QFontEngine::loadEngine: GetStockObject failed"); - hfont = systemFont(); - } - stockFont = true; - } else { - - int hint = FF_DONTCARE; - switch (request.styleHint) { - case QFont::Helvetica: - hint = FF_SWISS; - break; - case QFont::Times: - hint = FF_ROMAN; - break; - case QFont::Courier: - hint = FF_MODERN; - break; - case QFont::OldEnglish: - hint = FF_DECORATIVE; - break; - case QFont::System: - hint = FF_MODERN; - break; - default: - break; - } - - lf.lfHeight = -qRound(request.pixelSize); - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - if (desc == 0 || desc->style->key.weight == 50) - lf.lfWeight = FW_DONTCARE; - else - lf.lfWeight = (desc->style->key.weight*900)/99; - lf.lfItalic = (desc != 0 && desc->style->key.style != QFont::StyleNormal); - lf.lfCharSet = DEFAULT_CHARSET; - - int strat = OUT_DEFAULT_PRECIS; - if (request.styleStrategy & QFont::PreferBitmap) { - strat = OUT_RASTER_PRECIS; -#ifndef Q_WS_WINCE - } else if (request.styleStrategy & QFont::PreferDevice) { - strat = OUT_DEVICE_PRECIS; - } else if (request.styleStrategy & QFont::PreferOutline) { - strat = OUT_OUTLINE_PRECIS; - } else if (request.styleStrategy & QFont::ForceOutline) { - strat = OUT_TT_ONLY_PRECIS; -#endif - } - - lf.lfOutPrecision = strat; - - int qual = DEFAULT_QUALITY; - - if (request.styleStrategy & QFont::PreferMatch) - qual = DRAFT_QUALITY; -#ifndef Q_WS_WINCE - else if (request.styleStrategy & QFont::PreferQuality) - qual = PROOF_QUALITY; -#endif - - if (request.styleStrategy & QFont::PreferAntialias) { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) { - qual = CLEARTYPE_QUALITY; - preferClearTypeAA = true; - } else { - qual = ANTIALIASED_QUALITY; - } - } else if (request.styleStrategy & QFont::NoAntialias) { - qual = NONANTIALIASED_QUALITY; - } - - lf.lfQuality = qual; - - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfPitchAndFamily = DEFAULT_PITCH | hint; - - QString fam = font_name; - - if(fam.isEmpty()) - fam = QLatin1String("MS Sans Serif"); - - if ((fam == QLatin1String("MS Sans Serif")) - && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { - fam = QLatin1String("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale - } - if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) - fam = QLatin1String("Courier New"); - - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded - - hfont = CreateFontIndirect(&lf); - if (!hfont) - qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed"); - - stockFont = (hfont == 0); - bool ttf = false; - int avWidth = 0; - BOOL res; - HGDIOBJ oldObj = SelectObject(hdc, hfont); - - TEXTMETRIC tm; - res = GetTextMetrics(hdc, &tm); - avWidth = tm.tmAveCharWidth; - ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; - SelectObject(hdc, oldObj); - - if (!ttf || !useDirectWrite) { - useDirectWrite = false; - - if (hfont && (!ttf || request.stretch != 100)) { - DeleteObject(hfont); - if (!res) - qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed"); - lf.lfWidth = avWidth * request.stretch/100; - hfont = CreateFontIndirect(&lf); - if (!hfont) - qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed"); - } - -#ifndef Q_WS_WINCE - if (hfont == 0) { - hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); - stockFont = true; - } -#else - if (hfont == 0) { - hfont = (HFONT)GetStockObject(SYSTEM_FONT); - stockFont = true; - } -#endif - - } - -#if !defined(QT_NO_DIRECTWRITE) - else { - // Default to false for DirectWrite (and re-enable once/if everything - // turns out okay) - useDirectWrite = false; - - QFontDatabasePrivate *db = privateDb(); - if (db->directWriteFactory == 0) { - HRESULT hr = DWriteCreateFactory( - DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast(&db->directWriteFactory) - ); - if (FAILED(hr)) { - qErrnoWarning("QFontEngine::loadEngine: DWriteCreateFactory failed"); - } else { - hr = db->directWriteFactory->GetGdiInterop(&db->directWriteGdiInterop); - if (FAILED(hr)) - qErrnoWarning("QFontEngine::loadEngine: GetGdiInterop failed"); - } - } - - if (db->directWriteGdiInterop != 0) { - QString nameSubstitute = fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName)); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), - sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); - - HRESULT hr = db->directWriteGdiInterop->CreateFontFromLOGFONT( - &lf, - &directWriteFont); - if (FAILED(hr)) { -#ifndef QT_NO_DEBUG - qErrnoWarning("QFontEngine::loadEngine: CreateFontFromLOGFONT failed " - "for %ls (0x%lx)", - lf.lfFaceName, hr); -#endif - } else { - DeleteObject(hfont); - useDirectWrite = true; - } - } - } -#endif - - } - - QFontEngine *fe = 0; - if (!useDirectWrite) { - QFontEngineWin *few = new QFontEngineWin(font_name, hfont, stockFont, lf); - if (preferClearTypeAA) - few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask; - - // Also check for OpenType tables when using complex scripts - // ### TODO: This only works for scripts that require OpenType. More generally - // for scripts that do not require OpenType we should just look at the list of - // supported writing systems in the font's OS/2 table. - if (scriptRequiresOpenType(script)) { - HB_Face hbFace = few->harfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { - FM_DEBUG(" OpenType support missing for script\n"); - delete few; - return 0; - } - } - - initFontInfo(few, request, fontHdc, dpi); - fe = few; - } - -#if !defined(QT_NO_DIRECTWRITE) - else { - QFontDatabasePrivate *db = privateDb(); - - IDWriteFontFace *directWriteFontFace = NULL; - HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace); - if (SUCCEEDED(hr)) { - QFontEngineDirectWrite *fedw = new QFontEngineDirectWrite(db->directWriteFactory, - directWriteFontFace, - request.pixelSize); - - initFontInfo(fedw, request, dpi, directWriteFont); - - fe = fedw; - } else { - qErrnoWarning(hr, "QFontEngine::loadEngine: CreateFontFace failed"); - } - } - - if (directWriteFont != 0) - directWriteFont->Release(); -#endif - - if(script == QUnicodeTables::Common - && !(request.styleStrategy & QFont::NoFontMerging) - && desc != 0 - && !(desc->family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) { - if(!tryFonts) { - LANGID lid = GetUserDefaultLangID(); - switch( lid&0xff ) { - case LANG_CHINESE: // Chinese (Taiwan) - if ( lid == 0x0804 ) // Taiwan - tryFonts = ch_TW_tryFonts; - else - tryFonts = ch_CN_tryFonts; - break; - case LANG_JAPANESE: - tryFonts = jp_tryFonts; - break; - case LANG_KOREAN: - tryFonts = kr_tryFonts; - break; - default: - tryFonts = other_tryFonts; - break; - } - } - QStringList fm = QFontDatabase().families(); - QStringList list = family_list; - const char **tf = tryFonts; - while(tf && *tf) { - if(fm.contains(QLatin1String(*tf))) - list << QLatin1String(*tf); - ++tf; - } - QFontEngine *mfe = new QFontEngineMultiWin(fe, list); - mfe->fontDef = fe->fontDef; - fe = mfe; - } - return fe; -} - -QFontEngine *qt_load_font_engine_win(const QFontDef &request) -{ - // From qfont.cpp - extern int qt_defaultDpi(); - - QFontCache::Key key(request, QUnicodeTables::Common); - QFontEngine *fe = QFontCache::instance()->findEngine(key); - if (fe != 0) - return fe; - else - return loadEngine(QUnicodeTables::Common, request, 0, qt_defaultDpi(), false, 0, - QStringList()); -} - -const char *styleHint(const QFontDef &request) -{ - const char *stylehint = 0; - switch (request.styleHint) { - case QFont::SansSerif: - stylehint = "Arial"; - break; - case QFont::Serif: - stylehint = "Times New Roman"; - break; - case QFont::TypeWriter: - stylehint = "Courier New"; - break; - default: - if (request.fixedPitch) - stylehint = "Courier New"; - break; - } - return stylehint; -} - -static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &req) -{ - // list of families to try - QStringList family_list = familyList(req); - - const char *stylehint = styleHint(d->request); - if (stylehint) - family_list << QLatin1String(stylehint); - - // append the default fallback font for the specified script - // family_list << ... ; ########### - - // add the default family - QString defaultFamily = QApplication::font().family(); - if (! family_list.contains(defaultFamily)) - family_list << defaultFamily; - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - family_list << QApplication::font().defaultFamily(); - - // null family means find the first font matching the specified script - family_list << QString(); - - QtFontDesc desc; - QFontEngine *fe = 0; - QList blacklistedFamilies; - - while (!fe) { - for (int i = 0; i < family_list.size(); ++i) { - QString family, foundry; - parseFontName(family_list.at(i), foundry, family); - FM_DEBUG("loadWin: >>>>>>>>>>>>>>trying to match '%s'", family.toLatin1().data()); - QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies); - if (desc.family) - break; - } - if (!desc.family) - break; - fe = loadEngine(script, req, d->hdc, d->dpi, d->rawMode, &desc, family_list); - if (!fe) - blacklistedFamilies.append(desc.familyIndex); - } - return fe; -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - // sanity checks - if (!qApp) - qWarning("QFontDatabase::load: Must construct QApplication first"); - Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); - - // normalize the request to get better caching - QFontDef req = d->request; - if (req.pixelSize <= 0) - req.pixelSize = floor((100.0 * req.pointSize * d->dpi) / 72. + 0.5) / 100; - if (req.pixelSize < 1) - req.pixelSize = 1; - 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; - - QFontEngine *fe = QFontCache::instance()->findEngine(key); - - // set it to the actual pointsize, so QFontInfo will do the right thing - if (req.pointSize < 0) - req.pointSize = req.pixelSize*72./d->dpi; - - if (!fe) { - if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - fe = new QTestFontEngine(req.pixelSize); - fe->fontDef = req; - } else { - QMutexLocker locker(fontDatabaseMutex()); - if (!privateDb()->count) - initializeDb(); - fe = loadWin(d, script, req); - } - if (!fe) { - fe = new QFontEngineBox(req.pixelSize); - fe->fontDef = QFontDef(); - } - } - d->engineData->engines[script] = fe; - fe->ref.ref(); - QFontCache::instance()->insertEngine(key, fe); -} - -#if !defined(FR_PRIVATE) -#define FR_PRIVATE 0x10 -#endif - -typedef int (WINAPI *PtrAddFontResourceExW)(LPCWSTR, DWORD, PVOID); -typedef HANDLE (WINAPI *PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *); -typedef BOOL (WINAPI *PtrRemoveFontResourceExW)(LPCWSTR, DWORD, PVOID); -typedef BOOL (WINAPI *PtrRemoveFontMemResourceEx)(HANDLE); - -static QList getTrueTypeFontOffsets(const uchar *fontData) -{ - QList offsets; - const quint32 headerTag = *reinterpret_cast(fontData); - if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) { - if (headerTag != MAKE_TAG(0, 1, 0, 0) - && headerTag != MAKE_TAG('O', 'T', 'T', 'O') - && headerTag != MAKE_TAG('t', 'r', 'u', 'e') - && headerTag != MAKE_TAG('t', 'y', 'p', '1')) - return offsets; - offsets << 0; - return offsets; - } - const quint32 numFonts = qFromBigEndian(fontData + 8); - for (uint i = 0; i < numFonts; ++i) { - offsets << qFromBigEndian(fontData + 12 + i * 4); - } - return offsets; -} - -static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length) -{ - const quint16 numTables = qFromBigEndian(data + 4); - for (uint i = 0; i < numTables; ++i) { - const quint32 offset = 12 + 16 * i; - if (*reinterpret_cast(data + offset) == tag) { - *table = fileBegin + qFromBigEndian(data + offset + 8); - *length = qFromBigEndian(data + offset + 12); - return; - } - } - *table = 0; - *length = 0; - return; -} - -static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePrivate::ApplicationFont *appFont) -{ - const uchar *data = reinterpret_cast(fontData.constData()); - - QList offsets = getTrueTypeFontOffsets(data); - if (offsets.isEmpty()) - return; - - for (int i = 0; i < offsets.count(); ++i) { - const uchar *font = data + offsets.at(i); - const uchar *table; - quint32 length; - getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); - if (!table) - continue; - QString name = getEnglishName(table, length); - if (name.isEmpty()) - continue; - - appFont->families << name; - FONTSIGNATURE signature; - getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); - if (table && length >= 86) { - // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec - signature.fsUsb[0] = qFromBigEndian(table + 42); - signature.fsUsb[1] = qFromBigEndian(table + 46); - signature.fsUsb[2] = qFromBigEndian(table + 50); - signature.fsUsb[3] = qFromBigEndian(table + 54); - - signature.fsCsb[0] = qFromBigEndian(table + 78); - signature.fsCsb[1] = qFromBigEndian(table + 82); - } else { - memset(&signature, 0, sizeof(signature)); - } - appFont->signatures << signature; - } -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - if(!fnt->data.isEmpty()) { -#ifndef Q_OS_WINCE - PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), - "AddFontMemResourceEx"); - if (!ptrAddFontMemResourceEx) - return; -#endif - getFamiliesAndSignatures(fnt->data, fnt); - if (fnt->families.isEmpty()) - return; - -#ifdef Q_OS_WINCE - HANDLE handle = 0; - - { -#ifdef QT_NO_TEMPORARYFILE - wchar_t lpBuffer[MAX_PATH]; - GetTempPath(MAX_PATH, lpBuffer); - QString s = QString::fromWCharArray(lpBuffer); - QFile tempfile(s + QLatin1String("/font") + QString::number(GetTickCount()) + QLatin1String(".ttf")); - if (!tempfile.open(QIODevice::ReadWrite)) -#else - QTemporaryFile tempfile(QLatin1String("XXXXXXXX.ttf")); - if (!tempfile.open()) -#endif // QT_NO_TEMPORARYFILE - return; - if (tempfile.write(fnt->data) == -1) - return; - -#ifndef QT_NO_TEMPORARYFILE - tempfile.setAutoRemove(false); -#endif - fnt->fileName = QFileInfo(tempfile.fileName()).absoluteFilePath(); - } - - if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0) { - QFile(fnt->fileName).remove(); - return; - } -#else - DWORD dummy = 0; - HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), fnt->data.size(), 0, - &dummy); - if (handle == 0) - return; -#endif // Q_OS_WINCE - - fnt->handle = handle; - fnt->data = QByteArray(); - fnt->memoryFont = true; - } else { - QFile f(fnt->fileName); - if (!f.open(QIODevice::ReadOnly)) - return; - QByteArray data = f.readAll(); - f.close(); - getFamiliesAndSignatures(data, fnt); - -#ifdef Q_OS_WINCE - QFileInfo fileinfo(fnt->fileName); - fnt->fileName = fileinfo.absoluteFilePath(); - if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0) - return; -#else - PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), - "AddFontResourceExW"); - if (!ptrAddFontResourceExW - || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0) - return; -#endif // Q_OS_WINCE - - fnt->memoryFont = false; - } -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (handle < 0 || handle >= db->applicationFonts.count()) - return false; - - const QFontDatabasePrivate::ApplicationFont font = db->applicationFonts.at(handle); - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - if (font.memoryFont) { -#ifdef Q_OS_WINCE - bool removeSucceeded = RemoveFontResource((LPCWSTR)font.fileName.utf16()); - QFile tempfile(font.fileName); - tempfile.remove(); - if (!removeSucceeded) - return false; -#else - PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), - "RemoveFontMemResourceEx"); - if (!ptrRemoveFontMemResourceEx - || !ptrRemoveFontMemResourceEx(font.handle)) - return false; -#endif // Q_OS_WINCE - } else { -#ifdef Q_OS_WINCE - if (!RemoveFontResource((LPCWSTR)font.fileName.utf16())) - return false; -#else - PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), - "RemoveFontResourceExW"); - if (!ptrRemoveFontResourceExW - || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0)) - return false; -#endif // Q_OS_WINCE - } - - db->invalidate(); - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - for (int i = 0; i < db->applicationFonts.count(); ++i) - if (!removeApplicationFont(i)) - return false; - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return true; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qfontengine_win.cpp b/src/widgets/platforms/win/qfontengine_win.cpp deleted file mode 100644 index 9d3afb57d9..0000000000 --- a/src/widgets/platforms/win/qfontengine_win.cpp +++ /dev/null @@ -1,1336 +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$ -** -****************************************************************************/ - -#if _WIN32_WINNT < 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif - -#include "qfontengine_p.h" -#include "qtextengine_p.h" -#include -#include "qt_windows.h" -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include "qpaintengine.h" -#include "qvarlengtharray.h" -#include -#include - -#if defined(Q_WS_WINCE) -#include "qguifunctions_wince.h" -#endif - -//### mingw needed define -#ifndef TT_PRIM_CSPLINE -#define TT_PRIM_CSPLINE 3 -#endif - -#ifdef MAKE_TAG -#undef MAKE_TAG -#endif -// GetFontData expects the tags in little endian ;( -#define MAKE_TAG(ch1, ch2, ch3, ch4) (\ - (((quint32)(ch4)) << 24) | \ - (((quint32)(ch3)) << 16) | \ - (((quint32)(ch2)) << 8) | \ - ((quint32)(ch1)) \ - ) - -// common DC for all fonts - -QT_BEGIN_NAMESPACE - -class QtHDC -{ - HDC _hdc; -public: - QtHDC() - { - HDC displayDC = GetDC(0); - _hdc = CreateCompatibleDC(displayDC); - ReleaseDC(0, displayDC); - } - ~QtHDC() - { - if (_hdc) - DeleteDC(_hdc); - } - HDC hdc() const - { - return _hdc; - } -}; - -#ifndef QT_NO_THREAD -Q_GLOBAL_STATIC(QThreadStorage, local_shared_dc) -HDC shared_dc() -{ - QtHDC *&hdc = local_shared_dc()->localData(); - if (!hdc) - hdc = new QtHDC; - return hdc->hdc(); -} -#else -HDC shared_dc() -{ - return 0; -} -#endif - -#ifndef Q_WS_WINCE -typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT); -static PtrGetCharWidthI ptrGetCharWidthI = 0; -static bool resolvedGetCharWidthI = false; - -static void resolveGetCharWidthI() -{ - if (resolvedGetCharWidthI) - return; - resolvedGetCharWidthI = true; - ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); -} -#endif // !defined(Q_WS_WINCE) - -// defined in qtextengine_win.cpp -typedef void *SCRIPT_CACHE; -typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *); -extern fScriptFreeCache ScriptFreeCache; - -static inline quint32 getUInt(unsigned char *p) -{ - quint32 val; - val = *p++ << 24; - val |= *p++ << 16; - val |= *p++ << 8; - val |= *p; - - return val; -} - -static inline quint16 getUShort(unsigned char *p) -{ - quint16 val; - val = *p++ << 8; - val |= *p; - - return val; -} - -// general font engine - -QFixed QFontEngineWin::lineThickness() const -{ - if(lineWidth > 0) - return lineWidth; - - return QFontEngine::lineThickness(); -} - -static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc) -{ - int size; - size = GetOutlineTextMetrics(hdc, 0, 0); - OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size); - GetOutlineTextMetrics(hdc, size, otm); - return otm; -} - -void QFontEngineWin::getCMap() -{ - ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE); - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - bool symb = false; - if (ttf) { - cmapTable = getSfntTable(qbswap(MAKE_TAG('c', 'm', 'a', 'p'))); - int size = 0; - cmap = QFontEngine::getCMap(reinterpret_cast(cmapTable.constData()), - cmapTable.size(), &symb, &size); - } - if (!cmap) { - ttf = false; - symb = false; - } - symbol = symb; - designToDevice = 1; - _faceId.index = 0; - if(cmap) { - OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight); - unitsPerEm = otm->otmEMSquare; - x_height = (int)otm->otmsXHeight; - loadKerningPairs(designToDevice); - _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1(); - lineWidth = otm->otmsUnderscoreSize; - fsType = otm->otmfsType; - free(otm); - } else { - unitsPerEm = tm.tmHeight; - } -} - - -inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - uint ucs4 = str[i].unicode(); - if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate()) { - ++i; - ucs4 = QChar::surrogateToUcs4(ucs4, str[i].unicode()); - } - return ucs4; -} - -int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs, bool mirrored) const -{ - int i = 0; - int glyph_pos = 0; - if (mirrored) { -#if defined(Q_WS_WINCE) - { -#else - if (symbol) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); - if (!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else if (ttf) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, QChar::mirroredChar(uc)); - } - } else { -#endif - wchar_t first = tm.tmFirstChar; - wchar_t last = tm.tmLastChar; - - for (; i < numChars; ++i, ++glyph_pos) { - uint ucs = QChar::mirroredChar(getChar(str, i, numChars)); - if ( -#ifdef Q_WS_WINCE - tm.tmFirstChar > 60000 || // see line 375 -#endif - ucs >= first && ucs <= last) - glyphs->glyphs[glyph_pos] = ucs; - else - glyphs->glyphs[glyph_pos] = 0; - } - } - } else { -#if defined(Q_WS_WINCE) - { -#else - if (symbol) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); - if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else if (ttf) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); - } - } else { -#endif - wchar_t first = tm.tmFirstChar; - wchar_t last = tm.tmLastChar; - - for (; i < numChars; ++i, ++glyph_pos) { - uint uc = getChar(str, i, numChars); - if ( -#ifdef Q_WS_WINCE - tm.tmFirstChar > 60000 || // see comment in QFontEngineWin -#endif - uc >= first && uc <= last) - glyphs->glyphs[glyph_pos] = uc; - else - glyphs->glyphs[glyph_pos] = 0; - } - } - } - glyphs->numGlyphs = glyph_pos; - return glyph_pos; -} - - -QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont, LOGFONT lf) -{ - //qDebug("regular windows font engine created: font='%s', size=%d", name, lf.lfHeight); - - _name = name; - - cmap = 0; - hfont = _hfont; - logfont = lf; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - this->stockFont = stockFont; - fontDef.pixelSize = -lf.lfHeight; - - lbearing = SHRT_MIN; - rbearing = SHRT_MIN; - synthesized_flags = -1; - lineWidth = -1; - x_height = -1; - - BOOL res = GetTextMetrics(hdc, &tm); - fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - if (!res) { - qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); - ZeroMemory(&tm, sizeof(TEXTMETRIC)); - } - - cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000; - getCMap(); - - widthCache = 0; - widthCacheSize = 0; - designAdvances = 0; - designAdvancesSize = 0; - -#ifndef Q_WS_WINCE - if (!resolvedGetCharWidthI) - resolveGetCharWidthI(); -#endif -} - -QFontEngineWin::~QFontEngineWin() -{ - if (designAdvances) - free(designAdvances); - - if (widthCache) - free(widthCache); - - // make sure we aren't by accident still selected - SelectObject(shared_dc(), (HFONT)GetStockObject(SYSTEM_FONT)); - - if (!stockFont) { - if (!DeleteObject(hfont)) - qErrnoWarning("QFontEngineWin: failed to delete non-stock font..."); - } -} - -HGDIOBJ QFontEngineWin::selectDesignFont() const -{ - LOGFONT f = logfont; - f.lfHeight = unitsPerEm; - HFONT designFont = CreateFontIndirect(&f); - return SelectObject(shared_dc(), designFont); -} - -bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - *nglyphs = getGlyphIndexes(str, len, glyphs, flags & QTextEngine::RightToLeft); - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - recalcAdvances(glyphs, flags); - return true; -} - -inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width) -{ -#if defined(Q_WS_WINCE) - GetCharWidth32(hdc, glyph, glyph, &width); -#else - if (ptrGetCharWidthI) - ptrGetCharWidthI(hdc, glyph, 1, 0, &width); -#endif -} - -void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - HGDIOBJ oldFont = 0; - HDC hdc = shared_dc(); - if (ttf && (flags & QTextEngine::DesignMetrics)) { - for(int i = 0; i < glyphs->numGlyphs; i++) { - unsigned int glyph = glyphs->glyphs[i]; - if(int(glyph) >= designAdvancesSize) { - int newSize = (glyph + 256) >> 8 << 8; - designAdvances = q_check_ptr((QFixed *)realloc(designAdvances, - newSize*sizeof(QFixed))); - for(int i = designAdvancesSize; i < newSize; ++i) - designAdvances[i] = -1000000; - designAdvancesSize = newSize; - } - if (designAdvances[glyph] < -999999) { - if (!oldFont) - oldFont = selectDesignFont(); - - int width = 0; - calculateTTFGlyphWidth(hdc, glyph, width); - designAdvances[glyph] = QFixed(width) / designToDevice; - } - glyphs->advances_x[i] = designAdvances[glyph]; - glyphs->advances_y[i] = 0; - } - if(oldFont) - DeleteObject(SelectObject(hdc, oldFont)); - } else { - for(int i = 0; i < glyphs->numGlyphs; i++) { - unsigned int glyph = glyphs->glyphs[i]; - - glyphs->advances_y[i] = 0; - - if (glyph >= widthCacheSize) { - int newSize = (glyph + 256) >> 8 << 8; - widthCache = q_check_ptr((unsigned char *)realloc(widthCache, - newSize*sizeof(QFixed))); - memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize); - widthCacheSize = newSize; - } - glyphs->advances_x[i] = widthCache[glyph]; - // font-width cache failed - if (glyphs->advances_x[i] == 0) { - int width = 0; - if (!oldFont) - oldFont = SelectObject(hdc, hfont); - - if (!ttf) { - QChar ch[2] = { ushort(glyph), 0 }; - int chrLen = 1; - if (glyph > 0xffff) { - ch[0] = QChar::highSurrogate(glyph); - ch[1] = QChar::lowSurrogate(glyph); - ++chrLen; - } - SIZE size = {0, 0}; - GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size); - width = size.cx; - } else { - calculateTTFGlyphWidth(hdc, glyph, width); - } - glyphs->advances_x[i] = width; - // if glyph's within cache range, store it for later - if (width > 0 && width < 0x100) - widthCache[glyph] = width; - } - } - - if (oldFont) - SelectObject(hdc, oldFont); - } -} - -glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0); -} - -#ifndef Q_WS_WINCE -bool QFontEngineWin::getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const -{ - Q_ASSERT(metrics != 0); - - HDC hdc = shared_dc(); - - GLYPHMETRICS gm; - DWORD res = 0; - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - - if (t.type() > QTransform::TxTranslate) { - // We need to set the transform using the HDC's world - // matrix rather than using the MAT2 above, because the - // results provided when transforming via MAT2 does not - // match the glyphs that are drawn using a WorldTransform - XFORM xform; - xform.eM11 = t.m11(); - xform.eM12 = t.m12(); - xform.eM21 = t.m21(); - xform.eM22 = t.m22(); - xform.eDx = 0; - xform.eDy = 0; - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - } - - uint format = GGO_METRICS; - if (ttf) - format |= GGO_GLYPH_INDEX; - res = GetGlyphOutline(hdc, glyph, format, &gm, 0, 0, &mat); - - if (t.type() > QTransform::TxTranslate) { - XFORM xform; - xform.eM11 = xform.eM22 = 1; - xform.eM12 = xform.eM21 = xform.eDx = xform.eDy = 0; - SetWorldTransform(hdc, &xform); - SetGraphicsMode(hdc, GM_COMPATIBLE); - } - - if (res != GDI_ERROR) { - *metrics = glyph_metrics_t(gm.gmptGlyphOrigin.x, -gm.gmptGlyphOrigin.y, - (int)gm.gmBlackBoxX, (int)gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY); - return true; - } else { - return false; - } -} -#endif - -glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) -{ -#ifndef Q_WS_WINCE - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - - glyph_metrics_t glyphMetrics; - bool success = getOutlineMetrics(glyph, t, &glyphMetrics); - - if (!ttf && !success) { - // Bitmap fonts - wchar_t ch = glyph; - ABCFLOAT abc; - GetCharABCWidthsFloat(hdc, ch, ch, &abc); - int width = qRound(abc.abcfB); - - return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t); - } - - return glyphMetrics; -#else - HDC hdc = shared_dc(); - HGDIOBJ oldFont = SelectObject(hdc, hfont); - - ABC abc; - int width; - int advance; -#ifdef GWES_MGTT // true type fonts - if (GetCharABCWidths(hdc, glyph, glyph, &abc)) { - width = qAbs(abc.abcA) + abc.abcB + qAbs(abc.abcC); - advance = abc.abcA + abc.abcB + abc.abcC; - } - else -#endif -#if defined(GWES_MGRAST) || defined(GWES_MGRAST2) // raster fonts - if (GetCharWidth32(hdc, glyph, glyph, &width)) { - advance = width; - } - else -#endif - { // fallback - width = tm.tmMaxCharWidth; - advance = width; - } - - SelectObject(hdc, oldFont); - return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, advance, 0).transformed(t); -#endif -} - -QFixed QFontEngineWin::ascent() const -{ - return tm.tmAscent; -} - -QFixed QFontEngineWin::descent() const -{ - // ### we substract 1 to even out the historical +1 in QFontMetrics's - // ### height=asc+desc+1 equation. Fix in Qt5. - return tm.tmDescent - 1; -} - -QFixed QFontEngineWin::leading() const -{ - return tm.tmExternalLeading; -} - - -QFixed QFontEngineWin::xHeight() const -{ - if(x_height >= 0) - return x_height; - return QFontEngine::xHeight(); -} - -QFixed QFontEngineWin::averageCharWidth() const -{ - return tm.tmAveCharWidth; -} - -qreal QFontEngineWin::maxCharWidth() const -{ - return tm.tmMaxCharWidth; -} - -enum { max_font_count = 256 }; -static const ushort char_table[] = { - 40, - 67, - 70, - 75, - 86, - 88, - 89, - 91, - 102, - 114, - 124, - 127, - 205, - 645, - 884, - 922, - 1070, - 12386, - 0 -}; - -static const int char_table_entries = sizeof(char_table)/sizeof(ushort); - -#ifndef Q_CC_MINGW -void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) -{ - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - -#ifndef Q_WS_WINCE - if (ttf) -#endif - - { - ABC abcWidths; - GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths); - if (leftBearing) - *leftBearing = abcWidths.abcA; - if (rightBearing) - *rightBearing = abcWidths.abcC; - } - -#ifndef Q_WS_WINCE - else { - QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing); - } -#endif -} -#endif // Q_CC_MINGW - -qreal QFontEngineWin::minLeftBearing() const -{ - if (lbearing == SHRT_MIN) - minRightBearing(); // calculates both - - return lbearing; -} - -qreal QFontEngineWin::minRightBearing() const -{ -#ifdef Q_WS_WINCE - if (rbearing == SHRT_MIN) { - int ml = 0; - int mr = 0; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - if (ttf) { - ABC *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar; - if (n <= max_font_count) { - abc = new ABC[n+1]; - GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABC[char_table_entries+1]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidths(hdc, char_table[i], char_table[i], abc+i); - n = char_table_entries; - } - ml = abc[0].abcA; - mr = abc[0].abcC; - for (int i = 1; i < n; i++) { - if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) { - ml = qMin(ml,abc[i].abcA); - mr = qMin(mr,abc[i].abcC); - } - } - delete [] abc; - } - lbearing = ml; - rbearing = mr; - } - - return rbearing; -#else - if (rbearing == SHRT_MIN) { - int ml = 0; - int mr = 0; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - if (ttf) { - ABC *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar; - if (n <= max_font_count) { - abc = new ABC[n+1]; - GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABC[char_table_entries+1]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i); - n = char_table_entries; - } - ml = abc[0].abcA; - mr = abc[0].abcC; - for (int i = 1; i < n; i++) { - if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) { - ml = qMin(ml,abc[i].abcA); - mr = qMin(mr,abc[i].abcC); - } - } - delete [] abc; - } else { - ABCFLOAT *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar+1; - if (n <= max_font_count) { - abc = new ABCFLOAT[n]; - GetCharABCWidthsFloat(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABCFLOAT[char_table_entries]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i); - n = char_table_entries; - } - float fml = abc[0].abcfA; - float fmr = abc[0].abcfC; - for (int i=1; i string->unicode() || tm.tmLastChar < string->unicode()) - return false; - } - } - return true; -} - -QFontEngine::Type QFontEngineWin::type() const -{ - return QFontEngine::Win; -} - -static inline double qt_fixed_to_double(const FIXED &p) { - return ((p.value << 16) + p.fract) / 65536.0; -} - -static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) { - return QPointF(qt_fixed_to_double(pt.x) * scale, -qt_fixed_to_double(pt.y) * scale); -} - -#ifndef GGO_UNHINTED -#define GGO_UNHINTED 0x0100 -#endif - -static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, - QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1) -{ -#if defined(Q_WS_WINCE) - Q_UNUSED(glyph); - Q_UNUSED(hdc); -#endif - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - uint glyphFormat = GGO_NATIVE; - - if (ttf) - glyphFormat |= GGO_GLYPH_INDEX; - - GLYPHMETRICS gMetric; - memset(&gMetric, 0, sizeof(GLYPHMETRICS)); - int bufferSize = GDI_ERROR; -#if !defined(Q_WS_WINCE) - bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); -#endif - if ((DWORD)bufferSize == GDI_ERROR) { - return false; - } - - void *dataBuffer = new char[bufferSize]; - DWORD ret = GDI_ERROR; -#if !defined(Q_WS_WINCE) - ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat); -#endif - if (ret == GDI_ERROR) { - delete [](char *)dataBuffer; - return false; - } - - if(metric) { - // #### obey scale - *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y, - (int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY, - gMetric.gmCellIncX, gMetric.gmCellIncY); - } - - int offset = 0; - int headerOffset = 0; - TTPOLYGONHEADER *ttph = 0; - - QPointF oset = position.toPointF(); - while (headerOffset < bufferSize) { - ttph = (TTPOLYGONHEADER*)((char *)dataBuffer + headerOffset); - - QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale)); - path->moveTo(lastPoint + oset); - offset += sizeof(TTPOLYGONHEADER); - TTPOLYCURVE *curve; - while (offsetcb)) { - curve = (TTPOLYCURVE*)((char*)(dataBuffer) + offset); - switch (curve->wType) { - case TT_PRIM_LINE: { - for (int i=0; icpfx; ++i) { - QPointF p = qt_to_qpointf(curve->apfx[i], scale) + oset; - path->lineTo(p); - } - break; - } - case TT_PRIM_QSPLINE: { - const QPainterPath::Element &elm = path->elementAt(path->elementCount()-1); - QPointF prev(elm.x, elm.y); - QPointF endPoint; - for (int i=0; icpfx - 1; ++i) { - QPointF p1 = qt_to_qpointf(curve->apfx[i], scale) + oset; - QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale) + oset; - if (i < curve->cpfx - 2) { - endPoint = QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2); - } else { - endPoint = p2; - } - - path->quadTo(p1, endPoint); - prev = endPoint; - } - - break; - } - case TT_PRIM_CSPLINE: { - for (int i=0; icpfx; ) { - QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale) + oset; - QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale) + oset; - QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale) + oset; - path->cubicTo(p2, p3, p4); - } - break; - } - default: - qWarning("QFontEngineWin::addOutlineToPath, unhandled switch case"); - } - offset += sizeof(TTPOLYCURVE) + (curve->cpfx-1) * sizeof(POINTFX); - } - path->closeSubpath(); - headerOffset += ttph->cb; - } - delete [] (char*)dataBuffer; - - return true; -} - -void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags) -{ - LOGFONT lf = logfont; - // The sign must be negative here to make sure we match against character height instead of - // hinted cell height. This ensures that we get linear matching, and we need this for - // paths since we later on apply a scaling transform to the glyph outline to get the - // font at the correct pixel size. - lf.lfHeight = -unitsPerEm; - lf.lfWidth = 0; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = shared_dc(); - HGDIOBJ oldfont = SelectObject(hdc, hf); - - for(int i = 0; i < nglyphs; ++i) { - if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0, - qreal(fontDef.pixelSize) / unitsPerEm)) { - // Some windows fonts, like "Modern", are vector stroke - // fonts, which are reported as TMPF_VECTOR but do not - // support GetGlyphOutline, and thus we set this bit so - // that addOutLineToPath can check it and return safely... - hasOutline = false; - break; - } - } - DeleteObject(SelectObject(hdc, oldfont)); -} - -void QFontEngineWin::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, - QPainterPath *path, QTextItem::RenderFlags flags) -{ -#if !defined(Q_WS_WINCE) - if(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) { - hasOutline = true; - QFontEngine::addOutlineToPath(x, y, glyphs, path, flags); - if (hasOutline) { - // has_outline is set to false if addGlyphToPath gets - // false from GetGlyphOutline, meaning its not an outline - // font. - return; - } - } -#endif - QFontEngine::addBitmapFontToPath(x, y, glyphs, path, flags); -} - -QFontEngine::FaceId QFontEngineWin::faceId() const -{ - return _faceId; -} - -QT_BEGIN_INCLUDE_NAMESPACE -#include -QT_END_INCLUDE_NAMESPACE - -int QFontEngineWin::synthesized() const -{ - if(synthesized_flags == -1) { - synthesized_flags = 0; - if(ttf) { - const DWORD HEAD = MAKE_TAG('h', 'e', 'a', 'd'); - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - uchar data[4]; - GetFontData(hdc, HEAD, 44, &data, 4); - USHORT macStyle = getUShort(data); - if (tm.tmItalic && !(macStyle & 2)) - synthesized_flags = SynthesizedItalic; - if (fontDef.stretch != 100 && ttf) - synthesized_flags |= SynthesizedStretch; - if (tm.tmWeight >= 500 && !(macStyle & 1)) - synthesized_flags |= SynthesizedBold; - //qDebug() << "font is" << _name << - // "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags; - } - } - return synthesized_flags; -} - -QFixed QFontEngineWin::emSquareSize() const -{ - return unitsPerEm; -} - -QFontEngine::Properties QFontEngineWin::properties() const -{ - LOGFONT lf = logfont; - lf.lfHeight = unitsPerEm; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = shared_dc(); - HGDIOBJ oldfont = SelectObject(hdc, hf); - OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - Properties p; - p.emSquare = unitsPerEm; - p.italicAngle = otm->otmItalicAngle; - p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1(); - p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1(); - p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(p.postscriptName); - p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top, - otm->otmrcFontBox.right - otm->otmrcFontBox.left, - otm->otmrcFontBox.top - otm->otmrcFontBox.bottom); - p.ascent = otm->otmAscent; - p.descent = -otm->otmDescent; - p.leading = (int)otm->otmLineGap; - p.capHeight = 0; - p.lineWidth = otm->otmsUnderscoreSize; - free(otm); - DeleteObject(SelectObject(hdc, oldfont)); - return p; -} - -void QFontEngineWin::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - LOGFONT lf = logfont; - lf.lfHeight = unitsPerEm; - int flags = synthesized(); - if(flags & SynthesizedItalic) - lf.lfItalic = false; - lf.lfWidth = 0; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = shared_dc(); - HGDIOBJ oldfont = SelectObject(hdc, hf); - QFixedPoint p; - p.x = 0; - p.y = 0; - addGlyphToPath(glyph, p, hdc, path, ttf, metrics); - DeleteObject(SelectObject(hdc, oldfont)); -} - -bool QFontEngineWin::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - if (!ttf) - return false; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - DWORD t = qbswap(tag); - *length = GetFontData(hdc, t, 0, buffer, *length); - return *length != GDI_ERROR; -} - -#if !defined(CLEARTYPE_QUALITY) -# define CLEARTYPE_QUALITY 5 -#endif - -extern bool qt_cleartype_enabled; - -QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin, - const QTransform &t, QImage::Format mask_format) -{ - Q_UNUSED(mask_format) - glyph_metrics_t gm = boundingBox(glyph); - -// printf(" -> for glyph %4x\n", glyph); - - int gx = gm.x.toInt(); - int gy = gm.y.toInt(); - int iw = gm.width.toInt(); - int ih = gm.height.toInt(); - - if (iw <= 0 || ih <= 0) - return 0; - - bool has_transformation = t.type() > QTransform::TxTranslate; - -#ifndef Q_WS_WINCE - unsigned int options = ttf ? ETO_GLYPH_INDEX : 0; - XFORM xform; - - if (has_transformation) { - xform.eM11 = t.m11(); - xform.eM12 = t.m12(); - xform.eM21 = t.m21(); - xform.eM22 = t.m22(); - xform.eDx = margin; - xform.eDy = margin; - - QtHDC qthdc; - HDC hdc = qthdc.hdc(); - - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - HGDIOBJ old_font = SelectObject(hdc, font); - - int ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0); - GLYPHMETRICS tgm; - MAT2 mat; - memset(&mat, 0, sizeof(mat)); - mat.eM11.value = mat.eM22.value = 1; - - if (GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat) == GDI_ERROR) { - qWarning("QWinFontEngine: unable to query transformed glyph metrics..."); - return 0; - } - - iw = tgm.gmBlackBoxX; - ih = tgm.gmBlackBoxY; - - xform.eDx -= tgm.gmptGlyphOrigin.x; - xform.eDy += tgm.gmptGlyphOrigin.y; - - SetGraphicsMode(hdc, GM_COMPATIBLE); - SelectObject(hdc, old_font); - } -#else // else winc - unsigned int options = 0; -#ifdef DEBUG - Q_ASSERT(!has_transformation); -#else - Q_UNUSED(has_transformation); -#endif -#endif - - QNativeImage *ni = new QNativeImage(iw + 2 * margin + 4, - ih + 2 * margin + 4, - QNativeImage::systemFormat(), !qt_cleartype_enabled); - - /*If cleartype is enabled we use the standard system format even on Windows CE - and not the special textbuffer format we have to use if cleartype is disabled*/ - - ni->image.fill(0xffffffff); - - HDC hdc = ni->hdc; - - SelectObject(hdc, GetStockObject(NULL_BRUSH)); - SelectObject(hdc, GetStockObject(BLACK_PEN)); - SetTextColor(hdc, RGB(0,0,0)); - SetBkMode(hdc, TRANSPARENT); - SetTextAlign(hdc, TA_BASELINE); - - HGDIOBJ old_font = SelectObject(hdc, font); - -#ifndef Q_OS_WINCE - if (has_transformation) { - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - ExtTextOut(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0); - } else -#endif - { - ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0); - } - - SelectObject(hdc, old_font); - return ni; -} - - -extern uint qt_pow_gamma[256]; - -QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) -{ - HFONT font = hfont; - if (qt_cleartype_enabled) { - LOGFONT lf = logfont; - lf.lfQuality = ANTIALIASED_QUALITY; - font = CreateFontIndirect(&lf); - } - QImage::Format mask_format = QNativeImage::systemFormat(); -#ifndef Q_OS_WINCE - mask_format = QImage::Format_RGB32; -#endif - - QNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format); - if (mask == 0) - return QImage(); - - QImage indexed(mask->width(), mask->height(), QImage::Format_Indexed8); - - // ### This part is kinda pointless, but we'll crash later if we don't because some - // code paths expects there to be colortables for index8-bit... - QVector colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - // Copy data... Cannot use QPainter here as GDI has messed up the - // Alpha channel of the ni.image pixels... - for (int y=0; yheight(); ++y) { - uchar *dest = indexed.scanLine(y); - if (mask->image.format() == QImage::Format_RGB16) { - const qint16 *src = (qint16 *) ((const QImage &) mask->image).scanLine(y); - for (int x=0; xwidth(); ++x) - dest[x] = 255 - qGray(src[x]); - } else { - const uint *src = (uint *) ((const QImage &) mask->image).scanLine(y); - for (int x=0; xwidth(); ++x) { -#ifdef Q_OS_WINCE - dest[x] = 255 - qGray(src[x]); -#else - if (QNativeImage::systemFormat() == QImage::Format_RGB16) - dest[x] = 255 - qGray(src[x]); - else - dest[x] = 255 - (qt_pow_gamma[qGray(src[x])] * 255. / 2047.); -#endif - } - } - } - - // Cleanup... - delete mask; - if (qt_cleartype_enabled) { - DeleteObject(font); - } - - return indexed; -} - -#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C -#define SPI_SETFONTSMOOTHINGCONTRAST 0x200D - -QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) -{ - HFONT font = hfont; - - int contrast; - SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) 1000, 0); - - QNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) contrast, 0); - - if (mask == 0) - return QImage(); - - // Gracefully handle the odd case when the display is 16-bit - const QImage source = mask->image.depth() == 32 - ? mask->image - : mask->image.convertToFormat(QImage::Format_RGB32); - - QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32); - for (int y=0; yheight(); ++y) { - uint *dest = (uint *) rgbMask.scanLine(y); - const uint *src = (uint *) source.scanLine(y); - for (int x=0; xwidth(); ++x) { - dest[x] = 0xffffffff - (0x00ffffff & src[x]); - } - } - - delete mask; - - return rgbMask; -} - -// From qfontdatabase_win.cpp -extern QFontEngine *qt_load_font_engine_win(const QFontDef &request); -QFontEngine *QFontEngineWin::cloneWithSize(qreal pixelSize) const -{ - QFontDef request = fontDef; - QString actualFontName = request.family; - if (!uniqueFamilyName.isEmpty()) - request.family = uniqueFamilyName; - request.pixelSize = pixelSize; - - QFontEngine *fontEngine = qt_load_font_engine_win(request); - if (fontEngine != NULL) - fontEngine->fontDef.family = actualFontName; - - return fontEngine; -} - -// -------------------------------------- Multi font engine - -QFontEngineMultiWin::QFontEngineMultiWin(QFontEngine *first, const QStringList &fallbacks) - : QFontEngineMulti(fallbacks.size()+1), - fallbacks(fallbacks) -{ - engines[0] = first; - first->ref.ref(); - fontDef = engines[0]->fontDef; - cache_cost = first->cache_cost; -} - -void QFontEngineMultiWin::loadEngine(int at) -{ - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - QString fam = fallbacks.at(at-1); - - LOGFONT lf = static_cast(engines.at(0))->logfont; - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded - HFONT hfont = CreateFontIndirect(&lf); - - bool stockFont = false; - if (hfont == 0) { - hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); - stockFont = true; - } - engines[at] = new QFontEngineWin(fam, hfont, stockFont, lf); - engines[at]->ref.ref(); - engines[at]->fontDef = fontDef; - - // TODO: increase cost in QFontCache for the font engine loaded here -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qfontengine_win_p.h b/src/widgets/platforms/win/qfontengine_win_p.h deleted file mode 100644 index ebcafffceb..0000000000 --- a/src/widgets/platforms/win/qfontengine_win_p.h +++ /dev/null @@ -1,164 +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_WIN_P_H -#define QFONTENGINE_WIN_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 - -QT_BEGIN_NAMESPACE - -class QNativeImage; - -class QFontEngineWin : public QFontEngine -{ -public: - QFontEngineWin(const QString &name, HFONT, bool, LOGFONT); - ~QFontEngineWin(); - - virtual QFixed lineThickness() const; - virtual Properties properties() const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual FaceId faceId() const; - virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - virtual int synthesized() const; - virtual QFixed emSquareSize() const; - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const; - - virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); - virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); - - HGDIOBJ selectDesignFont() const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t g) { return boundingBox(g, QTransform()); } - virtual glyph_metrics_t boundingBox(glyph_t g, const QTransform &t); - - - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual QFixed xHeight() const; - virtual QFixed averageCharWidth() const; - virtual qreal maxCharWidth() const; - virtual qreal minLeftBearing() const; - virtual qreal minRightBearing() const; - - virtual const char *name() const; - - bool canRender(const QChar *string, int len); - - Type type() const; - - virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); } - virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); - virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); - - virtual QFontEngine *cloneWithSize(qreal pixelSize) const; - -#ifndef Q_CC_MINGW - virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); -#endif - - int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; - void getCMap(); - -#ifndef Q_WS_WINCE - bool getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const; -#endif - - QString _name; - QString uniqueFamilyName; - HFONT hfont; - LOGFONT logfont; - uint stockFont : 1; - uint ttf : 1; - uint hasOutline : 1; - TEXTMETRIC tm; - int lw; - const unsigned char *cmap; - QByteArray cmapTable; - mutable qreal lbearing; - mutable qreal rbearing; - QFixed designToDevice; - int unitsPerEm; - QFixed x_height; - FaceId _faceId; - - mutable int synthesized_flags; - mutable QFixed lineWidth; - mutable unsigned char *widthCache; - mutable uint widthCacheSize; - mutable QFixed *designAdvances; - mutable int designAdvancesSize; - -private: - QNativeImage *drawGDIGlyph(HFONT font, glyph_t, int margin, const QTransform &xform, - QImage::Format mask_format); - -}; - -class QFontEngineMultiWin : public QFontEngineMulti -{ -public: - QFontEngineMultiWin(QFontEngine *first, const QStringList &fallbacks); - void loadEngine(int at); - - QStringList fallbacks; -}; - -QT_END_NAMESPACE - -#endif // QFONTENGINE_WIN_P_H diff --git a/src/widgets/platforms/win/qguifunctions_wince.cpp b/src/widgets/platforms/win/qguifunctions_wince.cpp deleted file mode 100644 index 78dc469b88..0000000000 --- a/src/widgets/platforms/win/qguifunctions_wince.cpp +++ /dev/null @@ -1,408 +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 "qguifunctions_wince.h" -#include -#include - -QT_USE_NAMESPACE - -struct AygSHINITDLGINFO -{ - DWORD dwMask; - HWND hDlg; - DWORD dwFlags; -}; - -struct AygSIPINFO -{ - DWORD cbSize; - DWORD fdwFlags; - RECT rcVisibleDesktop; - RECT rcSipRect; - DWORD dwImDataSize; - void *pvImData; -}; - -#ifndef SHIDIF_CANCELBUTTON -#define SHIDIF_CANCELBUTTON 0x0080 -#endif - -#ifndef SHIDIM_FLAGS -#define SHIDIM_FLAGS 0x0001 -#endif - -#ifndef SHIDIF_DONEBUTTON -#define SHIDIF_DONEBUTTON 0x0001 -#endif -#ifndef SHIDIF_SIZEDLGFULLSCREEN -#define SHIDIF_SIZEDLGFULLSCREEN 0x0004 -#endif - -#ifndef SHDB_HIDE -#define SHDB_HIDE 0x0002 -#endif - -#ifndef SHFS_SHOWTASKBAR -#define SHFS_SHOWTASKBAR 0x0001 -#endif -#ifndef SHFS_HIDETASKBAR -#define SHFS_HIDETASKBAR 0x0002 -#endif -#ifndef SHFS_SHOWSIPBUTTON -#define SHFS_SHOWSIPBUTTON 0x0004 -#endif -#ifndef SHFS_HIDESIPBUTTON -#define SHFS_HIDESIPBUTTON 0x0008 -#endif -#ifndef SHFS_SHOWSTARTICON -#define SHFS_SHOWSTARTICON 0x0010 -#endif -#ifndef SHFS_HIDESTARTICON -#define SHFS_HIDESTARTICON 0x0020 -#endif - -#ifndef SIPF_OFF -#define SIPF_OFF 0x00000000 -#endif -#ifndef SIPF_ON -#define SIPF_ON 0x00000001 -#endif - -#ifndef SPI_SETSIPINFO -#define SPI_SETSIPINFO 224 -#endif -#ifndef SPI_GETSIPINFO -#define SPI_GETSIPINFO 225 -#endif -#ifndef SPI_GETPLATFORMTYPE -#define SPI_GETPLATFORMTYPE 257 -#endif - -typedef BOOL (*AygInitDialog)(AygSHINITDLGINFO*); -typedef BOOL (*AygFullScreen)(HWND, DWORD); -typedef BOOL (*AygSHSipInfo)(UINT, UINT, PVOID, UINT); -typedef BOOL (*AygSHDoneButton)(HWND, DWORD); - -static AygInitDialog ptrAygInitDialog = 0; -static AygFullScreen ptrAygFullScreen = 0; -static AygSHSipInfo ptrAygSHSipInfo = 0; -static AygSHDoneButton ptrAygSHDoneButton = 0; -static bool aygResolved = false; - -static void resolveAygLibs() -{ - if (!aygResolved) { - aygResolved = true; - QLibrary ayglib(QLatin1String("aygshell")); - ptrAygInitDialog = (AygInitDialog) ayglib.resolve("SHInitDialog"); - ptrAygFullScreen = (AygFullScreen) ayglib.resolve("SHFullScreen"); - ptrAygSHSipInfo = (AygSHSipInfo) ayglib.resolve("SHSipInfo"); - ptrAygSHDoneButton = (AygSHDoneButton) ayglib.resolve("SHDoneButton"); - } -} - -int qt_wince_GetDIBits(HDC /*hdc*/ , HBITMAP hSourceBitmap, uint, uint, LPVOID lpvBits, LPBITMAPINFO, uint) -{ - if (!lpvBits) { - qWarning("::GetDIBits(), lpvBits NULL"); - return 0; - } - BITMAP bm; - GetObject(hSourceBitmap, sizeof(BITMAP), &bm); - bm.bmHeight = qAbs(bm.bmHeight); - - HBITMAP hTargetBitmap; - void *pixels; - - BITMAPINFO dibInfo; - memset(&dibInfo, 0, sizeof(dibInfo)); - dibInfo.bmiHeader.biBitCount = 32; - dibInfo.bmiHeader.biClrImportant = 0; - dibInfo.bmiHeader.biClrUsed = 0; - dibInfo.bmiHeader.biCompression = BI_RGB;; - dibInfo.bmiHeader.biHeight = -bm.bmHeight; - dibInfo.bmiHeader.biWidth = bm.bmWidth; - dibInfo.bmiHeader.biPlanes = 1; - dibInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - dibInfo.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4; - - HDC displayDC = GetDC(NULL); - if (!displayDC) { - qWarning("::GetDIBits(), failed to GetDC"); - return 0; - } - - int ret = bm.bmHeight; - - hTargetBitmap = CreateDIBSection(displayDC, (const BITMAPINFO*) &dibInfo, DIB_RGB_COLORS, - (void**)&pixels, NULL, 0); - if (!hTargetBitmap) { - qWarning("::GetDIBits(), failed to CreateDIBSection"); - return 0; - } - - HDC hdcSrc = CreateCompatibleDC(displayDC); - HDC hdcDst = CreateCompatibleDC(displayDC); - - if (!(hdcDst && hdcSrc)) { - qWarning("::GetDIBits(), failed to CreateCompatibleDC"); - ret = 0; - } - - HBITMAP hOldBitmap1 = (HBITMAP) SelectObject(hdcSrc, hSourceBitmap); - HBITMAP hOldBitmap2 = (HBITMAP) SelectObject(hdcDst, hTargetBitmap); - - if (!(hOldBitmap1 && hOldBitmap2)) { - qWarning("::GetDIBits(), failed to SelectObject for bitmaps"); - ret = 0; - } - - if (!BitBlt(hdcDst, 0, 0, bm.bmWidth, bm.bmHeight, hdcSrc, 0, 0, SRCCOPY)) { - qWarning("::GetDIBits(), BitBlt failed"); - ret = 0; - } - - SelectObject(hdcSrc, hOldBitmap1); - SelectObject(hdcDst, hOldBitmap2); - - DeleteDC(hdcSrc); - DeleteDC(hdcDst); - - ReleaseDC(NULL, displayDC); - - memcpy(lpvBits, pixels, dibInfo.bmiHeader.biSizeImage); - - DeleteObject(hTargetBitmap); - return ret; -} - -HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd) -{ - SHELLEXECUTEINFO info; - info.hwnd = hwnd; - info.lpVerb = L"Open"; - info.lpFile = file; - info.lpParameters = params; - info.lpDirectory = dir; - info.nShow = showCmd; - info.cbSize = sizeof(info); - ShellExecuteEx(&info); - return info.hInstApp; -} - -// Clipboard -------------------------------------------------------- -BOOL qt_wince_ChangeClipboardChain( HWND /*hWndRemove*/, HWND /*hWndNewNext*/ ) -{ - return FALSE; -} - -HWND qt_wince_SetClipboardViewer( HWND /*hWndNewViewer*/ ) -{ - return NULL; -} - - -// Graphics --------------------------------------------------------- -COLORREF qt_wince_PALETTEINDEX( WORD /*wPaletteIndex*/) -{ - return 0; -} - -// Internal Qt ----------------------------------------------------- -bool qt_wince_is_platform(const QString &platformString) { - wchar_t tszPlatform[64]; - if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(wchar_t), tszPlatform, 0)) - if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) - return true; - return false; -} - -int qt_wince_get_build() -{ - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(osvi); - if (GetVersionEx(&osvi)) { - return osvi.dwBuildNumber; - } - return 0; -} - -int qt_wince_get_version() -{ - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(osvi); - if (GetVersionEx(&osvi)) { - return (osvi.dwMajorVersion * 10 + osvi.dwMinorVersion); - } - return 0; -} - -bool qt_wince_is_windows_mobile_65() -{ - const DWORD dwFirstWM65BuildNumber = 21139; - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(osvi); - if (!GetVersionEx(&osvi)) - return false; - return osvi.dwMajorVersion > 5 - || (osvi.dwMajorVersion == 5 && (osvi.dwMinorVersion > 2 || - (osvi.dwMinorVersion == 2 && osvi.dwBuildNumber >= dwFirstWM65BuildNumber))); -} - -bool qt_wince_is_pocket_pc() { - return qt_wince_is_platform(QString::fromLatin1("PocketPC")); -} - -bool qt_wince_is_smartphone() { - return qt_wince_is_platform(QString::fromLatin1("Smartphone")); -} -bool qt_wince_is_mobile() { - return (qt_wince_is_smartphone() || qt_wince_is_pocket_pc()); -} - -bool qt_wince_is_high_dpi() { - if (!qt_wince_is_pocket_pc()) - return false; - HDC deviceContext = GetDC(0); - int dpi = GetDeviceCaps(deviceContext, LOGPIXELSX); - ReleaseDC(0, deviceContext); - if ((dpi < 1000) && (dpi > 0)) - return dpi > 96; - else - return false; -} - -void qt_wince_maximize(QWidget *widget) -{ - HWND hwnd = widget->winId(); - if (qt_wince_is_mobile()) { - AygSHINITDLGINFO shidi; - shidi.dwMask = SHIDIM_FLAGS; - shidi.hDlg = hwnd; - shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN; - if (widget->windowFlags() & Qt::WindowCancelButtonHint) - shidi.dwFlags |= SHIDIF_CANCELBUTTON; - if (widget->windowFlags() & Qt::WindowOkButtonHint) - shidi.dwFlags |= SHIDIF_DONEBUTTON; - if (!(widget->windowFlags() & (Qt::WindowCancelButtonHint | Qt::WindowOkButtonHint))) - shidi.dwFlags |= SHIDIF_CANCELBUTTON; - resolveAygLibs(); - if (ptrAygInitDialog) - ptrAygInitDialog(&shidi); - } else { - RECT r; - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - MoveWindow(hwnd, r.top, r.left, r.right - r.left, r.bottom - r.top, true); - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NODRAG); - } -} - -void qt_wince_unmaximize(QWidget *widget) -{ - if (ptrAygSHDoneButton && qt_wince_is_mobile() - && !(widget->windowFlags() & (Qt::WindowCancelButtonHint | Qt::WindowOkButtonHint))) - { - // Hide the [X] button, we've added in qt_wince_maximize. - ptrAygSHDoneButton(widget->winId(), SHDB_HIDE); - } -} - -void qt_wince_minimize(HWND hwnd) -{ -#ifdef Q_OS_WINCE_WM - ShowWindow(hwnd, SW_HIDE); -#else - if (!IsWindowVisible(hwnd)) { - // Hack for an initial showMinimized. - // Without it, our widget doesn't appear in the task bar. - ShowWindow(hwnd, SW_SHOW); - } - ShowWindow(hwnd, SW_MINIMIZE); -#endif -} - -void qt_wince_hide_taskbar(HWND hwnd) { - if (ptrAygFullScreen) - ptrAygFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON); -} - -void qt_wince_full_screen(HWND hwnd, bool fullScreen, UINT swpf) { - resolveAygLibs(); - if (fullScreen) { - QRect r = qApp->desktop()->screenGeometry(QWidget::find(hwnd)); - SetWindowPos(hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf); - if (ptrAygFullScreen) - ptrAygFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON); - if (!qt_wince_is_mobile()) { - HWND handle = FindWindow(L"HHTaskBar", L""); - if (handle) { - ShowWindow(handle, 0); - EnableWindow(handle, false); - } - } - } else { - if (ptrAygFullScreen) - ptrAygFullScreen(hwnd, SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON | SHFS_SHOWSTARTICON); - SetWindowPos(hwnd, 0, 0, 0, 0, 0, swpf); - if (!qt_wince_is_mobile()) { - HWND handle = FindWindow(L"HHTaskBar", L""); - if (handle) { - ShowWindow(handle, 1); - EnableWindow(handle, true); - } - } - } -} - -void qt_wince_show_SIP(bool show) -{ - resolveAygLibs(); - if (!ptrAygSHSipInfo) - return; - - AygSIPINFO si; - memset(&si, 0, sizeof(si)); - si.cbSize = sizeof(si); - ptrAygSHSipInfo(SPI_GETSIPINFO, 0, &si, 0); - si.cbSize = sizeof(si); - si.fdwFlags = (show ? SIPF_ON : SIPF_OFF); - ptrAygSHSipInfo(SPI_SETSIPINFO, 0, &si, 0); -} diff --git a/src/widgets/platforms/win/qguifunctions_wince.h b/src/widgets/platforms/win/qguifunctions_wince.h deleted file mode 100644 index 6384e4ac62..0000000000 --- a/src/widgets/platforms/win/qguifunctions_wince.h +++ /dev/null @@ -1,151 +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 QGUIFUNCTIONS_WCE_H -#define QGUIFUNCTIONS_WCE_H -#ifdef Q_OS_WINCE -#include -#define UNDER_NT -#include - -#ifdef QT_BUILD_GUI_LIB -QT_BEGIN_HEADER -QT_BEGIN_NAMESPACE -QT_MODULE(Gui) -QT_END_NAMESPACE -QT_END_HEADER -#endif - -// application defines -#define SPI_SETNONCLIENTMETRICS 72 -#define SPI_SETICONTITLELOGFONT 0x0022 -#define WM_ACTIVATEAPP 0x001c -#define SW_PARENTCLOSING 1 -#define SW_OTHERMAXIMIZED 2 -#define SW_PARENTOPENING 3 -#define SW_OTHERRESTORED 4 -#define GET_XBUTTON_WPARAM(wParam) (HIWORD(wParam)) - -// drag n drop -#ifndef CFSTR_PERFORMEDDROPEFFECT -#define CFSTR_PERFORMEDDROPEFFECT TEXT("Performed DropEffect") -#endif -int qt_wince_GetDIBits(HDC, HBITMAP, uint, uint, void*, LPBITMAPINFO, uint); -#define GetDIBits(a,b,c,d,e,f,g) qt_wince_GetDIBits(a,b,c,d,e,f,g) - -// QWidget -#define SW_SHOWMINIMIZED SW_MINIMIZE - -// QRegion -#define ALTERNATE 0 -#define WINDING 1 - -// QFontEngine -typedef struct _FIXED { - WORD fract; - short value; -} FIXED; - -typedef struct tagPOINTFX { - FIXED x; - FIXED y; -} POINTFX; - -typedef struct _MAT2 { - FIXED eM11; - FIXED eM12; - FIXED eM21; - FIXED eM22; -} MAT2; - -typedef struct _GLYPHMETRICS { - UINT gmBlackBoxX; - UINT gmBlackBoxY; - POINT gmptGlyphOrigin; - short gmCellIncX; - short gmCellIncY; -} GLYPHMETRICS; - -typedef struct tagTTPOLYGONHEADER -{ - DWORD cb; - DWORD dwType; - POINTFX pfxStart; -} TTPOLYGONHEADER; - -typedef struct tagTTPOLYCURVE -{ - WORD wType; - WORD cpfx; - POINTFX apfx[1]; -} TTPOLYCURVE; - -#define GGO_NATIVE 2 -#define GGO_GLYPH_INDEX 0x0080 -#define TT_PRIM_LINE 1 -#define TT_PRIM_QSPLINE 2 -#define TT_PRIM_CSPLINE 3 -#define ANSI_VAR_FONT 12 - -HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd); -#define ShellExecute(a,b,c,d,e,f) qt_wince_ShellExecute(a,b,c,d,e,f) - - -// Clipboard -------------------------------------------------------- -#define WM_CHANGECBCHAIN 1 -#define WM_DRAWCLIPBOARD 2 - -BOOL qt_wince_ChangeClipboardChain( - HWND hWndRemove, // handle to window to remove - HWND hWndNewNext // handle to next window -); -#define ChangeClipboardChain(a,b) qt_wince_ChangeClipboardChain(a,b); - -HWND qt_wince_SetClipboardViewer( - HWND hWndNewViewer // handle to clipboard viewer window -); -#define SetClipboardViewer(a) qt_wince_SetClipboardViewer(a) - -// Graphics --------------------------------------------------------- -COLORREF qt_wince_PALETTEINDEX( WORD wPaletteIndex ); -#define PALETTEINDEX(a) qt_wince_PALETTEINDEX(a) - -#endif // Q_OS_WINCE -#endif // QGUIFUNCTIONS_WCE_H diff --git a/src/widgets/platforms/win/qkeymapper_win.cpp b/src/widgets/platforms/win/qkeymapper_win.cpp deleted file mode 100644 index 076b37038d..0000000000 --- a/src/widgets/platforms/win/qkeymapper_win.cpp +++ /dev/null @@ -1,1191 +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 -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -// Uncommend, to show debugging information for the keymapper -//#define DEBUG_KEYMAPPER - -// Implemented elsewhere -extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); - -extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); -#ifndef LANG_PASHTO -#define LANG_PASHTO 0x63 -#endif -#ifndef LANG_SYRIAC -#define LANG_SYRIAC 0x5a -#endif -#ifndef LANG_DIVEHI -#define LANG_DIVEHI 0x65 -#endif -#ifndef VK_OEM_PLUS -#define VK_OEM_PLUS 0xBB -#endif -#ifndef VK_OEM_3 -#define VK_OEM_3 0xC0 -#endif - -#if defined(Q_OS_WINCE) -bool GetKeyboardState(unsigned char* kbuffer) -{ - for (int i=0; i< 256; ++i) - kbuffer[i] = GetAsyncKeyState(i); - return true; -} -#endif -// Key recorder ------------------------------------------------------------------------[ start ] -- -struct KeyRecord { - KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {} - KeyRecord() {} - - int code; - int ascii; - int state; - QString text; -}; - -static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers... -struct KeyRecorder -{ - KeyRecorder() : nrecs(0) {} - - inline KeyRecord *findKey(int code, bool remove); - inline void storeKey(int code, int ascii, int state, const QString& text); - inline void clearKeys(); - - int nrecs; - KeyRecord deleted_record; // A copy of last entry removed from records[] - KeyRecord records[QT_MAX_KEY_RECORDINGS]; -}; -static KeyRecorder key_recorder; - -KeyRecord *KeyRecorder::findKey(int code, bool remove) -{ - KeyRecord *result = 0; - for (int i = 0; i < nrecs; ++i) { - if (records[i].code == code) { - if (remove) { - deleted_record = records[i]; - // Move rest down, and decrease count - while (i + 1 < nrecs) { - records[i] = records[i + 1]; - ++i; - } - --nrecs; - result = &deleted_record; - } else { - result = &records[i]; - } - break; - } - } - return result; -} - -void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text) -{ - Q_ASSERT_X(nrecs != QT_MAX_KEY_RECORDINGS, - "Internal KeyRecorder", - "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS"); - - if (nrecs == QT_MAX_KEY_RECORDINGS) { - qWarning("Qt: Internal keyboard buffer overflow"); - return; - } - records[nrecs++] = KeyRecord(code,ascii,state,text); -} - -void KeyRecorder::clearKeys() -{ - nrecs = 0; -} -// Key recorder --------------------------------------------------------------------------[ end ] -- - - -// Key translation ---------------------------------------------------------------------[ start ] -- -// Meaning of values: -// 0 = Character output key, needs keyboard driver mapping -// Key_unknown = Unknown Virtual Key, no translation possible, ignore -static const uint KeyTbl[] = { // Keyboard mapping table - // Dec | Hex | Windows Virtual key - Qt::Key_unknown, // 0 0x00 - Qt::Key_unknown, // 1 0x01 VK_LBUTTON | Left mouse button - Qt::Key_unknown, // 2 0x02 VK_RBUTTON | Right mouse button - Qt::Key_Cancel, // 3 0x03 VK_CANCEL | Control-Break processing - Qt::Key_unknown, // 4 0x04 VK_MBUTTON | Middle mouse button - Qt::Key_unknown, // 5 0x05 VK_XBUTTON1 | X1 mouse button - Qt::Key_unknown, // 6 0x06 VK_XBUTTON2 | X2 mouse button - Qt::Key_unknown, // 7 0x07 -- unassigned -- - Qt::Key_Backspace, // 8 0x08 VK_BACK | BackSpace key - Qt::Key_Tab, // 9 0x09 VK_TAB | Tab key - Qt::Key_unknown, // 10 0x0A -- reserved -- - Qt::Key_unknown, // 11 0x0B -- reserved -- - Qt::Key_Clear, // 12 0x0C VK_CLEAR | Clear key - Qt::Key_Return, // 13 0x0D VK_RETURN | Enter key - Qt::Key_unknown, // 14 0x0E -- unassigned -- - Qt::Key_unknown, // 15 0x0F -- unassigned -- - Qt::Key_Shift, // 16 0x10 VK_SHIFT | Shift key - Qt::Key_Control, // 17 0x11 VK_CONTROL | Ctrl key - Qt::Key_Alt, // 18 0x12 VK_MENU | Alt key - Qt::Key_Pause, // 19 0x13 VK_PAUSE | Pause key - Qt::Key_CapsLock, // 20 0x14 VK_CAPITAL | Caps-Lock - Qt::Key_unknown, // 21 0x15 VK_KANA / VK_HANGUL | IME Kana or Hangul mode - Qt::Key_unknown, // 22 0x16 -- unassigned -- - Qt::Key_unknown, // 23 0x17 VK_JUNJA | IME Junja mode - Qt::Key_unknown, // 24 0x18 VK_FINAL | IME final mode - Qt::Key_unknown, // 25 0x19 VK_HANJA / VK_KANJI | IME Hanja or Kanji mode - Qt::Key_unknown, // 26 0x1A -- unassigned -- - Qt::Key_Escape, // 27 0x1B VK_ESCAPE | Esc key - Qt::Key_unknown, // 28 0x1C VK_CONVERT | IME convert - Qt::Key_unknown, // 29 0x1D VK_NONCONVERT | IME non-convert - Qt::Key_unknown, // 30 0x1E VK_ACCEPT | IME accept - Qt::Key_Mode_switch,// 31 0x1F VK_MODECHANGE | IME mode change request - Qt::Key_Space, // 32 0x20 VK_SPACE | Spacebar - Qt::Key_PageUp, // 33 0x21 VK_PRIOR | Page Up key - Qt::Key_PageDown, // 34 0x22 VK_NEXT | Page Down key - Qt::Key_End, // 35 0x23 VK_END | End key - Qt::Key_Home, // 36 0x24 VK_HOME | Home key - Qt::Key_Left, // 37 0x25 VK_LEFT | Left arrow key - Qt::Key_Up, // 38 0x26 VK_UP | Up arrow key - Qt::Key_Right, // 39 0x27 VK_RIGHT | Right arrow key - Qt::Key_Down, // 40 0x28 VK_DOWN | Down arrow key - Qt::Key_Select, // 41 0x29 VK_SELECT | Select key - Qt::Key_Printer, // 42 0x2A VK_PRINT | Print key - Qt::Key_Execute, // 43 0x2B VK_EXECUTE | Execute key - Qt::Key_Print, // 44 0x2C VK_SNAPSHOT | Print Screen key - Qt::Key_Insert, // 45 0x2D VK_INSERT | Ins key - Qt::Key_Delete, // 46 0x2E VK_DELETE | Del key - Qt::Key_Help, // 47 0x2F VK_HELP | Help key - 0, // 48 0x30 (VK_0) | 0 key - 0, // 49 0x31 (VK_1) | 1 key - 0, // 50 0x32 (VK_2) | 2 key - 0, // 51 0x33 (VK_3) | 3 key - 0, // 52 0x34 (VK_4) | 4 key - 0, // 53 0x35 (VK_5) | 5 key - 0, // 54 0x36 (VK_6) | 6 key - 0, // 55 0x37 (VK_7) | 7 key - 0, // 56 0x38 (VK_8) | 8 key - 0, // 57 0x39 (VK_9) | 9 key - Qt::Key_unknown, // 58 0x3A -- unassigned -- - Qt::Key_unknown, // 59 0x3B -- unassigned -- - Qt::Key_unknown, // 60 0x3C -- unassigned -- - Qt::Key_unknown, // 61 0x3D -- unassigned -- - Qt::Key_unknown, // 62 0x3E -- unassigned -- - Qt::Key_unknown, // 63 0x3F -- unassigned -- - Qt::Key_unknown, // 64 0x40 -- unassigned -- - 0, // 65 0x41 (VK_A) | A key - 0, // 66 0x42 (VK_B) | B key - 0, // 67 0x43 (VK_C) | C key - 0, // 68 0x44 (VK_D) | D key - 0, // 69 0x45 (VK_E) | E key - 0, // 70 0x46 (VK_F) | F key - 0, // 71 0x47 (VK_G) | G key - 0, // 72 0x48 (VK_H) | H key - 0, // 73 0x49 (VK_I) | I key - 0, // 74 0x4A (VK_J) | J key - 0, // 75 0x4B (VK_K) | K key - 0, // 76 0x4C (VK_L) | L key - 0, // 77 0x4D (VK_M) | M key - 0, // 78 0x4E (VK_N) | N key - 0, // 79 0x4F (VK_O) | O key - 0, // 80 0x50 (VK_P) | P key - 0, // 81 0x51 (VK_Q) | Q key - 0, // 82 0x52 (VK_R) | R key - 0, // 83 0x53 (VK_S) | S key - 0, // 84 0x54 (VK_T) | T key - 0, // 85 0x55 (VK_U) | U key - 0, // 86 0x56 (VK_V) | V key - 0, // 87 0x57 (VK_W) | W key - 0, // 88 0x58 (VK_X) | X key - 0, // 89 0x59 (VK_Y) | Y key - 0, // 90 0x5A (VK_Z) | Z key - Qt::Key_Meta, // 91 0x5B VK_LWIN | Left Windows - MS Natural kbd - Qt::Key_Meta, // 92 0x5C VK_RWIN | Right Windows - MS Natural kbd - Qt::Key_Menu, // 93 0x5D VK_APPS | Application key-MS Natural kbd - Qt::Key_unknown, // 94 0x5E -- reserved -- - Qt::Key_Sleep, // 95 0x5F VK_SLEEP - Qt::Key_0, // 96 0x60 VK_NUMPAD0 | Numeric keypad 0 key - Qt::Key_1, // 97 0x61 VK_NUMPAD1 | Numeric keypad 1 key - Qt::Key_2, // 98 0x62 VK_NUMPAD2 | Numeric keypad 2 key - Qt::Key_3, // 99 0x63 VK_NUMPAD3 | Numeric keypad 3 key - Qt::Key_4, // 100 0x64 VK_NUMPAD4 | Numeric keypad 4 key - Qt::Key_5, // 101 0x65 VK_NUMPAD5 | Numeric keypad 5 key - Qt::Key_6, // 102 0x66 VK_NUMPAD6 | Numeric keypad 6 key - Qt::Key_7, // 103 0x67 VK_NUMPAD7 | Numeric keypad 7 key - Qt::Key_8, // 104 0x68 VK_NUMPAD8 | Numeric keypad 8 key - Qt::Key_9, // 105 0x69 VK_NUMPAD9 | Numeric keypad 9 key - Qt::Key_Asterisk, // 106 0x6A VK_MULTIPLY | Multiply key - Qt::Key_Plus, // 107 0x6B VK_ADD | Add key - Qt::Key_Comma, // 108 0x6C VK_SEPARATOR | Separator key - Qt::Key_Minus, // 109 0x6D VK_SUBTRACT | Subtract key - Qt::Key_Period, // 110 0x6E VK_DECIMAL | Decimal key - Qt::Key_Slash, // 111 0x6F VK_DIVIDE | Divide key - Qt::Key_F1, // 112 0x70 VK_F1 | F1 key - Qt::Key_F2, // 113 0x71 VK_F2 | F2 key - Qt::Key_F3, // 114 0x72 VK_F3 | F3 key - Qt::Key_F4, // 115 0x73 VK_F4 | F4 key - Qt::Key_F5, // 116 0x74 VK_F5 | F5 key - Qt::Key_F6, // 117 0x75 VK_F6 | F6 key - Qt::Key_F7, // 118 0x76 VK_F7 | F7 key - Qt::Key_F8, // 119 0x77 VK_F8 | F8 key - Qt::Key_F9, // 120 0x78 VK_F9 | F9 key - Qt::Key_F10, // 121 0x79 VK_F10 | F10 key - Qt::Key_F11, // 122 0x7A VK_F11 | F11 key - Qt::Key_F12, // 123 0x7B VK_F12 | F12 key - Qt::Key_F13, // 124 0x7C VK_F13 | F13 key - Qt::Key_F14, // 125 0x7D VK_F14 | F14 key - Qt::Key_F15, // 126 0x7E VK_F15 | F15 key - Qt::Key_F16, // 127 0x7F VK_F16 | F16 key - Qt::Key_F17, // 128 0x80 VK_F17 | F17 key - Qt::Key_F18, // 129 0x81 VK_F18 | F18 key - Qt::Key_F19, // 130 0x82 VK_F19 | F19 key - Qt::Key_F20, // 131 0x83 VK_F20 | F20 key - Qt::Key_F21, // 132 0x84 VK_F21 | F21 key - Qt::Key_F22, // 133 0x85 VK_F22 | F22 key - Qt::Key_F23, // 134 0x86 VK_F23 | F23 key - Qt::Key_F24, // 135 0x87 VK_F24 | F24 key - Qt::Key_unknown, // 136 0x88 -- unassigned -- - Qt::Key_unknown, // 137 0x89 -- unassigned -- - Qt::Key_unknown, // 138 0x8A -- unassigned -- - Qt::Key_unknown, // 139 0x8B -- unassigned -- - Qt::Key_unknown, // 140 0x8C -- unassigned -- - Qt::Key_unknown, // 141 0x8D -- unassigned -- - Qt::Key_unknown, // 142 0x8E -- unassigned -- - Qt::Key_unknown, // 143 0x8F -- unassigned -- - Qt::Key_NumLock, // 144 0x90 VK_NUMLOCK | Num Lock key - Qt::Key_ScrollLock, // 145 0x91 VK_SCROLL | Scroll Lock key - // Fujitsu/OASYS kbd -------------------- - 0, //Qt::Key_Jisho, // 146 0x92 VK_OEM_FJ_JISHO | 'Dictionary' key / - // VK_OEM_NEC_EQUAL = key on numpad on NEC PC-9800 kbd - Qt::Key_Massyo, // 147 0x93 VK_OEM_FJ_MASSHOU | 'Unregister word' key - Qt::Key_Touroku, // 148 0x94 VK_OEM_FJ_TOUROKU | 'Register word' key - 0, //Qt::Key_Oyayubi_Left,//149 0x95 VK_OEM_FJ_LOYA | 'Left OYAYUBI' key - 0, //Qt::Key_Oyayubi_Right,//150 0x96 VK_OEM_FJ_ROYA | 'Right OYAYUBI' key - Qt::Key_unknown, // 151 0x97 -- unassigned -- - Qt::Key_unknown, // 152 0x98 -- unassigned -- - Qt::Key_unknown, // 153 0x99 -- unassigned -- - Qt::Key_unknown, // 154 0x9A -- unassigned -- - Qt::Key_unknown, // 155 0x9B -- unassigned -- - Qt::Key_unknown, // 156 0x9C -- unassigned -- - Qt::Key_unknown, // 157 0x9D -- unassigned -- - Qt::Key_unknown, // 158 0x9E -- unassigned -- - Qt::Key_unknown, // 159 0x9F -- unassigned -- - Qt::Key_Shift, // 160 0xA0 VK_LSHIFT | Left Shift key - Qt::Key_Shift, // 161 0xA1 VK_RSHIFT | Right Shift key - Qt::Key_Control, // 162 0xA2 VK_LCONTROL | Left Ctrl key - Qt::Key_Control, // 163 0xA3 VK_RCONTROL | Right Ctrl key - Qt::Key_Alt, // 164 0xA4 VK_LMENU | Left Menu key - Qt::Key_Alt, // 165 0xA5 VK_RMENU | Right Menu key - Qt::Key_Back, // 166 0xA6 VK_BROWSER_BACK | Browser Back key - Qt::Key_Forward, // 167 0xA7 VK_BROWSER_FORWARD | Browser Forward key - Qt::Key_Refresh, // 168 0xA8 VK_BROWSER_REFRESH | Browser Refresh key - Qt::Key_Stop, // 169 0xA9 VK_BROWSER_STOP | Browser Stop key - Qt::Key_Search, // 170 0xAA VK_BROWSER_SEARCH | Browser Search key - Qt::Key_Favorites, // 171 0xAB VK_BROWSER_FAVORITES| Browser Favorites key - Qt::Key_HomePage, // 172 0xAC VK_BROWSER_HOME | Browser Start and Home key - Qt::Key_VolumeMute, // 173 0xAD VK_VOLUME_MUTE | Volume Mute key - Qt::Key_VolumeDown, // 174 0xAE VK_VOLUME_DOWN | Volume Down key - Qt::Key_VolumeUp, // 175 0xAF VK_VOLUME_UP | Volume Up key - Qt::Key_MediaNext, // 176 0xB0 VK_MEDIA_NEXT_TRACK | Next Track key - Qt::Key_MediaPrevious, //177 0xB1 VK_MEDIA_PREV_TRACK | Previous Track key - Qt::Key_MediaStop, // 178 0xB2 VK_MEDIA_STOP | Stop Media key - Qt::Key_MediaPlay, // 179 0xB3 VK_MEDIA_PLAY_PAUSE | Play/Pause Media key - Qt::Key_LaunchMail, // 180 0xB4 VK_LAUNCH_MAIL | Start Mail key - Qt::Key_LaunchMedia,// 181 0xB5 VK_LAUNCH_MEDIA_SELECT Select Media key - Qt::Key_Launch0, // 182 0xB6 VK_LAUNCH_APP1 | Start Application 1 key - Qt::Key_Launch1, // 183 0xB7 VK_LAUNCH_APP2 | Start Application 2 key - Qt::Key_unknown, // 184 0xB8 -- reserved -- - Qt::Key_unknown, // 185 0xB9 -- reserved -- - 0, // 186 0xBA VK_OEM_1 | ';:' for US - 0, // 187 0xBB VK_OEM_PLUS | '+' any country - 0, // 188 0xBC VK_OEM_COMMA | ',' any country - 0, // 189 0xBD VK_OEM_MINUS | '-' any country - 0, // 190 0xBE VK_OEM_PERIOD | '.' any country - 0, // 191 0xBF VK_OEM_2 | '/?' for US - 0, // 192 0xC0 VK_OEM_3 | '`~' for US - Qt::Key_unknown, // 193 0xC1 -- reserved -- - Qt::Key_unknown, // 194 0xC2 -- reserved -- - Qt::Key_unknown, // 195 0xC3 -- reserved -- - Qt::Key_unknown, // 196 0xC4 -- reserved -- - Qt::Key_unknown, // 197 0xC5 -- reserved -- - Qt::Key_unknown, // 198 0xC6 -- reserved -- - Qt::Key_unknown, // 199 0xC7 -- reserved -- - Qt::Key_unknown, // 200 0xC8 -- reserved -- - Qt::Key_unknown, // 201 0xC9 -- reserved -- - Qt::Key_unknown, // 202 0xCA -- reserved -- - Qt::Key_unknown, // 203 0xCB -- reserved -- - Qt::Key_unknown, // 204 0xCC -- reserved -- - Qt::Key_unknown, // 205 0xCD -- reserved -- - Qt::Key_unknown, // 206 0xCE -- reserved -- - Qt::Key_unknown, // 207 0xCF -- reserved -- - Qt::Key_unknown, // 208 0xD0 -- reserved -- - Qt::Key_unknown, // 209 0xD1 -- reserved -- - Qt::Key_unknown, // 210 0xD2 -- reserved -- - Qt::Key_unknown, // 211 0xD3 -- reserved -- - Qt::Key_unknown, // 212 0xD4 -- reserved -- - Qt::Key_unknown, // 213 0xD5 -- reserved -- - Qt::Key_unknown, // 214 0xD6 -- reserved -- - Qt::Key_unknown, // 215 0xD7 -- reserved -- - Qt::Key_unknown, // 216 0xD8 -- unassigned -- - Qt::Key_unknown, // 217 0xD9 -- unassigned -- - Qt::Key_unknown, // 218 0xDA -- unassigned -- - 0, // 219 0xDB VK_OEM_4 | '[{' for US - 0, // 220 0xDC VK_OEM_5 | '\|' for US - 0, // 221 0xDD VK_OEM_6 | ']}' for US - 0, // 222 0xDE VK_OEM_7 | ''"' for US - 0, // 223 0xDF VK_OEM_8 - Qt::Key_unknown, // 224 0xE0 -- reserved -- - Qt::Key_unknown, // 225 0xE1 VK_OEM_AX | 'AX' key on Japanese AX kbd - Qt::Key_unknown, // 226 0xE2 VK_OEM_102 | "<>" or "\|" on RT 102-key kbd - Qt::Key_unknown, // 227 0xE3 VK_ICO_HELP | Help key on ICO - Qt::Key_unknown, // 228 0xE4 VK_ICO_00 | 00 key on ICO - Qt::Key_unknown, // 229 0xE5 VK_PROCESSKEY | IME Process key - Qt::Key_unknown, // 230 0xE6 VK_ICO_CLEAR | - Qt::Key_unknown, // 231 0xE7 VK_PACKET | Unicode char as keystrokes - Qt::Key_unknown, // 232 0xE8 -- unassigned -- - // Nokia/Ericsson definitions --------------- - Qt::Key_unknown, // 233 0xE9 VK_OEM_RESET - Qt::Key_unknown, // 234 0xEA VK_OEM_JUMP - Qt::Key_unknown, // 235 0xEB VK_OEM_PA1 - Qt::Key_unknown, // 236 0xEC VK_OEM_PA2 - Qt::Key_unknown, // 237 0xED VK_OEM_PA3 - Qt::Key_unknown, // 238 0xEE VK_OEM_WSCTRL - Qt::Key_unknown, // 239 0xEF VK_OEM_CUSEL - Qt::Key_unknown, // 240 0xF0 VK_OEM_ATTN - Qt::Key_unknown, // 241 0xF1 VK_OEM_FINISH - Qt::Key_unknown, // 242 0xF2 VK_OEM_COPY - Qt::Key_unknown, // 243 0xF3 VK_OEM_AUTO - Qt::Key_unknown, // 244 0xF4 VK_OEM_ENLW - Qt::Key_unknown, // 245 0xF5 VK_OEM_BACKTAB - Qt::Key_unknown, // 246 0xF6 VK_ATTN | Attn key - Qt::Key_unknown, // 247 0xF7 VK_CRSEL | CrSel key - Qt::Key_unknown, // 248 0xF8 VK_EXSEL | ExSel key - Qt::Key_unknown, // 249 0xF9 VK_EREOF | Erase EOF key - Qt::Key_Play, // 250 0xFA VK_PLAY | Play key - Qt::Key_Zoom, // 251 0xFB VK_ZOOM | Zoom key - Qt::Key_unknown, // 252 0xFC VK_NONAME | Reserved - Qt::Key_unknown, // 253 0xFD VK_PA1 | PA1 key - Qt::Key_Clear, // 254 0xFE VK_OEM_CLEAR | Clear key - 0 -}; - -// Possible modifier states. -// NOTE: The order of these states match the order in QKeyMapperPrivate::updatePossibleKeyCodes()! -static const Qt::KeyboardModifiers ModsTbl[] = { - Qt::NoModifier, // 0 - Qt::ShiftModifier, // 1 - Qt::ControlModifier, // 2 - Qt::ControlModifier | Qt::ShiftModifier, // 3 - Qt::AltModifier, // 4 - Qt::AltModifier | Qt::ShiftModifier, // 5 - Qt::AltModifier | Qt::ControlModifier, // 6 - Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::NoModifier, // Fall-back to raw Key_* -}; - -/** - Remap return or action key to select key for windows mobile. -*/ -inline int winceKeyBend(int keyCode) -{ -#if defined(Q_OS_WINCE_WM) && defined(QT_KEYPAD_NAVIGATION) - // remap return or action key to select key for windows mobile. - // will be changed to a table remapping function in the next version (4.6/7). - if (keyCode == VK_RETURN && QApplication::keypadNavigationEnabled()) - return Qt::Key_Select; - else - return KeyTbl[keyCode]; -#else - return KeyTbl[keyCode]; -#endif -} - -#if defined(Q_OS_WINCE) - // Use the KeyTbl to resolve a Qt::Key out of the virtual keys. - // In case it is not resolvable, continue using the virtual key itself. - -QT_BEGIN_INCLUDE_NAMESPACE - -int ToUnicode(UINT vk, int /*scancode*/, unsigned char* /*kbdBuffer*/, LPWSTR unicodeBuffer, int, int) -{ - QT_USE_NAMESPACE - QChar* buf = reinterpret_cast< QChar*>(unicodeBuffer); - if (KeyTbl[vk] == 0) { - buf[0] = vk; - return 1; - } - return 0; -} - -int ToAscii(UINT vk, int scancode, unsigned char *kbdBuffer, LPWORD unicodeBuffer, int flag) -{ - return ToUnicode(vk, scancode, kbdBuffer, (LPWSTR) unicodeBuffer, 0, flag); - -} -QT_END_INCLUDE_NAMESPACE - -#endif - -// Translate a VK into a Qt key code, or unicode character -static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, bool *isDeadkey = 0) -{ - Q_ASSERT(vk > 0 && vk < 256); - int code = 0; - QChar unicodeBuffer[5]; - int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast(unicodeBuffer), 5, 0); - if (res) - code = unicodeBuffer[0].toUpper().unicode(); - - // Qt::Key_*'s are not encoded below 0x20, so try again, and DEL keys (0x7f) is encoded with a - // proper Qt::Key_ code - if (code < 0x20 || code == 0x7f) // Handles res==0 too - code = winceKeyBend(vk); - - if (isDeadkey) - *isDeadkey = (res == -1); - - return code == Qt::Key_unknown ? 0 : code; -} - -Q_WIDGETS_EXPORT int qt_translateKeyCode(int vk) -{ - int code = winceKeyBend((vk < 0 || vk > 255) ? 0 : vk); - return code == Qt::Key_unknown ? 0 : code; -} - -static inline int asciiToKeycode(char a, int state) -{ - if (a >= 'a' && a <= 'z') - a = toupper(a); - if ((state & Qt::ControlModifier) != 0) { - if (a >= 0 && a <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_ - a += '@'; // to @..A..Z.._ - } - return a & 0xff; -} - -static inline bool isModifierKey(int code) -{ - return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock); -} -// Key translation -----------------------------------------------------------------------[ end ]--- - - -static void qt_show_system_menu(QWidget* tlw) -{ - Q_ASSERT(tlw->testAttribute(Qt::WA_WState_Created)); - HMENU menu = GetSystemMenu(tlw->internalWinId(), FALSE); - if (!menu) - return; // no menu for this window - -#define enabled (MF_BYCOMMAND | MF_ENABLED) -#define disabled (MF_BYCOMMAND | MF_GRAYED) - -#ifndef Q_OS_WINCE - EnableMenuItem(menu, SC_MINIMIZE, (tlw->windowFlags() & Qt::WindowMinimizeButtonHint)?enabled:disabled); - bool maximized = IsZoomed(tlw->internalWinId()); - - EnableMenuItem(menu, SC_MAXIMIZE, ! (tlw->windowFlags() & Qt::WindowMaximizeButtonHint) || maximized?disabled:enabled); - EnableMenuItem(menu, SC_RESTORE, maximized?enabled:disabled); - - // We should _not_ check with the setFixedSize(x,y) case here, since Windows is not able to check - // this and our menu here would be out-of-sync with the menu produced by mouse-click on the - // System Menu, or right-click on the title bar. - EnableMenuItem(menu, SC_SIZE, (tlw->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || maximized?disabled:enabled); - EnableMenuItem(menu, SC_MOVE, maximized?disabled:enabled); - EnableMenuItem(menu, SC_CLOSE, enabled); - // Set bold on close menu item - MENUITEMINFO closeItem; - closeItem.cbSize = sizeof(MENUITEMINFO); - closeItem.fMask = MIIM_STATE; - closeItem.fState = MFS_DEFAULT; - SetMenuItemInfo(menu, SC_CLOSE, FALSE, &closeItem); -#endif - -#undef enabled -#undef disabled - int ret = TrackPopupMenuEx(menu, - TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, - tlw->geometry().x(), tlw->geometry().y(), - tlw->internalWinId(), - 0); - if (ret) - QtWndProc(tlw->internalWinId(), WM_SYSCOMMAND, ret, 0); -} - - -// QETWidget class is only for accessing the sendSpontaneousEvent function in QApplication -class QETWidget : public QWidget { -public: - static bool sendSpontaneousEvent(QObject *r, QEvent *e) - { return QApplication::sendSpontaneousEvent(r, e); } -}; - - -// Keyboard map private ----------------------------------------------------------------[ start ]--- - -/* - \internal - A Windows KeyboardLayoutItem has 8 possible states: - 1. Unmodified - 2. Shift - 3. Control - 4. Control + Shift - 5. Alt - 6. Alt + Shift - 7. Alt + Control - 8. Alt + Control + Shift -*/ -struct KeyboardLayoutItem { - bool dirty; - quint8 deadkeys; - quint32 qtKey[9]; // Can by any Qt::Key_, or unicode character -}; - -QKeyMapperPrivate::QKeyMapperPrivate() -{ - memset(keyLayout, 0, sizeof(keyLayout)); -} - -QKeyMapperPrivate::~QKeyMapperPrivate() -{ - deleteLayouts(); -} - -void QKeyMapperPrivate::deleteLayouts() -{ - for (int i = 0; i < 255; ++i) { - if (keyLayout[i]) { - delete keyLayout[i]; - keyLayout[i] = 0; - } - } -} - -void QKeyMapperPrivate::clearMappings() -{ - deleteLayouts(); - - /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout() - * returns a DWORD. */ - - LCID newLCID = MAKELCID((quintptr)GetKeyboardLayout(0), SORT_DEFAULT); -// keyboardInputLocale = qt_localeFromLCID(newLCID); - - bool bidi = false; - wchar_t LCIDFontSig[16]; - if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t)) - && (LCIDFontSig[7] & (wchar_t)0x0800)) - bidi = true; - - keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight; -} - -void QKeyMapperPrivate::clearRecordedKeys() -{ - key_recorder.clearKeys(); -} - - -inline void setKbdState(unsigned char *kbd, bool shift, bool ctrl, bool alt) -{ - kbd[VK_LSHIFT ] = (shift ? 0x80 : 0); - kbd[VK_SHIFT ] = (shift ? 0x80 : 0); - kbd[VK_LCONTROL] = (ctrl ? 0x80 : 0); - kbd[VK_CONTROL ] = (ctrl ? 0x80 : 0); - kbd[VK_RMENU ] = (alt ? 0x80 : 0); - kbd[VK_MENU ] = (alt ? 0x80 : 0); -} - -void QKeyMapperPrivate::updateKeyMap(const MSG &msg) -{ - unsigned char kbdBuffer[256]; // Will hold the complete keyboard state - GetKeyboardState(kbdBuffer); - quint32 scancode = (msg.lParam >> 16) & 0xfff; - updatePossibleKeyCodes(kbdBuffer, scancode, msg.wParam); -} - -void QKeyMapperPrivate::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode, - quint32 vk_key) -{ - if (!vk_key || (keyLayout[vk_key] && !keyLayout[vk_key]->dirty)) - return; - - if (!keyLayout[vk_key]) - keyLayout[vk_key] = new KeyboardLayoutItem; - - // Copy keyboard state, so we can modify and query output for each possible permutation - unsigned char buffer[256]; - memcpy(buffer, kbdBuffer, sizeof(buffer)); - // Always 0, as Windows doesn't treat these as modifiers; - buffer[VK_LWIN ] = 0; - buffer[VK_RWIN ] = 0; - buffer[VK_CAPITAL ] = 0; - buffer[VK_NUMLOCK ] = 0; - buffer[VK_SCROLL ] = 0; - // Always 0, since we'll only change the other versions - buffer[VK_RSHIFT ] = 0; - buffer[VK_RCONTROL] = 0; - buffer[VK_LMENU ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph - - bool isDeadKey = false; - keyLayout[vk_key]->deadkeys = 0; - keyLayout[vk_key]->dirty = false; - setKbdState(buffer, false, false, false); - keyLayout[vk_key]->qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x01 : 0; - setKbdState(buffer, true, false, false); - keyLayout[vk_key]->qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x02 : 0; - setKbdState(buffer, false, true, false); - keyLayout[vk_key]->qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x04 : 0; - setKbdState(buffer, true, true, false); - keyLayout[vk_key]->qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x08 : 0; - setKbdState(buffer, false, false, true); - keyLayout[vk_key]->qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x10 : 0; - setKbdState(buffer, true, false, true); - keyLayout[vk_key]->qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x20 : 0; - setKbdState(buffer, false, true, true); - keyLayout[vk_key]->qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x40 : 0; - setKbdState(buffer, true, true, true); - keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0; - // Add a fall back key for layouts which don't do composition and show non-latin1 characters - int fallbackKey = winceKeyBend(vk_key); - if (!fallbackKey || fallbackKey == Qt::Key_unknown) { - fallbackKey = 0; - if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) - fallbackKey = vk_key; - } - keyLayout[vk_key]->qtKey[8] = fallbackKey; - - // If this vk_key a Dead Key - if (MapVirtualKey(vk_key, 2) & 0x80000000) { - // Push a Space, then the original key through the low-level ToAscii functions. - // We do this because these functions (ToAscii / ToUnicode) will alter the internal state of - // the keyboard driver By doing the following, we set the keyboard driver state back to what - // it was before we wrecked it with the code above. - // We need to push the space with an empty keystate map, since the driver checks the map for - // transitions in modifiers, so this helps us capture all possible deadkeys. - unsigned char emptyBuffer[256]; - memset(emptyBuffer, 0, sizeof(emptyBuffer)); - ::ToAscii(VK_SPACE, 0, emptyBuffer, reinterpret_cast(&buffer), 0); - ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast(&buffer), 0); - } - -#ifdef DEBUG_KEYMAPPER - qDebug("updatePossibleKeyCodes for virtual key = 0x%02x!", vk_key); - for (int i = 0; i < 9; ++i) { - qDebug(" [%d] (%d,0x%02x,'%c') %s", i, - keyLayout[vk_key]->qtKey[i], - keyLayout[vk_key]->qtKey[i], - keyLayout[vk_key]->qtKey[i] ? keyLayout[vk_key]->qtKey[i] : 0x03, - keyLayout[vk_key]->deadkeys & (1<deadkeys & 1< QKeyMapperPrivate::possibleKeys(QKeyEvent *e) -{ - QList result; - - KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()]; - if(!kbItem) - return result; - - quint32 baseKey = kbItem->qtKey[0]; - Qt::KeyboardModifiers keyMods = e->modifiers(); - if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) { - result << int(Qt::Key_Enter + keyMods); - return result; - } - result << int(baseKey + keyMods); // The base key is _always_ valid, of course - - for(int i = 1; i < 9; ++i) { - Qt::KeyboardModifiers neededMods = ModsTbl[i]; - quint32 key = kbItem->qtKey[i]; - if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) - result << int(key + (keyMods & ~neededMods)); - } - - return result; -} - -bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool grab) -{ - Q_Q(QKeyMapper); - Q_UNUSED(q); // Strange, but the compiler complains on q not being referenced, even if it is.. - bool k0 = false; - bool k1 = false; - int msgType = msg.message; - - quint32 scancode = (msg.lParam >> 16) & 0xfff; - quint32 vk_key = MapVirtualKey(scancode, 1); - bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9); - quint32 nModifiers = 0; - -#if defined(Q_OS_WINCE) - nModifiers |= (GetKeyState(VK_SHIFT ) < 0 ? ShiftAny : 0); - nModifiers |= (GetKeyState(VK_CONTROL) < 0 ? ControlAny : 0); - nModifiers |= (GetKeyState(VK_MENU ) < 0 ? AltAny : 0); - nModifiers |= (GetKeyState(VK_LWIN ) < 0 ? MetaLeft : 0); - nModifiers |= (GetKeyState(VK_RWIN ) < 0 ? MetaRight : 0); -#else - // Map native modifiers to some bit representation - nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ? ShiftLeft : 0); - nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ? ShiftRight : 0); - nModifiers |= (GetKeyState(VK_LCONTROL) & 0x80 ? ControlLeft : 0); - nModifiers |= (GetKeyState(VK_RCONTROL) & 0x80 ? ControlRight : 0); - nModifiers |= (GetKeyState(VK_LMENU ) & 0x80 ? AltLeft : 0); - nModifiers |= (GetKeyState(VK_RMENU ) & 0x80 ? AltRight : 0); - nModifiers |= (GetKeyState(VK_LWIN ) & 0x80 ? MetaLeft : 0); - nModifiers |= (GetKeyState(VK_RWIN ) & 0x80 ? MetaRight : 0); - // Add Lock keys to the same bits - nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0); - nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0); - nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0); -#endif // Q_OS_WINCE - - if (msg.lParam & ExtendedKey) - nModifiers |= msg.lParam & ExtendedKey; - - // Get the modifier states (may be altered later, depending on key code) - int state = 0; - state |= (nModifiers & ShiftAny ? Qt::ShiftModifier : 0); - state |= (nModifiers & ControlAny ? Qt::ControlModifier : 0); - state |= (nModifiers & AltAny ? Qt::AltModifier : 0); - state |= (nModifiers & MetaAny ? Qt::MetaModifier : 0); - - // Now we know enough to either have MapVirtualKey or our own keymap tell us if it's a deadkey - bool isDeadKey = isADeadKey(msg.wParam, state) - || MapVirtualKey(msg.wParam, 2) & 0x80000000; - - // A multi-character key not found by our look-ahead - if (msgType == WM_CHAR) { - QString s; - QChar ch = QChar((ushort)msg.wParam); - if (!ch.isNull()) - s += ch; - - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers); - k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers); - } - - // Input method characters not found by our look-ahead - else if (msgType == WM_IME_CHAR) { - QString s; - QChar ch = QChar((ushort)msg.wParam); - if (!ch.isNull()) - s += ch; - - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers); - k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, 0, Qt::KeyboardModifier(state), s, false, 0, scancode, vk_key, nModifiers); - } - - else { - // handle Directionality changes (BiDi) with RTL extensions - if (qt_use_rtl_extensions) { - static int dirStatus = 0; - if (!dirStatus && state == Qt::ControlModifier - && msg.wParam == VK_CONTROL - && msgType == WM_KEYDOWN) { - if (GetKeyState(VK_LCONTROL) < 0) - dirStatus = VK_LCONTROL; - else if (GetKeyState(VK_RCONTROL) < 0) - dirStatus = VK_RCONTROL; - } else if (dirStatus) { - if (msgType == WM_KEYDOWN) { - if (msg.wParam == VK_SHIFT) { - if (dirStatus == VK_LCONTROL && GetKeyState(VK_LSHIFT) < 0) - dirStatus = VK_LSHIFT; - else if (dirStatus == VK_RCONTROL && GetKeyState(VK_RSHIFT) < 0) - dirStatus = VK_RSHIFT; - } else { - dirStatus = 0; - } - } else if (msgType == WM_KEYUP) { - if (dirStatus == VK_LSHIFT - && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL)) - || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) { - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_L, 0, - QString(), false, 0, - scancode, msg.wParam, nModifiers); - k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, Qt::Key_Direction_L, 0, - QString(), false, 0, - scancode, msg.wParam, nModifiers); - dirStatus = 0; - } else if (dirStatus == VK_RSHIFT - && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL)) - || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) { - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, Qt::Key_Direction_R, - 0, QString(), false, 0, - scancode, msg.wParam, nModifiers); - k1 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, Qt::Key_Direction_R, - 0, QString(), false, 0, - scancode, msg.wParam, nModifiers); - dirStatus = 0; - } else { - dirStatus = 0; - } - } else { - dirStatus = 0; - } - } - } - - // IME will process these keys, so simply return - if(msg.wParam == VK_PROCESSKEY) - return true; - - // Ignore invalid virtual keycodes (see bugs 127424, QTBUG-3630) - if (msg.wParam == 0 || msg.wParam == 0xFF) - return true; - - // Translate VK_* (native) -> Key_* (Qt) keys - // If it's a dead key, we cannot use the toKeyOrUnicode() function, since that will change - // the internal state of the keyboard driver, resulting in that dead keys no longer works. - // ..also if we're typing numbers on the keypad, while holding down the Alt modifier. - int code = 0; - if (isNumpad && (nModifiers & AltAny)) { - code = winceKeyBend(msg.wParam); - } else if (!isDeadKey) { - unsigned char kbdBuffer[256]; // Will hold the complete keyboard state - GetKeyboardState(kbdBuffer); - code = toKeyOrUnicode(msg.wParam, scancode, kbdBuffer); - } - - // Invert state logic: - // If the key actually pressed is a modifier key, then we remove its modifier key from the - // state, since a modifier-key can't have itself as a modifier - if (code == Qt::Key_Control) - state = state ^ Qt::ControlModifier; - else if (code == Qt::Key_Shift) - state = state ^ Qt::ShiftModifier; - else if (code == Qt::Key_Alt) - state = state ^ Qt::AltModifier; - - // If the bit 24 of lParm is set you received a enter, - // otherwise a Return. (This is the extended key bit) - if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000)) - code = Qt::Key_Enter; - - // All cursor keys without extended bit - if (!(msg.lParam & 0x1000000)) { - switch (code) { - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_PageUp: - case Qt::Key_PageDown: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Insert: - case Qt::Key_Delete: - case Qt::Key_Asterisk: - case Qt::Key_Plus: - case Qt::Key_Minus: - case Qt::Key_Period: - case Qt::Key_0: - case Qt::Key_1: - case Qt::Key_2: - case Qt::Key_3: - case Qt::Key_4: - case Qt::Key_5: - case Qt::Key_6: - case Qt::Key_7: - case Qt::Key_8: - case Qt::Key_9: - state |= ((msg.wParam >= '0' && msg.wParam <= '9') - || (msg.wParam >= VK_OEM_PLUS && msg.wParam <= VK_OEM_3)) - ? 0 : Qt::KeypadModifier; - default: - if ((uint)msg.lParam == 0x004c0001 || (uint)msg.lParam == 0xc04c0001) - state |= Qt::KeypadModifier; - break; - } - } - // Other keys with with extended bit - else { - switch (code) { - case Qt::Key_Enter: - case Qt::Key_Slash: - case Qt::Key_NumLock: - state |= Qt::KeypadModifier; - default: - break; - } - } - - // KEYDOWN --------------------------------------------------------------------------------- - if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) { - // Get the last record of this key press, so we can validate the current state - // The record is not removed from the list - KeyRecord *rec = key_recorder.findKey(msg.wParam, false); - - // If rec's state doesn't match the current state, something has changed behind our back - // (Consumed by modal widget is one possibility) So, remove the record from the list - // This will stop the auto-repeat of the key, should a modifier change, for example - if (rec && rec->state != state) { - key_recorder.findKey(msg.wParam, true); - rec = 0; - } - - // Find unicode character from Windows Message Queue - MSG wm_char; - UINT charType = (msgType == WM_KEYDOWN - ? WM_CHAR - : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR); - - QChar uch; - if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { - // Found a ?_CHAR - uch = QChar((ushort)wm_char.wParam); - if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN)) - uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter - if (!code && !uch.row()) - code = asciiToKeycode(uch.cell(), state); - } - - // Special handling for the WM_IME_KEYDOWN message. Microsoft IME (Korean) will not - // generate a WM_IME_CHAR message corresponding to this message. We might get wrong - // results, if we map this virtual key-code directly (for eg '?' US layouts). So try - // to find the correct key using the current message parameters & keyboard state. - if (uch.isNull() && msgType == WM_IME_KEYDOWN) { - BYTE keyState[256]; - wchar_t newKey[3] = {0}; - GetKeyboardState(keyState); - int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0); - if (val == 1) { - uch = QChar(newKey[0]); - } else { - // If we are still not able to find a unicode key, pass the WM_IME_KEYDOWN - // message to DefWindowProc() for generating a proper WM_KEYDOWN. - return false; - } - } - - // If no ?_CHAR was found in the queue; deduct character from the ?_KEYDOWN parameters - if (uch.isNull()) { - if (msg.wParam == VK_DELETE) { - uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one. - } else { - if (msgType != WM_SYSKEYDOWN || !code) { - UINT map = MapVirtualKey(msg.wParam, 2); - // If the high bit of the return value is set, it's a deadkey - if (!(map & 0x80000000)) - uch = QChar((ushort)map); - } - } - if (!code && !uch.row()) - code = asciiToKeycode(uch.cell(), state); - } - - // Special handling of global Windows hotkeys - if (state == Qt::AltModifier) { - switch (code) { - case Qt::Key_Escape: - case Qt::Key_Tab: - case Qt::Key_Enter: - case Qt::Key_F4: - return false; // Send the event on to Windows - case Qt::Key_Space: - // do not pass this key to windows, we will process it ourselves - qt_show_system_menu(widget->window()); - return true; - default: - break; - } - } - - // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation - if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier) - code = Qt::Key_Backtab; - - // If we have a record, it means that the key is already pressed, the state is the same - // so, we have an auto-repeating key - if (rec) { - if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) { - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, code, - Qt::KeyboardModifier(state), rec->text, true, 0, - scancode, msg.wParam, nModifiers); - k1 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, code, - Qt::KeyboardModifier(state), rec->text, true, 0, - scancode, msg.wParam, nModifiers); - } - } - // No record of the key being previous pressed, so we now send a QEvent::KeyPress event, - // and store the key data into our records. - else { - QString text; - if (!uch.isNull()) - text += uch; - char a = uch.row() ? 0 : uch.cell(); - key_recorder.storeKey(msg.wParam, a, state, text); - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyPress, code, Qt::KeyboardModifier(state), - text, false, 0, scancode, msg.wParam, nModifiers); - - bool store = true; - // Alt+ go to the Win32 menu system if unhandled by Qt -#if !defined(Q_OS_WINCE) - if (msgType == WM_SYSKEYDOWN && !k0 && a) { - HWND parent = GetParent(widget->internalWinId()); - while (parent) { - if (GetMenu(parent)) { - SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU, a); - store = false; - k0 = true; - break; - } - parent = GetParent(parent); - } - } -#endif - if (!store) - key_recorder.findKey(msg.wParam, true); - } - } - - // KEYUP ----------------------------------------------------------------------------------- - else { - // Try to locate the key in our records, and remove it if it exists. - // The key may not be in our records if, for example, the down event was handled by - // win32 natively, or our window gets focus while a key is already press, but now gets - // the key release event. - KeyRecord* rec = key_recorder.findKey(msg.wParam, true); - if (!rec && !(code == Qt::Key_Shift - || code == Qt::Key_Control - || code == Qt::Key_Meta - || code == Qt::Key_Alt)) { - // Someone ate the key down event - } else { - if (!code) - code = asciiToKeycode(rec->ascii ? rec->ascii : msg.wParam, state); - - // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation - if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier) - code = Qt::Key_Backtab; - - k0 = q->sendKeyEvent(widget, grab, QEvent::KeyRelease, code, Qt::KeyboardModifier(state), - (rec ? rec->text : QString()), false, 0, scancode, msg.wParam, nModifiers); - - // don't pass Alt to Windows unless we are embedded in a non-Qt window -#if !defined(Q_OS_WINCE) - if (code == Qt::Key_Alt) { - k0 = true; - HWND parent = GetParent(widget->internalWinId()); - while (parent) { - if (!QWidget::find(parent) && GetMenu(parent)) { - k0 = false; - break; - } - parent = GetParent(parent); - } - } -#endif - } - } - } - - // Return true, if a QKeyEvent was sent to a widget - return k0 || k1; -} - - -// QKeyMapper (Windows) implementation -------------------------------------------------[ start ]--- - -bool QKeyMapper::sendKeyEvent(QWidget *widget, bool grab, - QEvent::Type type, int code, Qt::KeyboardModifiers modifiers, - const QString &text, bool autorepeat, int count, - quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, - bool *) -{ - Q_UNUSED(grab); - Q_UNUSED(count); - if (!widget->isEnabled()) - return false; - - QKeyEventEx e(type, code, modifiers, - text, autorepeat, qMax(1, int(text.length())), - nativeScanCode, nativeVirtualKey, nativeModifiers); - QETWidget::sendSpontaneousEvent(widget, &e); - - if (!isModifierKey(code) - && modifiers == Qt::AltModifier - && ((code >= Qt::Key_A && code <= Qt::Key_Z) || (code >= Qt::Key_0 && code <= Qt::Key_9)) - && type == QEvent::KeyPress - && !e.isAccepted()) - QApplication::beep(); // Emulate windows behavior - - return e.isAccepted(); -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qmime_win.cpp b/src/widgets/platforms/win/qmime_win.cpp deleted file mode 100644 index b07214da82..0000000000 --- a/src/widgets/platforms/win/qmime_win.cpp +++ /dev/null @@ -1,1557 +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 "qmime.h" - -#include "qimagereader.h" -#include "qimagewriter.h" -#include "qdatastream.h" -#include "qbuffer.h" -#include "qt_windows.h" -#include "qapplication_p.h" -#include "qtextcodec.h" -#include "qregexp.h" -#include "qalgorithms.h" -#include "qmap.h" -#include "qdnd_p.h" -#include -#include "qurl.h" -#include "qvariant.h" -#include "qtextdocument.h" -#include "qdir.h" - -#if defined(Q_OS_WINCE) -#include "qguifunctions_wince.h" -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_IMAGEFORMAT_BMP -#ifndef CF_DIBV5 -#define CF_DIBV5 17 -#endif -/* The MSVC compilers allows multi-byte characters, that has the behavior of - * that each character gets shifted into position. 0x73524742 below is for MSVC - * equivalent to doing 'sRGB', but this does of course not work - * on conformant C++ compilers. */ -#define BMP_LCS_sRGB 0x73524742 -#define BMP_LCS_GM_IMAGES 0x00000004L - -struct _CIEXYZ { - long ciexyzX, ciexyzY, ciexyzZ; -}; - -struct _CIEXYZTRIPLE { - _CIEXYZ ciexyzRed, ciexyzGreen, ciexyzBlue; -}; - -struct BMP_BITMAPV5HEADER { - DWORD bV5Size; - LONG bV5Width; - LONG bV5Height; - WORD bV5Planes; - WORD bV5BitCount; - DWORD bV5Compression; - DWORD bV5SizeImage; - LONG bV5XPelsPerMeter; - LONG bV5YPelsPerMeter; - DWORD bV5ClrUsed; - DWORD bV5ClrImportant; - DWORD bV5RedMask; - DWORD bV5GreenMask; - DWORD bV5BlueMask; - DWORD bV5AlphaMask; - DWORD bV5CSType; - _CIEXYZTRIPLE bV5Endpoints; - DWORD bV5GammaRed; - DWORD bV5GammaGreen; - DWORD bV5GammaBlue; - DWORD bV5Intent; - DWORD bV5ProfileData; - DWORD bV5ProfileSize; - DWORD bV5Reserved; -}; -static const int BMP_BITFIELDS = 3; - -extern bool qt_read_dib(QDataStream&, QImage&); // qimage.cpp -extern bool qt_write_dib(QDataStream&, QImage); // qimage.cpp -static bool qt_write_dibv5(QDataStream &s, QImage image); -static bool qt_read_dibv5(QDataStream &s, QImage &image); -#endif - -//#define QMIME_DEBUG - - -// helpers for using global memory - -static int getCf(const FORMATETC &formatetc) -{ - return formatetc.cfFormat; -} - -static FORMATETC setCf(int cf) -{ - FORMATETC formatetc; - formatetc.cfFormat = cf; - formatetc.dwAspect = DVASPECT_CONTENT; - formatetc.lindex = -1; - formatetc.ptd = NULL; - formatetc.tymed = TYMED_HGLOBAL; - return formatetc; -} - -static bool setData(const QByteArray &data, STGMEDIUM *pmedium) -{ - HGLOBAL hData = GlobalAlloc(0, data.size()); - if (!hData) - return false; - - void *out = GlobalLock(hData); - memcpy(out, data.data(), data.size()); - GlobalUnlock(hData); - pmedium->tymed = TYMED_HGLOBAL; - pmedium->hGlobal = hData; - pmedium->pUnkForRelease = 0; - return true; -} - -static QByteArray getData(int cf, IDataObject *pDataObj) -{ - QByteArray data; - FORMATETC formatetc = setCf(cf); - STGMEDIUM s; - if (pDataObj->GetData(&formatetc, &s) == S_OK) { - DWORD * val = (DWORD*)GlobalLock(s.hGlobal); - data = QByteArray::fromRawData((char*)val, GlobalSize(s.hGlobal)); - data.detach(); - GlobalUnlock(s.hGlobal); - ReleaseStgMedium(&s); - } else { - //Try reading IStream data - formatetc.tymed = TYMED_ISTREAM; - if (pDataObj->GetData(&formatetc, &s) == S_OK) { - char szBuffer[4096]; - ULONG actualRead = 0; - LARGE_INTEGER pos = {{0, 0}}; - //Move to front (can fail depending on the data model implemented) - HRESULT hr = s.pstm->Seek(pos, STREAM_SEEK_SET, NULL); - while(SUCCEEDED(hr)){ - hr = s.pstm->Read(szBuffer, sizeof(szBuffer), &actualRead); - if (SUCCEEDED(hr) && actualRead > 0) { - data += QByteArray::fromRawData(szBuffer, actualRead); - } - if (actualRead != sizeof(szBuffer)) - break; - } - data.detach(); - ReleaseStgMedium(&s); - } - } - return data; -} - -static bool canGetData(int cf, IDataObject * pDataObj) -{ - FORMATETC formatetc = setCf(cf); - if (pDataObj->QueryGetData(&formatetc) != S_OK){ - formatetc.tymed = TYMED_ISTREAM; - return pDataObj->QueryGetData(&formatetc) == S_OK; - } - return true; -} - -class QWindowsMimeList -{ -public: - QWindowsMimeList(); - ~QWindowsMimeList(); - void addWindowsMime(QWindowsMime * mime); - void removeWindowsMime(QWindowsMime * mime); - QList windowsMimes(); - -private: - void init(); - bool initialized; - QList mimes; -}; - -Q_GLOBAL_STATIC(QWindowsMimeList, theMimeList); - - -/*! - \class QWindowsMime - \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. - \ingroup draganddrop - \inmodule QtWidgets - - Qt's drag-and-drop and clipboard facilities use the MIME standard. - On X11, this maps trivially to the Xdnd protocol, but on Windows - although some applications use MIME types to describe clipboard - formats, others use arbitrary non-standardized naming conventions, - or unnamed built-in formats of Windows. - - By instantiating subclasses of QWindowsMime that provide conversions - between Windows Clipboard and MIME formats, you can convert - proprietary clipboard formats to MIME formats. - - Qt has predefined support for the following Windows Clipboard formats: - - \table - \header \o Windows Format \o Equivalent MIME type - \row \o \c CF_UNICODETEXT \o \c text/plain - \row \o \c CF_TEXT \o \c text/plain - \row \o \c CF_DIB \o \c{image/xyz}, where \c xyz is - a \l{QImageWriter::supportedImageFormats()}{Qt image format} - \row \o \c CF_HDROP \o \c text/uri-list - \row \o \c CF_INETURL \o \c text/uri-list - \row \o \c CF_HTML \o \c text/html - \endtable - - An example use of this class would be to map the Windows Metafile - clipboard format (\c CF_METAFILEPICT) to and from the MIME type - \c{image/x-wmf}. This conversion might simply be adding or removing - a header, or even just passing on the data. See \l{Drag and Drop} - for more information on choosing and definition MIME types. - - You can check if a MIME type is convertible using canConvertFromMime() and - can perform conversions with convertToMime() and convertFromMime(). -*/ - -/*! -Constructs a new conversion object, adding it to the globally accessed -list of available converters. -*/ -QWindowsMime::QWindowsMime() -{ - theMimeList()->addWindowsMime(this); -} - -/*! -Destroys a conversion object, removing it from the global -list of available converters. -*/ -QWindowsMime::~QWindowsMime() -{ - theMimeList()->removeWindowsMime(this); -} - - -/*! - Registers the MIME type \a mime, and returns an ID number - identifying the format on Windows. -*/ -int QWindowsMime::registerMimeType(const QString &mime) -{ - int f = RegisterClipboardFormat(reinterpret_cast (mime.utf16())); - if (!f) - qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format"); - - return f; -} - - -/*! -\fn bool QWindowsMime::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const - - Returns true if the converter can convert from the \a mimeData to - the format specified in \a formatetc. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn bool QWindowsMime::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const - - Returns true if the converter can convert to the \a mimeType from - the available formats in \a pDataObj. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! -\fn QString QWindowsMime::mimeForFormat(const FORMATETC &formatetc) const - - Returns the mime type that will be created form the format specified - in \a formatetc, or an empty string if this converter does not support - \a formatetc. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! -\fn QVector QWindowsMime::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const - - Returns a QVector of FORMATETC structures representing the different windows clipboard - formats that can be provided for the \a mimeType from the \a mimeData. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! - \fn QVariant QWindowsMime::convertToMime(const QString &mimeType, IDataObject *pDataObj, - QVariant::Type preferredType) const - - Returns a QVariant containing the converted data for \a mimeType from \a pDataObj. - If possible the QVariant should be of the \a preferredType to avoid needless conversions. - - All subclasses must reimplement this pure virtual function. -*/ - -/*! -\fn bool QWindowsMime::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const - - Convert the \a mimeData to the format specified in \a formatetc. - The converted data should then be placed in \a pmedium structure. - - Return true if the conversion was successful. - - All subclasses must reimplement this pure virtual function. -*/ - - -QWindowsMime *QWindowsMime::converterFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) -{ - QList mimes = theMimeList()->windowsMimes(); - for (int i=mimes.size()-1; i>=0; --i) { - if (mimes.at(i)->canConvertFromMime(formatetc, mimeData)) - return mimes.at(i); - } - return 0; -} - -QWindowsMime *QWindowsMime::converterToMime(const QString &mimeType, IDataObject *pDataObj) -{ - QList mimes = theMimeList()->windowsMimes(); - for (int i=mimes.size()-1; i>=0; --i) { - if (mimes.at(i)->canConvertToMime(mimeType, pDataObj)) - return mimes.at(i); - } - return 0; -} - -QVector QWindowsMime::allFormatsForMime(const QMimeData *mimeData) -{ - QList mimes = theMimeList()->windowsMimes(); - QVector formatics; - formatics.reserve(20); -#ifndef QT_NO_DRAGANDDROP - QStringList formats = QInternalMimeData::formatsHelper(mimeData); - for (int f=0; f=0; --i) - formatics += mimes.at(i)->formatsForMime(formats.at(f), mimeData); - } -#else - Q_UNUSED(mimeData); -#endif //QT_NO_DRAGANDDROP - return formatics; -} - -QStringList QWindowsMime::allMimesForFormats(IDataObject *pDataObj) -{ - QList mimes = theMimeList()->windowsMimes(); - QStringList formats; - LPENUMFORMATETC FAR fmtenum; - HRESULT hr = pDataObj->EnumFormatEtc(DATADIR_GET, &fmtenum); - - if (hr == NOERROR) { - FORMATETC fmtetc; - while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { -#if defined(QMIME_DEBUG) && !defined(Q_OS_WINCE) - qDebug("QWindowsMime::allMimesForFormats()"); - wchar_t buf[256] = {0}; - GetClipboardFormatName(fmtetc.cfFormat, buf, 255); - qDebug("CF = %d : %s", fmtetc.cfFormat, QString::fromWCharArray(buf)); -#endif - for (int i=mimes.size()-1; i>=0; --i) { - QString format = mimes.at(i)->mimeForFormat(fmtetc); - if (!format.isEmpty() && !formats.contains(format)) { - formats += format; - } - } - // as documented in MSDN to avoid possible memleak - if (fmtetc.ptd) - CoTaskMemFree(fmtetc.ptd); - } - fmtenum->Release(); - } - - return formats; -} - - -class QWindowsMimeText : public QWindowsMime -{ -public: - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; -}; - -bool QWindowsMimeText::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const -{ - int cf = getCf(formatetc); - return (cf == CF_UNICODETEXT || cf == CF_TEXT) && mimeData->hasText(); -} - -/* -text/plain is defined as using CRLF, but so many programs don't, -and programmers just look for '\n' in strings. -Windows really needs CRLF, so we ensure it here. -*/ -bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const -{ - if (canConvertFromMime(formatetc, mimeData)) { - QByteArray data; - int cf = getCf(formatetc); - if (cf == CF_TEXT) { - data = mimeData->text().toLocal8Bit(); - // Anticipate required space for CRLFs at 1/40 - int maxsize=data.size()+data.size()/40+3; - QByteArray r(maxsize, '\0'); - char* o = r.data(); - const char* d = data.data(); - const int s = data.size(); - bool cr=false; - int j=0; - for (int i=0; i= maxsize) { - maxsize += maxsize/4; - r.resize(maxsize); - o = r.data(); - } - } - o[j]=0; - return setData(r, pmedium); - } else if (cf == CF_UNICODETEXT) { - QString str = mimeData->text(); - const QChar *u = str.unicode(); - QString res; - const int s = str.length(); - int maxsize = s + s/40 + 3; - res.resize(maxsize); - int ri = 0; - bool cr = false; - for (int i=0; i < s; ++i) { - if (*u == QLatin1Char('\r')) - cr = true; - else { - if (*u == QLatin1Char('\n') && !cr) - res[ri++] = QLatin1Char('\r'); - cr = false; - } - res[ri++] = *u; - if (ri+3 >= maxsize) { - maxsize += maxsize/4; - res.resize(maxsize); - } - ++u; - } - res.truncate(ri); - const int byteLength = res.length() * sizeof(ushort); - QByteArray r(byteLength + 2, '\0'); - memcpy(r.data(), res.unicode(), byteLength); - r[byteLength] = 0; - r[byteLength+1] = 0; - return setData(r, pmedium); - } - } - return false; -} - -bool QWindowsMimeText::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const -{ - return mimeType.startsWith(QLatin1String("text/plain")) - && (canGetData(CF_UNICODETEXT, pDataObj) - || canGetData(CF_TEXT, pDataObj)); -} - -QString QWindowsMimeText::mimeForFormat(const FORMATETC &formatetc) const -{ - int cf = getCf(formatetc); - if (cf == CF_UNICODETEXT || cf == CF_TEXT) - return QLatin1String("text/plain"); - return QString(); -} - - -QVector QWindowsMimeText::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const -{ - QVector formatics; - if (mimeType.startsWith(QLatin1String("text/plain")) && mimeData->hasText()) { - formatics += setCf(CF_UNICODETEXT); - formatics += setCf(CF_TEXT); - } - return formatics; -} - -QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const -{ - QVariant ret; - - if (canConvertToMime(mime, pDataObj)) { - QString str; - QByteArray data = getData(CF_UNICODETEXT, pDataObj); - if (!data.isEmpty()) { - str = QString::fromWCharArray((const wchar_t *)data.data()); - str.replace(QLatin1String("\r\n"), QLatin1String("\n")); - } else { - data = getData(CF_TEXT, pDataObj); - if (!data.isEmpty()) { - const char* d = data.data(); - const int s = qstrlen(d); - QByteArray r(data.size()+1, '\0'); - char* o = r.data(); - int j=0; - for (int i=0; i formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; -private: - int CF_INETURL_W; // wide char version - int CF_INETURL; -}; - -QWindowsMimeURI::QWindowsMimeURI() -{ - CF_INETURL_W = QWindowsMime::registerMimeType(QLatin1String("UniformResourceLocatorW")); - CF_INETURL = QWindowsMime::registerMimeType(QLatin1String("UniformResourceLocator")); -} - -bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const -{ - if (getCf(formatetc) == CF_HDROP) { - QList urls = mimeData->urls(); - for (int i=0; ihasFormat(QLatin1String("text/uri-list")); -} - -bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const -{ - if (canConvertFromMime(formatetc, mimeData)) { - if (getCf(formatetc) == CF_HDROP) { - QList urls = mimeData->urls(); - QStringList fileNames; - int size = sizeof(DROPFILES)+2; - for (int i=0; ipFiles = sizeof(DROPFILES); - GetCursorPos(&d->pt); // try - d->fNC = true; - char* files = ((char*)d) + d->pFiles; - - d->fWide = true; - wchar_t* f = (wchar_t*)files; - for (int i=0; i urls = mimeData->urls(); - QByteArray result; - if (!urls.isEmpty()) { - QString url = urls.at(0).toString(); - result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort)); - } - result.append('\0'); - result.append('\0'); - return setData(result, pmedium); - } else if (getCf(formatetc) == CF_INETURL) { - QList urls = mimeData->urls(); - QByteArray result; - if (!urls.isEmpty()) - result = urls.at(0).toString().toLocal8Bit(); - return setData(result, pmedium); - } - } - - return false; -} - -bool QWindowsMimeURI::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const -{ - return mimeType == QLatin1String("text/uri-list") - && (canGetData(CF_HDROP, pDataObj) || canGetData(CF_INETURL_W, pDataObj) || canGetData(CF_INETURL, pDataObj)); -} - -QString QWindowsMimeURI::mimeForFormat(const FORMATETC &formatetc) const -{ - QString format; - if (getCf(formatetc) == CF_HDROP || getCf(formatetc) == CF_INETURL_W || getCf(formatetc) == CF_INETURL) - format = QLatin1String("text/uri-list"); - return format; -} - -QVector QWindowsMimeURI::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const -{ - QVector formatics; - if (mimeType == QLatin1String("text/uri-list")) { - if (canConvertFromMime(setCf(CF_HDROP), mimeData)) - formatics += setCf(CF_HDROP); - if (canConvertFromMime(setCf(CF_INETURL_W), mimeData)) - formatics += setCf(CF_INETURL_W); - if (canConvertFromMime(setCf(CF_INETURL), mimeData)) - formatics += setCf(CF_INETURL); - } - return formatics; -} - -QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const -{ - if (mimeType == QLatin1String("text/uri-list")) { - if (canGetData(CF_HDROP, pDataObj)) { - QByteArray texturi; - QList urls; - - QByteArray data = getData(CF_HDROP, pDataObj); - if (data.isEmpty()) - return QVariant(); - - LPDROPFILES hdrop = (LPDROPFILES)data.data(); - if (hdrop->fWide) { - const wchar_t* filesw = (const wchar_t *)(data.data() + hdrop->pFiles); - int i = 0; - while (filesw[i]) { - QString fileurl = QString::fromWCharArray(filesw + i); - urls += QUrl::fromLocalFile(fileurl); - i += fileurl.length()+1; - } - } else { - const char* files = (const char *)data.data() + hdrop->pFiles; - int i=0; - while (files[i]) { - urls += QUrl::fromLocalFile(QString::fromLocal8Bit(files+i)); - i += int(strlen(files+i))+1; - } - } - - if (preferredType == QVariant::Url && urls.size() == 1) - return urls.at(0); - else if (!urls.isEmpty()) - return urls; - } else if (canGetData(CF_INETURL_W, pDataObj)) { - QByteArray data = getData(CF_INETURL_W, pDataObj); - if (data.isEmpty()) - return QVariant(); - return QUrl(QString::fromWCharArray((const wchar_t *)data.constData())); - } else if (canGetData(CF_INETURL, pDataObj)) { - QByteArray data = getData(CF_INETURL, pDataObj); - if (data.isEmpty()) - return QVariant(); - return QUrl(QString::fromLocal8Bit(data.constData())); - } - } - return QVariant(); -} - -class QWindowsMimeHtml : public QWindowsMime -{ -public: - QWindowsMimeHtml(); - - // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; - - // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; - -private: - int CF_HTML; -}; - -QWindowsMimeHtml::QWindowsMimeHtml() -{ - CF_HTML = QWindowsMime::registerMimeType(QLatin1String("HTML Format")); -} - -QVector QWindowsMimeHtml::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const -{ - QVector formatetcs; - if (mimeType == QLatin1String("text/html") && (!mimeData->html().isEmpty())) - formatetcs += setCf(CF_HTML); - return formatetcs; -} - -QString QWindowsMimeHtml::mimeForFormat(const FORMATETC &formatetc) const -{ - if (getCf(formatetc) == CF_HTML) - return QLatin1String("text/html"); - return QString(); -} - -bool QWindowsMimeHtml::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const -{ - return mimeType == QLatin1String("text/html") && canGetData(CF_HTML, pDataObj); -} - - -bool QWindowsMimeHtml::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const -{ - return getCf(formatetc) == CF_HTML && (!mimeData->html().isEmpty()); -} - -/* -The windows HTML clipboard format is as follows (xxxxxxxxxx is a 10 integer number giving the positions -in bytes). Charset used is mostly utf8, but can be different, ie. we have to look for the charset tag - - Version: 1.0 - StartHTML:xxxxxxxxxx - EndHTML:xxxxxxxxxx - StartFragment:xxxxxxxxxx - EndFragment:xxxxxxxxxx - ...html... - -*/ -QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const -{ - Q_UNUSED(preferredType); - QVariant result; - if (canConvertToMime(mime, pDataObj)) { - QByteArray html = getData(CF_HTML, pDataObj); -#ifdef QMIME_DEBUG - qDebug("QWindowsMimeHtml::convertToMime"); - qDebug("raw :"); - qDebug(html); -#endif - int start = html.indexOf("StartFragment:"); - int end = html.indexOf("EndFragment:"); - - if (start != -1) { - int startOffset = start + 14; - int i = startOffset; - while (html.at(i) != '\r' && html.at(i) != '\n') - ++i; - QByteArray bytecount = html.mid(startOffset, i - startOffset); - start = bytecount.toInt(); - } - - if (end != -1) { - int endOffset = end + 12; - int i = endOffset ; - while (html.at(i) != '\r' && html.at(i) != '\n') - ++i; - QByteArray bytecount = html.mid(endOffset , i - endOffset); - end = bytecount.toInt(); - } - - if (end > start && start > 0) { - html = "" + html.mid(start, end - start); - html += ""; - html.replace('\r', ""); - result = QString::fromUtf8(html); - } - } - return result; -} - -bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const -{ - if (canConvertFromMime(formatetc, mimeData)) { - QByteArray data = mimeData->html().toUtf8(); - QByteArray result = - "Version:1.0\r\n" // 0-12 - "StartHTML:0000000105\r\n" // 13-35 - "EndHTML:0000000000\r\n" // 36-55 - "StartFragment:0000000000\r\n" // 58-86 - "EndFragment:0000000000\r\n\r\n"; // 87-105 - - if (data.indexOf("") == -1) - result += ""; - result += data; - if (data.indexOf("") == -1) - result += ""; - - // set the correct number for EndHTML - QByteArray pos = QString::number(result.size()).toLatin1(); - memcpy((char *)(result.data() + 53 - pos.length()), pos.constData(), pos.length()); - - // set correct numbers for StartFragment and EndFragment - pos = QString::number(result.indexOf("") + 20).toLatin1(); - memcpy((char *)(result.data() + 79 - pos.length()), pos.constData(), pos.length()); - pos = QString::number(result.indexOf("")).toLatin1(); - memcpy((char *)(result.data() + 103 - pos.length()), pos.constData(), pos.length()); - - return setData(result, pmedium); - } - return false; -} - - -#ifndef QT_NO_IMAGEFORMAT_BMP -class QWindowsMimeImage : public QWindowsMime -{ -public: - QWindowsMimeImage(); - // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; - - // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; -private: - bool hasOriginalDIBV5(IDataObject *pDataObj) const; - UINT CF_PNG; -}; - -QWindowsMimeImage::QWindowsMimeImage() -{ - CF_PNG = RegisterClipboardFormat(L"PNG"); -} - -QVector QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const -{ - QVector formatetcs; - if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) { - //add DIBV5 if image has alpha channel - QImage image = qvariant_cast(mimeData->imageData()); - if (!image.isNull() && image.hasAlphaChannel()) - formatetcs += setCf(CF_DIBV5); - formatetcs += setCf(CF_DIB); - } - return formatetcs; -} - -QString QWindowsMimeImage::mimeForFormat(const FORMATETC &formatetc) const -{ - int cf = getCf(formatetc); - if (cf == CF_DIB || cf == CF_DIBV5 || cf == int(CF_PNG)) - return QLatin1String("application/x-qt-image"); - return QString(); -} - -bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const -{ - if ((mimeType == QLatin1String("application/x-qt-image")) && - (canGetData(CF_DIB, pDataObj) || canGetData(CF_PNG, pDataObj))) - return true; - return false; -} - -bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const -{ - int cf = getCf(formatetc); - if (mimeData->hasImage()) { - if (cf == CF_DIB) - return true; - else if (cf == CF_DIBV5) { - //support DIBV5 conversion only if the image has alpha channel - QImage image = qvariant_cast(mimeData->imageData()); - if (!image.isNull() && image.hasAlphaChannel()) - return true; - } - } - return false; -} - -bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const -{ - int cf = getCf(formatetc); - if ((cf == CF_DIB || cf == CF_DIBV5) && mimeData->hasImage()) { - QImage img = qvariant_cast(mimeData->imageData()); - if (img.isNull()) - return false; - QByteArray ba; - QDataStream s(&ba, QIODevice::WriteOnly); - s.setByteOrder(QDataStream::LittleEndian);// Intel byte order #### - if (cf == CF_DIB) { - if (img.format() > QImage::Format_ARGB32) - img = img.convertToFormat(QImage::Format_RGB32); - if (qt_write_dib(s, img)) - return setData(ba, pmedium); - } else { - if (qt_write_dibv5(s, img)) - return setData(ba, pmedium); - } - } - return false; -} - -bool QWindowsMimeImage::hasOriginalDIBV5(IDataObject *pDataObj) const -{ - bool isSynthesized = true; - IEnumFORMATETC *pEnum =NULL; - HRESULT res = pDataObj->EnumFormatEtc(1, &pEnum); - if (res == S_OK && pEnum) { - FORMATETC fc; - while ((res = pEnum->Next(1, &fc, 0)) == S_OK) { - if (fc.ptd) - CoTaskMemFree(fc.ptd); - if (fc.cfFormat == CF_DIB) - break; - else if (fc.cfFormat == CF_DIBV5) { - isSynthesized = false; - break; - } - } - pEnum->Release(); - } - return !isSynthesized; -} - -QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const -{ - Q_UNUSED(preferredType); - QVariant result; - if (mimeType != QLatin1String("application/x-qt-image")) - return result; - //Try to convert from a format which has more data - //DIBV5, use only if its is not synthesized - if (canGetData(CF_DIBV5, pDataObj) && hasOriginalDIBV5(pDataObj)) { - QImage img; - QByteArray data = getData(CF_DIBV5, pDataObj); - QDataStream s(&data, QIODevice::ReadOnly); - s.setByteOrder(QDataStream::LittleEndian); - if (qt_read_dibv5(s, img)) { // #### supports only 32bit DIBV5 - return img; - } - } - //PNG, MS Office place this (undocumented) - if (canGetData(CF_PNG, pDataObj)) { - QImage img; - QByteArray data = getData(CF_PNG, pDataObj); - if (img.loadFromData(data, "PNG")) { - return img; - } - } - //Fallback to DIB - if (canGetData(CF_DIB, pDataObj)) { - QImage img; - QByteArray data = getData(CF_DIB, pDataObj); - QDataStream s(&data, QIODevice::ReadOnly); - s.setByteOrder(QDataStream::LittleEndian);// Intel byte order #### - if (qt_read_dib(s, img)) { // ##### encaps "-14" - return img; - } - } - // Failed - return result; -} -#endif - -class QBuiltInMimes : public QWindowsMime -{ -public: - QBuiltInMimes(); - - // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; - - // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; - -private: - QMap outFormats; - QMap inFormats; -}; - -QBuiltInMimes::QBuiltInMimes() -: QWindowsMime() -{ - outFormats.insert(QWindowsMime::registerMimeType(QLatin1String("application/x-color")), QLatin1String("application/x-color")); - inFormats.insert(QWindowsMime::registerMimeType(QLatin1String("application/x-color")), QLatin1String("application/x-color")); -} - -bool QBuiltInMimes::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const -{ - // really check - return formatetc.tymed & TYMED_HGLOBAL - && outFormats.contains(formatetc.cfFormat) - && mimeData->formats().contains(outFormats.value(formatetc.cfFormat)); -} - -bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const -{ - if (canConvertFromMime(formatetc, mimeData)) { - QByteArray data; - if (outFormats.value(getCf(formatetc)) == QLatin1String("text/html")) { - // text/html is in wide chars on windows (compatible with mozillia) - QString html = mimeData->html(); - // same code as in the text converter up above - const QChar *u = html.unicode(); - QString res; - const int s = html.length(); - int maxsize = s + s/40 + 3; - res.resize(maxsize); - int ri = 0; - bool cr = false; - for (int i=0; i < s; ++i) { - if (*u == QLatin1Char('\r')) - cr = true; - else { - if (*u == QLatin1Char('\n') && !cr) - res[ri++] = QLatin1Char('\r'); - cr = false; - } - res[ri++] = *u; - if (ri+3 >= maxsize) { - maxsize += maxsize/4; - res.resize(maxsize); - } - ++u; - } - res.truncate(ri); - const int byteLength = res.length() * sizeof(ushort); - QByteArray r(byteLength + 2, '\0'); - memcpy(r.data(), res.unicode(), byteLength); - r[byteLength] = 0; - r[byteLength+1] = 0; - data = r; - } else { -#ifndef QT_NO_DRAGANDDROP - data = QInternalMimeData::renderDataHelper(outFormats.value(getCf(formatetc)), mimeData); -#endif //QT_NO_DRAGANDDROP - } - return setData(data, pmedium); - } - return false; -} - -QVector QBuiltInMimes::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const -{ - QVector formatetcs; - if (!outFormats.keys(mimeType).isEmpty() && mimeData->formats().contains(mimeType)) - formatetcs += setCf(outFormats.key(mimeType)); - return formatetcs; -} - -bool QBuiltInMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const -{ - return (!inFormats.keys(mimeType).isEmpty()) - && canGetData(inFormats.key(mimeType), pDataObj); -} - -QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const -{ - QVariant val; - if (canConvertToMime(mimeType, pDataObj)) { - QByteArray data = getData(inFormats.key(mimeType), pDataObj); - if (!data.isEmpty()) { -#ifdef QMIME_DEBUG - qDebug("QBuiltInMimes::convertToMime()"); -#endif - if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { - // text/html is in wide chars on windows (compatible with Mozilla) - val = QString::fromWCharArray((const wchar_t *)data.data()); - } else { - val = data; // it should be enough to return the data and let QMimeData do the rest. - } - } - } - return val; -} - -QString QBuiltInMimes::mimeForFormat(const FORMATETC &formatetc) const -{ - return inFormats.value(getCf(formatetc)); -} - - -class QLastResortMimes : public QWindowsMime -{ -public: - - QLastResortMimes(); - // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; - - // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; - -private: - QMap formats; - static QStringList ianaTypes; - static QStringList excludeList; -}; - -QStringList QLastResortMimes::ianaTypes; -QStringList QLastResortMimes::excludeList; - -QLastResortMimes::QLastResortMimes() -{ - //MIME Media-Types - if (!ianaTypes.size()) { - ianaTypes.append(QLatin1String("application/")); - ianaTypes.append(QLatin1String("audio/")); - ianaTypes.append(QLatin1String("example/")); - ianaTypes.append(QLatin1String("image/")); - ianaTypes.append(QLatin1String("message/")); - ianaTypes.append(QLatin1String("model/")); - ianaTypes.append(QLatin1String("multipart/")); - ianaTypes.append(QLatin1String("text/")); - ianaTypes.append(QLatin1String("video/")); - } - //Types handled by other classes - if (!excludeList.size()) { - excludeList.append(QLatin1String("HTML Format")); - excludeList.append(QLatin1String("UniformResourceLocator")); - excludeList.append(QLatin1String("text/html")); - excludeList.append(QLatin1String("text/plain")); - excludeList.append(QLatin1String("text/uri-list")); - excludeList.append(QLatin1String("application/x-qt-image")); - excludeList.append(QLatin1String("application/x-color")); - } -} - -bool QLastResortMimes::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const -{ - // really check -#ifndef QT_NO_DRAGANDDROP - return formatetc.tymed & TYMED_HGLOBAL - && (formats.contains(formatetc.cfFormat) - && QInternalMimeData::hasFormatHelper(formats.value(formatetc.cfFormat), mimeData)); -#else - Q_UNUSED(mimeData); - Q_UNUSED(formatetc); - return formatetc.tymed & TYMED_HGLOBAL - && formats.contains(formatetc.cfFormat); -#endif //QT_NO_DRAGANDDROP -} - -bool QLastResortMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const -{ -#ifndef QT_NO_DRAGANDDROP - return canConvertFromMime(formatetc, mimeData) - && setData(QInternalMimeData::renderDataHelper(formats.value(getCf(formatetc)), mimeData), pmedium); -#else - Q_UNUSED(mimeData); - Q_UNUSED(formatetc); - Q_UNUSED(pmedium); - return false; -#endif //QT_NO_DRAGANDDROP -} - -QVector QLastResortMimes::formatsForMime(const QString &mimeType, const QMimeData * /*mimeData*/) const -{ - QVector formatetcs; - if (!formats.keys(mimeType).isEmpty()) { - formatetcs += setCf(formats.key(mimeType)); - } else if (!excludeList.contains(mimeType, Qt::CaseInsensitive)){ - // register any other available formats - int cf = QWindowsMime::registerMimeType(mimeType); - QLastResortMimes *that = const_cast(this); - that->formats.insert(cf, mimeType); - formatetcs += setCf(cf); - } - return formatetcs; -} -static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\""; - -static bool isCustomMimeType(const QString &mimeType) -{ - return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive); -} - -static QString customMimeType(const QString &mimeType) -{ - int len = sizeof(x_qt_windows_mime) - 1; - int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len; - return mimeType.mid(len, n); -} - -bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const -{ - if (isCustomMimeType(mimeType)) { - QString clipFormat = customMimeType(mimeType); - int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); - return canGetData(cf, pDataObj); - } else if (formats.keys(mimeType).isEmpty()) { - // if it is not in there then register it an see if we can get it - int cf = QWindowsMime::registerMimeType(mimeType); - return canGetData(cf, pDataObj); - } else { - return canGetData(formats.key(mimeType), pDataObj); - } - return false; -} - -QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *pDataObj, QVariant::Type preferredType) const -{ - Q_UNUSED(preferredType); - QVariant val; - if (canConvertToMime(mimeType, pDataObj)) { - QByteArray data; - if (isCustomMimeType(mimeType)) { - QString clipFormat = customMimeType(mimeType); - int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); - data = getData(cf, pDataObj); - } else if (formats.keys(mimeType).isEmpty()) { - int cf = QWindowsMime::registerMimeType(mimeType); - data = getData(cf, pDataObj); - } else { - data = getData(formats.key(mimeType), pDataObj); - } - if (!data.isEmpty()) - val = data; // it should be enough to return the data and let QMimeData do the rest. - } - return val; -} - -QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const -{ - QString format = formats.value(getCf(formatetc)); - if (!format.isEmpty()) - return format; - - wchar_t buffer[256]; - int len = GetClipboardFormatName(getCf(formatetc), buffer, 256); - - if (len) { - QString clipFormat = QString::fromWCharArray(buffer, len); -#ifndef QT_NO_DRAGANDDROP - if (QInternalMimeData::canReadData(clipFormat)) - format = clipFormat; - else if((formatetc.cfFormat >= 0xC000)){ - //create the mime as custom. not registered. - if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) { - //check if this is a mime type - bool ianaType = false; - int sz = ianaTypes.size(); - for (int i = 0; i < sz; i++) { - if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) { - ianaType = true; - break; - } - } - if (!ianaType) - format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"'); - else - format = clipFormat; - } - } -#endif //QT_NO_DRAGANDDROP - } - - return format; -} - -QWindowsMimeList::QWindowsMimeList() - : initialized(false) -{ -} - -QWindowsMimeList::~QWindowsMimeList() -{ - while (mimes.size()) - delete mimes.first(); -} - - -void QWindowsMimeList::init() -{ - if (!initialized) { - initialized = true; -#ifndef QT_NO_IMAGEFORMAT_BMP - new QWindowsMimeImage; -#endif - new QLastResortMimes; - new QWindowsMimeText; - new QWindowsMimeURI; - - new QWindowsMimeHtml; - new QBuiltInMimes; - } -} - -void QWindowsMimeList::addWindowsMime(QWindowsMime * mime) -{ - init(); - mimes.append(mime); -} - -void QWindowsMimeList::removeWindowsMime(QWindowsMime * mime) -{ - init(); - mimes.removeAll(mime); -} - -QList QWindowsMimeList::windowsMimes() -{ - init(); - return mimes; -} - -#ifndef QT_NO_IMAGEFORMAT_BMP -static bool qt_write_dibv5(QDataStream &s, QImage image) -{ - QIODevice* d = s.device(); - if (!d->isWritable()) - return false; - - //depth will be always 32 - int bpl_bmp = image.width()*4; - - BMP_BITMAPV5HEADER bi ={0}; - bi.bV5Size = sizeof(BMP_BITMAPV5HEADER); - bi.bV5Width = image.width(); - bi.bV5Height = image.height(); - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5SizeImage = bpl_bmp*image.height(); - bi.bV5XPelsPerMeter = 0; - bi.bV5YPelsPerMeter = 0; - bi.bV5ClrUsed = 0; - bi.bV5ClrImportant = 0; - bi.bV5BlueMask = 0x000000ff; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5RedMask = 0x00ff0000; - bi.bV5AlphaMask = 0xff000000; - bi.bV5CSType = BMP_LCS_sRGB; //LCS_sRGB - bi.bV5Intent = BMP_LCS_GM_IMAGES; //LCS_GM_IMAGES - - d->write(reinterpret_cast(&bi), bi.bV5Size); - if (s.status() != QDataStream::Ok) - return false; - - DWORD colorSpace[3] = {0x00ff0000,0x0000ff00,0x000000ff}; - d->write(reinterpret_cast(colorSpace), sizeof(colorSpace)); - if (s.status() != QDataStream::Ok) - return false; - - if (image.format() != QImage::Format_ARGB32) - image = image.convertToFormat(QImage::Format_ARGB32); - - uchar *buf = new uchar[bpl_bmp]; - uchar *b; - - memset(buf, 0, bpl_bmp); - for (int y=image.height()-1; y>=0; y--) { - // write the image bits - QRgb *p = (QRgb *)image.scanLine(y); - QRgb *end = p + image.width(); - b = buf; - while (p < end) { - int alpha = qAlpha(*p); - if (alpha) { - *b++ = qBlue(*p); - *b++ = qGreen(*p); - *b++ = qRed(*p); - } else { - //white for fully transparent pixels. - *b++ = 0xff; - *b++ = 0xff; - *b++ = 0xff; - } - *b++ = alpha; - p++; - } - d->write((char*)buf, bpl_bmp); - if (s.status() != QDataStream::Ok) { - delete[] buf; - return false; - } - } - delete[] buf; - return true; -} - -static int calc_shift(int mask) -{ - int result = 0; - while (!(mask & 1)) { - result++; - mask >>= 1; - } - return result; -} - -//Supports only 32 bit DIBV5 -static bool qt_read_dibv5(QDataStream &s, QImage &image) -{ - BMP_BITMAPV5HEADER bi; - QIODevice* d = s.device(); - if (d->atEnd()) - return false; - - d->read((char *)&bi, sizeof(bi)); // read BITMAPV5HEADER header - if (s.status() != QDataStream::Ok) - return false; - - int nbits = bi.bV5BitCount; - int comp = bi.bV5Compression; - if (nbits != 32 || bi.bV5Planes != 1 || comp != BMP_BITFIELDS) - return false; //Unsupported DIBV5 format - - int w = bi.bV5Width, h = bi.bV5Height; - int red_mask = bi.bV5RedMask; - int green_mask = bi.bV5GreenMask; - int blue_mask = bi.bV5BlueMask; - int alpha_mask = bi.bV5AlphaMask; - int red_shift = 0; - int green_shift = 0; - int blue_shift = 0; - int alpha_shift = 0; - QImage::Format format = QImage::Format_ARGB32; - - if (bi.bV5Height < 0) - h = -h; // support images with negative height - if (image.size() != QSize(w, h) || image.format() != format) { - image = QImage(w, h, format); - if (image.isNull()) // could not create image - return false; - } - image.setDotsPerMeterX(bi.bV5XPelsPerMeter); - image.setDotsPerMeterY(bi.bV5YPelsPerMeter); - // read color table - DWORD colorSpace[3]; - if (d->read((char *)colorSpace, sizeof(colorSpace)) != sizeof(colorSpace)) - return false; - - red_shift = calc_shift(red_mask); - green_shift = calc_shift(green_mask); - blue_shift = calc_shift(blue_mask); - if (alpha_mask) { - alpha_shift = calc_shift(alpha_mask); - } - - int bpl = image.bytesPerLine(); - uchar *data = image.bits(); - register QRgb *p; - QRgb *end; - uchar *buf24 = new uchar[bpl]; - int bpl24 = ((w*nbits+31)/32)*4; - uchar *b; - unsigned int c; - - while (--h >= 0) { - p = (QRgb *)(data + h*bpl); - end = p + w; - if (d->read((char *)buf24,bpl24) != bpl24) - break; - b = buf24; - while (p < end) { - c = *b | (*(b+1))<<8 | (*(b+2))<<16 | (*(b+3))<<24; - *p++ = qRgba(((c & red_mask) >> red_shift) , - ((c & green_mask) >> green_shift), - ((c & blue_mask) >> blue_shift), - ((c & alpha_mask) >> alpha_shift)); - b += 4; - } - } - delete[] buf24; - - if (bi.bV5Height < 0) { - // Flip the image - uchar *buf = new uchar[bpl]; - h = -bi.bV5Height; - for (int y = 0; y < h/2; ++y) { - memcpy(buf, data + y*bpl, bpl); - memcpy(data + y*bpl, data + (h-y-1)*bpl, bpl); - memcpy(data + (h-y-1)*bpl, buf, bpl); - } - delete [] buf; - } - - return true; -} - -#endif - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qole_win.cpp b/src/widgets/platforms/win/qole_win.cpp deleted file mode 100644 index 1e1a672ac5..0000000000 --- a/src/widgets/platforms/win/qole_win.cpp +++ /dev/null @@ -1,255 +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 "qdnd_p.h" - -#if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD)) - -#if defined(Q_OS_WINCE) -#include -#include "qguifunctions_wince.h" -#endif - -QT_BEGIN_NAMESPACE - -QOleEnumFmtEtc::QOleEnumFmtEtc(const QVector &fmtetcs) -{ - m_isNull = false; - m_dwRefs = 1; - m_nIndex = 0; - - for (int idx = 0; idx < fmtetcs.count(); ++idx) { - LPFORMATETC destetc = new FORMATETC(); - if (copyFormatEtc(destetc, (LPFORMATETC)&(fmtetcs.at(idx)))) { - m_lpfmtetcs.append(destetc); - } else { - m_isNull = true; - delete destetc; - break; - } - } -} - -QOleEnumFmtEtc::QOleEnumFmtEtc(const QVector &lpfmtetcs) -{ - m_isNull = false; - m_dwRefs = 1; - m_nIndex = 0; - - for (int idx = 0; idx < lpfmtetcs.count(); ++idx) { - LPFORMATETC srcetc = lpfmtetcs.at(idx); - LPFORMATETC destetc = new FORMATETC(); - if (copyFormatEtc(destetc, srcetc)) { - m_lpfmtetcs.append(destetc); - } else { - m_isNull = true; - delete destetc; - break; - } - } -} - -QOleEnumFmtEtc::~QOleEnumFmtEtc() -{ - LPMALLOC pmalloc; - -#if !defined(Q_OS_WINCE) - if (CoGetMalloc(MEMCTX_TASK, &pmalloc) == NOERROR) { -#else - if (SHGetMalloc(&pmalloc) == NOERROR) { -#endif - for (int idx = 0; idx < m_lpfmtetcs.count(); ++idx) { - LPFORMATETC tmpetc = m_lpfmtetcs.at(idx); - if (tmpetc->ptd) - pmalloc->Free(tmpetc->ptd); - delete tmpetc; - } - - pmalloc->Release(); - } - m_lpfmtetcs.clear(); -} - -bool QOleEnumFmtEtc::isNull() const -{ - return m_isNull; -} - -// IUnknown methods -STDMETHODIMP -QOleEnumFmtEtc::QueryInterface(REFIID riid, void FAR* FAR* ppvObj) -{ - if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) { - *ppvObj = this; - AddRef(); - return NOERROR; - } - *ppvObj = NULL; - return ResultFromScode(E_NOINTERFACE); -} - -STDMETHODIMP_(ULONG) -QOleEnumFmtEtc::AddRef(void) -{ - return ++m_dwRefs; -} - -STDMETHODIMP_(ULONG) -QOleEnumFmtEtc::Release(void) -{ - if (--m_dwRefs == 0) { - delete this; - return 0; - } - return m_dwRefs; -} - -// IEnumFORMATETC methods -STDMETHODIMP -QOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched) -{ - ULONG i=0; - ULONG nOffset; - - if (rgelt == NULL) - return ResultFromScode(E_INVALIDARG); - - while (i < celt) { - nOffset = m_nIndex + i; - - if (nOffset < ULONG(m_lpfmtetcs.count())) { - copyFormatEtc((LPFORMATETC)&(rgelt[i]), m_lpfmtetcs.at(nOffset)); - i++; - } else { - break; - } - } - - m_nIndex += (WORD)i; - - if (pceltFetched != NULL) - *pceltFetched = i; - - if (i != celt) - return ResultFromScode(S_FALSE); - - return NOERROR; -} - -STDMETHODIMP -QOleEnumFmtEtc::Skip(ULONG celt) -{ - ULONG i=0; - ULONG nOffset; - - while (i < celt) { - nOffset = m_nIndex + i; - - if (nOffset < ULONG(m_lpfmtetcs.count())) { - i++; - } else { - break; - } - } - - m_nIndex += (WORD)i; - - if (i != celt) - return ResultFromScode(S_FALSE); - - return NOERROR; -} - -STDMETHODIMP -QOleEnumFmtEtc::Reset() -{ - m_nIndex = 0; - return NOERROR; -} - -STDMETHODIMP -QOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum) -{ - if (newEnum == NULL) - return ResultFromScode(E_INVALIDARG); - - QOleEnumFmtEtc *result = new QOleEnumFmtEtc(m_lpfmtetcs); - result->m_nIndex = m_nIndex; - - if (result->isNull()) { - delete result; - return ResultFromScode(E_OUTOFMEMORY); - } else { - *newEnum = result; - } - - return NOERROR; -} - -bool QOleEnumFmtEtc::copyFormatEtc(LPFORMATETC dest, LPFORMATETC src) const -{ - if (dest == NULL || src == NULL) - return false; - - *dest = *src; - - if (src->ptd) { - LPVOID pout; - LPMALLOC pmalloc; - -#if !defined(Q_OS_WINCE) - if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) -#else - if (SHGetMalloc(&pmalloc) != NOERROR) -#endif - return false; - - pout = (LPVOID)pmalloc->Alloc(src->ptd->tdSize); - memcpy(dest->ptd, src->ptd, size_t(src->ptd->tdSize)); - - pmalloc->Release(); - } - - return true; -} - -QT_END_NAMESPACE -#endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD diff --git a/src/widgets/platforms/win/qpaintdevice_win.cpp b/src/widgets/platforms/win/qpaintdevice_win.cpp deleted file mode 100644 index a6d79d8341..0000000000 --- a/src/widgets/platforms/win/qpaintdevice_win.cpp +++ /dev/null @@ -1,62 +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 -#include "qt_windows.h" -#include "qprinter.h" - -QT_BEGIN_NAMESPACE - -HDC QPaintDevice::getDC() const -{ - return 0; -} - -void QPaintDevice::releaseDC(HDC) const -{ -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qpixmap_win.cpp b/src/widgets/platforms/win/qpixmap_win.cpp deleted file mode 100644 index c5adb48f5d..0000000000 --- a/src/widgets/platforms/win/qpixmap_win.cpp +++ /dev/null @@ -1,477 +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 "qpixmap.h" -#include "qpixmap_raster_p.h" - -#include "qbitmap.h" -#include "qimage.h" -#include "qwidget.h" -#include "qpainter.h" -#include "qdatastream.h" -#include "qbuffer.h" -#include "qapplication.h" -#include "qevent.h" -#include "qfile.h" -#include "qfileinfo.h" -#include "qdatetime.h" -#include "qpixmapcache.h" -#include "qimagereader.h" -#include "qimagewriter.h" -#include "qdebug.h" -#include "qt_windows.h" - -#if defined(Q_WS_WINCE) -#include -#include "qguifunctions_wince.h" -extern bool qt_wince_is_high_dpi(); -extern bool qt_wince_is_pocket_pc(); -#endif - -#ifndef CAPTUREBLT -#define CAPTUREBLT ((DWORD)0x40000000) -#endif - -QT_BEGIN_NAMESPACE - -QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h ) -{ - RECT r; - GetClientRect(winId, &r); - - if (w < 0) w = r.right - r.left; - if (h < 0) h = r.bottom - r.top; - -#ifdef Q_WS_WINCE_WM - if (qt_wince_is_pocket_pc()) { - QWidget *widget = QWidget::find(winId); - if (qobject_cast(widget)) { - RECT rect = {0,0,0,0}; - AdjustWindowRectEx(&rect, WS_BORDER | WS_CAPTION, FALSE, 0); - int magicNumber = qt_wince_is_high_dpi() ? 4 : 2; - y += rect.top - magicNumber; - } - } -#endif - - // Create and setup bitmap - HDC display_dc = GetDC(0); - HDC bitmap_dc = CreateCompatibleDC(display_dc); - HBITMAP bitmap = CreateCompatibleBitmap(display_dc, w, h); - HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap); - - // copy data - HDC window_dc = GetDC(winId); - BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY -#ifndef Q_WS_WINCE - | CAPTUREBLT -#endif - ); - - // clean up all but bitmap - ReleaseDC(winId, window_dc); - SelectObject(bitmap_dc, null_bitmap); - DeleteDC(bitmap_dc); - - QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap); - - DeleteObject(bitmap); - ReleaseDC(0, display_dc); - - return pixmap; -} - -HBITMAP QPixmap::toWinHBITMAP(HBitmapFormat format) const -{ - if (isNull()) - return 0; - - HBITMAP bitmap = 0; - if (data->classId() == QPlatformPixmap::RasterClass) { - QRasterPlatformPixmap* d = static_cast(data.data()); - int w = d->image.width(); - int h = d->image.height(); - - HDC display_dc = GetDC(0); - - // Define the header - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = w; - bmi.bmiHeader.biHeight = -h; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = w * h * 4; - - // Create the pixmap - uchar *pixels = 0; - bitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, (void **) &pixels, 0, 0); - ReleaseDC(0, display_dc); - if (!bitmap) { - qErrnoWarning("QPixmap::toWinHBITMAP(), failed to create dibsection"); - return 0; - } - if (!pixels) { - qErrnoWarning("QPixmap::toWinHBITMAP(), did not allocate pixel data"); - return 0; - } - - // Copy over the data - QImage::Format imageFormat = QImage::Format_ARGB32; - if (format == NoAlpha) - imageFormat = QImage::Format_RGB32; - else if (format == PremultipliedAlpha) - imageFormat = QImage::Format_ARGB32_Premultiplied; - const QImage image = d->image.convertToFormat(imageFormat); - int bytes_per_line = w * 4; - for (int y=0; yfromImage(toImage(), Qt::AutoColor); - return QPixmap(data).toWinHBITMAP(format); - } - return bitmap; -} - -QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format) -{ - // Verify size - BITMAP bitmap_info; - memset(&bitmap_info, 0, sizeof(BITMAP)); - - int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info); - if (!res) { - qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info"); - return QPixmap(); - } - int w = bitmap_info.bmWidth; - int h = bitmap_info.bmHeight; - - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = w; - bmi.bmiHeader.biHeight = -h; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = w * h * 4; - - QImage result; - // Get bitmap bits - uchar *data = (uchar *) qMalloc(bmi.bmiHeader.biSizeImage); - - HDC display_dc = GetDC(0); - if (GetDIBits(display_dc, bitmap, 0, h, data, &bmi, DIB_RGB_COLORS)) { - - QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied; - uint mask = 0; - if (format == NoAlpha) { - imageFormat = QImage::Format_RGB32; - mask = 0xff000000; - } - - // Create image and copy data into image. - QImage image(w, h, imageFormat); - if (!image.isNull()) { // failed to alloc? - int bytes_per_line = w * sizeof(QRgb); - for (int y=0; y(image.scanLine(y)); - for (int x = 0; x < w ; x++) { - if (qAlpha(scanLine[x]) != 0) { - foundAlpha = true; - break; - } - } - } - if (!foundAlpha) { - //If no alpha was found, we use the mask to set alpha values - DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK); - QImage mask = qt_fromWinHBITMAP(hdc, winBitmap, w, h); - - for (int y = 0 ; y < h ; y++){ - QRgb *scanlineImage = reinterpret_cast(image.scanLine(y)); - QRgb *scanlineMask = mask.isNull() ? 0 : reinterpret_cast(mask.scanLine(y)); - for (int x = 0; x < w ; x++){ - if (scanlineMask && qRed(scanlineMask[x]) != 0) - scanlineImage[x] = 0; //mask out this pixel - else - scanlineImage[x] |= 0xff000000; // set the alpha channel to 255 - } - } - } - //dispose resources created by iconinfo call - DeleteObject(iconinfo.hbmMask); - DeleteObject(iconinfo.hbmColor); - - SelectObject(hdc, oldhdc); //restore state - DeleteObject(winBitmap); - DeleteDC(hdc); - return QPixmap::fromImage(image); -} -#else //ifndef Q_WS_WINCE -QPixmap QPixmap::fromWinHICON(HICON icon) -{ - HDC screenDevice = GetDC(0); - HDC hdc = CreateCompatibleDC(screenDevice); - ReleaseDC(0, screenDevice); - - ICONINFO iconinfo; - bool result = GetIconInfo(icon, &iconinfo); - if (!result) - qWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()"); - - int w = 0; - int h = 0; - if (!iconinfo.xHotspot || !iconinfo.yHotspot) { - // We could not retrieve the icon size via GetIconInfo, - // so we try again using the icon bitmap. - BITMAP bm; - int result = GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bm); - if (!result) result = GetObject(iconinfo.hbmMask, sizeof(BITMAP), &bm); - if (!result) { - qWarning("QPixmap::fromWinHICON(), failed to retrieve icon size"); - return QPixmap(); - } - w = bm.bmWidth; - h = bm.bmHeight; - } else { - // x and y Hotspot describes the icon center - w = iconinfo.xHotspot * 2; - h = iconinfo.yHotspot * 2; - } - const DWORD dwImageSize = w * h * 4; - - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFO); - bmi.bmiHeader.biWidth = w; - bmi.bmiHeader.biHeight = -h; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = dwImageSize; - - uchar* bits; - - HBITMAP winBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &bits, 0, 0); - if (winBitmap ) - memset(bits, 0xff, dwImageSize); - if (!winBitmap) { - qWarning("QPixmap::fromWinHICON(), failed to CreateDIBSection()"); - return QPixmap(); - } - - HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap); - if (!DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_NORMAL)) - qWarning("QPixmap::fromWinHICON(), failed to DrawIcon()"); - - uint mask = 0xff000000; - // Create image and copy data into image. - QImage image(w, h, QImage::Format_ARGB32); - - if (!image.isNull()) { // failed to alloc? - int bytes_per_line = w * sizeof(QRgb); - for (int y=0; y < h; ++y) { - QRgb *dest = (QRgb *) image.scanLine(y); - const QRgb *src = (const QRgb *) (bits + y * bytes_per_line); - for (int x=0; x < w; ++x) { - dest[x] = src[x]; - } - } - } - if (!DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK)) - qWarning("QPixmap::fromWinHICON(), failed to DrawIcon()"); - if (!image.isNull()) { // failed to alloc? - int bytes_per_line = w * sizeof(QRgb); - for (int y=0; y < h; ++y) { - QRgb *dest = (QRgb *) image.scanLine(y); - const QRgb *src = (const QRgb *) (bits + y * bytes_per_line); - for (int x=0; x < w; ++x) { - if (!src[x]) - dest[x] = dest[x] | mask; - } - } - } - SelectObject(hdc, oldhdc); //restore state - DeleteObject(winBitmap); - DeleteDC(hdc); - return QPixmap::fromImage(image); -} -#endif //ifndef Q_WS_WINCE -#endif //ifdef Q_WS_WIN - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qrawfont_win.cpp b/src/widgets/platforms/win/qrawfont_win.cpp deleted file mode 100644 index d8aa557975..0000000000 --- a/src/widgets/platforms/win/qrawfont_win.cpp +++ /dev/null @@ -1,709 +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 test suite 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 "qrawfont_p.h" -#include - -#if !defined(QT_NO_DIRECTWRITE) -# include "qfontenginedirectwrite_p.h" -# include -#endif - -#if !defined(QT_NO_RAWFONT) - -QT_BEGIN_NAMESPACE - -namespace { - - template - struct BigEndian - { - quint8 data[sizeof(T)]; - - operator T() const - { - T littleEndian = 0; - for (int i=0; i &operator=(const T &t) - { - for (int i=0; i> (sizeof(T) - i - 1) * 8) & 0xff); - } - - return *this; - } - }; - -# pragma pack(1) - - // Common structure for all formats of the "name" table - struct NameTable - { - BigEndian format; - BigEndian count; - BigEndian stringOffset; - }; - - struct NameRecord - { - BigEndian platformID; - BigEndian encodingID; - BigEndian languageID; - BigEndian nameID; - BigEndian length; - BigEndian offset; - }; - - struct OffsetSubTable - { - BigEndian scalerType; - BigEndian numTables; - BigEndian searchRange; - BigEndian entrySelector; - BigEndian rangeShift; - }; - - struct TableDirectory - { - BigEndian identifier; - BigEndian checkSum; - BigEndian offset; - BigEndian length; - }; - - struct OS2Table - { - BigEndian version; - BigEndian avgCharWidth; - BigEndian weightClass; - BigEndian widthClass; - BigEndian type; - BigEndian subscriptXSize; - BigEndian subscriptYSize; - BigEndian subscriptXOffset; - BigEndian subscriptYOffset; - BigEndian superscriptXSize; - BigEndian superscriptYSize; - BigEndian superscriptXOffset; - BigEndian superscriptYOffset; - BigEndian strikeOutSize; - BigEndian strikeOutPosition; - BigEndian familyClass; - quint8 panose[10]; - BigEndian unicodeRanges[4]; - quint8 vendorID[4]; - BigEndian selection; - BigEndian firstCharIndex; - BigEndian lastCharIndex; - BigEndian typoAscender; - BigEndian typoDescender; - BigEndian typoLineGap; - BigEndian winAscent; - BigEndian winDescent; - BigEndian codepageRanges[2]; - BigEndian height; - BigEndian capHeight; - BigEndian defaultChar; - BigEndian breakChar; - BigEndian maxContext; - }; - -# pragma pack() - - class EmbeddedFont - { - public: - EmbeddedFont(const QByteArray &fontData); - - QString changeFamilyName(const QString &newFamilyName); - QByteArray data() const { return m_fontData; } - TableDirectory *tableDirectoryEntry(const QByteArray &tagName); - QString familyName(TableDirectory *nameTableDirectory = 0); - - private: - QByteArray m_fontData; - }; - - EmbeddedFont::EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData) - { - } - - TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName) - { - Q_ASSERT(tagName.size() == 4); - - const BigEndian *tagIdPtr = - reinterpret_cast *>(tagName.constData()); - quint32 tagId = *tagIdPtr; - - OffsetSubTable *offsetSubTable = reinterpret_cast(m_fontData.data()); - TableDirectory *tableDirectory = reinterpret_cast(offsetSubTable + 1); - - TableDirectory *nameTableDirectoryEntry = 0; - for (int i=0; inumTables; ++i, ++tableDirectory) { - if (tableDirectory->identifier == tagId) { - nameTableDirectoryEntry = tableDirectory; - break; - } - } - - return nameTableDirectoryEntry; - } - - QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry) - { - QString name; - - if (nameTableDirectoryEntry == 0) - nameTableDirectoryEntry = tableDirectoryEntry("name"); - - if (nameTableDirectoryEntry != 0) { - NameTable *nameTable = reinterpret_cast(m_fontData.data() - + nameTableDirectoryEntry->offset); - NameRecord *nameRecord = reinterpret_cast(nameTable + 1); - for (int i=0; icount; ++i, ++nameRecord) { - if (nameRecord->nameID == 1 - && nameRecord->platformID == 3 // Windows - && nameRecord->languageID == 0x0409) { // US English - const void *ptr = reinterpret_cast(nameTable) - + nameTable->stringOffset - + nameRecord->offset; - - const BigEndian *s = reinterpret_cast *>(ptr); - for (int j=0; jlength / sizeof(quint16); ++j) - name += QChar(s[j]); - - break; - } - } - } - - return name; - } - - QString EmbeddedFont::changeFamilyName(const QString &newFamilyName) - { - TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name"); - if (nameTableDirectoryEntry == 0) - return QString(); - - QString oldFamilyName = familyName(nameTableDirectoryEntry); - - // Reserve size for name table header, five required name records and string - const int requiredRecordCount = 5; - quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 }; - - int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount; - int newFamilyNameSize = newFamilyName.size() * sizeof(quint16); - - const QString regularString = QString::fromLatin1("Regular"); - int regularStringSize = regularString.size() * sizeof(quint16); - - // Align table size of table to 32 bits (pad with 0) - int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4; - - QByteArray newNameTable(fullSize, char(0)); - - { - NameTable *nameTable = reinterpret_cast(newNameTable.data()); - nameTable->count = requiredRecordCount; - nameTable->stringOffset = sizeOfHeader; - - NameRecord *nameRecord = reinterpret_cast(nameTable + 1); - for (int i=0; inameID = nameIds[i]; - nameRecord->encodingID = 1; - nameRecord->languageID = 0x0409; - nameRecord->platformID = 3; - nameRecord->length = newFamilyNameSize; - - // Special case for sub-family - if (nameIds[i] == 4) { - nameRecord->offset = newFamilyNameSize; - nameRecord->length = regularStringSize; - } - } - - // nameRecord now points to string data - BigEndian *stringStorage = reinterpret_cast *>(nameRecord); - const quint16 *sourceString = newFamilyName.utf16(); - for (int i=0; i(newNameTable.data()); - quint32 *tableEnd = reinterpret_cast(newNameTable.data() + fullSize); - - quint32 checkSum = 0; - while (p < tableEnd) - checkSum += *(p++); - - nameTableDirectoryEntry->checkSum = checkSum; - nameTableDirectoryEntry->offset = m_fontData.size(); - nameTableDirectoryEntry->length = fullSize; - - m_fontData.append(newNameTable); - - return oldFamilyName; - } - -#if !defined(QT_NO_DIRECTWRITE) - - class DirectWriteFontFileStream: public IDWriteFontFileStream - { - public: - DirectWriteFontFileStream(const QByteArray &fontData) - : m_fontData(fontData) - , m_referenceCount(0) - { - } - - ~DirectWriteFontFileStream() - { - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset, - UINT64 fragmentSize, OUT void **fragmentContext); - void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext); - HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize); - HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime); - - private: - QByteArray m_fontData; - ULONG m_referenceCount; - }; - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object) - { - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) { - *object = this; - AddRef(); - return S_OK; - } else { - *object = NULL; - return E_NOINTERFACE; - } - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef() - { - return InterlockedIncrement(&m_referenceCount); - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release() - { - ULONG newCount = InterlockedDecrement(&m_referenceCount); - if (newCount == 0) - delete this; - return newCount; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment( - const void **fragmentStart, - UINT64 fileOffset, - UINT64 fragmentSize, - OUT void **fragmentContext) - { - *fragmentContext = NULL; - if (fragmentSize + fileOffset <= m_fontData.size()) { - *fragmentStart = m_fontData.data() + fileOffset; - return S_OK; - } else { - *fragmentStart = NULL; - return E_FAIL; - } - } - - void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *) - { - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize) - { - *fileSize = m_fontData.size(); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) - { - *lastWriteTime = 0; - return E_NOTIMPL; - } - - class DirectWriteFontFileLoader: public IDWriteFontFileLoader - { - public: - DirectWriteFontFileLoader() : m_referenceCount(0) {} - - ~DirectWriteFontFileLoader() - { - } - - inline void addKey(const void *key, const QByteArray &fontData) - { - Q_ASSERT(!m_fontDatas.contains(key)); - m_fontDatas.insert(key, fontData); - } - - inline void removeKey(const void *key) - { - m_fontDatas.remove(key); - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - OUT IDWriteFontFileStream **fontFileStream); - - private: - ULONG m_referenceCount; - QHash m_fontDatas; - }; - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid, - void **object) - { - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { - *object = this; - AddRef(); - return S_OK; - } else { - *object = NULL; - return E_NOINTERFACE; - } - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef() - { - return InterlockedIncrement(&m_referenceCount); - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release() - { - ULONG newCount = InterlockedDecrement(&m_referenceCount); - if (newCount == 0) - delete this; - return newCount; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey( - void const *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - IDWriteFontFileStream **fontFileStream) - { - Q_UNUSED(fontFileReferenceKeySize); - - if (fontFileReferenceKeySize != sizeof(const void *)) { - qWarning("DirectWriteFontFileLoader::CreateStreamFromKey: Wrong key size"); - return E_FAIL; - } - - const void *key = *reinterpret_cast(fontFileReferenceKey); - *fontFileStream = NULL; - if (!m_fontDatas.contains(key)) - return E_FAIL; - - QByteArray fontData = m_fontDatas.value(key); - DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData); - stream->AddRef(); - *fontFileStream = stream; - - return S_OK; - } - - class CustomFontFileLoader - { - public: - CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0) - { - HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast(&m_directWriteFactory)); - if (FAILED(hres)) { - qErrnoWarning(hres, "CustomFontFileLoader::CustomFontFileLoader: " - "DWriteCreateFactory failed."); - } else { - m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); - m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); - } - } - - ~CustomFontFileLoader() - { - if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0) - m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); - - if (m_directWriteFactory != 0) - m_directWriteFactory->Release(); - } - - void addKey(const void *key, const QByteArray &fontData) - { - if (m_directWriteFontFileLoader != 0) - m_directWriteFontFileLoader->addKey(key, fontData); - } - - void removeKey(const void *key) - { - if (m_directWriteFontFileLoader != 0) - m_directWriteFontFileLoader->removeKey(key); - } - - IDWriteFontFileLoader *loader() const - { - return m_directWriteFontFileLoader; - } - - private: - IDWriteFactory *m_directWriteFactory; - DirectWriteFontFileLoader *m_directWriteFontFileLoader; - }; - -#endif - -} // Anonymous namespace - - -// From qfontdatabase_win.cpp -extern QFontEngine *qt_load_font_engine_win(const QFontDef &request); -// From qfontdatabase.cpp -extern QFont::Weight weightFromInteger(int weight); - -void QRawFontPrivate::platformCleanUp() -{ - if (fontHandle != NULL) { - if (ptrRemoveFontMemResourceEx == NULL) { - QFunctionPointer func = - QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx"); - ptrRemoveFontMemResourceEx = - reinterpret_cast(func); - } - - if (ptrRemoveFontMemResourceEx == NULL) { - qWarning("QRawFont::platformCleanUp: Can't find RemoveFontMemResourceEx in gdi32"); - fontHandle = NULL; - } else { - ptrRemoveFontMemResourceEx(fontHandle); - fontHandle = NULL; - } - } -} - -void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData, - qreal pixelSize, - QFont::HintingPreference hintingPreference) -{ - QByteArray fontData(_fontData); - EmbeddedFont font(fontData); - -#if !defined(QT_NO_DIRECTWRITE) - if (hintingPreference == QFont::PreferDefaultHinting - || hintingPreference == QFont::PreferFullHinting) -#endif - { - GUID guid; - CoCreateGuid(&guid); - - QString uniqueFamilyName = QString::fromLatin1("f") - + QString::number(guid.Data1, 36) + QLatin1Char('-') - + QString::number(guid.Data2, 36) + QLatin1Char('-') - + QString::number(guid.Data3, 36) + QLatin1Char('-') - + QString::number(*reinterpret_cast(guid.Data4), 36); - - QString actualFontName = font.changeFamilyName(uniqueFamilyName); - if (actualFontName.isEmpty()) { - qWarning("QRawFont::platformLoadFromData: Can't change family name of font"); - return; - } - - if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) { - QFunctionPointer func = - QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx"); - ptrRemoveFontMemResourceEx = - reinterpret_cast(func); - - func = QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontMemResourceEx"); - ptrAddFontMemResourceEx = - reinterpret_cast(func); - } - - Q_ASSERT(fontHandle == NULL); - if (ptrAddFontMemResourceEx != NULL && ptrRemoveFontMemResourceEx != NULL) { - DWORD count = 0; - fontData = font.data(); - fontHandle = ptrAddFontMemResourceEx(fontData.data(), fontData.size(), 0, &count); - - if (count == 0 && fontHandle != NULL) { - ptrRemoveFontMemResourceEx(fontHandle); - fontHandle = NULL; - } - } - - if (fontHandle == NULL) { - qWarning("QRawFont::platformLoadFromData: AddFontMemResourceEx failed"); - } else { - QFontDef request; - request.family = uniqueFamilyName; - request.pixelSize = pixelSize; - request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch; - request.hintingPreference = hintingPreference; - - fontEngine = qt_load_font_engine_win(request); - if (request.family != fontEngine->fontDef.family) { - qWarning("QRawFont::platformLoadFromData: Failed to load font. " - "Got fallback instead: %s", qPrintable(fontEngine->fontDef.family)); - if (fontEngine->cache_count == 0 && fontEngine->ref == 0) - delete fontEngine; - fontEngine = 0; - } else { - Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref == 0); - - // Override the generated font name - static_cast(fontEngine)->uniqueFamilyName = uniqueFamilyName; - fontEngine->fontDef.family = actualFontName; - fontEngine->ref.ref(); - } - } - } -#if !defined(QT_NO_DIRECTWRITE) - else { - CustomFontFileLoader fontFileLoader; - fontFileLoader.addKey(this, fontData); - - IDWriteFactory *factory = NULL; - HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast(&factory)); - if (FAILED(hres)) { - qErrnoWarning(hres, "QRawFont::platformLoadFromData: DWriteCreateFactory failed"); - return; - } - - IDWriteFontFile *fontFile = NULL; - void *key = this; - - hres = factory->CreateCustomFontFileReference(&key, sizeof(void *), - fontFileLoader.loader(), &fontFile); - if (FAILED(hres)) { - qErrnoWarning(hres, "QRawFont::platformLoadFromData: " - "CreateCustomFontFileReference failed"); - factory->Release(); - return; - } - - BOOL isSupportedFontType; - DWRITE_FONT_FILE_TYPE fontFileType; - DWRITE_FONT_FACE_TYPE fontFaceType; - UINT32 numberOfFaces; - fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces); - if (!isSupportedFontType) { - fontFile->Release(); - factory->Release(); - return; - } - - IDWriteFontFace *directWriteFontFace = NULL; - hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE, - &directWriteFontFace); - if (FAILED(hres)) { - qErrnoWarning(hres, "QRawFont::platformLoadFromData: CreateFontFace failed"); - fontFile->Release(); - factory->Release(); - return; - } - - fontFile->Release(); - - fontEngine = new QFontEngineDirectWrite(factory, directWriteFontFace, pixelSize); - - // Get font family from font data - fontEngine->fontDef.family = font.familyName(); - fontEngine->ref.ref(); - - directWriteFontFace->Release(); - factory->Release(); - } -#endif - - // Get style and weight info - if (fontEngine != 0) { - TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2"); - if (os2TableEntry != 0) { - const OS2Table *os2Table = - reinterpret_cast(fontData.constData() - + os2TableEntry->offset); - - bool italic = os2Table->selection & 1; - bool oblique = os2Table->selection & 128; - - if (italic) - fontEngine->fontDef.style = QFont::StyleItalic; - else if (oblique) - fontEngine->fontDef.style = QFont::StyleOblique; - else - fontEngine->fontDef.style = QFont::StyleNormal; - - fontEngine->fontDef.weight = weightFromInteger(os2Table->weightClass); - } - } -} - -QT_END_NAMESPACE - -#endif // QT_NO_RAWFONT diff --git a/src/widgets/platforms/win/qregion_win.cpp b/src/widgets/platforms/win/qregion_win.cpp deleted file mode 100644 index 57fd0858e0..0000000000 --- a/src/widgets/platforms/win/qregion_win.cpp +++ /dev/null @@ -1,149 +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 "qatomic.h" -#include "qbitmap.h" -#include "qbuffer.h" -#include "qimage.h" -#include "qpolygon.h" -#include "qregion.h" -#include "qt_windows.h" -#include "qpainterpath.h" - -QT_BEGIN_NAMESPACE - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; - -HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region = 0; - switch (type) { - case QRegion::Rectangle: - region = CreateRectRgn(left, top, right, bottom); - break; - case QRegion::Ellipse: -#ifndef Q_OS_WINCE - region = CreateEllipticRgn(left, top, right, bottom); -#endif - break; - } - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} - -QRegion qt_region_from_HRGN(HRGN rgn) -{ - int numBytes = GetRegionData(rgn, 0, 0); - if (numBytes == 0) - return QRegion(); - - char *buf = new char[numBytes]; - if (buf == 0) - return QRegion(); - - RGNDATA *rd = reinterpret_cast(buf); - if (GetRegionData(rgn, numBytes, rd) == 0) { - delete [] buf; - return QRegion(); - } - - QRegion region; - RECT *r = reinterpret_cast(rd->Buffer); - for (uint i = 0; i < rd->rdh.nCount; ++i) { - QRect rect; - rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1); - ++r; - region |= rect; - } - - delete [] buf; - - return region; -} - -void qt_win_dispose_rgn(HRGN r) -{ - if (r) - DeleteObject(r); -} - -static void qt_add_rect(HRGN &winRegion, QRect r) -{ - HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - if (rgn) { - HRGN dest = CreateRectRgn(0,0,0,0); - int result = CombineRgn(dest, winRegion, rgn, RGN_OR); - if (result) { - DeleteObject(winRegion); - winRegion = dest; - } - DeleteObject(rgn); - } -} - -void QRegion::ensureHandle() const -{ - if (d->rgn) - DeleteObject(d->rgn); - d->rgn = CreateRectRgn(0,0,0,0); - if (d->qt_rgn) { - if (d->qt_rgn->numRects == 1) { - QRect r = d->qt_rgn->extents; - qt_add_rect(d->rgn, r); - return; - } - for (int i = 0;i < d->qt_rgn->numRects;i++) { - QRect r = d->qt_rgn->rects.at(i); - qt_add_rect(d->rgn, r); - } - } -} - - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qsound_win.cpp b/src/widgets/platforms/win/qsound_win.cpp deleted file mode 100644 index 3c77dacf2a..0000000000 --- a/src/widgets/platforms/win/qsound_win.cpp +++ /dev/null @@ -1,205 +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 "qapplication.h" -#include "qapplication_p.h" -#include -#include "qpointer.h" -#include "qsound_p.h" - -#include - -QT_BEGIN_NAMESPACE - -class QAuServerWindows : public QAuServer { - Q_OBJECT - -public: - QAuServerWindows(QObject* parent); - ~QAuServerWindows(); - - void playHelper(const QString &filename, int loop, QSound *snd); - void play(const QString& filename, int loop); - void play(QSound*); - - void stop(QSound*); - bool okay(); - - int decLoop(QSound *snd) { return QAuServer::decLoop(snd); } - - HANDLE current; - HANDLE mutex; - HANDLE event; -}; - -QAuServerWindows::QAuServerWindows(QObject* parent) : - QAuServer(parent), current(0) -{ - mutex = CreateMutex(0, 0, 0); - event = CreateEvent(0, FALSE, FALSE, 0); -} - -QAuServerWindows::~QAuServerWindows() -{ - HANDLE mtx = mutex; - WaitForSingleObject(mtx, INFINITE); - mutex = 0; - - ReleaseMutex(mtx); - CloseHandle(mtx); - CloseHandle(event); -} - -struct SoundInfo -{ - SoundInfo(const QString &fn, int lp, QSound *snd, QAuServerWindows *srv) - : sound(snd), server(srv), filename(fn), loops(lp) - { - } - - QSound *sound; - QAuServerWindows *server; - QString filename; - int loops; -}; - -DWORD WINAPI SoundPlayProc(LPVOID param) -{ - SoundInfo *info = (SoundInfo*)param; - - // copy data before waking up GUI thread - QAuServerWindows *server = info->server; - QSound *sound = info->sound; - int loops = info->loops; - QString filename = info->filename; - HANDLE mutex = server->mutex; - HANDLE event = server->event; - info = 0; - - // server must not be destroyed until thread finishes - // and all other sounds have to wait - WaitForSingleObject(mutex, INFINITE); - - if (loops <= 1) { - server->current = 0; - int flags = SND_FILENAME|SND_ASYNC; - if (loops == -1) - flags |= SND_LOOP; - - PlaySound((wchar_t*)filename.utf16(), 0, flags); - if (sound && loops == 1) - server->decLoop(sound); - - // GUI thread continues, but we are done as well. - SetEvent(event); - } else { - // signal GUI thread to continue - sound might be reset! - QPointer guarded_sound = sound; - SetEvent(event); - - for (int l = 0; l < loops && server->current; ++l) { - PlaySound((wchar_t*)filename.utf16(), 0, SND_FILENAME | SND_SYNC); - - if (guarded_sound) - server->decLoop(guarded_sound); - } - server->current = 0; - } - ReleaseMutex(mutex); - - return 0; -} - -void QAuServerWindows::playHelper(const QString &filename, int loop, QSound *snd) -{ - if (loop == 0) - return; - // busy? - if (WaitForSingleObject(mutex, 0) == WAIT_TIMEOUT) - return; - ReleaseMutex(mutex); - - DWORD threadid = 0; - SoundInfo info(filename, loop, snd, this); - current = CreateThread(0, 0, SoundPlayProc, &info, 0, &threadid); - CloseHandle(current); - - WaitForSingleObject(event, INFINITE); -} - -void QAuServerWindows::play(const QString& filename, int loop) -{ - playHelper(filename, loop, 0); -} - -void QAuServerWindows::play(QSound* s) -{ - playHelper(s->fileName(), s->loops(), s); -} - -void QAuServerWindows::stop(QSound*) -{ - // stop unlooped sound - if (!current) - PlaySound(0, 0, 0); - // stop after loop is done - current = 0; -} - -bool QAuServerWindows::okay() -{ - return true; -} - -QAuServer* qt_new_audio_server() -{ - return new QAuServerWindows(qApp); -} - -QT_END_NAMESPACE - -#include "qsound_win.moc" - -#endif // QT_NO_SOUND diff --git a/src/widgets/platforms/win/qwidget_win.cpp b/src/widgets/platforms/win/qwidget_win.cpp deleted file mode 100644 index 60446ddb08..0000000000 --- a/src/widgets/platforms/win/qwidget_win.cpp +++ /dev/null @@ -1,2139 +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 "qapplication_p.h" -#include "qbitmap.h" -#include "qcursor.h" -#include "qdesktopwidget.h" -#include "qevent.h" -#include "qimage.h" -#include "qlayout.h" -#include "qpainter.h" -#include "qstack.h" -#include "qt_windows.h" -#include "qwidget.h" -#include "qwidget_p.h" -#include "private/qbackingstore_p.h" -#include "private/qwindowsurface_raster_p.h" - -#include "qscrollbar.h" -#include "qabstractscrollarea.h" -#include - -#include - -#include -#include -#include -#include - -#if defined(Q_WS_WINCE) -#include "qguifunctions_wince.h" -QT_USE_NAMESPACE -extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp -extern void qt_wince_unmaximize(QWidget *widget); //defined in qguifunctions_wince.cpp -extern void qt_wince_minimize(HWND hwnd); //defined in qguifunctions_wince.cpp -extern void qt_wince_full_screen(HWND hwnd, bool fullScreen, UINT swpf); //defined in qguifunctions_wince.cpp -extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp -#endif - -typedef BOOL (WINAPI *PtrSetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags); -static PtrSetLayeredWindowAttributes ptrSetLayeredWindowAttributes = 0; - -#ifndef QT_NO_DIRECTDRAW -#include -#include -static IDirectDraw *qt_ddraw_object; -static IDirectDrawSurface *qt_ddraw_primary; -#endif - - - -#if defined(QT_NON_COMMERCIAL) -#include "qnc_win.h" -#endif - -#if !defined(WS_EX_TOOLWINDOW) -#define WS_EX_TOOLWINDOW 0x00000080 -#endif - -#if !defined(GWLP_WNDPROC) -#define GWLP_WNDPROC GWL_WNDPROC -#endif - -//#define TABLET_DEBUG -#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \ - | PK_ORIENTATION | PK_CURSOR | PK_Z) -#define PACKETMODE 0 -#include -#include - -QT_BEGIN_NAMESPACE - -typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL); -typedef BOOL (API *PtrWTClose)(HCTX); -typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID); -typedef BOOL (API *PtrWTEnable)(HCTX, BOOL); -typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL); -typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID); -typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT); -typedef int (API *PtrWTQueueSizeGet)(HCTX); -typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int); - -static PtrWTOpen ptrWTOpen = 0; -static PtrWTClose ptrWTClose = 0; -static PtrWTInfo ptrWTInfo = 0; -static PtrWTQueueSizeGet ptrWTQueueSizeGet = 0; -static PtrWTQueueSizeSet ptrWTQueueSizeSet = 0; -#ifndef QT_NO_TABLETEVENT -static void init_wintab_functions(); -static void qt_tablet_init(); -static void qt_tablet_cleanup(); -#endif // QT_NO_TABLETEVENT -extern HCTX qt_tablet_context; -extern bool qt_tablet_tilt_support; - -static QWidget *qt_tablet_widget = 0; -QWidget* qt_get_tablet_widget() -{ - return qt_tablet_widget; -} - -extern bool qt_is_gui_used; - -#ifndef QT_NO_TABLETEVENT -static void init_wintab_functions() -{ -#if defined(Q_OS_WINCE) - return; -#else - if (!qt_is_gui_used) - return; - QSystemLibrary library(QLatin1String("wintab32")); - ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW"); - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTClose = (PtrWTClose)library.resolve("WTClose"); - ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet"); - ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet"); -#endif // Q_OS_WINCE -} - -static void qt_tablet_init() -{ - static bool firstTime = true; - if (!firstTime) - return; - firstTime = false; - qt_tablet_widget = new QWidget(0); - qt_tablet_widget->createWinId(); - qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget")); - // We don't need this internal widget to appear in QApplication::topLevelWidgets() - if (QWidgetPrivate::allWidgets) - QWidgetPrivate::allWidgets->remove(qt_tablet_widget); - LOGCONTEXT lcMine; - qAddPostRoutine(qt_tablet_cleanup); - struct tagAXIS tpOri[3]; - init_wintab_functions(); - if (ptrWTInfo && ptrWTOpen && ptrWTQueueSizeGet && ptrWTQueueSizeSet) { - // make sure we have WinTab - if (!ptrWTInfo(0, 0, NULL)) { -#ifdef TABLET_DEBUG - qWarning("QWidget: Wintab services not available"); -#endif - return; - } - - // some tablets don't support tilt, check if it is possible, - qt_tablet_tilt_support = ptrWTInfo(WTI_DEVICES, DVC_ORIENTATION, &tpOri); - if (qt_tablet_tilt_support) { - // check for azimuth and altitude - qt_tablet_tilt_support = tpOri[0].axResolution && tpOri[1].axResolution; - } - // build our context from the default context - ptrWTInfo(WTI_DEFSYSCTX, 0, &lcMine); - // Go for the raw coordinates, the tablet event will return good stuff - lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; - lcMine.lcPktData = PACKETDATA; - lcMine.lcPktMode = PACKETMODE; - lcMine.lcMoveMask = PACKETDATA; - lcMine.lcOutOrgX = 0; - lcMine.lcOutExtX = lcMine.lcInExtX; - lcMine.lcOutOrgY = 0; - lcMine.lcOutExtY = -lcMine.lcInExtY; - qt_tablet_context = ptrWTOpen(qt_tablet_widget->winId(), &lcMine, true); -#ifdef TABLET_DEBUG - qDebug("Tablet is %p", qt_tablet_context); -#endif - if (!qt_tablet_context) { -#ifdef TABLET_DEBUG - qWarning("QWidget: Failed to open the tablet"); -#endif - return; - } - // Set the size of the Packet Queue to the correct size... - int currSize = ptrWTQueueSizeGet(qt_tablet_context); - if (!ptrWTQueueSizeSet(qt_tablet_context, QT_TABLET_NPACKETQSIZE)) { - // Ideally one might want to use a smaller - // multiple, but for now, since we managed to destroy - // the existing Q with the previous call, set it back - // to the other size, which should work. If not, - // there will be trouble. - if (!ptrWTQueueSizeSet(qt_tablet_context, currSize)) { - Q_ASSERT_X(0, "Qt::Internal", "There is no packet queue for" - " the tablet. The tablet will not work"); - } - } - } -} - -static void qt_tablet_cleanup() -{ - if (ptrWTClose) - ptrWTClose(qt_tablet_context); - delete qt_tablet_widget; - qt_tablet_widget = 0; -} -#endif // QT_NO_TABLETEVENT - -const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp - -#ifndef QT_NO_DRAGANDDROP -void qt_olednd_unregister(QWidget* widget, QOleDropTarget *dst); // dnd_win -QOleDropTarget* qt_olednd_register(QWidget* widget); -#endif - -extern bool qt_nograb(); -extern HRGN qt_win_bitmapToRegion(const QBitmap& bitmap); - -static QWidget *mouseGrb = 0; -static QCursor *mouseGrbCur = 0; -static QWidget *keyboardGrb = 0; -static HHOOK journalRec = 0; - -extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); - -#define XCOORD_MAX 16383 -#define WRECT_MAX 16383 - -/***************************************************************************** - QWidget member functions - *****************************************************************************/ - -#ifndef Q_WS_WINCE -void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) -{ - Q_Q(QWidget); - static int sw = -1, sh = -1; - - Qt::WindowType type = q->windowType(); - Qt::WindowFlags flags = data.window_flags; - - bool topLevel = (flags & Qt::Window); - bool popup = (type == Qt::Popup); - bool dialog = (type == Qt::Dialog - || type == Qt::Sheet - || (flags & Qt::MSWindowsFixedSizeDialogHint)); - bool desktop = (type == Qt::Desktop); - bool tool = (type == Qt::Tool || type == Qt::Drawer); - - HINSTANCE appinst = qWinAppInst(); - HWND parentw, destroyw = 0; - WId id = 0; - - QString windowClassName = qt_reg_winclass(q); - - if (!window) // always initialize - initializeWindow = true; - - if (popup) - flags |= Qt::WindowStaysOnTopHint; // a popup stays on top - - if (sw < 0) { // get the (primary) screen size - sw = GetSystemMetrics(SM_CXSCREEN); - sh = GetSystemMetrics(SM_CYSCREEN); - } - - if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget - popup = false; // force this flags off - data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */), - GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */)); - } - - parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0; - - QString title; - int style = WS_CHILD; - int exsty = 0; - - if (window) { - style = GetWindowLong(window, GWL_STYLE); - if (!style) - qErrnoWarning("QWidget::create: GetWindowLong failed"); - topLevel = false; // #### needed for some IE plugins?? - } else if (popup || (type == Qt::ToolTip) || (type == Qt::SplashScreen)) { - style = WS_POPUP; - } else if (topLevel && !desktop) { - if (flags & Qt::FramelessWindowHint) - style = WS_POPUP; // no border - else if (flags & Qt::WindowTitleHint) - style = WS_OVERLAPPED; - else - style = 0; - } - if (!desktop) { - // if (!testAttribute(Qt::WA_PaintUnclipped)) - // ### Commented out for now as it causes some problems, but - // this should be correct anyway, so dig some more into this -#ifndef Q_FLATTEN_EXPOSE - style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ; -#endif - if (topLevel) { - if ((type == Qt::Window || dialog || tool)) { - if (!(flags & Qt::FramelessWindowHint)) { - style |= WS_POPUP; - if (!(flags & Qt::MSWindowsFixedSizeDialogHint)) - style |= WS_THICKFRAME; - else - style |= WS_DLGFRAME; - } - if (flags & Qt::WindowTitleHint) - style |= WS_CAPTION; - if (flags & Qt::WindowSystemMenuHint) - style |= WS_SYSMENU; - if (flags & Qt::WindowMinimizeButtonHint) - style |= WS_MINIMIZEBOX; - if (shouldShowMaximizeButton()) - style |= WS_MAXIMIZEBOX; - if (tool) - exsty |= WS_EX_TOOLWINDOW; - if (flags & Qt::WindowContextHelpButtonHint) - exsty |= WS_EX_CONTEXTHELP; - } else { - exsty |= WS_EX_TOOLWINDOW; - } - } - } - - if (flags & Qt::WindowTitleHint) { - title = q->isWindow() ? qAppName() : q->objectName(); - } - - // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in - // qapplication_win.cpp. We switch it off temporarily to avoid move - // and resize events during creationt - q->setAttribute(Qt::WA_WState_Created, false); - - if (window) { // override the old window - if (destroyOldWindow) - destroyw = data.winid; - id = window; - setWinId(window); - LONG res = SetWindowLong(window, GWL_STYLE, style); - if (!res) - qErrnoWarning("QWidget::create: Failed to set window style"); -#ifdef _WIN64 - res = SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc ); -#else - res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc ); -#endif - if (!res) - qErrnoWarning("QWidget::create: Failed to set window procedure"); - } else if (desktop) { // desktop widget - id = GetDesktopWindow(); -// QWidget *otherDesktop = QWidget::find(id); // is there another desktop? -// if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) { -// otherDesktop->d_func()->setWinId(0); // remove id from widget mapper -// d->setWinId(id); // make sure otherDesktop is -// otherDesktop->d_func()->setWinId(id); // found first -// } else { - setWinId(id); -// } - } else if (topLevel) { // create top-level widget - if (popup) - parentw = 0; - - const bool wasMoved = q->testAttribute(Qt::WA_Moved); - int x = wasMoved ? data.crect.left() : CW_USEDEFAULT; - int y = wasMoved ? data.crect.top() : CW_USEDEFAULT; - int w = CW_USEDEFAULT; - int h = CW_USEDEFAULT; - - // Adjust for framestrut when needed - RECT rect = {0,0,0,0}; - bool isVisibleOnScreen = !q->testAttribute(Qt::WA_DontShowOnScreen); - if (isVisibleOnScreen && AdjustWindowRectEx(&rect, style & ~WS_OVERLAPPED, FALSE, exsty)) { - QTLWExtra *td = maybeTopData(); - if (wasMoved && (td && !td->posFromMove)) { - x = data.crect.x() + rect.left; - y = data.crect.y() + rect.top; - } - - if (q->testAttribute(Qt::WA_Resized)) { - w = data.crect.width() + (rect.right - rect.left); - h = data.crect.height() + (rect.bottom - rect.top); - } - } - //update position & initial size of POPUP window - if (isVisibleOnScreen && topLevel && initializeWindow && (style & WS_POPUP)) { - if (!q->testAttribute(Qt::WA_Resized)) { - w = sw/2; - h = 4*sh/10; - if (extra) { - int dx = rect.right - rect.left; - int dy = rect.bottom - rect.top; - w = qMin(w, extra->maxw + dx); - h = qMin(h, extra->maxh + dy); - w = qMax(w, extra->minw + dx); - h = qMax(h, extra->minh + dy); - } - } - if (!wasMoved) { - x = sw/2 - w/2; - y = sh/2 - h/2; - } - } - - id = CreateWindowEx(exsty, reinterpret_cast(windowClassName.utf16()), - reinterpret_cast(title.utf16()), style, - x, y, w, h, - parentw, NULL, appinst, NULL); - if (!id) - qErrnoWarning("QWidget::create: Failed to create window"); - setWinId(id); - if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) { - SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - if (flags & Qt::WindowStaysOnBottomHint) - qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time"; - } else if (flags & Qt::WindowStaysOnBottomHint) - SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - winUpdateIsOpaque(); - } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget - id = CreateWindowEx(exsty, reinterpret_cast(windowClassName.utf16()), - reinterpret_cast(title.utf16()), style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), - parentw, NULL, appinst, NULL); - if (!id) - qErrnoWarning("QWidget::create: Failed to create window"); - SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - setWinId(id); - } - - if (desktop) { - q->setAttribute(Qt::WA_WState_Visible); - } else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) { - RECT cr; - GetClientRect(id, &cr); - // one cannot trust cr.left and cr.top, use a correction POINT instead - POINT pt; - pt.x = 0; - pt.y = 0; - ClientToScreen(id, &pt); - - if (data.crect.width() == 0 || data.crect.height() == 0) { - data.crect = QRect(pt.x, pt.y, data.crect.width(), data.crect.height()); - } else { - data.crect = QRect(QPoint(pt.x, pt.y), - QPoint(pt.x + cr.right - 1, pt.y + cr.bottom - 1)); - } - - if (data.fstrut_dirty) { - // be nice to activeqt - updateFrameStrut(); - } - } - - if (topLevel) { - if (data.window_flags & Qt::CustomizeWindowHint - && data.window_flags & Qt::WindowTitleHint) { - HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE); - if (data.window_flags & Qt::WindowCloseButtonHint) - EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED); - else - EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); - } - } - - q->setAttribute(Qt::WA_WState_Created); // accept move/resize events - hd = 0; // no display context - - if (q->testAttribute(Qt::WA_AcceptTouchEvents)) - registerTouchWindow(); - - if (window) { // got window from outside - if (IsWindowVisible(window)) - q->setAttribute(Qt::WA_WState_Visible); - else - q->setAttribute(Qt::WA_WState_Visible, false); - } - - if (extra && !extra->mask.isEmpty()) - setMask_sys(extra->mask); - -#if defined(QT_NON_COMMERCIAL) - QT_NC_WIDGET_CREATE -#endif - - if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) - q->inputContext()->setFocusWidget(q); - - if (destroyw) { - DestroyWindow(destroyw); - } - -#ifndef QT_NO_TABLETEVENT - if (q != qt_tablet_widget && QWidgetPrivate::mapper) - qt_tablet_init(); -#endif // QT_NO_TABLETEVENT - - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - - if (maybeTopData() && maybeTopData()->opacity != 255) - q->setWindowOpacity(maybeTopData()->opacity/255.); - - 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()); - ShowWindow(q->internalWinId(), SW_SHOW); - } -} - -#endif //Q_WS_WINCE - - -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); - for(int i = 0; i < d->children.size(); ++i) { // destroy all widget children - register QObject *obj = d->children.at(i); - if (obj->isWidgetType()) - ((QWidget*)obj)->destroy(destroySubWindows, - destroySubWindows); - } - if (mouseGrb == this) - releaseMouse(); - if (keyboardGrb == this) - releaseKeyboard(); - if (testAttribute(Qt::WA_ShowModal)) // just be sure we leave modal - QApplicationPrivate::leaveModal(this); - else if ((windowType() == Qt::Popup)) - qApp->d_func()->closePopup(this); - if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) { - DestroyWindow(internalWinId()); - } -#ifdef Q_WS_WINCE - if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) { - DestroyWindow(internalWinId()); - } - -#endif - QT_TRY { - d->setWinId(0); - } QT_CATCH (const std::bad_alloc &) { - // swallow - destructors must not throw - } - } -} - -void QWidgetPrivate::reparentChildren() -{ - Q_Q(QWidget); - 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->windowType() == Qt::Popup)) { - ; - } else if (w->isWindow()) { - bool showIt = w->isVisible(); - QPoint old_pos = w->pos(); - w->setParent(q, w->windowFlags()); - w->move(old_pos); - if (showIt) - w->show(); - } else { - w->d_func()->invalidateBuffer(w->rect()); - SetParent(w->effectiveWinId(), q->effectiveWinId()); - w->d_func()->reparentChildren(); - } - } - } -} - -void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) -{ - Q_Q(QWidget); - bool wasCreated = q->testAttribute(Qt::WA_WState_Created); - if (q->isVisible() && q->parentWidget() && parent != q->parentWidget()) - q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); - - WId old_winid = data.winid; - // hide and reparent our own window away. Otherwise we might get - // destroyed when emitting the child remove event below. See QWorkspace. - if (q->isVisible() && data.winid) { - ShowWindow(data.winid, SW_HIDE); - SetParent(data.winid, 0); - } - bool dropSiteWasRegistered = false; - if (q->testAttribute(Qt::WA_DropSiteRegistered)) { - dropSiteWasRegistered = true; - q->setAttribute(Qt::WA_DropSiteRegistered, false); // ole dnd unregister (we will register again below) - } - - if ((q->windowType() == Qt::Desktop)) - old_winid = 0; - setWinId(0); - - QObjectPrivate::setParent_helper(parent); - bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); - - data.window_flags = f; - data.fstrut_dirty = true; - 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 || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created))) - createWinId(); - if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden) - q->setAttribute(Qt::WA_WState_Hidden); - q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); - - if (wasCreated) { - reparentChildren(); - } - - if (extra && !extra->mask.isEmpty()) { - QRegion r = extra->mask; - extra->mask = QRegion(); - q->setMask(r); - } - if (extra && extra->topextra && !extra->topextra->caption.isEmpty()) { - setWindowIcon_sys(true); - setWindowTitle_helper(extra->topextra->caption); - } - if (old_winid) - DestroyWindow(old_winid); - - if (q->testAttribute(Qt::WA_AcceptDrops) || dropSiteWasRegistered - || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) - q->setAttribute(Qt::WA_DropSiteRegistered, true); - -#ifdef Q_WS_WINCE - // Show borderless toplevel windows in tasklist & NavBar - if (!parent) { - QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle(); - SetWindowText(q->internalWinId(), (wchar_t*)txt.utf16()); - } -#endif - invalidateBuffer(q->rect()); -} - - -QPoint QWidget::mapToGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - QWidget *parentWindow = window(); - QWExtra *extra = parentWindow->d_func()->extra; - if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId() - || (extra -#ifndef QT_NO_GRAPHICSVIEW - && extra->proxyWidget -#endif //QT_NO_GRAPHICSVIEW - )) { - if (extra && extra->topextra && extra->topextra->embedded) { - QPoint pt = mapTo(parentWindow, pos); - POINT p = {pt.x(), pt.y()}; - ClientToScreen(parentWindow->effectiveWinId(), &p); - return QPoint(p.x, p.y); - } else { - QPoint toGlobal = mapTo(parentWindow, pos) + parentWindow->pos(); - // Adjust for window decorations - toGlobal += parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft(); - return toGlobal; - } - } - POINT p; - QPoint tmp = d->mapToWS(pos); - p.x = tmp.x(); - p.y = tmp.y(); - ClientToScreen(internalWinId(), &p); - return QPoint(p.x, p.y); -} - -QPoint QWidget::mapFromGlobal(const QPoint &pos) const -{ - Q_D(const QWidget); - QWidget *parentWindow = window(); - QWExtra *extra = parentWindow->d_func()->extra; - if (!isVisible() || parentWindow->isMinimized() || !testAttribute(Qt::WA_WState_Created) || !internalWinId() - || (extra -#ifndef QT_NO_GRAPHICSVIEW - && extra->proxyWidget -#endif //QT_NO_GRAPHICSVIEW - )) { - if (extra && extra->topextra && extra->topextra->embedded) { - POINT p = {pos.x(), pos.y()}; - ScreenToClient(parentWindow->effectiveWinId(), &p); - return mapFrom(parentWindow, QPoint(p.x, p.y)); - } else { - QPoint fromGlobal = mapFrom(parentWindow, pos - parentWindow->pos()); - // Adjust for window decorations - fromGlobal -= parentWindow->geometry().topLeft() - parentWindow->frameGeometry().topLeft(); - return fromGlobal; - } - } - POINT p; - p.x = pos.x(); - p.y = pos.y(); - ScreenToClient(internalWinId(), &p); - return d->mapFromWS(QPoint(p.x, p.y)); -} - -void QWidgetPrivate::updateSystemBackground() {} - -#ifndef QT_NO_CURSOR -void QWidgetPrivate::setCursor_sys(const QCursor &cursor) -{ - Q_UNUSED(cursor); - Q_Q(QWidget); - qt_win_set_cursor(q, false); -} - -void QWidgetPrivate::unsetCursor_sys() -{ - Q_Q(QWidget); - qt_win_set_cursor(q, false); -} -#endif - -void QWidgetPrivate::setWindowTitle_sys(const QString &caption) -{ - Q_Q(QWidget); - if (!q->isWindow()) - return; - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16()); -} - -HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache) -{ - HICON result = 0; - if (!icon.isNull()) { // valid icon - QSize size = icon.actualSize(QSize(xSize, ySize)); - QPixmap pm = icon.pixmap(size); - if (pm.isNull()) - return 0; - - result = pm.toWinHICON(); - - if (cache) { - delete *cache; - *cache = new QPixmap(pm);; - } - } - return result; -} - -void QWidgetPrivate::setWindowIcon_sys(bool forceReset) -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow()) - return; - QTLWExtra* x = topData(); - if (x->iconPixmap && !forceReset) - // already been set - return; - - if (x->winIconBig) { - DestroyIcon(x->winIconBig); - x->winIconBig = 0; - } - if (x->winIconSmall) { - DestroyIcon(x->winIconSmall); - x->winIconSmall = 0; - } - - x->winIconSmall = qt_createIcon(q->windowIcon(), - GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), - &(x->iconPixmap)); - x->winIconBig = qt_createIcon(q->windowIcon(), - GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), - &(x->iconPixmap)); - if (x->winIconBig) { - SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); - SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig); - } else { - SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); - SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall); - } -} - - -void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) -{ - Q_UNUSED(iconText); -} - - -QCursor *qt_grab_cursor() -{ - return mouseGrbCur; -} - -// The procedure does nothing, but is required for mousegrabbing to work -#ifndef Q_WS_WINCE -LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) -{ - return CallNextHookEx(journalRec, nCode, wParam, lParam); -} -#endif //Q_WS_WINCE - -/* Works only as long as pointer is inside the application's window, - which is good enough for QDockWidget. - - Doesn't call SetWindowsHookEx() - this function causes a system-wide - freeze if any other app on the system installs a hook and fails to - process events. */ -void QWidgetPrivate::grabMouseWhileInWindow() -{ - Q_Q(QWidget); - if (!qt_nograb()) { - if (mouseGrb) - mouseGrb->releaseMouse(); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - SetCapture(q->effectiveWinId()); - mouseGrb = q; -#ifndef QT_NO_CURSOR - mouseGrbCur = new QCursor(mouseGrb->cursor()); -#endif - } -} - -#ifndef Q_WS_WINCE -void QWidget::grabMouse() -{ - if (!qt_nograb()) { - if (mouseGrb) - mouseGrb->releaseMouse(); - journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - SetCapture(effectiveWinId()); - mouseGrb = this; -#ifndef QT_NO_CURSOR - mouseGrbCur = new QCursor(mouseGrb->cursor()); -#endif - } -} - -#ifndef QT_NO_CURSOR -void QWidget::grabMouse(const QCursor &cursor) -{ - if (!qt_nograb()) { - if (mouseGrb) - mouseGrb->releaseMouse(); - journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - SetCapture(effectiveWinId()); - mouseGrbCur = new QCursor(cursor); - SetCursor(mouseGrbCur->handle()); - mouseGrb = this; - } -} -#endif - -void QWidget::releaseMouse() -{ - if (!qt_nograb() && mouseGrb == this) { - ReleaseCapture(); - if (journalRec) { - UnhookWindowsHookEx(journalRec); - journalRec = 0; - } - if (mouseGrbCur) { - delete mouseGrbCur; - mouseGrbCur = 0; - } - mouseGrb = 0; - } -} -#endif - -void QWidget::grabKeyboard() -{ - if (!qt_nograb()) { - if (keyboardGrb) - keyboardGrb->releaseKeyboard(); - keyboardGrb = this; - } -} - -void QWidget::releaseKeyboard() -{ - if (!qt_nograb() && keyboardGrb == this) - keyboardGrb = 0; -} - - -QWidget *QWidget::mouseGrabber() -{ - return mouseGrb; -} - -QWidget *QWidget::keyboardGrabber() -{ - return keyboardGrb; -} - -void QWidget::activateWindow() -{ - window()->createWinId(); - SetForegroundWindow(window()->internalWinId()); -} - -#ifndef Q_WS_WINCE -void QWidget::setWindowState(Qt::WindowStates newstate) -{ - Q_D(QWidget); - Qt::WindowStates oldstate = windowState(); - if (oldstate == newstate) - return; - - int max = SW_MAXIMIZE; - int min = SW_MINIMIZE; - - int normal = SW_SHOWNOACTIVATE; - if (newstate & Qt::WindowActive) { - max = SW_SHOWMAXIMIZED; - min = SW_SHOWMINIMIZED; - normal = SW_SHOWNORMAL; - } - - if (isWindow()) { - createWinId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - - // Ensure the initial size is valid, since we store it as normalGeometry below. - if (!testAttribute(Qt::WA_Resized) && !isVisible()) - adjustSize(); - - if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { - if (newstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen)) - d->topData()->normalGeometry = geometry(); - if (isVisible() && !(newstate & Qt::WindowMinimized)) { - ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal); - if (!(newstate & Qt::WindowFullScreen)) { - QRect r = d->topData()->normalGeometry; - if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) { - if (pos() != r.topLeft() || size() !=r.size()) { - d->topData()->normalGeometry = QRect(0,0,-1,-1); - setGeometry(r); - } - } - } else { - d->updateFrameStrut(); - } - } - } - - if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { - if (newstate & Qt::WindowFullScreen) { - if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) - d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = Qt::WindowFlags(GetWindowLong(internalWinId(), GWL_STYLE)); -#ifndef Q_FLATTEN_EXPOSE - UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; -#else - UINT style = WS_POPUP; -#endif - if (ulong(d->topData()->savedFlags) & WS_SYSMENU) - style |= WS_SYSMENU; - if (isVisible()) - style |= WS_VISIBLE; - SetWindowLong(internalWinId(), GWL_STYLE, style); - QRect r = QApplication::desktop()->screenGeometry(this); - UINT swpf = SWP_FRAMECHANGED; - if (newstate & Qt::WindowActive) - swpf |= SWP_NOACTIVATE; - - SetWindowPos(internalWinId(), HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf); - d->updateFrameStrut(); - } else { - UINT style = d->topData()->savedFlags; - if (isVisible()) - style |= WS_VISIBLE; - SetWindowLong(internalWinId(), GWL_STYLE, style); - - UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; - if (newstate & Qt::WindowActive) - swpf |= SWP_NOACTIVATE; - SetWindowPos(internalWinId(), 0, 0, 0, 0, 0, swpf); - d->updateFrameStrut(); - - // preserve maximized state - if (isVisible()) - ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal); - - if (!(newstate & Qt::WindowMaximized)) { - QRect r = d->topData()->normalGeometry; - d->topData()->normalGeometry = QRect(0,0,-1,-1); - if (r.isValid()) - setGeometry(r); - } - } - } - - if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { - if (isVisible()) - ShowWindow(internalWinId(), (newstate & Qt::WindowMinimized) ? min : - (newstate & Qt::WindowMaximized) ? max : normal); - } - } - data->window_state = newstate; - QWindowStateChangeEvent e(oldstate); - QApplication::sendEvent(this, &e); -} -#endif //Q_WS_WINCE - - -/* - \internal - Platform-specific part of QWidget::hide(). -*/ - -void QWidgetPrivate::hide_sys() -{ - Q_Q(QWidget); - deactivateWidgetCleanup(); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); -#ifdef Q_WS_WINCE - if (!qt_wince_is_mobile() && q->isFullScreen()) { - HWND handle = FindWindow(L"HHTaskBar", L""); - if (handle) { - ShowWindow(handle, 1); - EnableWindow(handle, true); - } - } -#endif - if (q->windowFlags() != Qt::Desktop) { - if ((q->windowFlags() & Qt::Popup) && q->internalWinId()) - ShowWindow(q->internalWinId(), SW_HIDE); - else if (q->internalWinId()) - SetWindowPos(q->internalWinId(),0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER); - } - if (q->isWindow()) { - if (QWidgetBackingStore *bs = maybeBackingStore()) - bs->releaseBuffer(); - } else { - invalidateBuffer(q->rect()); - } - q->setAttribute(Qt::WA_Mapped, false); -} - - -/* - \internal - Platform-specific part of QWidget::show(). -*/ -#ifndef Q_WS_WINCE -void QWidgetPrivate::show_sys() -{ - Q_Q(QWidget); -#if defined(QT_NON_COMMERCIAL) - QT_NC_SHOW_WINDOW -#endif - if (q->testAttribute(Qt::WA_OutsideWSRange)) - return; - q->setAttribute(Qt::WA_Mapped); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if (q->testAttribute(Qt::WA_DontShowOnScreen)) { - invalidateBuffer(q->rect()); - return; - } - - if (data.window_flags & Qt::Window) { - QTLWExtra *extra = topData(); - if (!extra->hotkeyRegistered) { - // Try to set the hotkey using information from STARTUPINFO - STARTUPINFO startupInfo; - GetStartupInfo(&startupInfo); - // If STARTF_USEHOTKEY is set, hStdInput is the virtual keycode - if (startupInfo.dwFlags & 0x00000200) { - WPARAM hotKey = (WPARAM)startupInfo.hStdInput; - SendMessage(data.winid, WM_SETHOTKEY, hotKey, 0); - } - extra->hotkeyRegistered = 1; - } - } - - int sm = SW_SHOWNORMAL; - bool fakedMaximize = false; - if (q->isWindow()) { - if (q->isMinimized()) { - sm = SW_SHOWMINIMIZED; - if (!IsWindowVisible(q->internalWinId())) - sm = SW_SHOWMINNOACTIVE; - } else if (q->isMaximized()) { - sm = SW_SHOWMAXIMIZED; - // Windows will not behave correctly when we try to maximize a window which does not - // have minimize nor maximize buttons in the window frame. Windows would then ignore - // non-available geometry, and rather maximize the widget to the full screen, minus the - // window frame (caption). So, we do a trick here, by adding a maximize button before - // maximizing the widget, and then remove the maximize button afterwards. - Qt::WindowFlags &flags = data.window_flags; - if (flags & Qt::WindowTitleHint && - !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) { - fakedMaximize = TRUE; - int style = GetWindowLong(q->internalWinId(), GWL_STYLE); - SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX); - } - } - } - if (q->testAttribute(Qt::WA_ShowWithoutActivating) - || (q->windowType() == Qt::Popup) - || (q->windowType() == Qt::ToolTip) - || (q->windowType() == Qt::Tool)) { - sm = SW_SHOWNOACTIVATE; - } - - - if (q->internalWinId()) - ShowWindow(q->internalWinId(), sm); - - if (fakedMaximize) { - int style = GetWindowLong(q->internalWinId(), GWL_STYLE); - SetWindowLong(q->internalWinId(), GWL_STYLE, style & ~WS_MAXIMIZEBOX); - SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER - | SWP_FRAMECHANGED); - } - - if (q->internalWinId()) { - if (IsIconic(q->internalWinId())) - data.window_state |= Qt::WindowMinimized; - if (IsZoomed(q->internalWinId())) - data.window_state |= Qt::WindowMaximized; - // This is to resolve the problem where popups are opened from the - // system tray and not being implicitly activated - if (q->windowType() == Qt::Popup && - !q->parentWidget() && !qApp->activeWindow()) - q->activateWindow(); - } - - winSetupGestures(); - - invalidateBuffer(q->rect()); -} -#endif //Q_WS_WINCE - -void QWidgetPrivate::setFocus_sys() -{ - Q_Q(QWidget); - if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup) - SetFocus(q->effectiveWinId()); -} - -void QWidgetPrivate::raise_sys() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) - SetWindowPos(q->internalWinId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -} - -void QWidgetPrivate::lower_sys() -{ - Q_Q(QWidget); - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) - SetWindowPos(q->internalWinId(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - 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()) - SetWindowPos(q->internalWinId(), w->internalWinId() , 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - invalidateBuffer(q->rect()); -} - - -/* - Helper function for non-toplevel widgets. Helps to map Qt's 32bit - coordinate system to Windpws's 16bit coordinate system. - - This code is duplicated from the X11 code, so any changes there - should also (most likely) be reflected here. - - (In all comments below: s/X/Windows/g) - */ - -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). - */ - 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 (q->internalWinId()) - MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), true); - 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 (q->internalWinId()) - ShowWindow(q->internalWinId(), SW_HIDE); - 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... - for (int i = 0; i < children.size(); ++i) { - QObject *object = children.at(i); - if (object->isWidgetType()) { - QWidget *w = static_cast(object); - if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) - w->d_func()->setWSGeometry(); - } - } - - // 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 (q->internalWinId()) { - if (!parent->internalWinId()) - xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0))); - MoveWindow(q->internalWinId(), xrect.x(), xrect.y(), xrect.width(), xrect.height(), !jump); - } - if (mapWindow && !dontShow) { - q->setAttribute(Qt::WA_Mapped); - if (q->internalWinId()) - ShowWindow(q->internalWinId(), SW_SHOWNOACTIVATE); - } - - if (jump && q->internalWinId()) - InvalidateRect(q->internalWinId(), 0, false); - -} - -// -// The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move, -// resize and setGeometry requests for a widget that is already -// processing a config event. The purpose is to avoid recursion. -// -void qWinRequestConfig(WId, int, int, int, int, int); - -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)); - 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); - } - if (q->isWindow()) - topData()->normalGeometry = QRect(0, 0, -1, -1); - - QSize oldSize(q->size()); - QPoint oldPos(q->pos()); - - if (!q->isWindow()) - isMove = (data.crect.topLeft() != QPoint(x, y)); - bool isResize = w != oldSize.width() || h != oldSize.height(); - - if (!isMove && !isResize) - return; - - if (isResize && !q->testAttribute(Qt::WA_StaticContents) && q->internalWinId()) - ValidateRgn(q->internalWinId(), 0); - -#ifdef Q_WS_WINCE - // On Windows CE we can't just fiddle around with the window state. - // Too much magic in setWindowState. - if (isResize && q->isMaximized()) - q->setWindowState(q->windowState() & ~Qt::WindowMaximized); -#else - if (isResize) - data.window_state &= ~Qt::WindowMaximized; -#endif - - if (data.window_state & Qt::WindowFullScreen) { - QTLWExtra *top = topData(); - - if (q->isWindow()) { - // We need to update these flags when we remove the full screen state - // or the frame will not be updated - UINT style = top->savedFlags; - if (q->isVisible()) - style |= WS_VISIBLE; - SetWindowLong(q->internalWinId(), GWL_STYLE, style); - - UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; - if (data.window_state & Qt::WindowActive) - swpf |= SWP_NOACTIVATE; - SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, swpf); - updateFrameStrut(); - } - data.window_state &= ~Qt::WindowFullScreen; - topData()->savedFlags = 0; - } - - QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false; - const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint) - && GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED; - - if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event - if (q->internalWinId()) - qWinRequestConfig(q->internalWinId(), isMove ? 2 : 1, x, y, w, h); - } else { - if (!q->testAttribute(Qt::WA_DontShowOnScreen)) - q->setAttribute(Qt::WA_WState_ConfigPending); - if (q->windowType() == Qt::Desktop) { - data.crect.setRect(x, y, w, h); - } else if (q->isWindow()) { - QRect fs(frameStrut()); - if (extra) { - fs.setLeft(x - fs.left()); - fs.setTop(y - fs.top()); - fs.setRight((x + w - 1) + fs.right()); - fs.setBottom((y + h - 1) + fs.bottom()); - } - if (w == 0 || h == 0) { - q->setAttribute(Qt::WA_OutsideWSRange, true); - if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) - hide_sys(); - data.crect = QRect(x, y, w, h); - } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) { - q->setAttribute(Qt::WA_OutsideWSRange, false); - - // put the window in its place and show it - MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true); - RECT rect; - if (!q->testAttribute(Qt::WA_DontShowOnScreen)) { - GetClientRect(q->internalWinId(), &rect); - data.crect.setRect(x, y, rect.right - rect.left, rect.bottom - rect.top); - } else { - data.crect.setRect(x, y, w, h); - } - - show_sys(); - } else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) { - q->setAttribute(Qt::WA_OutsideWSRange, false); -#ifndef Q_WS_WINCE - // If the window is hidden and in maximized state or minimized, instead of moving the - // window, set the normal position of the window. - WINDOWPLACEMENT wndpl; - GetWindowPlacement(q->internalWinId(), &wndpl); - if ((wndpl.showCmd == SW_MAXIMIZE && !IsWindowVisible(q->internalWinId())) || wndpl.showCmd == SW_SHOWMINIMIZED) { - RECT normal = {fs.x(), fs.y(), fs.x()+fs.width(), fs.y()+fs.height()}; - wndpl.rcNormalPosition = normal; - wndpl.showCmd = wndpl.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE; - SetWindowPlacement(q->internalWinId(), &wndpl); - } else { -#else - if (data.window_state & Qt::WindowMaximized) { - qt_wince_maximize(q); - } else { -#endif - MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true); - } - if (!q->isVisible()) - InvalidateRect(q->internalWinId(), 0, FALSE); - RECT rect; - // If the layout has heightForWidth, the MoveWindow() above can - // change the size/position, so refresh them. - - if (isTranslucentWindow) { - data.crect.setRect(x, y, w, h); - } else { - GetClientRect(q->internalWinId(), &rect); - RECT rcNormalPosition ={0}; - // Use (0,0) as window position for embedded ActiveQt controls. - if (!tlwExtra || !tlwExtra->embedded) - GetWindowRect(q->internalWinId(), &rcNormalPosition); - QRect fStrut(frameStrut()); - data.crect.setRect(rcNormalPosition.left + fStrut.left(), - rcNormalPosition.top + fStrut.top(), - rect.right - rect.left, - rect.bottom - rect.top); - isResize = data.crect.size() != oldSize; - } - } else { - q->setAttribute(Qt::WA_OutsideWSRange, false); - data.crect.setRect(x, y, w, h); - } - } else { - QRect oldGeom(data.crect); - data.crect.setRect(x, y, w, h); - if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) { - // Top-level resize optimization does not work for native child widgets; - // disable it for this particular widget. - if (inTopLevelResize) - tlwExtra->inTopLevelResize = false; - - if (!isResize) - moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y()); - else - invalidateBuffer_resizeHelper(oldPos, oldSize); - - if (inTopLevelResize) - tlwExtra->inTopLevelResize = true; - } - if (q->testAttribute(Qt::WA_WState_Created)) - setWSGeometry(); - } - q->setAttribute(Qt::WA_WState_ConfigPending, false); - } - - if (q->isWindow() && q->isVisible() && isResize && !inTopLevelResize) { - invalidateBuffer(q->rect()); //after the resize - } - - // Process events immediately rather than in translateConfigEvent to - // avoid windows message process delay. - if (q->isVisible()) { - if (isMove && q->pos() != oldPos) { - QMoveEvent e(q->pos(), oldPos); - 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); - } -} - -bool QWidgetPrivate::shouldShowMaximizeButton() -{ - if (data.window_flags & Qt::MSWindowsFixedSizeDialogHint) - return false; - // if the user explicitly asked for the maximize button, we try to add - // it even if the window has fixed size. - if (data.window_flags & Qt::CustomizeWindowHint && - data.window_flags & Qt::WindowMaximizeButtonHint) - return true; - if (extra) { - if ((extra->maxw && extra->maxw != QWIDGETSIZE_MAX && extra->maxw != QLAYOUTSIZE_MAX) - || (extra->maxh && extra->maxh != QWIDGETSIZE_MAX && extra->maxh != QLAYOUTSIZE_MAX)) - return false; - } - return data.window_flags & Qt::WindowMaximizeButtonHint; -} - -void QWidgetPrivate::winUpdateIsOpaque() -{ -#ifndef Q_WS_WINCE - Q_Q(QWidget); - - if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground)) - return; - - if ((data.window_flags & Qt::FramelessWindowHint) == 0) - return; - - if (!isOpaque && ptrUpdateLayeredWindowIndirect) { - SetWindowLong(q->internalWinId(), GWL_EXSTYLE, - GetWindowLong(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED); - } else { - SetWindowLong(q->internalWinId(), GWL_EXSTYLE, - GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED); - } -#endif -} - -void QWidgetPrivate::setConstraints_sys() -{ -#ifndef Q_WS_WINCE_WM - Q_Q(QWidget); - if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) { - int style = GetWindowLong(q->internalWinId(), GWL_STYLE); - if (shouldShowMaximizeButton()) - style |= WS_MAXIMIZEBOX; - else - style &= ~WS_MAXIMIZEBOX; - SetWindowLong(q->internalWinId(), GWL_STYLE, style); - } -#endif -} - -void QWidgetPrivate::scroll_sys(int dx, int dy) -{ - Q_Q(QWidget); - scrollChildren(dx, dy); - - if (!paintOnScreen()) { - scrollRect(q->rect(), dx, dy); - } else { - UINT flags = SW_INVALIDATE; - if (!q->testAttribute(Qt::WA_OpaquePaintEvent)) - flags |= SW_ERASE; - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - ScrollWindowEx(q->internalWinId(), dx, dy, 0, 0, 0, 0, flags); - UpdateWindow(q->internalWinId()); - } -} - -void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) -{ - Q_Q(QWidget); - - if (!paintOnScreen()) { - scrollRect(r, dx, dy); - } else { - RECT wr; - wr.top = r.top(); - wr.left = r.left(); - wr.bottom = r.bottom()+1; - wr.right = r.right()+1; - - UINT flags = SW_INVALIDATE; - if (!q->testAttribute(Qt::WA_OpaquePaintEvent)) - flags |= SW_ERASE; - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - ScrollWindowEx(q->internalWinId(), dx, dy, &wr, &wr, 0, 0, flags); - UpdateWindow(q->internalWinId()); - } -} - -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 { - HDC gdc = GetDC(0); - switch (m) { - case PdmDpiX: - case PdmPhysicalDpiX: - if (d->extra && d->extra->customDpiX) - val = d->extra->customDpiX; - else if (d->parent) - val = static_cast(d->parent)->metric(m); - else - val = GetDeviceCaps(gdc, LOGPIXELSX); - break; - case PdmDpiY: - case PdmPhysicalDpiY: - if (d->extra && d->extra->customDpiY) - val = d->extra->customDpiY; - else if (d->parent) - val = static_cast(d->parent)->metric(m); - else - val = GetDeviceCaps(gdc, LOGPIXELSY); - break; - case PdmWidthMM: - val = data->crect.width() - * GetDeviceCaps(gdc, HORZSIZE) - / GetDeviceCaps(gdc, HORZRES); - break; - case PdmHeightMM: - val = data->crect.height() - * GetDeviceCaps(gdc, VERTSIZE) - / GetDeviceCaps(gdc, VERTRES); - break; - case PdmNumColors: - if (GetDeviceCaps(gdc, RASTERCAPS) & RC_PALETTE) - val = GetDeviceCaps(gdc, SIZEPALETTE); - else { - HDC hd = d->hd ? HDC(d->hd) : gdc; - int bpp = GetDeviceCaps(hd, BITSPIXEL); - if (bpp == 32) - val = INT_MAX; // ### this is bogus, it should be 2^24 colors for 32 bit as well - else if(bpp<=8) - val = GetDeviceCaps(hd, NUMCOLORS); - else - val = 1 << (bpp * GetDeviceCaps(hd, PLANES)); - } - break; - case PdmDepth: - val = GetDeviceCaps(gdc, BITSPIXEL); - break; - default: - val = 0; - qWarning("QWidget::metric: Invalid metric command"); - } - ReleaseDC(0, gdc); - } - return val; -} - -void QWidgetPrivate::createSysExtra() -{ -#ifndef QT_NO_DRAGANDDROP - extra->dropTarget = 0; -#endif -} - -#ifndef Q_WS_WINCE -void QWidgetPrivate::deleteSysExtra() -{ -} -#endif //Q_WS_WINCE - -void QWidgetPrivate::createTLSysExtra() -{ - extra->topextra->hotkeyRegistered = 0; - extra->topextra->savedFlags = 0; - extra->topextra->winIconBig = 0; - extra->topextra->winIconSmall = 0; -} - -void QWidgetPrivate::deleteTLSysExtra() -{ - if (extra->topextra->winIconSmall) - DestroyIcon(extra->topextra->winIconSmall); - if (extra->topextra->winIconBig) - DestroyIcon(extra->topextra->winIconBig); -} - -void QWidgetPrivate::registerDropSite(bool on) -{ - Q_Q(QWidget); - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - // Enablement is defined by d->extra->dropTarget != 0. - if (on) { - // Turn on. - createExtra(); -#ifndef QT_NO_DRAGANDDROP - if (!q->internalWinId()) - q->nativeParentWidget()->d_func()->createExtra(); - QWExtra *extra = extraData(); - if (!extra->dropTarget) - extra->dropTarget = registerOleDnd(q); -#endif - } else { - // Turn off. - QWExtra *extra = extraData(); -#ifndef QT_NO_DRAGANDDROP - if (extra && extra->dropTarget) { - unregisterOleDnd(q, extra->dropTarget); - extra->dropTarget = 0; - } -#endif - } -} - -#ifndef QT_NO_DRAGANDDROP -QOleDropTarget* QWidgetPrivate::registerOleDnd(QWidget *widget) -{ - QOleDropTarget *dropTarget = new QOleDropTarget(widget); - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - if (!widget->internalWinId()) { - QWidget *nativeParent = widget->nativeParentWidget(); - Q_ASSERT(nativeParent); - QWExtra *nativeExtra = nativeParent->d_func()->extra; - Q_ASSERT(nativeExtra); - if (!nativeParent->acceptDrops()) - nativeParent->setAcceptDrops(true); - if (!nativeExtra->oleDropWidgets.contains(widget)) - nativeExtra->oleDropWidgets.append(widget); - if (!nativeExtra->dropTarget) { - nativeExtra->dropTarget = registerOleDnd(nativeParent); - Q_ASSERT(nativeExtra->dropTarget); -#ifndef Q_OS_WINCE - CoLockObjectExternal(nativeExtra->dropTarget, false, true); -#endif - RegisterDragDrop(nativeParent->internalWinId(), nativeExtra->dropTarget); - } - } else { - RegisterDragDrop(widget->internalWinId(), dropTarget); -#ifndef Q_OS_WINCE - CoLockObjectExternal(dropTarget, true, true); -#endif - } - return dropTarget; -} - -void QWidgetPrivate::unregisterOleDnd(QWidget *widget, QOleDropTarget *dropTarget) -{ - dropTarget->releaseQt(); - dropTarget->Release(); - Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created)); - if (!widget->internalWinId()) { - QWidget *nativeParent = widget->nativeParentWidget(); - Q_ASSERT(nativeParent); - QWExtra *nativeExtra = nativeParent->d_func()->extra; - Q_ASSERT(nativeExtra); - nativeExtra->oleDropWidgets.removeAll(widget); - nativeExtra->oleDropWidgets.removeAll(static_cast(0)); - if (nativeExtra->oleDropWidgets.isEmpty() && nativeExtra->dropTarget - && !nativeParent->testAttribute(Qt::WA_DropSiteRegistered)) { -#ifndef Q_OS_WINCE - CoLockObjectExternal(nativeExtra->dropTarget, false, true); -#endif - RevokeDragDrop(nativeParent->internalWinId()); - nativeExtra->dropTarget = 0; - } - } else { -#ifndef Q_OS_WINCE - CoLockObjectExternal(dropTarget, false, true); -#endif - RevokeDragDrop(widget->internalWinId()); - } -} - -#endif //QT_NO_DRAGANDDROP - -// from qregion_win.cpp -extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom); -void QWidgetPrivate::setMask_sys(const QRegion ®ion) -{ - Q_Q(QWidget); - if (!q->internalWinId()) - return; - - if (region.isEmpty()) { - SetWindowRgn(q->internalWinId(), 0, true); - return; - } - - // Since SetWindowRegion takes ownership, and we need to translate, - // we take a copy. - HRGN wr = qt_tryCreateRegion(QRegion::Rectangle, 0,0,0,0); - CombineRgn(wr, region.handle(), 0, RGN_COPY); - - QPoint offset = (q->isWindow() - ? frameStrut().topLeft() - : QPoint(0, 0)); - OffsetRgn(wr, offset.x(), offset.y()); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (!SetWindowRgn(data.winid, wr, true)) - DeleteObject(wr); -} - -void QWidgetPrivate::updateFrameStrut() -{ - Q_Q(QWidget); - - if (!q->testAttribute(Qt::WA_WState_Created)) - return; - - if (!q->internalWinId()) { - data.fstrut_dirty = false; - return; - } - - RECT rect = {0,0,0,0}; - - QTLWExtra *top = topData(); - uint exstyle = GetWindowLong(q->internalWinId(), GWL_EXSTYLE); - uint style = GetWindowLong(q->internalWinId(), GWL_STYLE); -#ifndef Q_WS_WINCE - if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) { -#else - if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) { -#endif - top->frameStrut.setCoords(-rect.left, -rect.top, rect.right, rect.bottom); - data.fstrut_dirty = false; - } -} - -#ifndef Q_WS_WINCE -void QWidgetPrivate::setWindowOpacity_sys(qreal level) -{ - Q_Q(QWidget); - - if (!isOpaque && ptrUpdateLayeredWindow && (data.window_flags & Qt::FramelessWindowHint)) { - if (GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) { - BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA}; - ptrUpdateLayeredWindow(q->internalWinId(), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA); - } - return; - } - - static bool function_resolved = false; - if (!function_resolved) { - ptrSetLayeredWindowAttributes = - (PtrSetLayeredWindowAttributes) QSystemLibrary::resolve(QLatin1String("user32"), - "SetLayeredWindowAttributes"); - function_resolved = true; - } - - if (!ptrSetLayeredWindowAttributes) - return; - - int wl = GetWindowLong(q->internalWinId(), GWL_EXSTYLE); - - if (level != 1.0) { - if ((wl&Q_WS_EX_LAYERED) == 0) - SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl | Q_WS_EX_LAYERED); - } else if (wl&Q_WS_EX_LAYERED) { - SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED); - } - ptrSetLayeredWindowAttributes(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA); -} -#endif //Q_WS_WINCE - -// class QGlobalRasterPaintEngine: public QRasterPaintEngine -// { -// public: -// inline QGlobalRasterPaintEngine() : QRasterPaintEngine() { setFlushOnEnd(false); } -// }; -// Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine) - - -#ifndef QT_NO_DIRECTDRAW -static uchar *qt_primary_surface_bits; -static int qt_primary_surface_stride; -static QImage::Format qt_primary_surface_format; - -void qt_win_initialize_directdraw() -{ - HRESULT res; - - // Some initialization... - if (!qt_ddraw_object) { - res = DirectDrawCreate(0, &qt_ddraw_object, 0); - - if (res != DD_OK) - qWarning("DirectDrawCreate failed: %d", res); - - qt_ddraw_object->SetCooperativeLevel(0, DDSCL_NORMAL); - - DDSURFACEDESC surfaceDesc; - memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC)); - - surfaceDesc.dwSize = sizeof(DDSURFACEDESC); - surfaceDesc.dwFlags = DDSD_CAPS; - surfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - res = qt_ddraw_object->CreateSurface(&surfaceDesc, &qt_ddraw_primary, 0); - if (res != DD_OK) - qWarning("CreateSurface failed: %d", res); - - memset(&surfaceDesc, 0, sizeof(DDSURFACEDESC)); - surfaceDesc.dwSize = sizeof(DDSURFACEDESC); - res = qt_ddraw_primary->Lock(0, &surfaceDesc, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, 0); - if (res != DD_OK) - qWarning("Locking surface failed: %d", res); - - if (surfaceDesc.ddpfPixelFormat.dwFlags == DDPF_RGB) { - qt_primary_surface_bits = (uchar *) surfaceDesc.lpSurface; - qt_primary_surface_stride = surfaceDesc.lPitch; - qt_primary_surface_format = QImage::Format_RGB32; - } else { - qWarning("QWidget painting: unsupported device depth for onscreen painting...\n"); - } - - qt_ddraw_primary->Unlock(0); - } -} - -class QOnScreenRasterPaintEngine : public QRasterPaintEngine -{ -public: - // The image allocated here leaks... Fix if this code is ifdef'ed - // in - QOnScreenRasterPaintEngine() - : QRasterPaintEngine(new QImage(qt_primary_surface_bits, - QApplication::desktop()->width(), - QApplication::desktop()->height(), - qt_primary_surface_stride, - qt_primary_surface_format)) - { - device = static_cast(d_func()->device); - } - - bool begin(QPaintDevice *) - { - QRegion clip = systemClip(); - originalSystemClip = clip; - clip.translate(widget->mapToGlobal(QPoint(0, 0))); - setSystemClip(clip); - - QRect bounds = clip.boundingRect(); - DDSURFACEDESC surface; - surface.dwSize = sizeof(DDSURFACEDESC); - HRESULT res = qt_ddraw_primary->Lock((RECT *) &bounds, &surface, DDLOCK_WAIT, 0); - if (res != DD_OK) { - qWarning("QWidget painting: locking onscreen bits failed: %d\n", res); - return false; - } - - if (surface.lpSurface == qt_primary_surface_bits) { - qt_primary_surface_bits = (uchar *) surface.lpSurface; - device->data_ptr()->data = qt_primary_surface_bits; - } - - return QRasterPaintEngine::begin(device); - } - - bool end() - { - HRESULT res = qt_ddraw_primary->Unlock(0); - if (res != DD_OK) - qWarning("QWidget::paint, failed to unlock DirectDraw surface: %d", res); - bool ok = QRasterPaintEngine::end(); - setSystemClip(originalSystemClip); - return ok; - } - - QPoint coordinateOffset() const { - return -widget->mapToGlobal(QPoint(0, 0)); - } - - const QWidget *widget; - QImage *device; - QRegion originalSystemClip; -}; -Q_GLOBAL_STATIC(QOnScreenRasterPaintEngine, onScreenPaintEngine) -#else -void qt_win_initialize_directdraw() { } -#endif - -QPaintEngine *QWidget::paintEngine() const -{ -#ifndef QT_NO_DIRECTDRAW - QOnScreenRasterPaintEngine *pe = onScreenPaintEngine(); - pe->widget = this; - return pe; -#endif - - // We set this bit which is checked in setAttribute for - // Qt::WA_PaintOnScreen. We do this to allow these two scenarios: - // - // 1. Users accidentally set Qt::WA_PaintOnScreen on X and port to - // windows which would mean suddenly their widgets stop working. - // - // 2. Users set paint on screen and subclass paintEngine() to - // return 0, in which case we have a "hole" in the backingstore - // allowing use of GDI or DirectX directly. - // - // 1 is WRONG, but to minimize silent failures, we have set this - // bit to ignore the setAttribute call. 2. needs to be - // supported because its our only means of embeddeding native - // graphics stuff. - const_cast(d_func())->noPaintOnScreen = 1; - - return 0; -} - -QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() -{ - Q_Q(QWidget); - return new QRasterWindowSurface(q); -} - -void QWidgetPrivate::setModal_sys() -{ -} - -void QWidgetPrivate::registerTouchWindow() -{ - Q_Q(QWidget); - - // enable WM_TOUCH* messages on our window - if (q->testAttribute(Qt::WA_WState_Created) - && QApplicationPrivate::RegisterTouchWindow - && q->windowType() != Qt::Desktop) - QApplicationPrivate::RegisterTouchWindow(q->effectiveWinId(), 0); -} - -void QWidgetPrivate::winSetupGestures() -{ -#if !defined(QT_NO_GESTURES) && !defined(QT_NO_NATIVE_GESTURES) - Q_Q(QWidget); - if (!q || !q->isVisible() || !nativeGesturePanEnabled) - return; - - if (!QApplicationPrivate::HasTouchSupport) - return; - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - if (!qAppPriv->SetGestureConfig) - return; - WId winid = q->internalWinId(); - - bool needh = false; - bool needv = false; - bool singleFingerPanEnabled = false; - -#ifndef QT_NO_SCROLLAREA - if (QAbstractScrollArea *asa = qobject_cast(q->parent())) { - QScrollBar *hbar = asa->horizontalScrollBar(); - QScrollBar *vbar = asa->verticalScrollBar(); - Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy(); - Qt::ScrollBarPolicy vbarpolicy = asa->verticalScrollBarPolicy(); - needh = (hbarpolicy == Qt::ScrollBarAlwaysOn || - (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum())); - needv = (vbarpolicy == Qt::ScrollBarAlwaysOn || - (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum())); - singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled; - if (!winid) { - winid = q->winId(); // enforces the native winid on the viewport - } - } -#endif //QT_NO_SCROLLAREA - if (winid) { - GESTURECONFIG gc[1]; - memset(gc, 0, sizeof(gc)); - gc[0].dwID = GID_PAN; - if (nativeGesturePanEnabled) { - gc[0].dwWant = GC_PAN; - if (needv && singleFingerPanEnabled) - gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; - else - gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY; - if (needh && singleFingerPanEnabled) - gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; - else - gc[0].dwBlock |= GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; - } else { - gc[0].dwBlock = GC_PAN; - } - - qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0])); - } -#endif -} - -QT_END_NAMESPACE - -#ifdef Q_WS_WINCE -# include "qwidget_wince.cpp" -#endif diff --git a/src/widgets/platforms/win/qwidget_wince.cpp b/src/widgets/platforms/win/qwidget_wince.cpp deleted file mode 100644 index b16be300e7..0000000000 --- a/src/widgets/platforms/win/qwidget_wince.cpp +++ /dev/null @@ -1,675 +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$ -** -****************************************************************************/ - -#ifdef Q_WS_WINCE - -#include "qguifunctions_wince.h" - -QT_BEGIN_NAMESPACE - -const QString qt_reg_winclass(QWidget *w); // defined in qapplication_win.cpp -extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); - -//#define TABLET_DEBUG -#define PACKETDATA (PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE \ - | PK_ORIENTATION | PK_CURSOR | PK_Z) -#define PACKETMODE 0 - -typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL); -typedef BOOL (API *PtrWTClose)(HCTX); -typedef UINT (API *PtrWTInfo)(UINT, UINT, LPVOID); -typedef BOOL (API *PtrWTEnable)(HCTX, BOOL); -typedef BOOL (API *PtrWTOverlap)(HCTX, BOOL); -typedef int (API *PtrWTPacketsGet)(HCTX, int, LPVOID); -typedef BOOL (API *PtrWTGet)(HCTX, LPLOGCONTEXT); -typedef int (API *PtrWTQueueSizeGet)(HCTX); -typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int); - -#ifndef QT_NO_TABLETEVENT -static void qt_tablet_init_wce(); -static void qt_tablet_cleanup_wce(); - -static void qt_tablet_init_wce() { - static bool firstTime = true; - if (!firstTime) - return; - firstTime = false; - qt_tablet_widget = new QWidget(0); - qt_tablet_widget->createWinId(); - qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget")); - LOGCONTEXT lcMine; - qAddPostRoutine(qt_tablet_cleanup_wce); - struct tagAXIS tpOri[3]; - if (ptrWTInfo && ptrWTOpen && ptrWTQueueSizeGet && ptrWTQueueSizeSet) { - // make sure we have WinTab - if (!ptrWTInfo(0, 0, NULL)) { -#ifdef TABLET_DEBUG - qWarning("QWidget: Wintab services not available"); -#endif - return; - } - - // some tablets don't support tilt, check if it is possible, - qt_tablet_tilt_support = ptrWTInfo(WTI_DEVICES, DVC_ORIENTATION, &tpOri); - if (qt_tablet_tilt_support) { - // check for azimuth and altitude - qt_tablet_tilt_support = tpOri[0].axResolution && tpOri[1].axResolution; - } - // build our context from the default context - ptrWTInfo(WTI_DEFSYSCTX, 0, &lcMine); - // Go for the raw coordinates, the tablet event will return good stuff - lcMine.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; - lcMine.lcPktData = PACKETDATA; - lcMine.lcPktMode = PACKETMODE; - lcMine.lcMoveMask = PACKETDATA; - lcMine.lcOutOrgX = 0; - lcMine.lcOutExtX = lcMine.lcInExtX; - lcMine.lcOutOrgY = 0; - lcMine.lcOutExtY = -lcMine.lcInExtY; - qt_tablet_context = ptrWTOpen(qt_tablet_widget->winId(), &lcMine, true); -#ifdef TABLET_DEBUG - qDebug("Tablet is %p", qt_tablet_context); -#endif - if (!qt_tablet_context) { -#ifdef TABLET_DEBUG - qWarning("QWidget: Failed to open the tablet"); -#endif - return; - } - // Set the size of the Packet Queue to the correct size... - int currSize = ptrWTQueueSizeGet(qt_tablet_context); - if (!ptrWTQueueSizeSet(qt_tablet_context, QT_TABLET_NPACKETQSIZE)) { - // Ideally one might want to use a smaller - // multiple, but for now, since we managed to destroy - // the existing Q with the previous call, set it back - // to the other size, which should work. If not, - // there will be trouble. - if (!ptrWTQueueSizeSet(qt_tablet_context, currSize)) { - Q_ASSERT_X(0, "Qt::Internal", "There is no packet queue for" - " the tablet. The tablet will not work"); - } - } - } -} - -static void qt_tablet_cleanup_wce() { - if (ptrWTClose) - ptrWTClose(qt_tablet_context); - delete qt_tablet_widget; - qt_tablet_widget = 0; -} -#endif // QT_NO_TABLETEVENT - - -// The internal qWinRequestConfig, defined in qapplication_win.cpp, stores move, -// resize and setGeometry requests for a widget that is already -// processing a config event. The purpose is to avoid recursion. -// -void qWinRequestConfig(WId, int, int, int, int, int); - -void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) { - Q_Q(QWidget); - static int sw = -1, sh = -1; - - Qt::WindowType type = q->windowType(); - Qt::WindowFlags flags = data.window_flags; - - bool topLevel = (flags & Qt::Window); - bool popup = (type == Qt::Popup); - bool dialog = (type == Qt::Dialog - || type == Qt::Sheet - || (flags & Qt::MSWindowsFixedSizeDialogHint)); - bool desktop = (type == Qt::Desktop); - bool tool = (type == Qt::Tool || type == Qt::Drawer); - - HINSTANCE appinst = qWinAppInst(); - HWND parentw, destroyw = 0; - WId id; - - QString windowClassName = qt_reg_winclass(q); - - if (!window) // always initialize - initializeWindow = true; - - if (popup) - flags |= Qt::WindowStaysOnTopHint; // a popup stays on top - - if (flags & (Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowContextHelpButtonHint)) { - flags |= Qt::WindowSystemMenuHint; - flags |= Qt::WindowTitleHint; - flags &= ~Qt::FramelessWindowHint; - } - - if (sw < 0) { // get the (primary) screen size - sw = GetSystemMetrics(SM_CXSCREEN); - sh = GetSystemMetrics(SM_CYSCREEN); - } - - if (desktop) { // desktop widget - popup = false; // force this flags off - data.crect.setRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - } - - parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0; - - QString title; - int style = WS_CHILD; - int exsty = WS_EX_NOPARENTNOTIFY; - - if (topLevel) { - if (!(flags & Qt::FramelessWindowHint) && !tool && !q->testAttribute(Qt::WA_DontShowOnScreen)) - style = (WS_OVERLAPPED) | WS_SYSMENU; - else - style = WS_POPUP; - if ((type == Qt::ToolTip) || (type == Qt::SplashScreen)) { - style = WS_POPUP; - exsty |= WS_EX_NOANIMATION; - } else { - if (flags & Qt::WindowTitleHint) - style |= WS_CAPTION; - if (flags & Qt::WindowSystemMenuHint) - style |= WS_SYSMENU; - if (flags & Qt::WindowContextHelpButtonHint) - exsty |= WS_EX_CONTEXTHELP; -#ifndef Q_WS_WINCE_WM - if (flags & Qt::WindowMinimizeButtonHint) - style |= WS_MINIMIZEBOX; - if (shouldShowMaximizeButton()) - style |= WS_MAXIMIZEBOX; -#endif - if (tool) - exsty |= WS_EX_TOOLWINDOW; - } - } - if (dialog) { - style = WS_BORDER | WS_CAPTION; - if (flags & Qt::WindowOkButtonHint) - exsty |= WS_EX_CAPTIONOKBTN; - if (flags & Qt::WindowCancelButtonHint || flags & Qt::WA_DeleteOnClose) - style |= WS_SYSMENU; - if (flags & Qt::WindowContextHelpButtonHint) - exsty |= WS_EX_CONTEXTHELP; - } - if (popup) { - style = WS_POPUP; - exsty |= WS_EX_NOANIMATION; - } - - if (flags & Qt::WindowTitleHint) { - title = q->isWindow() ? qAppName() : q->objectName(); - } - - // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in - // qapplication_win.cpp. We switch it off temporarily to avoid move - // and resize events during creationt - q->setAttribute(Qt::WA_WState_Created, false); - - if (window) { // override the old window - if (destroyOldWindow) - destroyw = data.winid; - id = window; - setWinId(window); - LONG res = SetWindowLong(window, GWL_STYLE, style); - if (!res) - qErrnoWarning("QWidget::create: Failed to set window style"); - - res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc ); - - if (!res) - qErrnoWarning("QWidget::create: Failed to set window procedure"); - } else if (desktop) { // desktop widget - id = GetDesktopWindow(); - if (!id) { //Create a dummy desktop - RECT r; - SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - id = CreateWindow(reinterpret_cast(windowClassName.utf16()), - reinterpret_cast(title.utf16()), style, - r.left, r.top, r.right - r.left, r.bottom - r.top, - 0, 0, appinst, 0); - } - setWinId(id); - } else if (topLevel) { // create top-level widget - const bool wasMoved = q->testAttribute(Qt::WA_Moved); - - int x, y; - if (qt_wince_is_mobile()) { - x = wasMoved ? data.crect.left() : CW_USEDEFAULT; - y = wasMoved ? data.crect.top() : CW_USEDEFAULT; - } else { - x = wasMoved ? data.crect.left() : 100; - y = wasMoved ? data.crect.top() : 100; - } - - int w = CW_USEDEFAULT; - int h = CW_USEDEFAULT; - - // Adjust for framestrut when needed - RECT rect = {0,0,0,0}; - if (AdjustWindowRectEx(&rect, style, FALSE, exsty)) { - QTLWExtra *td = maybeTopData(); - if (wasMoved && (td && !td->posFromMove)) { - x = data.crect.x() + rect.left; - y = data.crect.y() + rect.top; - } - - if (q->testAttribute(Qt::WA_Resized)) { - w = data.crect.width() + (rect.right - rect.left); - h = data.crect.height() + (rect.bottom - rect.top); - } - } - - id = CreateWindowEx(exsty, reinterpret_cast(windowClassName.utf16()), - reinterpret_cast(title.utf16()), style, - x, y, w, h, - 0, 0, appinst, 0); - - if (!id) - qErrnoWarning("QWidget::create: Failed to create window"); - setWinId(id); - if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) - SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget - id = CreateWindowEx(exsty, (wchar_t*)windowClassName.utf16(), (wchar_t*)title.utf16(), style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), - parentw, NULL, appinst, NULL); - if (!id) - qErrnoWarning("QWidget::create: Failed to create window"); - SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - setWinId(id); - } - - if (desktop) { - q->setAttribute(Qt::WA_WState_Visible); - } else if (topLevel && !q->testAttribute(Qt::WA_DontShowOnScreen)) { - RECT cr; - GetClientRect(id, &cr); - // one cannot trust cr.left and cr.top, use a correction POINT instead - POINT pt; - pt.x = 0; - pt.y = 0; - if (!q->testAttribute(Qt::WA_DontShowOnScreen) || q->testAttribute(Qt::WA_Moved)) - ClientToScreen(id, &pt); - data.crect = QRect(QPoint(pt.x, pt.y), - QPoint(pt.x + cr.right - 1, pt.y + cr.bottom - 1)); - - if (data.fstrut_dirty) { - // be nice to activeqt - updateFrameStrut(); - } - } - - q->setAttribute(Qt::WA_WState_Created); // accept move/resize events - hd = 0; // no display context - - if (window) { // got window from outside - if (IsWindowVisible(window)) - q->setAttribute(Qt::WA_WState_Visible); - else - q->setAttribute(Qt::WA_WState_Visible, false); - } - - if (extra && !extra->mask.isEmpty()) - setMask_sys(extra->mask); - -#if defined(QT_NON_COMMERCIAL) - QT_NC_WIDGET_CREATE -#endif - - if (q->hasFocus() && q->testAttribute(Qt::WA_InputMethodEnabled)) - q->inputContext()->setFocusWidget(q); - - if (destroyw) { - DestroyWindow(destroyw); - } - -#ifndef QT_NO_TABLETEVENT - if (q != qt_tablet_widget && QWidgetPrivate::mapper) - qt_tablet_init_wce(); -#endif // QT_NO_TABLETEVENT - - if (q->testAttribute(Qt::WA_DropSiteRegistered)) - registerDropSite(true); - - if (maybeTopData() && maybeTopData()->opacity != 255) - q->setWindowOpacity(maybeTopData()->opacity/255.); - - if (!topLevel && q->testAttribute(Qt::WA_NativeWindow) && q->testAttribute(Qt::WA_Mapped)) { - Q_ASSERT(q->internalWinId()); - ShowWindow(q->internalWinId(), SW_SHOW); - } -} - -/* - \internal - Platform-specific part of QWidget::show(). -*/ -void QWidgetPrivate::show_sys() { - Q_Q(QWidget); -#if defined(QT_NON_COMMERCIAL) - QT_NC_SHOW_WINDOW -#endif - if (q->testAttribute(Qt::WA_OutsideWSRange)) - return; - - q->setAttribute(Qt::WA_Mapped); - - Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - - if (q->testAttribute(Qt::WA_DontShowOnScreen)) { - invalidateBuffer(q->rect()); - return; - } - - - int sm = SW_SHOW; - bool fakedMaximize = false; - if (q->isWindow()) { -#ifndef Q_WS_WINCE_WM - if (q->isMinimized()) { - sm = SW_SHOWMINIMIZED; - } else if (q->isMaximized()) { - sm = SW_SHOWMAXIMIZED; - // Windows will not behave correctly when we try to maximize a window which does not - // have minimize nor maximize buttons in the window frame. Windows would then ignore - // non-available geometry, and rather maximize the widget to the full screen, minus the - // window frame (caption). So, we do a trick here, by adding a maximize button before - // maximizing the widget, and then remove the maximize button afterwards. - Qt::WindowFlags &flags = data.window_flags; - if (flags & Qt::WindowTitleHint && - !(flags & (Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint))) { - fakedMaximize = TRUE; - int style = GetWindowLong(q->internalWinId(), GWL_STYLE); - SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX); - } - } else -#else - // Imitate minimizing on Windows mobile by hiding the widget. - if (q->isMinimized()) - sm = SW_HIDE; -#endif - if (q->isHidden()) { - sm = SW_HIDE; - } - } - if (q->testAttribute(Qt::WA_ShowWithoutActivating) - || (q->windowType() == Qt::Popup) - || (q->windowType() == Qt::ToolTip) - || (q->windowType() == Qt::Tool)) { - sm = SW_SHOWNOACTIVATE; - } - - ShowWindow(q->internalWinId(), sm); - - if (q->isMaximized() && q->isWindow()) - qt_wince_maximize(q); - -#ifndef Q_WS_WINCE_WM - if (!qt_wince_is_mobile() && q->isFullScreen()) { - HWND handle = FindWindow(L"HHTaskBar", L""); - if (handle) { - ShowWindow(handle, SW_HIDE); - EnableWindow(handle, false); - } - } - - if (fakedMaximize) { - int style = GetWindowLong(q->internalWinId(), GWL_STYLE); - SetWindowLong(q->internalWinId(), GWL_STYLE, style & ~WS_MAXIMIZEBOX); - SetWindowPos(q->internalWinId(), 0, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER - | SWP_FRAMECHANGED); - } -#else - Q_UNUSED(fakedMaximize); -#endif - - if (q->isWindow() && sm == SW_SHOW) - SetForegroundWindow(q->internalWinId()); - - invalidateBuffer(q->rect()); -} - -void QWidget::setWindowState(Qt::WindowStates newstate) -{ - Q_D(QWidget); - Qt::WindowStates oldstate = windowState(); - if (oldstate == newstate) - return; - - int max = SW_SHOWNORMAL; - int normal = SW_SHOWNOACTIVATE; - - if ((oldstate & Qt::WindowMinimized) && !(newstate & Qt::WindowMinimized)) - newstate |= Qt::WindowActive; - if (newstate & Qt::WindowActive) - normal = SW_SHOWNORMAL; - if (isWindow()) { - createWinId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - // Ensure the initial size is valid, since we store it as normalGeometry below. - if ((!testAttribute(Qt::WA_Resized) && !isVisible())) - adjustSize(); - if (!d->topData()->normalGeometry.isValid()) { - if (newstate & Qt::WindowMaximized && !(oldstate & Qt::WindowFullScreen)) - d->topData()->normalGeometry = geometry(); - if (newstate & Qt::WindowMinimized && !(oldstate & Qt::WindowFullScreen)) - d->topData()->normalGeometry = geometry(); - } - if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { - if (!(newstate & Qt::WindowMaximized)) { - int style = GetWindowLong(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION; - SetWindowLong(internalWinId(), GWL_STYLE, style); - SetWindowLong(internalWinId(), GWL_EXSTYLE, GetWindowLong (internalWinId(), GWL_EXSTYLE) & ~ WS_EX_NODRAG); - qt_wince_unmaximize(this); - } - if (isVisible() && newstate & Qt::WindowMaximized) - qt_wince_maximize(this); - if (isVisible() && !(newstate & Qt::WindowMinimized)) { - ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal); - if (!(newstate & Qt::WindowFullScreen)) { - QRect r = d->topData()->normalGeometry; - if (!(newstate & Qt::WindowMaximized) && r.width() >= 0) { - if (pos() != r.topLeft() || size() !=r.size()) { - d->topData()->normalGeometry = QRect(0,0,-1,-1); - setGeometry(r); - } - } - } else { - d->updateFrameStrut(); - } - } - } - if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) { - if (newstate & Qt::WindowFullScreen) { - if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) - d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = (Qt::WindowFlags)GetWindowLong(internalWinId(), GWL_STYLE); - UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; - if (isVisible()) - style |= WS_VISIBLE; - SetWindowLong(internalWinId(), GWL_STYLE, style); - QRect r = qApp->desktop()->screenGeometry(this); - UINT swpf = SWP_FRAMECHANGED; - if (newstate & Qt::WindowActive) - swpf |= SWP_NOACTIVATE; - qt_wince_full_screen(internalWinId(), true, swpf); - d->updateFrameStrut(); - } else { - UINT style = d->topData()->savedFlags; - if (isVisible()) - style |= WS_VISIBLE; - SetWindowLong(internalWinId(), GWL_STYLE, style); - UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; - if (newstate & Qt::WindowActive) - swpf |= SWP_NOACTIVATE; - qt_wince_full_screen(internalWinId(), false, swpf); - d->updateFrameStrut(); - - // preserve maximized state - if (isVisible()) { - ShowWindow(internalWinId(), (newstate & Qt::WindowMaximized) ? max : normal); - if (newstate & Qt::WindowMaximized) - qt_wince_maximize(this); - } - if (!(newstate & Qt::WindowMaximized)) { - QRect r = d->topData()->normalGeometry; - d->topData()->normalGeometry = QRect(0,0,-1,-1); - if (r.isValid()) - setGeometry(r); - } - } - } - if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { - if (newstate & Qt::WindowMinimized) - qt_wince_minimize(internalWinId()); - else if (newstate & Qt::WindowMaximized) { - ShowWindow(internalWinId(), max); - qt_wince_maximize(this); - } else { - ShowWindow(internalWinId(), normal); - } - } - } - data->window_state = newstate; - QWindowStateChangeEvent e(oldstate); - QApplication::sendEvent(this, &e); -} - -void QWidgetPrivate::deleteSysExtra() -{ - Q_Q(QWidget); - if (!qt_wince_is_mobile() && q->isFullScreen()) { - HWND handle = FindWindow(L"HHTaskBar", L""); - if (handle) { - ShowWindow(handle, SW_SHOWNORMAL); - EnableWindow(handle, true); - } - } -} - -void QWidgetPrivate::setWindowOpacity_sys(qreal level) { - Q_UNUSED(level); - return; -} - -// The procedure does nothing, but is required for mousegrabbing to work -LRESULT QT_WIN_CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) { - Q_UNUSED(nCode); - Q_UNUSED(wParam); - Q_UNUSED(lParam); - return 0; -} - -void QWidget::grabMouse() { - if (!qt_nograb()) { - if (mouseGrb) - mouseGrb->releaseMouse(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - SetCapture(internalWinId()); - mouseGrb = this; - } -} - -#ifndef QT_NO_CURSOR -void QWidget::grabMouse(const QCursor &cursor) { - if (!qt_nograb()) { - if (mouseGrb) - mouseGrb->releaseMouse(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - SetCapture(internalWinId()); - mouseGrbCur = new QCursor(cursor); - SetCursor(mouseGrbCur->handle()); - mouseGrb = this; - } -} -#endif - -void QWidget::releaseMouse() { - if (!qt_nograb() && mouseGrb == this) { - ReleaseCapture(); - if (journalRec) { - journalRec = 0; - } - if (mouseGrbCur) { - delete mouseGrbCur; - mouseGrbCur = 0; - } - mouseGrb = 0; - } -} - -void QWidget::show() -{ - Qt::WindowFlags flags = windowFlags() & 0xff; - int threshold = qApp->autoMaximizeThreshold(); - if ((threshold < 0) || (windowState() & Qt::WindowFullScreen) || (windowState() & Qt::WindowMaximized)) { - setVisible(true); - return; - } - int height = sizeHint().height(); - int screenHeight = (qreal(threshold) / 100.0f * qApp->desktop()->screenGeometry(this).height()); - bool maximize = height > screenHeight; - if (!maximize) { - // If we do not maximize yet we check the widget and its child widgets whether they are - //vertically expanding. If one of the widgets is expanding we maximize. - QList list = findChildren(); - bool expandingChild = sizePolicy().verticalPolicy () == QSizePolicy::Expanding; - for (int i = 0; (i < list.size()) && !expandingChild; ++i) { - expandingChild = list.at(i)->sizePolicy().verticalPolicy () == QSizePolicy::Expanding; - } - maximize = expandingChild; - } - if ((minimumSizeHint().height() > qApp->desktop()->screenGeometry(this).height()) || (minimumSizeHint().width() > qApp->desktop()->screenGeometry(this).width())) - maximize = false; - - if ((flags == Qt::Window || flags == Qt::Dialog) && maximize) { - setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) - | Qt::WindowMaximized); - setVisible(true); - } - else { - setVisible(true); - } -} - -QT_END_NAMESPACE - -#endif // Q_WS_WINCE diff --git a/src/widgets/platforms/win/qwininputcontext_p.h b/src/widgets/platforms/win/qwininputcontext_p.h deleted file mode 100644 index c0a6ac6b6f..0000000000 --- a/src/widgets/platforms/win/qwininputcontext_p.h +++ /dev/null @@ -1,111 +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 QWININPUTCONTEXT_P_H -#define QWININPUTCONTEXT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qinputcontext.cpp. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtWidgets/qinputcontext.h" -#include "QtCore/qt_windows.h" - -#if !defined(IMR_RECONVERTSTRING) -typedef struct tagRECONVERTSTRING { - DWORD dwSize; - DWORD dwVersion; - DWORD dwStrLen; - DWORD dwStrOffset; - DWORD dwCompStrLen; - DWORD dwCompStrOffset; - DWORD dwTargetStrLen; - DWORD dwTargetStrOffset; -} RECONVERTSTRING, *PRECONVERTSTRING; -#endif - -QT_BEGIN_NAMESPACE - -class QWinInputContext : public QInputContext -{ - Q_OBJECT -public: - explicit QWinInputContext(QObject* parent = 0); - virtual ~QWinInputContext(); - - virtual QString identifierName() { return QLatin1String("win"); } - virtual QString language(); - - virtual void reset(); - virtual void update(); - - virtual void mouseHandler(int x, QMouseEvent *event); - virtual bool isComposing() const; - - virtual void setFocusWidget(QWidget *w); - - bool startComposition(); - bool endComposition(); - bool composition(LPARAM lparam); - int reconvertString(RECONVERTSTRING *reconv); - - static void TranslateMessage(const MSG *msg); - static LRESULT DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - - static void updateImeStatus(QWidget *w, bool hasFocus); - static void enablePopupChild(QWidget *w, bool e); - static void enable(QWidget *w, bool e); - -private: - void init(); - bool recursionGuard; -}; - -QT_END_NAMESPACE - -#endif // QWININPUTCONTEXT_P_H diff --git a/src/widgets/platforms/win/qwininputcontext_win.cpp b/src/widgets/platforms/win/qwininputcontext_win.cpp deleted file mode 100644 index 9ec9942af8..0000000000 --- a/src/widgets/platforms/win/qwininputcontext_win.cpp +++ /dev/null @@ -1,847 +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 "qwininputcontext_p.h" -#include "qinputcontext_p.h" - -#include "qfont.h" -#include "qwidget.h" -#include "qapplication.h" -#include "qevent.h" -#include "qtextformat.h" -#include "qtextboundaryfinder.h" - -//#define Q_IME_DEBUG - -#ifdef Q_IME_DEBUG -#include "qdebug.h" -#endif - -#if defined(Q_WS_WINCE) -extern void qt_wince_show_SIP(bool show); // defined in qguifunctions_wince.cpp -#endif - -QT_BEGIN_NAMESPACE - -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); - - -DEFINE_GUID(IID_IActiveIMMApp, -0x08c0e040, 0x62d1, 0x11d1, 0x93, 0x26, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e); - - - -DEFINE_GUID(CLSID_CActiveIMM, -0x4955DD33, 0xB159, 0x11d0, 0x8F, 0xCF, 0x0, 0xAA, 0x00, 0x6B, 0xCC, 0x59); - - - -DEFINE_GUID(IID_IActiveIMMMessagePumpOwner, -0xb5cf2cfa, 0x8aeb, 0x11d1, 0x93, 0x64, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e); - - - -interface IEnumRegisterWordW; -interface IEnumInputContext; - - -bool qt_sendSpontaneousEvent(QObject*, QEvent*); - - -#define IFMETHOD HRESULT STDMETHODCALLTYPE - -interface IActiveIMMApp : public IUnknown -{ -public: - virtual IFMETHOD AssociateContext(HWND hWnd, HIMC hIME, HIMC __RPC_FAR *phPrev) = 0; - virtual IFMETHOD dummy_ConfigureIMEA() = 0; - virtual IFMETHOD ConfigureIMEW(HKL hKL, HWND hWnd, DWORD dwMode, REGISTERWORDW __RPC_FAR *pData) = 0; - virtual IFMETHOD CreateContext(HIMC __RPC_FAR *phIMC) = 0; - virtual IFMETHOD DestroyContext(HIMC hIME) = 0; - virtual IFMETHOD dummy_EnumRegisterWordA() = 0; - virtual IFMETHOD EnumRegisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister, LPVOID pData, - IEnumRegisterWordW __RPC_FAR *__RPC_FAR *pEnum) = 0; - virtual IFMETHOD dummy_EscapeA() = 0; - virtual IFMETHOD EscapeW(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID pData, LRESULT __RPC_FAR *plResult) = 0; - virtual IFMETHOD dummy_GetCandidateListA() = 0; - virtual IFMETHOD GetCandidateListW(HIMC hIMC, DWORD dwIndex, UINT uBufLen, CANDIDATELIST __RPC_FAR *pCandList, - UINT __RPC_FAR *puCopied) = 0; - virtual IFMETHOD dummy_GetCandidateListCountA() = 0; - virtual IFMETHOD GetCandidateListCountW(HIMC hIMC, DWORD __RPC_FAR *pdwListSize, DWORD __RPC_FAR *pdwBufLen) = 0; - virtual IFMETHOD GetCandidateWindow(HIMC hIMC, DWORD dwIndex, CANDIDATEFORM __RPC_FAR *pCandidate) = 0; - virtual IFMETHOD dummy_GetCompositionFontA() = 0; - virtual IFMETHOD GetCompositionFontW(HIMC hIMC, LOGFONTW __RPC_FAR *plf) = 0; - virtual IFMETHOD dummy_GetCompositionStringA() = 0; - virtual IFMETHOD GetCompositionStringW(HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LONG __RPC_FAR *plCopied, LPVOID pBuf) = 0; - virtual IFMETHOD GetCompositionWindow(HIMC hIMC, COMPOSITIONFORM __RPC_FAR *pCompForm) = 0; - virtual IFMETHOD GetContext(HWND hWnd, HIMC __RPC_FAR *phIMC) = 0; - virtual IFMETHOD dummy_GetConversionListA() = 0; - virtual IFMETHOD GetConversionListW(HKL hKL, HIMC hIMC, LPWSTR pSrc, UINT uBufLen, UINT uFlag, - CANDIDATELIST __RPC_FAR *pDst, UINT __RPC_FAR *puCopied) = 0; - virtual IFMETHOD GetConversionStatus(HIMC hIMC, DWORD __RPC_FAR *pfdwConversion, DWORD __RPC_FAR *pfdwSentence) = 0; - virtual IFMETHOD GetDefaultIMEWnd(HWND hWnd, HWND __RPC_FAR *phDefWnd) = 0; - virtual IFMETHOD dummy_GetDescriptionA() = 0; - virtual IFMETHOD GetDescriptionW(HKL hKL, UINT uBufLen, LPWSTR szDescription, UINT __RPC_FAR *puCopied) = 0; - virtual IFMETHOD dummy_GetGuideLineA() = 0; - virtual IFMETHOD GetGuideLineW(HIMC hIMC, DWORD dwIndex, DWORD dwBufLen, LPWSTR pBuf, DWORD __RPC_FAR *pdwResult) = 0; - virtual IFMETHOD dummy_GetIMEFileNameA() = 0; - virtual IFMETHOD GetIMEFileNameW(HKL hKL, UINT uBufLen, LPWSTR szFileName, UINT __RPC_FAR *puCopied) = 0; - virtual IFMETHOD GetOpenStatus(HIMC hIMC) = 0; - virtual IFMETHOD GetProperty(HKL hKL, DWORD fdwIndex, DWORD __RPC_FAR *pdwProperty) = 0; - virtual IFMETHOD dummy_GetRegisterWordStyleA() = 0; - virtual IFMETHOD GetRegisterWordStyleW(HKL hKL, UINT nItem, STYLEBUFW __RPC_FAR *pStyleBuf, UINT __RPC_FAR *puCopied) = 0; - virtual IFMETHOD GetStatusWindowPos(HIMC hIMC, POINT __RPC_FAR *pptPos) = 0; - virtual IFMETHOD GetVirtualKey(HWND hWnd, UINT __RPC_FAR *puVirtualKey) = 0; - virtual IFMETHOD dummy_InstallIMEA() = 0; - virtual IFMETHOD InstallIMEW(LPWSTR szIMEFileName, LPWSTR szLayoutText, HKL __RPC_FAR *phKL) = 0; - virtual IFMETHOD IsIME(HKL hKL) = 0; - virtual IFMETHOD dummy_IsUIMessageA() = 0; - virtual IFMETHOD IsUIMessageW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) = 0; - virtual IFMETHOD NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) = 0; - virtual IFMETHOD dummy_RegisterWordA() = 0; - virtual IFMETHOD RegisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szRegister) = 0; - virtual IFMETHOD ReleaseContext(HWND hWnd, HIMC hIMC) = 0; - virtual IFMETHOD SetCandidateWindow(HIMC hIMC, CANDIDATEFORM __RPC_FAR *pCandidate) = 0; - virtual IFMETHOD SetCompositionFontA(HIMC hIMC, LOGFONTA __RPC_FAR *plf) = 0; - virtual IFMETHOD SetCompositionFontW(HIMC hIMC, LOGFONTW __RPC_FAR *plf) = 0; - virtual IFMETHOD dummy_SetCompositionStringA() = 0; - virtual IFMETHOD SetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen, - LPVOID pRead, DWORD dwReadLen) = 0; - virtual IFMETHOD SetCompositionWindow(HIMC hIMC, COMPOSITIONFORM __RPC_FAR *pCompForm) = 0; - virtual IFMETHOD SetConversionStatus(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) = 0; - virtual IFMETHOD SetOpenStatus(HIMC hIMC, BOOL fOpen) = 0; - virtual IFMETHOD SetStatusWindowPos(HIMC hIMC, POINT __RPC_FAR *pptPos) = 0; - virtual IFMETHOD SimulateHotKey(HWND hWnd, DWORD dwHotKeyID) = 0; - virtual IFMETHOD dummy_UnregisterWordA() = 0; - virtual IFMETHOD UnregisterWordW(HKL hKL, LPWSTR szReading, DWORD dwStyle, LPWSTR szUnregister) = 0; - virtual IFMETHOD Activate(BOOL fRestoreLayout) = 0; - virtual IFMETHOD Deactivate(void) = 0; - virtual IFMETHOD OnDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT __RPC_FAR *plResult) = 0; - virtual IFMETHOD FilterClientWindows(ATOM __RPC_FAR *aaClassList, UINT uSize) = 0; - virtual IFMETHOD dummy_GetCodePageA() = 0; - virtual IFMETHOD GetLangId(HKL hKL, LANGID __RPC_FAR *plid) = 0; - virtual IFMETHOD AssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) = 0; - virtual IFMETHOD DisableIME(DWORD idThread) = 0; - virtual IFMETHOD dummy_GetImeMenuItemsA() = 0; - virtual IFMETHOD GetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, /*IMEMENUITEMINFOW*/ void __RPC_FAR *pImeParentMenu, - /*IMEMENUITEMINFOW*/ void __RPC_FAR *pImeMenu, DWORD dwSize, DWORD __RPC_FAR *pdwResult) = 0; - virtual IFMETHOD EnumInputContext(DWORD idThread, IEnumInputContext __RPC_FAR *__RPC_FAR *ppEnum) = 0; -}; - -interface IActiveIMMMessagePumpOwner : public IUnknown -{ -public: - virtual IFMETHOD Start(void) = 0; - virtual IFMETHOD End(void) = 0; - virtual IFMETHOD OnTranslateMessage(const MSG __RPC_FAR *pMsg) = 0; - virtual IFMETHOD Pause(DWORD __RPC_FAR *pdwCookie) = 0; - virtual IFMETHOD Resume(DWORD dwCookie) = 0; -}; - - -static IActiveIMMApp *aimm = 0; -static IActiveIMMMessagePumpOwner *aimmpump = 0; -static QString *imeComposition = 0; -static int imePosition = -1; -bool qt_use_rtl_extensions = false; -static bool haveCaret = false; - -#ifndef LGRPID_INSTALLED -#define LGRPID_INSTALLED 0x00000001 // installed language group ids -#define LGRPID_SUPPORTED 0x00000002 // supported language group ids -#endif - -#ifndef LGRPID_ARABIC -#define LGRPID_WESTERN_EUROPE 0x0001 // Western Europe & U.S. -#define LGRPID_CENTRAL_EUROPE 0x0002 // Central Europe -#define LGRPID_BALTIC 0x0003 // Baltic -#define LGRPID_GREEK 0x0004 // Greek -#define LGRPID_CYRILLIC 0x0005 // Cyrillic -#define LGRPID_TURKISH 0x0006 // Turkish -#define LGRPID_JAPANESE 0x0007 // Japanese -#define LGRPID_KOREAN 0x0008 // Korean -#define LGRPID_TRADITIONAL_CHINESE 0x0009 // Traditional Chinese -#define LGRPID_SIMPLIFIED_CHINESE 0x000a // Simplified Chinese -#define LGRPID_THAI 0x000b // Thai -#define LGRPID_HEBREW 0x000c // Hebrew -#define LGRPID_ARABIC 0x000d // Arabic -#define LGRPID_VIETNAMESE 0x000e // Vietnamese -#define LGRPID_INDIC 0x000f // Indic -#define LGRPID_GEORGIAN 0x0010 // Georgian -#define LGRPID_ARMENIAN 0x0011 // Armenian -#endif - -static DWORD WM_MSIME_MOUSE = 0; - -QWinInputContext::QWinInputContext(QObject *parent) - : QInputContext(parent), recursionGuard(false) -{ -#ifndef Q_WS_WINCE - QSysInfo::WinVersion ver = QSysInfo::windowsVersion(); - if (ver & QSysInfo::WV_NT_based && ver >= QSysInfo::WV_VISTA) { - // Since the IsValidLanguageGroup/IsValidLocale functions always return true on - // Vista, check the Keyboard Layouts for enabling RTL. - UINT nLayouts = GetKeyboardLayoutList(0, 0); - if (nLayouts) { - HKL *lpList = new HKL[nLayouts]; - GetKeyboardLayoutList(nLayouts, lpList); - for (int i = 0; i<(int)nLayouts; i++) { - WORD plangid = PRIMARYLANGID((quintptr)lpList[i]); - if (plangid == LANG_ARABIC - || plangid == LANG_HEBREW - || plangid == LANG_FARSI -#ifdef LANG_SYRIAC - || plangid == LANG_SYRIAC -#endif - ) { - qt_use_rtl_extensions = true; - break; - } - } - delete []lpList; - } - } else { - // figure out whether a RTL language is installed - qt_use_rtl_extensions = IsValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED) - || IsValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED) - || IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) - || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) -#ifdef LANG_SYRIAC - || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) -#endif - || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED); - } -#else - qt_use_rtl_extensions = false; -#endif - - WM_MSIME_MOUSE = RegisterWindowMessage(L"MSIMEMouseOperation"); -} - -QWinInputContext::~QWinInputContext() -{ - // release active input method if we have one - if (aimm) { - aimmpump->End(); - aimmpump->Release(); - aimm->Deactivate(); - aimm->Release(); - aimm = 0; - aimmpump = 0; - } - delete imeComposition; - imeComposition = 0; -} - -static HWND getDefaultIMEWnd(HWND wnd) -{ - HWND ime_wnd; - if(aimm) - aimm->GetDefaultIMEWnd(wnd, &ime_wnd); - else - ime_wnd = ImmGetDefaultIMEWnd(wnd); - return ime_wnd; -} - -static HIMC getContext(HWND wnd) -{ - HIMC imc; - if (aimm) - aimm->GetContext(wnd, &imc); - else - imc = ImmGetContext(wnd); - - return imc; -} - -static void releaseContext(HWND wnd, HIMC imc) -{ - if (aimm) - aimm->ReleaseContext(wnd, imc); - else - ImmReleaseContext(wnd, imc); -} - -static void notifyIME(HIMC imc, DWORD dwAction, DWORD dwIndex, DWORD dwValue) -{ - if (!imc) - return; - if (aimm) - aimm->NotifyIME(imc, dwAction, dwIndex, dwValue); - else - ImmNotifyIME(imc, dwAction, dwIndex, dwValue); -} - -static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD dBufLen) -{ - LONG len = 0; - if (aimm) - aimm->GetCompositionStringW(himc, dwIndex, dBufLen, &len, lpbuf); - else - len = ImmGetCompositionString(himc, dwIndex, lpbuf, dBufLen); - return len; -} - -static int getCursorPosition(HIMC himc) -{ - return getCompositionString(himc, GCS_CURSORPOS, 0, 0); -} - -static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLength = 0) -{ - const int bufferSize = 256; - wchar_t buffer[bufferSize]; - int len = getCompositionString(himc, dwindex, buffer, bufferSize * sizeof(wchar_t)); - - if (selStart) { - char attrbuffer[bufferSize]; - int attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, bufferSize); - *selStart = attrlen+1; - *selLength = -1; - for (int i = 0; i < attrlen; i++) { - if (attrbuffer[i] & ATTR_TARGET_CONVERTED) { - *selStart = qMin(*selStart, i); - *selLength = qMax(*selLength, i); - } - } - *selLength = qMax(0, *selLength - *selStart + 1); - } - - if (len <= 0) - return QString(); - - return QString((QChar*)buffer, len / sizeof(QChar)); -} - -void QWinInputContext::TranslateMessage(const MSG *msg) -{ - if (!aimmpump || aimmpump->OnTranslateMessage(msg) != S_OK) - ::TranslateMessage(msg); -} - -LRESULT QWinInputContext::DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - LRESULT retval; - if (!aimm || aimm->OnDefWindowProc(hwnd, msg, wParam, lParam, &retval) != S_OK) - { - retval = ::DefWindowProc(hwnd, msg, wParam, lParam); - } - return retval; -} - - -void QWinInputContext::update() -{ - QWidget *w = focusWidget(); - if(!w) - return; - - Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); - HIMC imc = getContext(w->effectiveWinId()); - - if (!imc) - return; - - QFont f = qvariant_cast(w->inputMethodQuery(Qt::ImFont)); - HFONT hf; - hf = f.handle(); - - LOGFONT lf; - if (GetObject(hf, sizeof(lf), &lf)) { - if (aimm) - aimm->SetCompositionFontW(imc, &lf); - else - ImmSetCompositionFont(imc, &lf); - } - - QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect(); - - // The ime window positions are based on the WinId with active focus. - QWidget *imeWnd = QWidget::find(::GetFocus()); - if (imeWnd && !aimm) { - QPoint pt (r.topLeft()); - pt = w->mapToGlobal(pt); - pt = imeWnd->mapFromGlobal(pt); - r.moveTo(pt); - } - - COMPOSITIONFORM cf; - // ### need X-like inputStyle config settings - cf.dwStyle = CFS_FORCE_POSITION; - cf.ptCurrentPos.x = r.x(); - cf.ptCurrentPos.y = r.y(); - - CANDIDATEFORM candf; - candf.dwIndex = 0; - candf.dwStyle = CFS_EXCLUDE; - candf.ptCurrentPos.x = r.x(); - candf.ptCurrentPos.y = r.y() + r.height(); - candf.rcArea.left = r.x(); - candf.rcArea.top = r.y(); - candf.rcArea.right = r.x() + r.width(); - candf.rcArea.bottom = r.y() + r.height(); - - if(haveCaret) - SetCaretPos(r.x(), r.y()); - - if (aimm) { - aimm->SetCompositionWindow(imc, &cf); - aimm->SetCandidateWindow(imc, &candf); - } else { - ImmSetCompositionWindow(imc, &cf); - ImmSetCandidateWindow(imc, &candf); - } - - releaseContext(w->effectiveWinId(), imc); -} - - -bool QWinInputContext::endComposition() -{ - QWidget *fw = focusWidget(); -#ifdef Q_IME_DEBUG - qDebug("endComposition! fw = %s", fw ? fw->className() : "(null)"); -#endif - bool result = true; - if(imePosition == -1 || recursionGuard) - return result; - - // Googles Pinyin Input Method likes to call endComposition again - // when we call notifyIME with CPS_CANCEL, so protect ourselves - // against that. - recursionGuard = true; - - if (fw) { - Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created)); - HIMC imc = getContext(fw->effectiveWinId()); - notifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0); - releaseContext(fw->effectiveWinId(), imc); - if(haveCaret) { - DestroyCaret(); - haveCaret = false; - } - } - - if (!fw) - fw = QApplication::focusWidget(); - - if (fw) { - QInputMethodEvent e; - result = qt_sendSpontaneousEvent(fw, &e); - } - - if (imeComposition) - imeComposition->clear(); - imePosition = -1; - - recursionGuard = false; - - return result; -} - -void QWinInputContext::reset() -{ - QWidget *fw = focusWidget(); - -#ifdef Q_IME_DEBUG - qDebug("sending accept to focus widget %s", fw ? fw->className() : "(null)"); -#endif - - if (fw && imePosition != -1) { - QInputMethodEvent e; - if (imeComposition) - e.setCommitString(*imeComposition); - imePosition = -1; - qt_sendSpontaneousEvent(fw, &e); - } - - if (imeComposition) - imeComposition->clear(); - imePosition = -1; - - if (fw) { - Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created)); - HIMC imc = getContext(fw->effectiveWinId()); - notifyIME(imc, NI_COMPOSITIONSTR, CPS_CANCEL, 0); - releaseContext(fw->effectiveWinId(), imc); - } - -} - - -bool QWinInputContext::startComposition() -{ -#ifdef Q_IME_DEBUG - qDebug("startComposition"); -#endif - - if (!imeComposition) - imeComposition = new QString(); - - QWidget *fw = focusWidget(); - if (fw) { - Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created)); - imePosition = 0; - haveCaret = CreateCaret(fw->effectiveWinId(), 0, 1, 1); - HideCaret(fw->effectiveWinId()); - update(); - } - return fw != 0; -} - -enum StandardFormat { - PreeditFormat, - SelectionFormat -}; - -bool QWinInputContext::composition(LPARAM lParam) -{ -#ifdef Q_IME_DEBUG - QString str; - if (lParam & GCS_RESULTSTR) - str += "RESULTSTR "; - if (lParam & GCS_COMPSTR) - str += "COMPSTR "; - if (lParam & GCS_COMPATTR) - str += "COMPATTR "; - if (lParam & GCS_CURSORPOS) - str += "CURSORPOS "; - if (lParam & GCS_COMPCLAUSE) - str += "COMPCLAUSE "; - if (lParam & CS_INSERTCHAR) - str += "INSERTCHAR "; - if (lParam & CS_NOMOVECARET) - str += "NOMOVECARET "; - qDebug("composition, lParam=(%x) %s imePosition=%d", lParam, str.latin1(), imePosition); -#endif - - bool result = true; - - if(!lParam) - // bogus event - return true; - - QWidget *fw = QApplication::focusWidget(); - if (fw) { - Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created)); - HIMC imc = getContext(fw->effectiveWinId()); - QInputMethodEvent e; - if (lParam & (GCS_COMPSTR | GCS_COMPATTR | GCS_CURSORPOS)) { - if (imePosition == -1) - // need to send a start event - startComposition(); - - // some intermediate composition result - int selStart, selLength; - *imeComposition = getString(imc, GCS_COMPSTR, &selStart, &selLength); - imePosition = getCursorPosition(imc); - if (lParam & CS_INSERTCHAR && lParam & CS_NOMOVECARET) { - // make korean work correctly. Hope this is correct for all IMEs - selStart = 0; - selLength = imeComposition->length(); - } - if(selLength == 0) - selStart = 0; - - QList attrs; - if (selStart > 0) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selStart, - standardFormat(PreeditFormat)); - if (selLength) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart, selLength, - standardFormat(SelectionFormat)); - if (selStart + selLength < imeComposition->length()) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selStart + selLength, - imeComposition->length() - selStart - selLength, - standardFormat(PreeditFormat)); - if(imePosition >= 0) - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, imePosition, selLength ? 0 : 1, QVariant()); - - e = QInputMethodEvent(*imeComposition, attrs); - } - if (lParam & GCS_RESULTSTR) { - if(imePosition == -1) - startComposition(); - // a fixed result, return the converted string - *imeComposition = getString(imc, GCS_RESULTSTR); - imePosition = -1; - e.setCommitString(*imeComposition); - imeComposition->clear(); - } - result = qt_sendSpontaneousEvent(fw, &e); - update(); - releaseContext(fw->effectiveWinId(), imc); - } -#ifdef Q_IME_DEBUG - qDebug("imecomposition: cursor pos at %d, str=%x", imePosition, str[0].unicode()); -#endif - return result; -} - -static HIMC defaultContext = 0; - -// checks whether widget is a popup -inline bool isPopup(QWidget *w) -{ - if (w && (w->windowFlags() & Qt::Popup) == Qt::Popup) - return true; - else - return false; -} -// checks whether widget is in a popup -inline bool isInPopup(QWidget *w) -{ - if (w && (isPopup(w) || isPopup(w->window()))) - return true; - else - return false; -} - -// find the parent widget, which is a non popup toplevel -// this is valid only if the widget is/in a popup -inline QWidget *findParentforPopup(QWidget *w) -{ - QWidget *e = QWidget::find(w->effectiveWinId()); - // check if this or its parent is a popup - while (isInPopup(e)) { - e = e->window()->parentWidget(); - if (!e) - break; - e = QWidget::find(e->effectiveWinId()); - } - if (e) - return e->window(); - else - return 0; -} - -// enables or disables the ime -inline void enableIme(QWidget *w, bool value) -{ - if (value) { - // enable ime - if (defaultContext) - ImmAssociateContext(w->effectiveWinId(), defaultContext); -#ifdef Q_WS_WINCE - if (qApp->autoSipEnabled()) - qt_wince_show_SIP(true); -#endif - } else { - // disable ime - HIMC oldimc = ImmAssociateContext(w->effectiveWinId(), 0); - if (!defaultContext) - defaultContext = oldimc; -#ifdef Q_WS_WINCE - if (qApp->autoSipEnabled()) - qt_wince_show_SIP(false); -#endif - } -} - - -void QWinInputContext::updateImeStatus(QWidget *w, bool hasFocus) -{ - if (!w) - return; - // It's always the proxy that carries the hints. - QWidget *focusProxyWidget = w->focusProxy(); - if (!focusProxyWidget) - focusProxyWidget = w; - bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled() - && !(focusProxyWidget->inputMethodHints() & (Qt::ImhExclusiveInputMask | Qt::ImhHiddenText)); - bool hasIme = e && hasFocus; -#ifdef Q_IME_DEBUG - qDebug("%s HasFocus = %d hasIme = %d e = %d ", w->className(), hasFocus, hasIme, e); -#endif - if (hasFocus || e) { - if (isInPopup(w)) - QWinInputContext::enablePopupChild(w, hasIme); - else - QWinInputContext::enable(w, hasIme); - } -} - -void QWinInputContext::enablePopupChild(QWidget *w, bool e) -{ - if (aimm) { - enable(w, e); - return; - } - - if (!w || !isInPopup(w)) - return; -#ifdef Q_IME_DEBUG - qDebug("enablePopupChild: w=%s, enable = %s", w ? w->className() : "(null)" , e ? "true" : "false"); -#endif - QWidget *parent = findParentforPopup(w); - if (parent) { - // update ime status of the normal toplevel parent of the popup - enableIme(parent, e); - } - QWidget *toplevel = w->window(); - if (toplevel) { - // update ime status of the toplevel popup - enableIme(toplevel, e); - } -} - -void QWinInputContext::enable(QWidget *w, bool e) -{ - if(w) { -#ifdef Q_IME_DEBUG - qDebug("enable: w=%s, enable = %s", w ? w->className() : "(null)" , e ? "true" : "false"); -#endif - if (!w->testAttribute(Qt::WA_WState_Created)) - return; - if(aimm) { - HIMC oldimc; - if (!e) { - aimm->AssociateContext(w->effectiveWinId(), 0, &oldimc); - if (!defaultContext) - defaultContext = oldimc; - } else if (defaultContext) { - aimm->AssociateContext(w->effectiveWinId(), defaultContext, &oldimc); - } - } else { - // update ime status on the widget - QWidget *p = QWidget::find(w->effectiveWinId()); - if (p) - enableIme(p, e); - } - } -} - -void QWinInputContext::setFocusWidget(QWidget *w) -{ - QWidget *oldFocus = focusWidget(); - if (oldFocus == w) - return; - if (w) { - QWinInputContext::updateImeStatus(w, true); - } else { - if (oldFocus) - QWinInputContext::updateImeStatus(oldFocus , false); - } - QInputContext::setFocusWidget(w); - update(); -} - -bool QWinInputContext::isComposing() const -{ - return imeComposition && !imeComposition->isEmpty(); -} - -void QWinInputContext::mouseHandler(int pos, QMouseEvent *e) -{ - if(e->type() != QEvent::MouseButtonPress) - return; - - if (pos < 0 || pos > imeComposition->length()) - reset(); - - // Probably should pass the correct button, but it seems to work fine like this. - DWORD button = MK_LBUTTON; - - QWidget *fw = focusWidget(); - if (fw) { - Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created)); - HIMC himc = getContext(fw->effectiveWinId()); - HWND ime_wnd = getDefaultIMEWnd(fw->effectiveWinId()); - SendMessage(ime_wnd, WM_MSIME_MOUSE, MAKELONG(MAKEWORD(button, pos == 0 ? 2 : 1), pos), (LPARAM)himc); - releaseContext(fw->effectiveWinId(), himc); - } - //qDebug("mouseHandler: got value %d pos=%d", ret,pos); -} - -QString QWinInputContext::language() -{ - return QString(); -} - -int QWinInputContext::reconvertString(RECONVERTSTRING *reconv) -{ - QWidget *w = focusWidget(); - if(!w) - return -1; - - Q_ASSERT(w->testAttribute(Qt::WA_WState_Created)); - QString surroundingText = qvariant_cast(w->inputMethodQuery(Qt::ImSurroundingText)); - int memSize = sizeof(RECONVERTSTRING)+(surroundingText.length()+1)*sizeof(ushort); - // If memory is not allocated, return the required size. - if (!reconv) { - if (surroundingText.isEmpty()) - return -1; - else - return memSize; - } - int pos = qvariant_cast(w->inputMethodQuery(Qt::ImCursorPosition)); - // find the word in the surrounding text. - QTextBoundaryFinder bounds(QTextBoundaryFinder::Word, surroundingText); - bounds.setPosition(pos); - if (bounds.isAtBoundary()) { - if (QTextBoundaryFinder::EndWord == bounds.boundaryReasons()) - bounds.toPreviousBoundary(); - } else { - bounds.toPreviousBoundary(); - } - int startPos = bounds.position(); - bounds.toNextBoundary(); - int endPos = bounds.position(); - // select the text, this will be overwritten by following ime events. - QList attrs; - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, startPos, endPos-startPos, QVariant()); - QInputMethodEvent e(QString(), attrs); - qt_sendSpontaneousEvent(w, &e); - - reconv->dwSize = memSize; - reconv->dwVersion = 0; - - reconv->dwStrLen = surroundingText.length(); - reconv->dwStrOffset = sizeof(RECONVERTSTRING); - reconv->dwCompStrLen = endPos-startPos; - reconv->dwCompStrOffset = startPos*sizeof(ushort); - reconv->dwTargetStrLen = reconv->dwCompStrLen; - reconv->dwTargetStrOffset = reconv->dwCompStrOffset; - memcpy((char*)(reconv+1), surroundingText.utf16(), surroundingText.length()*sizeof(ushort)); - return memSize; -} - -QT_END_NAMESPACE diff --git a/src/widgets/platforms/win/qwinnativepangesturerecognizer_win.cpp b/src/widgets/platforms/win/qwinnativepangesturerecognizer_win.cpp deleted file mode 100644 index 85ef0a949f..0000000000 --- a/src/widgets/platforms/win/qwinnativepangesturerecognizer_win.cpp +++ /dev/null @@ -1,133 +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/qwinnativepangesturerecognizer_win_p.h" - -#include "qevent.h" -#include "qgraphicsitem.h" -#include "qgesture.h" - -#include "private/qgesture_p.h" -#include "private/qevent_p.h" -#include "private/qapplication_p.h" -#include "private/qwidget_p.h" - -#ifndef QT_NO_GESTURES - -QT_BEGIN_NAMESPACE - -#if !defined(QT_NO_NATIVE_GESTURES) - -QWinNativePanGestureRecognizer::QWinNativePanGestureRecognizer() -{ -} - -QGesture *QWinNativePanGestureRecognizer::create(QObject *target) -{ - if (!target) - return new QPanGesture; // a special case - if (!target->isWidgetType()) - return 0; - if (qobject_cast(target)) - return 0; - - QWidget *q = static_cast(target); - QWidgetPrivate *d = q->d_func(); - d->nativeGesturePanEnabled = true; - d->winSetupGestures(); - - return new QPanGesture; -} - -QGestureRecognizer::Result QWinNativePanGestureRecognizer::recognize(QGesture *state, - QObject *, - QEvent *event) -{ - QPanGesture *q = static_cast(state); - QPanGesturePrivate *d = q->d_func(); - - QGestureRecognizer::Result result = QGestureRecognizer::Ignore; - if (event->type() == QEvent::NativeGesture) { - QNativeGestureEvent *ev = static_cast(event); - switch(ev->gestureType) { - case QNativeGestureEvent::GestureBegin: - break; - case QNativeGestureEvent::Pan: - result = QGestureRecognizer::TriggerGesture; - event->accept(); - break; - case QNativeGestureEvent::GestureEnd: - if (q->state() == Qt::NoGesture) - return QGestureRecognizer::Ignore; // some other gesture has ended - result = QGestureRecognizer::FinishGesture; - break; - default: - return QGestureRecognizer::Ignore; - } - if (q->state() == Qt::NoGesture) { - d->lastOffset = d->offset = QPointF(); - d->startPosition = ev->position; - } else { - d->lastOffset = d->offset; - d->offset = QPointF(ev->position.x() - d->startPosition.x(), - ev->position.y() - d->startPosition.y()); - } - } - return result; -} - -void QWinNativePanGestureRecognizer::reset(QGesture *state) -{ - QPanGesture *pan = static_cast(state); - QPanGesturePrivate *d = pan->d_func(); - - d->lastOffset = d->offset = QPointF(); - d->startPosition = QPoint(); - d->acceleration = 0; - - QGestureRecognizer::reset(state); -} - -#endif // QT_NO_NATIVE_GESTURES - -QT_END_NAMESPACE - -#endif // QT_NO_GESTURES diff --git a/src/widgets/platforms/win/qwinnativepangesturerecognizer_win_p.h b/src/widgets/platforms/win/qwinnativepangesturerecognizer_win_p.h deleted file mode 100644 index 4f15a82b7e..0000000000 --- a/src/widgets/platforms/win/qwinnativepangesturerecognizer_win_p.h +++ /dev/null @@ -1,80 +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 QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H -#define QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#ifndef QT_NO_GESTURES - -QT_BEGIN_NAMESPACE - -#if !defined(QT_NO_NATIVE_GESTURES) - -class QWinNativePanGestureRecognizer : public QGestureRecognizer -{ -public: - QWinNativePanGestureRecognizer(); - - QGesture *create(QObject *target); - QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event); - void reset(QGesture *state); -}; - -#endif // QT_NO_NATIVE_GESTURES - -QT_END_NAMESPACE - -#endif // QT_NO_GESTURES - -#endif // QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H 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 -#include -#include -#include -#include -#include "qstyle.h" -#include "qmetaobject.h" -#include "qtimer.h" -#include "qlibrary.h" -#include -#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 -# 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 - -#include - -// Input method stuff -#ifndef QT_NO_IM -#include "qinputcontext.h" -#include "qinputcontextfactory.h" -#endif // QT_NO_IM - -#ifndef QT_NO_XFIXES -#include -#endif // QT_NO_XFIXES - -#include "qt_x11_p.h" -#include "qx11info_x11.h" - -#define XK_MISCELLANY -#include -#if !defined(QT_NO_XINPUT) -#include -#endif - -#include -#include -#include -#include - -#include "qwidget_p.h" - -#include - -#ifdef QT_RX71_MULTITOUCH -# include -# include -# include -#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, x11Filters) - -Q_WIDGETS_EXPORT void qt_installX11EventFilter(QX11FilterFunction func) -{ - Q_ASSERT(func); - - if (QList *list = x11Filters()) - list->append(func); -} - -Q_WIDGETS_EXPORT void qt_removeX11EventFilter(QX11FilterFunction func) -{ - Q_ASSERT(func); - - if (QList *list = x11Filters()) - list->removeOne(func); -} - - -static bool qt_x11EventFilter(XEvent* ev) -{ - long unused; - if (qApp->filterEvent(ev, &unused)) - return true; - if (const QList *list = x11Filters()) { - for (QList::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 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 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(arg); - if (event->type == X11->xfixes_eventbase + XFixesSelectionNotify) { - XFixesSelectionNotifyEvent *xfixes_event = reinterpret_cast(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(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(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(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); - 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; idisplay) - 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(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(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(q_func()->sender())) { - QHash::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(const_cast(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(const_cast(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(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(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(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(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(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(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(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(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(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(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(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(reinterpret_cast(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(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 -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 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 buf(qMax(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 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 - -#ifndef QT_NO_XFIXES -#include -#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 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(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(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(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(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 types; - QStringList formats = QInternalMimeData::formatsHelper(d->source()); - for (int i = 0; i < formats.size(); ++i) { - QList 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 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 -#include - -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 colors; - QVector 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 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 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 -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifndef QT_NO_XCURSOR -# include -#endif // QT_NO_XCURSOR - -#ifndef QT_NO_XFIXES -#ifndef Status -#define Status int -#endif -# include -#endif // QT_NO_XFIXES - -#include "qx11info_x11.h" -#include - -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(cursor_bits16[i]), 16, 16); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast(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(cursor_bits32[i]), 32, 32); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast(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(cursor_bits20[i]), 20, 20); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast(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(open ? openhand_bits : closedhand_bits), 16, 16); - pmm = XCreateBitmapFromData(dpy, rootwin, reinterpret_cast(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 - -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 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 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(mozUri.utf16()), mozUri.length() * 2); - ret = true; - } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) { - QPixmap pm = qvariant_cast(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 QX11Data::xdndMimeAtomsForFormat(const QString &format) -{ - QList 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 - // 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 diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp index 35f022bac4..a2fabde736 100644 --- a/src/widgets/styles/qgtkstyle_p.cpp +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -73,7 +73,6 @@ #include <QtWidgets/QMenuBar> #include <QtWidgets/QToolBar> #include <QtWidgets/QToolButton> -#include <QtWidgets/QX11Info> #include <private/qt_x11_p.h> @@ -947,7 +946,9 @@ void QGtkStylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *p XSetTransientForHint(QGtkStylePrivate::gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), QGtkStylePrivate::gdk_x11_drawable_get_xid(gtkFileChooser->window), modalFor->winId()); +#ifdef Q_WS_X11 QGtkStylePrivate::gdk_x11_window_set_user_time (gtkFileChooser->window, QX11Info::appUserTime()); +#endif } diff --git a/src/widgets/styles/qmotifstyle.cpp b/src/widgets/styles/qmotifstyle.cpp index c1c1ffccd5..a18fc3ba97 100644 --- a/src/widgets/styles/qmotifstyle.cpp +++ b/src/widgets/styles/qmotifstyle.cpp @@ -72,10 +72,6 @@ #include <QtWidgets/qgraphicsproxywidget.h> #include <QtWidgets/qgraphicsview.h> -#ifdef Q_WS_X11 -#include "qx11info_x11.h" -#endif - QT_BEGIN_NAMESPACE // old constants that might still be useful... @@ -2693,13 +2689,9 @@ QMotifStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWidget *w /*! \reimp */ QPalette QMotifStyle::standardPalette() const { -#ifdef Q_WS_X11 QColor background(0xcf, 0xcf, 0xcf); - if (QX11Info::appDepth() <= 8) + if (QPixmap::defaultDepth() <= 8) background = QColor(0xc0, 0xc0, 0xc0); -#else - QColor background = QColor(0xcf, 0xcf, 0xcf); -#endif QColor light = background.lighter(); QColor mid = QColor(0xa6, 0xa6, 0xa6); diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 32fe0ce923..44b8f3bc0f 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -52,10 +52,6 @@ #include "qdebug.h" #endif -#ifdef Q_WS_X11 -#include <qx11info_x11.h> -#endif - #include <limits.h> QT_BEGIN_NAMESPACE @@ -2194,15 +2190,8 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up */ QPalette QStyle::standardPalette() const { -#ifdef Q_WS_X11 - QColor background; - if (QX11Info::appDepth() > 8) - background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey - else - background = QColor(192, 192, 192); -#else - QColor background(0xd4, 0xd0, 0xc8); // win 2000 grey -#endif + QColor background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey + QColor light(background.lighter()); QColor dark(background.darker()); QColor mid(Qt::gray); diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index d876873bd4..4f684869f4 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -11,8 +11,7 @@ SUBDIRS=\ qwindowsurface \ qwsembedwidget \ qwsinputmethod \ - qwswindowsystem \ - qx11info \ + qwswindowsystem # This test cannot be run on Mac OS mac*:SUBDIRS -= \ diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 98b8570b12..4be8a40547 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -65,10 +65,6 @@ #include <qscreen_qws.h> #endif -#ifdef Q_WS_X11 -#include <QX11Info> -#endif - //TESTED_CLASS= //TESTED_FILES= @@ -180,10 +176,8 @@ static bool lenientCompare(const QPixmap &actual, const QPixmap &expected) int size = actual.width() * actual.height(); int threshold = 2; -#ifdef Q_WS_X11 - if (QX11Info::appDepth() == 16) + if (QPixmap::defaultDepth() == 16) threshold = 10; -#endif QRgb *a = (QRgb *)actualImage.bits(); QRgb *e = (QRgb *)expectedImage.bits(); @@ -245,10 +239,8 @@ void tst_QPixmap::swap() void tst_QPixmap::fromImage_data() { bool is16bit = false; -#ifdef Q_WS_X11 - if (QX11Info::appDepth() == 16) + if (QPixmap::defaultDepth() == 16) is16bit = true; -#endif QTest::addColumn<QImage::Format>("format"); diff --git a/tests/auto/qwindowsurface/tst_qwindowsurface.cpp b/tests/auto/qwindowsurface/tst_qwindowsurface.cpp index d7e716b4ab..22a0110423 100644 --- a/tests/auto/qwindowsurface/tst_qwindowsurface.cpp +++ b/tests/auto/qwindowsurface/tst_qwindowsurface.cpp @@ -45,7 +45,6 @@ #include <QPalette> #include <QWindowsStyle> #include <QDesktopWidget> -#include <QX11Info> #if QT_VERSION < 0x050000 #include <private/qwindowsurface_p.h> diff --git a/tests/auto/qx11info/.gitignore b/tests/auto/qx11info/.gitignore deleted file mode 100644 index afe460a3a6..0000000000 --- a/tests/auto/qx11info/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qx11info diff --git a/tests/auto/qx11info/qx11info.pro b/tests/auto/qx11info/qx11info.pro deleted file mode 100644 index e9ad008eb5..0000000000 --- a/tests/auto/qx11info/qx11info.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TARGET = tst_qx11info -QT += widgets testlib -SOURCES += tst_qx11info.cpp - - -mac*:CONFIG+=insignificant_test diff --git a/tests/auto/qx11info/tst_qx11info.cpp b/tests/auto/qx11info/tst_qx11info.cpp deleted file mode 100644 index 6d0476f88e..0000000000 --- a/tests/auto/qx11info/tst_qx11info.cpp +++ /dev/null @@ -1,127 +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 test suite 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 <QtTest/QtTest> -#include <QApplication> -#include <QX11Info> - -class tst_QX11Info : public QObject -{ - Q_OBJECT - -#ifndef Q_WS_X11 -public slots: - void initTestCase(); -#else -private slots: - void staticFunctionsBeforeQApplication(); -#endif -}; - -#ifndef Q_WS_X11 -void tst_QX11Info::initTestCase() -{ - QSKIP("This test is only valid for X11"); -} - -#else - -void tst_QX11Info::staticFunctionsBeforeQApplication() -{ - QVERIFY(!QApplication::instance()); - - // none of these functions should crash if QApplication hasn't - // been constructed - - Display *display = QX11Info::display(); - QCOMPARE(display, (Display *)0); - const char *appClass = QX11Info::appClass(); - QCOMPARE(appClass, (const char *)0); - int appScreen = QX11Info::appScreen(); - QCOMPARE(appScreen, 0); - int appDepth = QX11Info::appDepth(); - QCOMPARE(appDepth, 32); - int appCells = QX11Info::appCells(); - QCOMPARE(appCells, 0); - Qt::HANDLE appColormap = QX11Info::appColormap(); - QCOMPARE(appColormap, static_cast<Qt::HANDLE>(0)); - void *appVisual = QX11Info::appVisual(); - QCOMPARE(appVisual, static_cast<void *>(0)); - Qt::HANDLE appRootWindow = QX11Info::appRootWindow(); - QCOMPARE(appRootWindow, static_cast<Qt::HANDLE>(0)); - - bool appDefaultColormap = QX11Info::appDefaultColormap(); - QCOMPARE(appDefaultColormap, true); - bool appDefaultVisual = QX11Info::appDefaultVisual(); - QCOMPARE(appDefaultVisual, true); - - int appDpiX = QX11Info::appDpiX(); - int appDpiY = QX11Info::appDpiY(); - QCOMPARE(appDpiX, 75); - QCOMPARE(appDpiY, 75); - - // the setAppDpi{X,Y} calls do nothing if QApplication hasn't been - // constructed - QX11Info::setAppDpiX(-1, 120); - QX11Info::setAppDpiY(-1, 120); - appDpiX = QX11Info::appDpiX(); - appDpiY = QX11Info::appDpiY(); - QCOMPARE(appDpiX, 75); - QCOMPARE(appDpiY, 75); - - unsigned long appTime = QX11Info::appTime(); - unsigned long appUserTime = QX11Info::appUserTime(); - QCOMPARE(appTime, 0ul); - QCOMPARE(appTime, 0ul); - // setApp*Time do nothing without QApplication - QX11Info::setAppTime(1234); - QX11Info::setAppUserTime(5678); - appTime = QX11Info::appTime(); - appUserTime = QX11Info::appUserTime(); - QCOMPARE(appTime, 0ul); - QCOMPARE(appTime, 0ul); -} - -#endif - -QTEST_APPLESS_MAIN(tst_QX11Info) -#include "tst_qx11info.moc"