diff options
Diffstat (limited to 'src/plugins')
97 files changed, 7514 insertions, 6229 deletions
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp index 7b30b5d64c..5682d113ef 100644 --- a/src/plugins/bearer/generic/qgenericengine.cpp +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -147,6 +147,9 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf QGenericEngine::QGenericEngine(QObject *parent) : QBearerEngineImpl(parent) { + //workaround for deadlock in __cxa_guard_acquire with webkit on macos x + //initialise the Q_GLOBAL_STATIC in same thread as the AtomicallyInitializedStatic + (void)QNetworkInterface::interfaceFromIndex(0); } QGenericEngine::~QGenericEngine() diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp index f9237e3325..73aa6419d3 100644 --- a/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -62,8 +62,8 @@ QT_BEGIN_NAMESPACE // simple builtin US keymap #include "qevdevkeyboard_defaultmap.h" -QEvdevKeyboardHandler::QEvdevKeyboardHandler(int deviceDescriptor, const QString &device, bool disableZap, bool enableCompose, const QString &keymapFile) - : m_fd(deviceDescriptor), m_device(device), +QEvdevKeyboardHandler::QEvdevKeyboardHandler(int deviceDescriptor, bool disableZap, bool enableCompose, const QString &keymapFile) + : m_fd(deviceDescriptor), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff), m_no_zap(disableZap), m_do_compose(enableCompose), m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0) @@ -136,7 +136,7 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::createLinuxInputKeyboardHandler(co ::ioctl(fd, EVIOCSREP, kbdrep); } - return new QEvdevKeyboardHandler(fd, device, disableZap, enableCompose, keymapFile); + return new QEvdevKeyboardHandler(fd, disableZap, enableCompose, keymapFile); } else { qWarning("Cannot open keyboard input device '%s': %s", qPrintable(device), strerror(errno)); return 0; diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h b/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h index 76b5c5703b..5a1253857f 100644 --- a/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h +++ b/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h @@ -125,7 +125,7 @@ class QEvdevKeyboardHandler : public QObject { Q_OBJECT public: - QEvdevKeyboardHandler(int deviceDescriptor, const QString &device, bool disableZap, bool enableCompose, const QString &keymapFile); + QEvdevKeyboardHandler(int deviceDescriptor, bool disableZap, bool enableCompose, const QString &keymapFile); ~QEvdevKeyboardHandler(); enum KeycodeAction { @@ -174,7 +174,6 @@ private: void switchLed(int, bool); int m_fd; - QString m_device; // keymap handling quint8 m_modifiers; diff --git a/src/plugins/generic/evdevmouse/evdevmouse.pro b/src/plugins/generic/evdevmouse/evdevmouse.pro index 781d901f28..f322a5bd1a 100644 --- a/src/plugins/generic/evdevmouse/evdevmouse.pro +++ b/src/plugins/generic/evdevmouse/evdevmouse.pro @@ -5,12 +5,14 @@ DESTDIR = $$QT.gui.plugins/generic target.path = $$[QT_INSTALL_PLUGINS]/generic INSTALLS += target -HEADERS = qevdevmouse.h +HEADERS = qevdevmousehandler.h \ + qevdevmousemanager.h QT += core-private platformsupport-private SOURCES = main.cpp \ - qevdevmouse.cpp + qevdevmousehandler.cpp \ + qevdevmousemanager.cpp OTHER_FILES += \ evdevmouse.json diff --git a/src/plugins/generic/evdevmouse/main.cpp b/src/plugins/generic/evdevmouse/main.cpp index 47a4ddf56b..b49c183d7b 100644 --- a/src/plugins/generic/evdevmouse/main.cpp +++ b/src/plugins/generic/evdevmouse/main.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include <qgenericplugin_qpa.h> -#include "qevdevmouse.h" +#include "qevdevmousemanager.h" QT_BEGIN_NAMESPACE @@ -71,7 +71,7 @@ QObject* QEvdevMousePlugin::create(const QString &key, const QString &specification) { if (!key.compare(QLatin1String("EvdevMouse"), Qt::CaseInsensitive)) - return new QEvdevMouseHandler(key, specification); + return new QEvdevMouseManager(key, specification); return 0; } diff --git a/src/plugins/generic/evdevmouse/qevdevmouse.cpp b/src/plugins/generic/evdevmouse/qevdevmousehandler.cpp index be779c68a5..1821c2b06b 100644 --- a/src/plugins/generic/evdevmouse/qevdevmouse.cpp +++ b/src/plugins/generic/evdevmouse/qevdevmousehandler.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qevdevmouse.h" +#include "qevdevmousehandler.h" #include <QSocketNotifier> #include <QStringList> @@ -48,7 +48,7 @@ #include <qplatformdefs.h> #include <private/qcore_unix_p.h> // overrides QT_OPEN -#include <QtPlatformSupport/private/qudevhelper_p.h> +#include <QtPlatformSupport/private/qudevicehelper_p.h> #include <errno.h> @@ -57,61 +57,82 @@ #include <qdebug.h> +//#define QT_QPA_MOUSE_HANDLER_DEBUG + QT_BEGIN_NAMESPACE -QEvdevMouseHandler::QEvdevMouseHandler(const QString &key, - const QString &specification) - : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), - m_xoffset(0), m_yoffset(0), m_buttons(0) +QEvdevMouseHandler *QEvdevMouseHandler::createLinuxInputMouseHandler(const QString &key, const QString &specification) { - Q_UNUSED(key); - setObjectName(QLatin1String("Evdev Mouse Handler")); - - QString dev; - q_udev_devicePath(UDev_Mouse | UDev_Touchpad, &dev); - if (dev.isEmpty()) - dev = QLatin1String("/dev/input/event0"); - - m_compression = true; - m_smooth = false; +#ifdef QT_QPA_MOUSE_HANDLER_DEBUG + qWarning() << "Try to create mouse handler with" << key << specification; +#else + Q_UNUSED(key) +#endif + + QString device = "/dev/input/event0"; + bool compression = true; + bool smooth = false; int jitterLimit = 0; + int xoffset = 0; + int yoffset = 0; QStringList args = specification.split(QLatin1Char(':')); foreach (const QString &arg, args) { if (arg == "nocompress") - m_compression = false; + compression = false; else if (arg.startsWith("dejitter=")) jitterLimit = arg.mid(9).toInt(); else if (arg.startsWith("xoffset=")) - m_xoffset = arg.mid(8).toInt(); + xoffset = arg.mid(8).toInt(); else if (arg.startsWith("yoffset=")) - m_yoffset = arg.mid(8).toInt(); + yoffset = arg.mid(8).toInt(); else if (arg.startsWith(QLatin1String("/dev/"))) - dev = arg; + device = arg; } - m_jitterLimitSquared = jitterLimit*jitterLimit; - qDebug("evdevmouse: Using device %s", qPrintable(dev)); - m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); - if (m_fd >= 0) { - m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); - connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); +#ifdef QT_QPA_MOUSE_HANDLER_DEBUG + qDebug("evdevmouse: Using device %s", qPrintable(device)); +#endif + + int fd; + fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); + if (fd >= 0) { + return new QEvdevMouseHandler(fd, compression, smooth, jitterLimit, xoffset, yoffset); } else { - qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno)); - return; + qWarning("Cannot open mouse input device '%s': %s", qPrintable(device), strerror(errno)); + return 0; } } +QEvdevMouseHandler::QEvdevMouseHandler(int deviceDescriptor, bool compression, bool smooth, int jitterLimit, int xoffset, int yoffset) + : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), + m_fd(deviceDescriptor), m_compression(compression), m_smooth(smooth), + m_xoffset(xoffset), m_yoffset(yoffset), m_buttons(0) +{ + setObjectName(QLatin1String("Evdev Mouse Handler")); + + m_jitterLimitSquared = jitterLimit * jitterLimit; + + // socket notifier for events on the mouse device + QSocketNotifier *notifier; + notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(readMouseData())); +} + QEvdevMouseHandler::~QEvdevMouseHandler() { if (m_fd >= 0) - QT_CLOSE(m_fd); + qt_safe_close(m_fd); } void QEvdevMouseHandler::sendMouseEvent() { QPoint pos(m_x + m_xoffset, m_y + m_yoffset); - //qDebug("mouse event %d %d %d", pos.x(), pos.y(), int(m_buttons)); + +#ifdef QT_QPA_MOUSE_HANDLER_DEBUG + qDebug("mouse event %d %d %d", pos.x(), pos.y(), int(m_buttons)); +#endif + QWindowSystemInterface::handleMouseEvent(0, pos, pos, m_buttons); m_prevx = m_x; m_prevy = m_y; diff --git a/src/plugins/generic/evdevmouse/qevdevmouse.h b/src/plugins/generic/evdevmouse/qevdevmousehandler.h index 9542d133f2..7a74eaa701 100644 --- a/src/plugins/generic/evdevmouse/qevdevmouse.h +++ b/src/plugins/generic/evdevmouse/qevdevmousehandler.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QEVDEVMOUSE_H -#define QEVDEVMOUSE_H +#ifndef QEVDEVMOUSEHANDLER_H +#define QEVDEVMOUSEHANDLER_H #include <QObject> #include <QString> @@ -55,25 +55,26 @@ class QEvdevMouseHandler : public QObject { Q_OBJECT public: - QEvdevMouseHandler(const QString &key, const QString &specification); + static QEvdevMouseHandler *createLinuxInputMouseHandler(const QString &key, const QString &specification); ~QEvdevMouseHandler(); private slots: void readMouseData(); private: + QEvdevMouseHandler(int deviceDescriptor, bool compression, bool smooth, int jitterLimit, int xoffset, int yoffset); + void sendMouseEvent(); - void pathFromUdev(QString *path); QSocketNotifier *m_notify; - int m_fd; int m_x, m_y; int m_prevx, m_prevy; - int m_xoffset, m_yoffset; - int m_smoothx, m_smoothy; - Qt::MouseButtons m_buttons; + int m_fd; bool m_compression; bool m_smooth; + int m_xoffset, m_yoffset; + Qt::MouseButtons m_buttons; + int m_smoothx, m_smoothy; int m_jitterLimitSquared; }; @@ -81,4 +82,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QEVDEVMOUSE_H +#endif // QEVDEVMOUSEHANDLER_H diff --git a/src/plugins/generic/evdevmouse/qevdevmousemanager.cpp b/src/plugins/generic/evdevmouse/qevdevmousemanager.cpp new file mode 100644 index 0000000000..f8e77abe55 --- /dev/null +++ b/src/plugins/generic/evdevmouse/qevdevmousemanager.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 "qevdevmousemanager.h" + +#include <QStringList> +#include <QCoreApplication> + +//#define QT_QPA_MOUSEMANAGER_DEBUG + +#ifdef QT_QPA_MOUSEMANAGER_DEBUG +#include <QDebug> +#endif + +QT_BEGIN_NAMESPACE + +QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specification) +{ + Q_UNUSED(key); + + bool useUDev = true; + QStringList args = specification.split(QLatin1Char(':')); + QStringList devices; + + foreach (const QString &arg, args) { + if (arg.startsWith("udev") && arg.contains("no")) { + useUDev = false; + } else if (arg.startsWith("/dev/")) { + // if device is specified try to use it + devices.append(arg); + args.removeAll(arg); + } + } + + // build new specification without /dev/ elements + m_spec = args.join(":"); + + // add all mice for devices specified in the argument list + foreach (const QString &device, devices) + addMouse(device); + + if (useUDev) { +#ifdef QT_QPA_MOUSEMANAGER_DEBUG + qWarning() << "Use UDev for device discovery"; +#endif + + m_udeviceHelper = QUDeviceHelper::createUDeviceHelper(QUDeviceHelper::UDev_Mouse | QUDeviceHelper::UDev_Touchpad, this); + if (m_udeviceHelper) { + // scan and add already connected keyboards + QStringList devices = m_udeviceHelper->scanConnectedDevices(); + foreach (QString device, devices) { + addMouse(device); + } + + connect(m_udeviceHelper, SIGNAL(deviceDetected(QString,QUDeviceTypes)), this, SLOT(addMouse(QString))); + connect(m_udeviceHelper, SIGNAL(deviceRemoved(QString,QUDeviceTypes)), this, SLOT(removeMouse(QString))); + } + } +} + +QEvdevMouseManager::~QEvdevMouseManager() +{ + qDeleteAll(m_mice); + m_mice.clear(); +} + +void QEvdevMouseManager::addMouse(const QString &deviceNode) +{ +#ifdef QT_QPA_MOUSEMANAGER_DEBUG + qWarning() << "Adding mouse at" << deviceNode; +#endif + + QString specification = m_spec; + + if (!deviceNode.isEmpty()) { + specification.append(":"); + specification.append(deviceNode); + } + + QEvdevMouseHandler *handler; + handler = QEvdevMouseHandler::createLinuxInputMouseHandler("EvdevMouse", specification); + if (handler) + m_mice.insert(deviceNode, handler); + else + qWarning("Failed to open mouse"); +} + +void QEvdevMouseManager::removeMouse(const QString &deviceNode) +{ + if (m_mice.contains(deviceNode)) { +#ifdef QT_QPA_MOUSEMANAGER_DEBUG + qWarning() << "Removing mouse at" << deviceNode; +#endif + QEvdevMouseHandler *handler = m_mice.value(deviceNode); + m_mice.remove(deviceNode); + delete handler; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitintegration.h b/src/plugins/generic/evdevmouse/qevdevmousemanager.h index 21ef9efb29..a42257b6a2 100644 --- a/src/plugins/platforms/uikit/quikitintegration.h +++ b/src/plugins/generic/evdevmouse/qevdevmousemanager.h @@ -3,7 +3,7 @@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,34 +39,40 @@ ** ****************************************************************************/ -#ifndef QPLATFORMINTEGRATION_UIKIT_H -#define QPLATFORMINTEGRATION_UIKIT_H +#ifndef QEVDEVMOUSEMANAGER_H +#define QEVDEVMOUSEMANAGER_H -#include <QtGui/QPlatformIntegration> +#include "qevdevmousehandler.h" -QT_BEGIN_NAMESPACE +#include <QtPlatformSupport/private/qudevicehelper_p.h> -class QUIKitIntegration : public QPlatformIntegration -{ -public: - QUIKitIntegration(); - ~QUIKitIntegration(); +#include <QObject> +#include <QHash> +#include <QSocketNotifier> - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; - QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; - QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; +QT_BEGIN_HEADER - QList<QPlatformScreen *> screens() const; +QT_BEGIN_NAMESPACE - QPlatformFontDatabase *fontDatabase() const; +class QEvdevMouseManager : public QObject +{ + Q_OBJECT +public: + explicit QEvdevMouseManager(const QString &key, const QString &specification); + ~QEvdevMouseManager(); - QPlatformEventLoopIntegration *createEventLoopIntegration() const; +private slots: + void addMouse(const QString &deviceNode = QString()); + void removeMouse(const QString &deviceNode); private: - QList<QPlatformScreen *> mScreens; + QString m_spec; + QHash<QString,QEvdevMouseHandler*> m_mice; + QUDeviceHelper *m_udeviceHelper; }; -QT_END_NAMESPACE +QT_END_HEADER -#endif +QT_END_NAMESPACE +#endif // QEVDEVMOUSEMANAGER_H diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.cpp b/src/plugins/generic/evdevtouch/qevdevtouch.cpp index 9e6347457d..b702807cab 100644 --- a/src/plugins/generic/evdevtouch/qevdevtouch.cpp +++ b/src/plugins/generic/evdevtouch/qevdevtouch.cpp @@ -46,7 +46,7 @@ #include <QGuiApplication> #include <QDebug> #include <QtCore/private/qcore_unix_p.h> -#include <QtPlatformSupport/private/qudevhelper_p.h> +#include <QtPlatformSupport/private/qudevicehelper_p.h> #include <linux/input.h> #ifdef USE_MTDEV @@ -146,7 +146,17 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec) setObjectName(QLatin1String("Evdev Touch Handler")); QString dev; - q_udev_devicePath(UDev_Touchpad | UDev_Touchscreen, &dev); + + // try to let udev scan for already connected devices + QScopedPointer<QUDeviceHelper> udeviceHelper(QUDeviceHelper::createUDeviceHelper(QUDeviceHelper::UDev_Touchpad | QUDeviceHelper::UDev_Touchscreen, this)); + if (udeviceHelper) { + QStringList devices = udeviceHelper->scanConnectedDevices(); + + // only the first device found is used for now + if (devices.size() > 0) + dev = devices[0]; + } + if (dev.isEmpty()) dev = QLatin1String("/dev/input/event0"); diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index b953210720..e861f48e7b 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -27,10 +27,15 @@ OBJECTIVE_SOURCES += main.mm \ qcocoafiledialoghelper.mm \ qcocoafontdialoghelper.mm \ qcocoacursor.mm \ + qcocoaclipboard.mm \ qcocoadrag.mm \ qmacclipboard.mm \ qmacmime.mm \ qcocoasystemsettings.mm \ + qcocoainputcontext.mm \ + qpaintengine_mac.mm \ + qprintengine_mac.mm \ + qcocoaprintersupport.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -55,17 +60,22 @@ HEADERS += qcocoaintegration.h \ qcocoafiledialoghelper.h \ qcocoafontdialoghelper.h \ qcocoacursor.h \ + qcocoaclipboard.h \ qcocoadrag.h \ qmacclipboard.h \ qmacmime.h \ qcocoasystemsettings.h \ + qcocoainputcontext.h \ + qpaintengine_mac_p.h \ + qprintengine_mac_p.h \ + qcocoaprintersupport.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui RESOURCES += qcocoaresources.qrc LIBS += -framework Cocoa -QT += core-private gui-private widgets-private platformsupport-private +QT += core-private gui-private widgets-private platformsupport-private printsupport OTHER_FILES += cocoa.json target.path += $$[QT_INSTALL_PLUGINS]/platforms diff --git a/src/plugins/platforms/uikit/quikitscreen.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h index e53589b2c7..27505058bf 100644 --- a/src/plugins/platforms/uikit/quikitscreen.h +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h @@ -39,37 +39,32 @@ ** ****************************************************************************/ -#ifndef QUIKITSCREEN_H -#define QUIKITSCREEN_H +#ifndef QCOCOACLIPBOARD_H +#define QCOCOACLIPBOARD_H -#include <UIKit/UIKit.h> - -#include <QtGui/QPlatformScreen> +#include <qplatformclipboard_qpa.h> +#include "qmacclipboard.h" +#include <QtCore/QScopedPointer> QT_BEGIN_NAMESPACE -class QUIKitScreen : public QPlatformScreen +class QCocoaClipboard : public QPlatformClipboard { public: - QUIKitScreen(int screenIndex); - ~QUIKitScreen(); - - QRect geometry() const { return m_geometry; } - int depth() const { return m_depth; } - QImage::Format format() const { return m_format; } - QSizeF physicalSize() const { return m_physicalSize; } + QCocoaClipboard(); - UIScreen *uiScreen() const; + QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard); + void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard); + bool supportsMode(QClipboard::Mode mode) const; + bool ownsMode(QClipboard::Mode mode) const; +protected: + QMacPasteboard *pasteboardForMode(QClipboard::Mode mode) const; private: - QRect m_geometry; - int m_depth; - QImage::Format m_format; - QSizeF m_physicalSize; - int m_index; + QScopedPointer<QMacPasteboard> m_clipboard; + QScopedPointer<QMacPasteboard> m_find; }; QT_END_NAMESPACE - #endif diff --git a/src/plugins/platforms/uikit/main.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm index db413c0775..799fb85183 100644 --- a/src/plugins/platforms/uikit/main.mm +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm @@ -39,36 +39,55 @@ ** ****************************************************************************/ -#include <UIKit/UIKit.h> - -#include <QtGui/QPlatformIntegrationPlugin> -#include "quikitintegration.h" +#include "QCocoaclipboard.h" +#include "qmacmime.h" +#include "qmacclipboard.h" QT_BEGIN_NAMESPACE -class QUIKitIntegrationPlugin : public QPlatformIntegrationPlugin +QCocoaClipboard::QCocoaClipboard() + :m_clipboard(new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP)) + ,m_find(new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP)) { -public: - QStringList keys() const; - QPlatformIntegration *create(const QString&, const QStringList&); -}; -QStringList QUIKitIntegrationPlugin::keys() const +} + +QMimeData *QCocoaClipboard::mimeData(QClipboard::Mode mode) { - QStringList list; - list << "UIKit"; - return list; + if (QMacPasteboard *pasteBoard = pasteboardForMode(mode)) { + pasteBoard->sync(); + return pasteBoard->mimeData(); + } + return 0; } -QPlatformIntegration * QUIKitIntegrationPlugin::create(const QString& system, const QStringList& paramList) +void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) { - Q_UNUSED(paramList); - if (system.toLower() == "uikit") - return new QUIKitIntegration; + if (QMacPasteboard *pasteBoard = pasteboardForMode(mode)) { + pasteBoard->sync(); + pasteBoard->setMimeData(data); + emitChanged(mode); + } +} - return 0; +bool QCocoaClipboard::supportsMode(QClipboard::Mode mode) const +{ + return (mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer); +} + +bool QCocoaClipboard::ownsMode(QClipboard::Mode mode) const +{ + return false; } -Q_EXPORT_PLUGIN2(UIKit, QUIKitIntegrationPlugin) +QMacPasteboard *QCocoaClipboard::pasteboardForMode(QClipboard::Mode mode) const +{ + if (mode == QClipboard::Clipboard) + return m_clipboard.data(); + else if (mode == QClipboard::FindBuffer) + return m_find.data(); + else + return 0; +} QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 3e3e8fa507..5113aca3f7 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -74,6 +74,15 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm); NSSize qt_mac_toNSSize(const QSize &qtSize); +QColor qt_mac_toQColor(const NSColor *color); + +// Creates a mutable shape, it's the caller's responsibility to release. +HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion); + +OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage); + +CGFloat qt_mac_get_scalefactor(); + QChar qt_mac_qtKey2CocoaKey(Qt::Key key); Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index ec4399b66c..60590b966e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -132,11 +132,46 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm) return qt_mac_cgimage_to_nsimage(qt_mac_image_to_cgimage(image)); } +HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion) +{ + HIMutableShapeRef shape = HIShapeCreateMutable(); + QVector<QRect> rects = region.rects(); + if (!rects.isEmpty()) { + int n = rects.count(); + const QRect *qt_r = rects.constData(); + while (n--) { + CGRect cgRect = CGRectMake(qt_r->x(), qt_r->y(), qt_r->width(), qt_r->height()); + HIShapeUnionWithRect(shape, &cgRect); + ++qt_r; + } + } + return shape; +} + NSSize qt_mac_toNSSize(const QSize &qtSize) { return NSMakeSize(qtSize.width(), qtSize.height()); } +QColor qt_mac_toQColor(const NSColor *color) +{ + QColor qtColor; + NSString *colorSpace = [color colorSpaceName]; + if (colorSpace == NSDeviceCMYKColorSpace) { + CGFloat cyan, magenta, yellow, black, alpha; + [color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha]; + qtColor.setCmykF(cyan, magenta, yellow, black, alpha); + } else { + NSColor *tmpColor; + tmpColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace]; + CGFloat red, green, blue, alpha; + [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha]; + qtColor.setRgbF(red, green, blue, alpha); + } + return qtColor; +} + + // Use this method to keep all the information in the TextSegment. As long as it is ordered // we are in OK shape, and we can influence that ourselves. struct KeyPair @@ -519,4 +554,31 @@ NSRect qt_mac_flipRect(const QRect &rect, QWindow *window) return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); } +OSStatus qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBounds, CGImageRef inImage) +{ + // Verbatim copy if HIViewDrawCGImage (as shown on Carbon-Dev) + OSStatus err = noErr; + + require_action(inContext != NULL, InvalidContext, err = paramErr); + require_action(inBounds != NULL, InvalidBounds, err = paramErr); + require_action(inImage != NULL, InvalidImage, err = paramErr); + + CGContextSaveGState( inContext ); + CGContextTranslateCTM (inContext, 0, inBounds->origin.y + CGRectGetMaxY(*inBounds)); + CGContextScaleCTM(inContext, 1, -1); + + CGContextDrawImage(inContext, *inBounds, inImage); + + CGContextRestoreGState(inContext); +InvalidImage: +InvalidBounds: +InvalidContext: + return err; +} + +CGFloat qt_mac_get_scalefactor() +{ + return [[NSScreen mainScreen] userSpaceScaleFactor]; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h b/src/plugins/platforms/cocoa/qcocoainputcontext.h index b4627c15ff..172c87e2dc 100644 --- a/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.h @@ -1,5 +1,3 @@ - - /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). @@ -41,21 +39,32 @@ ** ****************************************************************************/ -#ifndef QUIKITSOFTWAREINPUTHANDLER_H -#define QUIKITSOFTWAREINPUTHANDLER_H +#ifndef QCOCOAINPUTCONTEXT_H +#define QCOCOAINPUTCONTEXT_H -#include <QtCore/QObject> +#include <QtGui/QPlatformInputContext> +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE -class QUIKitSoftwareInputHandler : public QObject +class QCocoaInputContext : public QPlatformInputContext { Q_OBJECT - public: - bool eventFilter(QObject *obj, QEvent *event); + explicit QCocoaInputContext(); + ~QCocoaInputContext(); + + virtual bool isValid() const { return true; } + + virtual void reset(); + +private Q_SLOTS: + void inputItemChanged(); + +private: + QPointer<QWindow> mWindow; }; QT_END_NAMESPACE -#endif +#endif // QCOCOAINPUTCONTEXT_H diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm new file mode 100644 index 0000000000..db3488a0f5 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 "qnsview.h" +#include "qcocoainputcontext.h" +#include "qcocoanativeinterface.h" +#include "qcocoaautoreleasepool.h" + +#include <QtCore/QRect> +#include <QtGui/QGuiApplication> +#include <QtGui/QWindow> + +QT_BEGIN_NAMESPACE + +/*! + \class QCocoaInputContext + \brief Cocoa Input context implementation + + Handles input of foreign characters (particularly East Asian) + languages. + + \section1 Testing + + \list + \o Select input sources like 'Kotoeri' in Language & Text Preferences + \o Compile the \a mainwindows/mdi example and open a text window. + \o In the language bar, switch to 'Hiragana'. + \o In a text editor control, type the syllable \a 'la'. + Underlined characters show up, indicating that there is completion + available. Press the Space key two times. A completion popup occurs + which shows the options. + \endlist + + \section1 Interaction + + Input method support in Cocoa uses NSTextInput protorol. Therefore + almost all functionality is implemented in QNSView. + + \ingroup qt-lighthouse-cocoa +*/ + + + +QCocoaInputContext::QCocoaInputContext() + : QPlatformInputContext() + , mWindow(QGuiApplication::focusWindow()) +{ + connect(qApp->inputMethod(), SIGNAL(inputItemChanged()), this, SLOT(inputItemChanged())); +} + +QCocoaInputContext::~QCocoaInputContext() +{ +} + +/*! + \brief Cancels a composition. +*/ + +void QCocoaInputContext::reset() +{ + QPlatformInputContext::reset(); + + if (!mWindow) return; + + QCocoaNativeInterface *nativeInterface = qobject_cast<QCocoaNativeInterface *>(QGuiApplication::platformNativeInterface()); + if (!nativeInterface) return; + + QNSView *view = static_cast<QNSView *>(nativeInterface->nativeResourceForWindow("nsview", mWindow)); + if (!view) return; + + QCocoaAutoReleasePool pool; + NSInputManager *currentIManager = [NSInputManager currentInputManager]; + if (currentIManager) { + [currentIManager markedTextAbandoned:view]; + [view unmarkText]; + } +} + +void QCocoaInputContext::inputItemChanged() +{ + mWindow = QGuiApplication::focusWindow(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index bf54915365..97e7a7ffde 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -46,6 +46,7 @@ #include "qcocoaautoreleasepool.h" #include "qcocoacursor.h" +#include "qcocoaclipboard.h" #include "qcocoadrag.h" #include <QtCore/QScopedPointer> @@ -89,18 +90,24 @@ public: QPlatformFontDatabase *fontDatabase() const; QPlatformNativeInterface *nativeInterface() const; + QPlatformInputContext *inputContext() const; QPlatformAccessibility *accessibility() const; + QPlatformClipboard *clipboard() const; QPlatformDrag *drag() const; - QPlatformTheme *platformTheme() const; + QStringList themeNames() const; + QPlatformTheme *createPlatformTheme(const QString &name) const; + private: QScopedPointer<QPlatformFontDatabase> mFontDb; QAbstractEventDispatcher *mEventDispatcher; + QScopedPointer<QPlatformInputContext> mInputContext; QScopedPointer<QPlatformAccessibility> mAccessibility; QScopedPointer<QPlatformTheme> mPlatformTheme; QList<QCocoaScreen *> mScreens; + QCocoaClipboard *mCocoaClipboard; QScopedPointer<QCocoaDrag> mCocoaDrag; }; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 8411a795c1..f5febd4a16 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -52,6 +52,7 @@ #include "qmenu_mac.h" #include "qcocoafiledialoghelper.h" #include "qcocoatheme.h" +#include "qcocoainputcontext.h" #include "qmacmime.h" #include <QtGui/qplatformaccessibility_qpa.h> @@ -90,8 +91,9 @@ QCocoaScreen::~QCocoaScreen() QCocoaIntegration::QCocoaIntegration() : mFontDb(new QCoreTextFontDatabase()) , mEventDispatcher(new QCocoaEventDispatcher()) + , mInputContext(new QCocoaInputContext) , mAccessibility(new QPlatformAccessibility) - , mPlatformTheme(new QCocoaTheme) + , mCocoaClipboard(new QCocoaClipboard) , mCocoaDrag(new QCocoaDrag) { QCocoaAutoReleasePool pool; @@ -139,13 +141,19 @@ QCocoaIntegration::QCocoaIntegration() screenAdded(screen); } - QMacPasteboardMime::initialize(); + QMacPasteboardMime::initializeMimeTypes(); } QCocoaIntegration::~QCocoaIntegration() { [[NSApplication sharedApplication] setDelegate: 0]; + // Delete the clipboard integration and destroy mime type converters. + // Deleting the clipboard integration flushes promised pastes using + // the mime converters - the ordering here is important. + delete mCocoaClipboard; + QMacPasteboardMime::destroyMimeTypes(); + // Delete screens in reverse order to avoid crash in case of multiple screens while (!mScreens.isEmpty()) { delete mScreens.takeLast(); @@ -195,19 +203,36 @@ QPlatformNativeInterface *QCocoaIntegration::nativeInterface() const return new QCocoaNativeInterface(); } +QPlatformInputContext *QCocoaIntegration::inputContext() const +{ + return mInputContext.data(); +} + QPlatformAccessibility *QCocoaIntegration::accessibility() const { return mAccessibility.data(); } +QPlatformClipboard *QCocoaIntegration::clipboard() const +{ + return mCocoaClipboard; +} + QPlatformDrag *QCocoaIntegration::drag() const { return mCocoaDrag.data(); } -QPlatformTheme *QCocoaIntegration::platformTheme() const +QStringList QCocoaIntegration::themeNames() const +{ + return QStringList(QLatin1String(QCocoaTheme::name)); +} + +QPlatformTheme *QCocoaIntegration::createPlatformTheme(const QString &name) const { - return mPlatformTheme.data(); + if (name == QLatin1String(QCocoaTheme::name)) + return new QCocoaTheme; + return QPlatformIntegration::createPlatformTheme(name); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 7c6fb38577..8856e90cf3 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -43,13 +43,34 @@ #define QCOCOANATIVEINTERFACE_H #include <QtGui/QPlatformNativeInterface> +#include <QtPrintSupport/QPlatformPrinterSupport> class QWidget; class QCocoaNativeInterface : public QPlatformNativeInterface { + Q_OBJECT public: void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); + +private: + /* + "Virtual" function to create the platform printer support + implementation. + + We use an invokable function instead of a virtual one, we do not want + this in the QPlatform* API yet. + + This was added here only because QPlatformNativeInterface is a QObject + and allow us to use QMetaObject::indexOfMethod() from the printsupport + plugin. + */ + Q_INVOKABLE QPlatformPrinterSupport *createPlatformPrinterSupport(); + /* + Function to return the NSPrintInfo * from QMacPaintEnginePrivate. + Needed by the native print dialog in the QtPrintSupport library. + */ + Q_INVOKABLE void *NSPrintInfoForPrintEngine(QPrintEngine *printEngine); }; #endif // QCOCOANATIVEINTERFACE_H diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 443369df75..29c2e58959 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -42,6 +42,8 @@ #include "qcocoanativeinterface.h" #include "qcocoaglcontext.h" #include "qcocoawindow.h" +#include "qcocoaprintersupport.h" + #include <qbytearray.h> #include <qwindow.h> #include "qplatformwindow_qpa.h" @@ -50,6 +52,8 @@ #include "qopenglcontext.h" #include <qdebug.h> +#include "qprintengine_mac_p.h" + void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { if (!window->handle()) { @@ -66,3 +70,14 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS } return 0; } + +QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport() +{ + return new QCocoaPrinterSupport(); +} + +void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine) +{ + QMacPrintEngine *macPrintEngine = static_cast<QMacPrintEngine *>(printEngine); + return macPrintEngine->d_func()->printInfo; +} diff --git a/src/plugins/platforms/uikit/quikiteventloop.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index e7f503c42a..db473dfabb 100644 --- a/src/plugins/platforms/uikit/quikiteventloop.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -3,7 +3,7 @@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtPrintSupport module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,34 +39,22 @@ ** ****************************************************************************/ -#ifndef QUIKITEVENTLOOP_H -#define QUIKITEVENTLOOP_H +#ifndef QCOCOAPRINTERSUPPORT_H +#define QCOCOAPRINTERSUPPORT_H -#include "quikitsoftwareinputhandler.h" +#include <QtPrintSupport/QPlatformPrinterSupport> -#include <QtCore/QEvent> -#include <QtGui/QPlatformEventLoopIntegration> - -@class EventLoopHelper; -@class NSTimer; - -QT_BEGIN_NAMESPACE - -class QUIKitEventLoop : public QPlatformEventLoopIntegration +class QCocoaPrinterSupport : public QPlatformPrinterSupport { public: - QUIKitEventLoop(); - ~QUIKitEventLoop(); + QCocoaPrinterSupport(); + ~QCocoaPrinterSupport(); - void startEventLoop(); - void quitEventLoop(); - void qtNeedsToProcessEvents(); + Q_DECL_OVERRIDE QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); + Q_DECL_OVERRIDE QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode); + Q_DECL_OVERRIDE QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const; - EventLoopHelper *mHelper; - NSTimer *mTimer; - QUIKitSoftwareInputHandler *mInputHandler; + Q_DECL_OVERRIDE QList<QPrinterInfo> availablePrinters(); }; -QT_END_NAMESPACE - -#endif +#endif // QCOCOAPRINTERSUPPORT_H diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm new file mode 100644 index 0000000000..6653c81a4a --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtPrintSupport 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 "qcocoaprintersupport.h" +#include "qprintengine_mac_p.h" + +#include <QtPrintSupport/QPrinter> +#include <QtPrintSupport/QPrinterInfo> + +QCocoaPrinterSupport::QCocoaPrinterSupport() +{ } + +QCocoaPrinterSupport::~QCocoaPrinterSupport() +{ } + +QPrintEngine *QCocoaPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode printerMode) +{ + return new QMacPrintEngine(printerMode); +} + +QPaintEngine *QCocoaPrinterSupport::createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode printerMode) +{ + Q_UNUSED(printerMode); + /* + QMacPrintEngine multiply inherits from QPrintEngine and QPaintEngine, + the cast here allows conversion of QMacPrintEngine* to QPaintEngine* + */ + return static_cast<QMacPrintEngine *>(printEngine); +} + +QList<QPrinter::PaperSize> QCocoaPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const +{ + QList<QPrinter::PaperSize> returnValue; + if (printerInfo.isNull()) + return returnValue; + + PMPrinter printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(printerInfo.printerName())); + if (!printer) + return returnValue; + + CFArrayRef array; + if (PMPrinterGetPaperList(printer, &array) != noErr) { + PMRelease(printer); + return returnValue; + } + + CFIndex count = CFArrayGetCount(array); + for (CFIndex i = 0; i < count; ++i) { + PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(array, i))); + double width, height; + if (PMPaperGetWidth(paper, &width) == noErr + && PMPaperGetHeight(paper, &height) == noErr) { + // width and height are in points, convertQSizeFToPaperSize() expects millimeters + static const double OnePointInMillimeters = 1.0 / 72.0 * 25.4; + QSizeF size(width * OnePointInMillimeters, height * OnePointInMillimeters); + returnValue += QPlatformPrinterSupport::convertQSizeFToPaperSize(size); + } + } + + PMRelease(printer); + + return returnValue; +} + +QList<QPrinterInfo> QCocoaPrinterSupport::availablePrinters() +{ + QList<QPrinterInfo> returnValue; + QCFType<CFArrayRef> printerList; + if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i = 0; i < count; ++i) { + PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i))); + QString printerName = QCFString::toQString(PMPrinterGetName(printer)); + returnValue += QPlatformPrinterSupport::printerInfo(printerName, PMPrinterIsDefault(printer)); + } + } + return returnValue; +} diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index 030db1822c..5cb6f7437d 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -64,6 +64,9 @@ public: const QFont *font(Font type = SystemFont) const; QVariant themeHint(ThemeHint hint) const; + + static const char *name; + private: mutable QPalette *m_systemPalette; mutable QHash<QPlatformTheme::Palette, QPalette*> m_palettes; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 8ec6e3801e..d17ee30096 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -49,6 +49,8 @@ QT_BEGIN_NAMESPACE +const char *QCocoaTheme::name = "cocoa"; + QCocoaTheme::QCocoaTheme() :m_systemPalette(0) { diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index ba56a8991d..8bdb5535d5 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -49,17 +49,17 @@ #include "qcocoaglcontext.h" #include "qnsview.h" +class QCocoaWindow; @interface QNSWindow : NSWindow { - + @public QCocoaWindow *m_cocoaPlatformWindow; } - (BOOL)canBecomeKeyWindow; - @end @interface QNSPanel : NSPanel { - + @public QCocoaWindow *m_cocoaPlatformWindow; } - (BOOL)canBecomeKeyWindow; @end @@ -93,6 +93,7 @@ public: void setGeometry(const QRect &rect); void setVisible(bool visible); + Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); void setWindowTitle(const QString &title); void raise(); void lower(); @@ -101,8 +102,11 @@ public: bool setMouseGrabEnabled(bool grab); WId winId() const; + void setParent(const QPlatformWindow *window); + NSView *contentView() const; + void windowWillMove(); void windowDidMove(); void windowDidResize(); void windowWillClose(); @@ -111,8 +115,12 @@ public: QCocoaGLContext *currentContext() const; protected: - void determineWindowClass(); - NSWindow *createWindow(); + // NSWindow handling. The QCocoaWindow/QNSView can either be displayed + // in an existing NSWindow or in one created by Qt. + NSWindow *createNSWindow(); + void setNSWindow(NSWindow *window); + void clearNSWindow(NSWindow *window); + QRect windowGeometry() const; QCocoaWindow *parentCocoaWindow() const; @@ -123,9 +131,9 @@ public: // for QNSView QNSView *m_contentView; QNSWindow *m_nsWindow; + Qt::WindowFlags m_windowFlags; + QPointer<QWindow> m_activePopupWindow; - quint32 m_windowAttributes; - quint32 m_windowClass; bool m_inConstructor; QCocoaGLContext *m_glContext; }; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 3f566ccb44..5c30e7f38b 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -58,73 +58,56 @@ - (BOOL)canBecomeKeyWindow { - // The default implementation returns NO for title-bar less windows, // override and return yes here to make sure popup windows such as // the combobox popup can become the key window. return YES; } +- (BOOL)canBecomeMainWindow +{ + BOOL canBecomeMain = YES; // By default, windows can become the main window + + // Windows with a transient parent (such as combobox popup windows) + // cannot become the main window: + if (m_cocoaPlatformWindow->window()->transientParent()) + canBecomeMain = NO; + + return canBecomeMain; +} + + @end @implementation QNSPanel - (BOOL)canBecomeKeyWindow { - return YES; + return NO; } @end QCocoaWindow::QCocoaWindow(QWindow *tlw) : QPlatformWindow(tlw) - , m_windowAttributes(0) - , m_windowClass(0) , m_glContext(0) , m_inConstructor(true) { QCocoaAutoReleasePool pool; - determineWindowClass(); - m_nsWindow = createWindow(); - - QNSWindowDelegate *delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this]; - [m_nsWindow setDelegate:delegate]; - [m_nsWindow setAcceptsMouseMovedEvents:YES]; - - // Prevent Cocoa from releasing the window on close. Qt - // handles the close event asynchronously and we want to - // make sure that m_nsWindow stays valid until the - // QCocoaWindow is deleted by Qt. - [m_nsWindow setReleasedWhenClosed : NO]; - m_contentView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; - - [[NSNotificationCenter defaultCenter] addObserver:m_contentView - selector:@selector(windowDidBecomeKey) - name:NSWindowDidBecomeKeyNotification - object:m_nsWindow]; - - [[NSNotificationCenter defaultCenter] addObserver:m_contentView - selector:@selector(windowDidResignKey) - name:NSWindowDidResignKeyNotification - object:m_nsWindow]; - - // ### Accept touch events by default. - // Beware that enabling touch events has a negative impact on the overall performance. - // We probably need a QWindowSystemInterface API to enable/disable touch events. - [m_contentView setAcceptsTouchEvents:YES]; - setGeometry(tlw->geometry()); - [m_nsWindow setContentView:m_contentView]; + m_nsWindow = createNSWindow(); + setNSWindow(m_nsWindow); + m_inConstructor = false; } QCocoaWindow::~QCocoaWindow() { - [[NSNotificationCenter defaultCenter] removeObserver:m_contentView]; [m_contentView release]; + clearNSWindow(m_nsWindow); [m_nsWindow release]; } @@ -146,23 +129,44 @@ void QCocoaWindow::setVisible(bool visible) { QCocoaAutoReleasePool pool; #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QCocoaWindow::setVisible" << this << visible; + qDebug() << "QCocoaWindow::setVisible" << window() << visible; #endif if (visible) { - // The parent window might have moved while this window was hidden, - // update the window geometry if there is a parent. - if (window()->transientParent()) + if (window()->transientParent()) { + // The parent window might have moved while this window was hidden, + // update the window geometry if there is a parent. setGeometry(window()->geometry()); + // Register popup windows so that the parent window can + // close them when needed. + if (window()->windowType() == Qt::Popup) { + // qDebug() << "transientParent and popup" << window()->windowType() << Qt::Popup << (window()->windowType() & Qt::Popup); + + QCocoaWindow *parentCocoaWindow = static_cast<QCocoaWindow *>(window()->transientParent()->handle()); + parentCocoaWindow->m_activePopupWindow = window(); + } + + } + // Make sure the QWindow has a frame ready before we show the NSWindow. QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size())); - [m_nsWindow makeKeyAndOrderFront:nil]; + if ([m_nsWindow canBecomeKeyWindow]) + [m_nsWindow makeKeyAndOrderFront:nil]; + else + [m_nsWindow orderFront: nil]; } else { - [m_nsWindow orderOut:nil]; + // qDebug() << "close" << this; + [m_nsWindow orderOut:m_nsWindow]; } } +Qt::WindowFlags QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) +{ + m_windowFlags = flags; + return m_windowFlags; +} + void QCocoaWindow::setWindowTitle(const QString &title) { QCocoaAutoReleasePool pool; @@ -174,13 +178,14 @@ void QCocoaWindow::setWindowTitle(const QString &title) void QCocoaWindow::raise() { + //qDebug() << "raise" << this; // ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm) [m_nsWindow orderFront: m_nsWindow]; } void QCocoaWindow::lower() { - [m_nsWindow orderFront: m_nsWindow]; + [m_nsWindow orderBack: m_nsWindow]; } void QCocoaWindow::propagateSizeHints() @@ -229,11 +234,31 @@ WId QCocoaWindow::winId() const return WId(m_nsWindow); } +void QCocoaWindow::setParent(const QPlatformWindow *window) +{ + // recreate the window for compatibility + clearNSWindow(m_nsWindow); + [m_nsWindow close]; + [m_nsWindow release]; + + m_nsWindow = createNSWindow(); + setNSWindow(m_nsWindow); +} + NSView *QCocoaWindow::contentView() const { return [m_nsWindow contentView]; } +void QCocoaWindow::windowWillMove() +{ + // Close any open popups on window move + if (m_activePopupWindow) { + QWindowSystemInterface::handleSynchronousCloseEvent(m_activePopupWindow); + m_activePopupWindow = 0; + } +} + void QCocoaWindow::windowDidMove() { [m_contentView updateGeometry]; @@ -261,156 +286,95 @@ QCocoaGLContext *QCocoaWindow::currentContext() const return m_glContext; } -/* - Determine the window class based on the window type and - window flags, and widget attr Sets m_windowAttributes - and m_windowClass. -*/ -void QCocoaWindow::determineWindowClass() +NSWindow * QCocoaWindow::createNSWindow() { + QCocoaAutoReleasePool pool; + + NSRect frame = qt_mac_flipRect(window()->geometry(), window()); + Qt::WindowType type = window()->windowType(); Qt::WindowFlags flags = window()->windowFlags(); - const bool popup = (type == Qt::Popup); - - if (type == Qt::ToolTip || type == Qt::SplashScreen || popup) - flags |= Qt::FramelessWindowHint; - - m_windowClass = kSheetWindowClass; - - if (popup || type == Qt::SplashScreen) - m_windowClass = kModalWindowClass; - else if (type == Qt::ToolTip) - m_windowClass = kHelpWindowClass; - else if (type == Qt::Tool) - m_windowClass = kFloatingWindowClass; - else - m_windowClass = kDocumentWindowClass; - - m_windowAttributes = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute); - -// if(qt_mac_is_macsheet(window())) { -// m_windowClass = kSheetWindowClass; -// } else - - { - // Shift things around a bit to get the correct window class based on the presence - // (or lack) of the border. - - bool customize = flags & Qt::CustomizeWindowHint; - bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint))); - if (framelessWindow) { - if (m_windowClass == kDocumentWindowClass) { - m_windowAttributes |= kWindowNoTitleBarAttribute; - } else if (m_windowClass == kFloatingWindowClass) { - m_windowAttributes |= kWindowNoTitleBarAttribute; - } else if (m_windowClass == kMovableModalWindowClass) { - m_windowClass = kModalWindowClass; - } - } else { - m_windowAttributes |= NSTitledWindowMask; - if (m_windowClass != kModalWindowClass) - m_windowAttributes |= NSResizableWindowMask; - } + NSUInteger styleMask; + NSWindow *createdWindow = 0; - // Only add extra decorations (well, buttons) for widgets that can have them - // and have an actual border we can put them on. - - if(m_windowClass != kModalWindowClass && m_windowClass != kMovableModalWindowClass - && m_windowClass != kSheetWindowClass && m_windowClass != kPlainWindowClass - && !framelessWindow && m_windowClass != kDrawerWindowClass - && m_windowClass != kHelpWindowClass) { - if (flags & Qt::WindowMinimizeButtonHint) - m_windowAttributes |= NSMiniaturizableWindowMask; - if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint) - m_windowAttributes |= NSClosableWindowMask; + // Use NSPanel for popup-type windows. (Popup, Tool, ToolTip, SplashScreen) + if ((type & Qt::Popup) == Qt::Popup) { + if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::SplashScreen) { + styleMask = NSBorderlessWindowMask; } else { - // Clear these hints so that we aren't call them on invalid windows - flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint - | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint); + styleMask = (NSUtilityWindowMask | NSResizableWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSTitledWindowMask); } + QNSPanel *window; + window = [[QNSPanel alloc] initWithContentRect:frame + styleMask: styleMask + backing:NSBackingStoreBuffered + defer:NO]; // Deferring window creation breaks OpenGL (the GL context is set up + // before the window is shown and needs a proper window.). + [window setHasShadow:YES]; + createdWindow = window; + } else { + styleMask = (NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask); + QNSWindow *window; + window = [[QNSWindow alloc] initWithContentRect:frame + styleMask: styleMask + backing:NSBackingStoreBuffered + defer:NO]; // Deferring window creation breaks OpenGL (the GL context is set up + // before the window is shown and needs a proper window.). + window->m_cocoaPlatformWindow = this; + createdWindow = window; } - - if((popup || type == Qt::Tool) && !window()->isModal()) - m_windowAttributes |= kWindowHideOnSuspendAttribute; - m_windowAttributes |= kWindowLiveResizeAttribute; + return createdWindow; } -/* - -*/ -NSWindow * QCocoaWindow::createWindow() +void QCocoaWindow::setNSWindow(NSWindow *window) { - // Determine if we need to add in our "custom window" attribute. Cocoa is rather clever - // in deciding if we need the maximize button or not (i.e., it's resizable, so you - // must need a maximize button). So, the only buttons we have control over are the - // close and minimize buttons. If someone wants to customize and NOT have the maximize - // button, then we have to do our hack. We only do it for these cases because otherwise - // the window looks different when activated. This "QtMacCustomizeWindow" attribute is - // intruding on a public space and WILL BREAK in the future. - // One can hope that there is a more public API available by that time. -/* - Qt::WindowFlags flags = widget ? widget->windowFlags() : Qt::WindowFlags(0); - if ((flags & Qt::CustomizeWindowHint)) { - if ((flags & (Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint - | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint)) - && !(flags & Qt::WindowMaximizeButtonHint)) - wattr |= QtMacCustomizeWindow; - } -*/ - NSRect frame = qt_mac_flipRect(window()->geometry(), window()); - QCocoaAutoReleasePool pool; - NSWindow *window; - - switch (m_windowClass) { - case kMovableModalWindowClass: - case kModalWindowClass: - case kSheetWindowClass: - case kFloatingWindowClass: - case kOverlayWindowClass: - case kHelpWindowClass: { - NSPanel *panel; - - BOOL needFloating = NO; - //BOOL worksWhenModal = (this->window()->windowType() == Qt::Popup); - - // Add in the extra flags if necessary. - switch (m_windowClass) { - case kSheetWindowClass: - m_windowAttributes |= NSDocModalWindowMask; - break; - case kFloatingWindowClass: - case kHelpWindowClass: - needFloating = YES; - m_windowAttributes |= NSUtilityWindowMask; - break; - default: - break; - } + QNSWindowDelegate *delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this]; + [window setDelegate:delegate]; + [window setAcceptsMouseMovedEvents:YES]; - panel = [[QNSPanel alloc] initWithContentRect:frame - styleMask:m_windowAttributes - backing:NSBackingStoreBuffered - defer:NO]; // see window case below -// ### crashes -// [panel setFloatingPanel:needFloating]; -// [panel setWorksWhenModal:worksWhenModal]; - window = static_cast<NSWindow *>(panel); - break; - } - default: - window = [[QNSWindow alloc] initWithContentRect:frame - styleMask:(NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask) - backing:NSBackingStoreBuffered - defer:NO]; // Deferring window creation breaks OpenGL (the GL context is set up - // before the window is shown and needs a proper window.). - break; - } + // Prevent Cocoa from releasing the window on close. Qt + // handles the close event asynchronously and we want to + // make sure that m_nsWindow stays valid until the + // QCocoaWindow is deleted by Qt. + [window setReleasedWhenClosed : NO]; - //qt_syncCocoaTitleBarButtons(window, widget); - return window; + [[NSNotificationCenter defaultCenter] addObserver:m_contentView + selector:@selector(windowDidBecomeKey) + name:NSWindowDidBecomeKeyNotification + object:m_nsWindow]; + + [[NSNotificationCenter defaultCenter] addObserver:m_contentView + selector:@selector(windowDidResignKey) + name:NSWindowDidResignKeyNotification + object:m_nsWindow]; + + [[NSNotificationCenter defaultCenter] addObserver:m_contentView + selector:@selector(windowDidBecomeMain) + name:NSWindowDidBecomeMainNotification + object:m_nsWindow]; + + [[NSNotificationCenter defaultCenter] addObserver:m_contentView + selector:@selector(windowDidResignMain) + name:NSWindowDidResignMainNotification + object:m_nsWindow]; + + + // ### Accept touch events by default. + // Beware that enabling touch events has a negative impact on the overall performance. + // We probably need a QWindowSystemInterface API to enable/disable touch events. + [m_contentView setAcceptsTouchEvents:YES]; + + [window setContentView:m_contentView]; +} + +void QCocoaWindow::clearNSWindow(NSWindow *window) +{ + [[NSNotificationCenter defaultCenter] removeObserver:m_contentView]; } + // Returns the current global screen geometry for the nswindow associated with this window. QRect QCocoaWindow::windowGeometry() const { diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index d5af6de69c..eff2c5b07a 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -63,106 +63,6 @@ QT_USE_NAMESPACE *****************************************************************************/ //#define DEBUG_PASTEBOARD -#ifndef QT_NO_CLIPBOARD - -/***************************************************************************** - QClipboard member functions for mac. - *****************************************************************************/ - -static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0}; - -static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode) -{ - Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer); - if (mode == QClipboard::Clipboard) - return qt_mac_pasteboards[0]; - else - return qt_mac_pasteboards[1]; -} - -static void qt_mac_cleanupPasteboard() { - delete qt_mac_pasteboards[0]; - delete qt_mac_pasteboards[1]; - qt_mac_pasteboards[0] = 0; - qt_mac_pasteboards[1] = 0; -} - -static bool qt_mac_updateScrap(QClipboard::Mode mode) -{ - if (!qt_mac_pasteboards[0]) { - qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP); - qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP); - qAddPostRoutine(qt_mac_cleanupPasteboard); - return true; - } - return qt_mac_pasteboard(mode)->sync(); -} - -void QClipboard::clear(Mode mode) -{ - if (!supportsMode(mode)) - return; - qt_mac_updateScrap(mode); - qt_mac_pasteboard(mode)->clear(); - setMimeData(0, mode); -} - -void QClipboard::ownerDestroyed() -{ -} - - -void QClipboard::connectNotify(const char *signal) -{ - Q_UNUSED(signal); -} - -bool QClipboard::event(QEvent *e) -{ - if (e->type() != QEvent::Clipboard) - return QObject::event(e); - - if (qt_mac_updateScrap(QClipboard::Clipboard)) { - emitChanged(QClipboard::Clipboard); - } - - if (qt_mac_updateScrap(QClipboard::FindBuffer)) { - emitChanged(QClipboard::FindBuffer); - } - - return QObject::event(e); -} - -const QMimeData *QClipboard::mimeData(Mode mode) const -{ - if (!supportsMode(mode)) - return 0; - qt_mac_updateScrap(mode); - return qt_mac_pasteboard(mode)->mimeData(); -} - -void QClipboard::setMimeData(QMimeData *src, Mode mode) -{ - if (!supportsMode(mode)) - return; - qt_mac_updateScrap(mode); - qt_mac_pasteboard(mode)->setMimeData(src); - emitChanged(mode); -} - -bool QClipboard::supportsMode(Mode mode) const -{ - return (mode == Clipboard || mode == FindBuffer); -} - -bool QClipboard::ownsMode(Mode mode) const -{ - Q_UNUSED(mode); - return false; -} - -#endif // QT_NO_CLIPBOARD - /***************************************************************************** QMacPasteboard code *****************************************************************************/ diff --git a/src/plugins/platforms/cocoa/qmacmime.h b/src/plugins/platforms/cocoa/qmacmime.h index 842caa5f2f..7226caef28 100644 --- a/src/plugins/platforms/cocoa/qmacmime.h +++ b/src/plugins/platforms/cocoa/qmacmime.h @@ -58,7 +58,8 @@ public: explicit QMacPasteboardMime(char); virtual ~QMacPasteboardMime(); - static void initialize(); + static void initializeMimeTypes(); + static void destroyMimeTypes(); static QList<QMacPasteboardMime*> all(uchar); static QMacPasteboardMime *convertor(uchar, const QString &mime, QString flav); diff --git a/src/plugins/platforms/cocoa/qmacmime.mm b/src/plugins/platforms/cocoa/qmacmime.mm index db86deb91c..8cb684fbea 100644 --- a/src/plugins/platforms/cocoa/qmacmime.mm +++ b/src/plugins/platforms/cocoa/qmacmime.mm @@ -64,14 +64,6 @@ extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage typedef QList<QMacPasteboardMime*> MimeList; Q_GLOBAL_STATIC(MimeList, globalMimeList) - -static void cleanup_mimes() -{ - MimeList *mimes = globalMimeList(); - while (!mimes->isEmpty()) - delete mimes->takeFirst(); -} - Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList) /*! @@ -791,11 +783,9 @@ QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, This is an internal function. */ -void QMacPasteboardMime::initialize() +void QMacPasteboardMime::initializeMimeTypes() { if (globalMimeList()->isEmpty()) { - qAddPostRoutine(cleanup_mimes); - //standard types that we wrap new QMacPasteboardMimeTiff; new QMacPasteboardMimeUnicodeText; @@ -811,6 +801,16 @@ void QMacPasteboardMime::initialize() } /*! + \internal +*/ +void QMacPasteboardMime::destroyMimeTypes() +{ + MimeList *mimes = globalMimeList(); + while (!mimes->isEmpty()) + delete mimes->takeFirst(); +} + +/*! Returns the most-recently created QMacPasteboardMime of type \a t that can convert between the \a mime and \a flav formats. Returns 0 if no such convertor exists. diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 1a1a1cd3b9..f09c9331f6 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -44,6 +44,7 @@ #include <Cocoa/Cocoa.h> +#include <QtCore/QPointer> #include <QtGui/QImage> #include <QtGui/QAccessible> @@ -51,12 +52,14 @@ QT_BEGIN_NAMESPACE class QCocoaWindow; QT_END_NAMESPACE -@interface QNSView : NSView { +@interface QNSView : NSView <NSTextInput> { CGImageRef m_cgImage; QWindow *m_window; QCocoaWindow *m_platformWindow; Qt::MouseButtons m_buttons; QAccessibleInterface *m_accessibleRoot; + QString m_composingText; + bool m_keyEventsAccepted; QStringList *currentCustomDragTypes; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9ed3332ba5..a28c5959ce 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -51,6 +51,7 @@ #include "qcocoadrag.h" #include <QtGui/QWindowSystemInterface> +#include <QtGui/QTextFormat> #include <QtCore/QDebug> #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR @@ -94,6 +95,7 @@ static QTouchDevice *touchDevice = 0; m_window = window; m_platformWindow = platformWindow; m_accessibleRoot = 0; + m_keyEventsAccepted = false; #ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR // prevent rift in space-time continuum, disable @@ -144,14 +146,27 @@ static QTouchDevice *touchDevice = 0; - (void)windowDidBecomeKey { - QWindowSystemInterface::handleWindowActivated(m_window); +// QWindowSystemInterface::handleWindowActivated(m_window); } - (void)windowDidResignKey { +// QWindowSystemInterface::handleWindowActivated(0); +} + +- (void)windowDidBecomeMain +{ +// qDebug() << "window did become main" << m_window; + QWindowSystemInterface::handleWindowActivated(m_window); +} + +- (void)windowDidResignMain +{ +// qDebug() << "window did resign main" << m_window; QWindowSystemInterface::handleWindowActivated(0); } + - (void) setImage:(QImage *)image { CGImageRelease(m_cgImage); @@ -266,14 +281,24 @@ static QTouchDevice *touchDevice = 0; qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); } ulong timestamp = [theEvent timestamp] * 1000; - QWindowSystemInterface::handleMouseEvent(m_window, timestamp, qtWindowPoint, qtScreenPoint, m_buttons); } - (void)mouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::LeftButton; - [self handleMouseEvent:theEvent]; + if (m_platformWindow->m_activePopupWindow) { + QWindowSystemInterface::handleSynchronousCloseEvent(m_platformWindow->m_activePopupWindow); + m_platformWindow->m_activePopupWindow = 0; + } + if ([self hasMarkedText]) { + NSInputManager* inputManager = [NSInputManager currentInputManager]; + if ([inputManager wantsToHandleMouseEvents]) { + [inputManager handleMouseEvent:theEvent]; + } + } else { + m_buttons |= Qt::LeftButton; + [self handleMouseEvent:theEvent]; + } } - (void)mouseDragged:(NSEvent *)theEvent @@ -327,7 +352,53 @@ static QTouchDevice *touchDevice = 0; - (void)otherMouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::RightButton; + switch ([theEvent buttonNumber]) { + case 3: + m_buttons |= Qt::MiddleButton; + break; + case 4: + m_buttons |= Qt::ExtraButton1; // AKA Qt::BackButton + break; + case 5: + m_buttons |= Qt::ExtraButton2; // AKA Qt::ForwardButton + break; + case 6: + m_buttons |= Qt::ExtraButton3; + break; + case 7: + m_buttons |= Qt::ExtraButton4; + break; + case 8: + m_buttons |= Qt::ExtraButton5; + break; + case 9: + m_buttons |= Qt::ExtraButton6; + break; + case 10: + m_buttons |= Qt::ExtraButton7; + break; + case 11: + m_buttons |= Qt::ExtraButton8; + break; + case 12: + m_buttons |= Qt::ExtraButton9; + break; + case 13: + m_buttons |= Qt::ExtraButton10; + break; + case 14: + m_buttons |= Qt::ExtraButton11; + break; + case 15: + m_buttons |= Qt::ExtraButton12; + break; + case 16: + m_buttons |= Qt::ExtraButton13; + break; + default: + m_buttons |= Qt::MiddleButton; + break; + } [self handleMouseEvent:theEvent]; } @@ -340,7 +411,53 @@ static QTouchDevice *touchDevice = 0; - (void)otherMouseUp:(NSEvent *)theEvent { - m_buttons &= QFlag(~int(Qt::MiddleButton)); + switch ([theEvent buttonNumber]) { + case 3: + m_buttons &= QFlag(~int(Qt::MiddleButton)); + break; + case 4: + m_buttons &= QFlag(~int(Qt::ExtraButton1)); // AKA Qt::BackButton + break; + case 5: + m_buttons &= QFlag(~int(Qt::ExtraButton2)); // AKA Qt::ForwardButton + break; + case 6: + m_buttons &= QFlag(~int(Qt::ExtraButton3)); + break; + case 7: + m_buttons &= QFlag(~int(Qt::ExtraButton4)); + break; + case 8: + m_buttons &= QFlag(~int(Qt::ExtraButton5)); + break; + case 9: + m_buttons &= QFlag(~int(Qt::ExtraButton6)); + break; + case 10: + m_buttons &= QFlag(~int(Qt::ExtraButton7)); + break; + case 11: + m_buttons &= QFlag(~int(Qt::ExtraButton8)); + break; + case 12: + m_buttons &= QFlag(~int(Qt::ExtraButton9)); + break; + case 13: + m_buttons &= QFlag(~int(Qt::ExtraButton10)); + break; + case 14: + m_buttons &= QFlag(~int(Qt::ExtraButton11)); + break; + case 15: + m_buttons &= QFlag(~int(Qt::ExtraButton12)); + break; + case 16: + m_buttons &= QFlag(~int(Qt::ExtraButton13)); + break; + default: + m_buttons &= QFlag(~int(Qt::MiddleButton)); + break; + } [self handleMouseEvent:theEvent]; } @@ -467,12 +584,228 @@ static QTouchDevice *touchDevice = 0; - (void)keyDown:(NSEvent *)theEvent { - [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; + QObject *fo = QGuiApplication::focusObject(); + m_keyEventsAccepted = false; + if (fo) { + QInputMethodQueryEvent queryEvent(Qt::ImHints); + if (QCoreApplication::sendEvent(fo, &queryEvent)) { + Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt()); + if (!(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) { + [self interpretKeyEvents:[NSArray arrayWithObject: theEvent]]; + } + } + } + + if (!m_keyEventsAccepted && m_composingText.isEmpty()) { + [self handleKeyEvent : theEvent eventType :int(QEvent::KeyPress)]; + } } - (void)keyUp:(NSEvent *)theEvent { - [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; + if (!m_keyEventsAccepted && m_composingText.isEmpty()) { + [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; + } +} + +- (void) doCommandBySelector:(SEL)aSelector +{ + [self tryToPerform:aSelector with:self]; +} + +- (void) insertText:(id)aString +{ + QString commitString; + if ([aString length]) { + if ([aString isKindOfClass:[NSAttributedString class]]) { + commitString = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); + } else { + commitString = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); + }; + } + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e; + e.setCommitString(commitString); + QCoreApplication::sendEvent(fo, &e); + m_keyEventsAccepted = true; + } + + m_composingText.clear(); + } + +- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange +{ + QString preeditString; + + QList<QInputMethodEvent::Attribute> attrs; + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selRange.location + selRange.length, 1, QVariant()); + + if ([aString isKindOfClass:[NSAttributedString class]]) { + // Preedit string has attribution + preeditString = QCFString::toQString(reinterpret_cast<CFStringRef>([aString string])); + int composingLength = preeditString.length(); + int index = 0; + // Create attributes for individual sections of preedit text + while (index < composingLength) { + NSRange effectiveRange; + NSRange range = NSMakeRange(index, composingLength-index); + NSDictionary *attributes = [aString attributesAtIndex:index + longestEffectiveRange:&effectiveRange + inRange:range]; + NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName]; + if (underlineStyle) { + QColor clr (Qt::black); + NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName]; + if (color) { + clr = qt_mac_toQColor(color); + } + QTextCharFormat format; + format.setFontUnderline(true); + format.setUnderlineColor(clr); + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, + effectiveRange.location, + effectiveRange.length, + format); + } + index = effectiveRange.location + effectiveRange.length; + } + } else { + // No attributes specified, take only the preedit text. + preeditString = QCFString::toQString(reinterpret_cast<CFStringRef>(aString)); + } + + if (attrs.isEmpty()) { + QTextCharFormat format; + format.setFontUnderline(true); + attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, + 0, preeditString.length(), format); + } + + m_composingText = preeditString; + + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e(preeditString, attrs); + QCoreApplication::sendEvent(fo, &e); + m_keyEventsAccepted = true; + } +} + +- (void) unmarkText +{ + if (!m_composingText.isEmpty()) { + QObject *fo = QGuiApplication::focusObject(); + if (fo) { + QInputMethodEvent e; + e.setCommitString(m_composingText); + QCoreApplication::sendEvent(fo, &e); + } + } + m_composingText.clear(); +} + +- (BOOL) hasMarkedText +{ + return (m_composingText.isEmpty() ? NO: YES); +} + +- (NSInteger) conversationIdentifier +{ + return (NSInteger)self; +} + +- (NSAttributedString *) attributedSubstringFromRange:(NSRange)theRange +{ + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return nil; + QInputMethodQueryEvent queryEvent(Qt::ImCurrentSelection); + if (!QCoreApplication::sendEvent(fo, &queryEvent)) + return nil; + + QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString(); + if (selectedText.isEmpty()) + return nil; + + QCFString string(selectedText.mid(theRange.location, theRange.length)); + const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string); + return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease]; +} + +- (NSRange) markedRange +{ + NSRange range; + if (!m_composingText.isEmpty()) { + range.location = 0; + range.length = m_composingText.length(); + } else { + range.location = NSNotFound; + range.length = 0; + } + return range; +} + + +- (NSRange) selectedRange +{ + NSRange selRange = {NSNotFound, 0}; + selRange.location = NSNotFound; + selRange.length = 0; + + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return selRange; + QInputMethodQueryEvent queryEvent(Qt::ImCurrentSelection); + if (!QCoreApplication::sendEvent(fo, &queryEvent)) + return selRange; + QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString(); + + if (!selectedText.isEmpty()) { + selRange.location = 0; + selRange.length = selectedText.length(); + } + return selRange; +} + +- (NSRect) firstRectForCharacterRange:(NSRange)theRange +{ + Q_UNUSED(theRange); + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return NSZeroRect; + + if (!m_window) + return NSZeroRect; + + // The returned rect is always based on the internal cursor. + QRect mr = qApp->inputMethod()->cursorRectangle().toRect(); + QPoint mp = m_window->mapToGlobal(mr.bottomLeft()); + + NSRect rect; + rect.origin.x = mp.x(); + rect.origin.y = qt_mac_flipYCoordinate(mp.y()); + rect.size.width = mr.width(); + rect.size.height = mr.height(); + return rect; +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint +{ + // We dont support cursor movements using mouse while composing. + Q_UNUSED(thePoint); + return NSNotFound; +} + +- (NSArray*) validAttributesForMarkedText +{ + QObject *fo = QGuiApplication::focusObject(); + if (!fo) + return nil; + + // Support only underline color/style. + return [NSArray arrayWithObjects:NSUnderlineColorAttributeName, + NSUnderlineStyleAttributeName, nil]; } -(void)registerDragTypes diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index a0e98e0ed1..2548fb4a9d 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -64,6 +64,14 @@ } } +- (void)windowWillMove:(NSNotification *)notification +{ + Q_UNUSED(notification); + if (m_cocoaWindow) { + m_cocoaWindow->windowWillMove(); + } +} + - (void)windowDidMove:(NSNotification *)notification { Q_UNUSED(notification); diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm new file mode 100644 index 0000000000..8b8445c995 --- /dev/null +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -0,0 +1,1788 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 "qpaintengine_mac_p.h" +#include "qprintengine_mac_p.h" + +#include <qbitmap.h> +#include <qpaintdevice.h> +#include <qpainterpath.h> +#include <qpixmapcache.h> +#include <private/qpaintengine_raster_p.h> +#include <qprinter.h> +#include <qstack.h> +#include <qtextcodec.h> +#include <qwidget.h> +#include <qvarlengtharray.h> +#include <qdebug.h> +#include <qcoreapplication.h> +#include <qmath.h> + +#include <QtGui/qplatformpixmap_qpa.h> + +#include <private/qfont_p.h> +#include <private/qfontengine_p.h> +#include <private/qfontengine_coretext_p.h> +#include <private/qnumeric_p.h> +#include <private/qpainter_p.h> +#include <private/qpainterpath_p.h> +#include <private/qtextengine_p.h> +#include <private/qwidget_p.h> + +#include "qcocoahelpers.h" + +#include <string.h> + +QT_BEGIN_NAMESPACE + +extern int qt_antialiasing_threshold; // from qcoretextfontdatabase.mm + +/***************************************************************************** + QCoreGraphicsPaintEngine utility functions + *****************************************************************************/ + +void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform) +{ + CGAffineTransform old_xform = CGAffineTransformIdentity; + if (orig_xform) { //setup xforms + old_xform = CGContextGetCTM(hd); + CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); + CGContextConcatCTM(hd, *orig_xform); + } + + //do the clipping + CGContextBeginPath(hd); + if (rgn.isEmpty()) { + CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); + } else { +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { + QCFType<HIMutableShapeRef> shape = qt_mac_QRegionToHIMutableShape(rgn); + Q_ASSERT(!HIShapeIsEmpty(shape)); + HIShapeReplacePathInCGContext(shape, hd); + } else +#endif + { + QVector<QRect> rects = rgn.rects(); + const int count = rects.size(); + for (int i = 0; i < count; i++) { + const QRect &r = rects[i]; + CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); + CGContextAddRect(hd, mac_r); + } + } + + } + CGContextClip(hd); + + if (orig_xform) {//reset xforms + CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); + CGContextConcatCTM(hd, old_xform); + } +} + +CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) +{ + bool isWidget = (paintDevice->devType() == QInternal::Widget); + return QCoreGraphicsPaintEngine::macDisplayColorSpace(isWidget ? static_cast<const QWidget *>(paintDevice) + : 0); +} + +// Implemented for qt_mac_p.h +QMacCGContext::QMacCGContext(QPainter *p) +{ + QPaintEngine *pe = p->paintEngine(); + if (pe->type() == QPaintEngine::MacPrinter) + pe = static_cast<QMacPrintEngine*>(pe)->paintEngine(); + pe->syncState(); + context = 0; + if (pe->type() == QPaintEngine::CoreGraphics) + context = static_cast<QCoreGraphicsPaintEngine*>(pe)->handle(); + + int devType = p->device()->devType(); + if (pe->type() == QPaintEngine::Raster + && (devType == QInternal::Widget || devType == QInternal::Pixmap || devType == QInternal::Image)) { + + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pe->paintDevice()); + uint flags = kCGImageAlphaPremultipliedFirst; +#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version + flags |= kCGBitmapByteOrder32Host; +#endif + const QImage *image = (const QImage *) pe->paintDevice(); + + context = CGBitmapContextCreate((void *) image->bits(), image->width(), image->height(), + 8, image->bytesPerLine(), colorspace, flags); + + CGContextTranslateCTM(context, 0, image->height()); + CGContextScaleCTM(context, 1, -1); + + if (devType == QInternal::Widget) { + QRegion clip = p->paintEngine()->systemClip(); + QTransform native = p->deviceTransform(); + QTransform logical = p->combinedTransform(); + + if (p->hasClipping()) { + QRegion r = p->clipRegion(); + r.translate(native.dx(), native.dy()); + if (clip.isEmpty()) + clip = r; + else + clip &= r; + } + qt_mac_clip_cg(context, clip, 0); + + CGContextTranslateCTM(context, native.dx(), native.dy()); + } + } else { + CGContextRetain(context); + } +} + +void qt_mac_cgimage_data_free(void *, const void *memoryToFree, size_t) +{ + free(const_cast<void *>(memoryToFree)); +} + +CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr) +{ + QImage image = pixmap.toImage(); + if (image.format() != QImage::Format_ARGB32_Premultiplied) + image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + const int sx = qRound(sr.x()), sy = qRound(sr.y()), sw = qRound(sr.width()), sh = qRound(sr.height()); + const int sbpr = image.bytesPerLine(); + const uint nbytes = sw * sh; + // alpha is always 255 for bitmaps, ignore it in this case. + const quint32 mask = pixmap.depth() == 1 ? 0x00ffffff : 0xffffffff; + quint8 *dptr = static_cast<quint8 *>(malloc(nbytes)); + quint32 *sptr = reinterpret_cast<quint32 *>(image.scanLine(0)), *srow; + for (int y = sy, offset=0; y < sh; ++y) { + srow = sptr + (y * (sbpr / 4)); + for (int x = sx; x < sw; ++x) + *(dptr+(offset++)) = (*(srow+x) & mask) ? 255 : 0; + } + QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, dptr, nbytes, qt_mac_cgimage_data_free); + return CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, 0, 0); +} + +//conversion +inline static float qt_mac_convert_color_to_cg(int c) { return ((float)c * 1000 / 255) / 1000; } +inline static int qt_mac_convert_color_from_cg(float c) { return qRound(c * 255); } +CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) { + return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy()); +} + +/*! \internal + + Returns the CoreGraphics CGContextRef of the paint device. 0 is + returned if it can't be obtained. It is the caller's responsibility to + CGContextRelease the context when finished using it. + + \warning This function is only available on Mac OS X. + \warning This function is duplicated in qmacstyle_mac.mm +*/ +CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) +{ + if (pdev->devType() == QInternal::Pixmap) { + const QPixmap *pm = static_cast<const QPixmap*>(pdev); + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); + uint flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; + CGContextRef ret = 0; + + QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data(); + if (data->classId() == QPlatformPixmap::RasterClass) { + QImage *image = data->buffer(); + ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), + 8, image->bytesPerLine(), colorspace, flags); + } else { + qDebug() << "qt_mac_cg_context: Unsupported pixmap class"; + } + + CGContextTranslateCTM(ret, 0, pm->height()); + CGContextScaleCTM(ret, 1, -1); + return ret; + } else if (pdev->devType() == QInternal::Widget) { + //CGContextRef ret = static_cast<CGContextRef>(static_cast<const QWidget *>(pdev)->macCGHandle()); + ///CGContextRetain(ret); + //return ret; + qDebug() << "qt_mac_cg_context: not implemented: Widget class"; + return 0; + } + return 0; +} + +inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevice *pdev) +{ + CGFloat components[] = { + qt_mac_convert_color_to_cg(col.red()), + qt_mac_convert_color_to_cg(col.green()), + qt_mac_convert_color_to_cg(col.blue()), + qt_mac_convert_color_to_cg(col.alpha()) + }; + return CGColorCreate(qt_mac_colorSpaceForDeviceType(pdev), components); +} + +// There's architectural problems with using native gradients +// on the Mac at the moment, so disable them. +// #define QT_MAC_USE_NATIVE_GRADIENTS + +#ifdef QT_MAC_USE_NATIVE_GRADIENTS +static bool drawGradientNatively(const QGradient *gradient) +{ + return gradient->spread() == QGradient::PadSpread; +} + +// gradiant callback +static void qt_mac_color_gradient_function(void *info, const CGFloat *in, CGFloat *out) +{ + QBrush *brush = static_cast<QBrush *>(info); + Q_ASSERT(brush && brush->gradient()); + + const QGradientStops stops = brush->gradient()->stops(); + const int n = stops.count(); + Q_ASSERT(n >= 1); + const QGradientStop *begin = stops.constBegin(); + const QGradientStop *end = begin + n; + + qreal p = in[0]; + const QGradientStop *i = begin; + while (i != end && i->first < p) + ++i; + + QRgb c; + if (i == begin) { + c = begin->second.rgba(); + } else if (i == end) { + c = (end - 1)->second.rgba(); + } else { + const QGradientStop &s1 = *(i - 1); + const QGradientStop &s2 = *i; + qreal p1 = s1.first; + qreal p2 = s2.first; + QRgb c1 = s1.second.rgba(); + QRgb c2 = s2.second.rgba(); + int idist = 256 * (p - p1) / (p2 - p1); + int dist = 256 - idist; + c = qRgba(INTERPOLATE_PIXEL_256(qRed(c1), dist, qRed(c2), idist), + INTERPOLATE_PIXEL_256(qGreen(c1), dist, qGreen(c2), idist), + INTERPOLATE_PIXEL_256(qBlue(c1), dist, qBlue(c2), idist), + INTERPOLATE_PIXEL_256(qAlpha(c1), dist, qAlpha(c2), idist)); + } + + out[0] = qt_mac_convert_color_to_cg(qRed(c)); + out[1] = qt_mac_convert_color_to_cg(qGreen(c)); + out[2] = qt_mac_convert_color_to_cg(qBlue(c)); + out[3] = qt_mac_convert_color_to_cg(qAlpha(c)); +} +#endif + +//clipping handling +void QCoreGraphicsPaintEnginePrivate::resetClip() +{ + static bool inReset = false; + if (inReset) + return; + inReset = true; + + CGAffineTransform old_xform = CGContextGetCTM(hd); + + //setup xforms + CGContextConcatCTM(hd, CGAffineTransformInvert(old_xform)); + while (stackCount > 0) { + restoreGraphicsState(); + } + saveGraphicsState(); + inReset = false; + //reset xforms + CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); + CGContextConcatCTM(hd, old_xform); +} + +static CGRect qt_mac_compose_rect(const QRectF &r, float off=0) +{ + return CGRectMake(r.x()+off, r.y()+off, r.width(), r.height()); +} + +static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0) +{ + CGMutablePathRef ret = CGPathCreateMutable(); + QPointF startPt; + for (int i=0; i<p.elementCount(); ++i) { + const QPainterPath::Element &elm = p.elementAt(i); + switch (elm.type) { + case QPainterPath::MoveToElement: + if (i > 0 + && p.elementAt(i - 1).x == startPt.x() + && p.elementAt(i - 1).y == startPt.y()) + CGPathCloseSubpath(ret); + startPt = QPointF(elm.x, elm.y); + CGPathMoveToPoint(ret, 0, elm.x+off, elm.y+off); + break; + case QPainterPath::LineToElement: + CGPathAddLineToPoint(ret, 0, elm.x+off, elm.y+off); + break; + case QPainterPath::CurveToElement: + Q_ASSERT(p.elementAt(i+1).type == QPainterPath::CurveToDataElement); + Q_ASSERT(p.elementAt(i+2).type == QPainterPath::CurveToDataElement); + CGPathAddCurveToPoint(ret, 0, + elm.x+off, elm.y+off, + p.elementAt(i+1).x+off, p.elementAt(i+1).y+off, + p.elementAt(i+2).x+off, p.elementAt(i+2).y+off); + i+=2; + break; + default: + qFatal("QCoreGraphicsPaintEngine::drawPath(), unhandled type: %d", elm.type); + break; + } + } + if (!p.isEmpty() + && p.elementAt(p.elementCount() - 1).x == startPt.x() + && p.elementAt(p.elementCount() - 1).y == startPt.y()) + CGPathCloseSubpath(ret); + return ret; +} + +CGColorSpaceRef QCoreGraphicsPaintEngine::m_genericColorSpace = 0; +QHash<CGDirectDisplayID, CGColorSpaceRef> QCoreGraphicsPaintEngine::m_displayColorSpaceHash; +bool QCoreGraphicsPaintEngine::m_postRoutineRegistered = false; + +CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace() +{ +#if 0 + if (!m_genericColorSpace) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + } else +#endif + { + m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); + } + if (!m_postRoutineRegistered) { + m_postRoutineRegistered = true; + qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); + } + } + return m_genericColorSpace; +#else + // Just return the main display colorspace for the moment. + return macDisplayColorSpace(); +#endif +} + +/* + Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. + to support multiple displays correctly. +*/ +CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *widget) +{ + CGColorSpaceRef colorSpace; + + CGDirectDisplayID displayID; + CMProfileRef displayProfile = 0; + if (widget == 0) { + displayID = CGMainDisplayID(); + } else { + const QRect &qrect = widget->window()->geometry(); + CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); + CGDisplayCount throwAway; + CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); + if (dErr != kCGErrorSuccess) + return macDisplayColorSpace(0); // fall back on main display + } + if ((colorSpace = m_displayColorSpaceHash.value(displayID))) + return colorSpace; + + CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile); + if (err == noErr) { + colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile); + } else if (widget) { + return macDisplayColorSpace(0); // fall back on main display + } + + if (colorSpace == 0) + colorSpace = CGColorSpaceCreateDeviceRGB(); + + m_displayColorSpaceHash.insert(displayID, colorSpace); + CMCloseProfile(displayProfile); + if (!m_postRoutineRegistered) { + m_postRoutineRegistered = true; + qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); + } + return colorSpace; +} + +void QCoreGraphicsPaintEngine::cleanUpMacColorSpaces() +{ + if (m_genericColorSpace) { + CFRelease(m_genericColorSpace); + m_genericColorSpace = 0; + } + QHash<CGDirectDisplayID, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin(); + while (it != m_displayColorSpaceHash.constEnd()) { + if (it.value()) + CFRelease(it.value()); + ++it; + } + m_displayColorSpaceHash.clear(); +} + +//pattern handling (tiling) +#if 1 +# define QMACPATTERN_MASK_MULTIPLIER 32 +#else +# define QMACPATTERN_MASK_MULTIPLIER 1 +#endif +class QMacPattern +{ +public: + QMacPattern() : as_mask(false), pdev(0), image(0) { data.bytes = 0; } + ~QMacPattern() { CGImageRelease(image); } + int width() { + if (image) + return CGImageGetWidth(image); + if (data.bytes) + return 8*QMACPATTERN_MASK_MULTIPLIER; + return data.pixmap.width(); + } + int height() { + if (image) + return CGImageGetHeight(image); + if (data.bytes) + return 8*QMACPATTERN_MASK_MULTIPLIER; + return data.pixmap.height(); + } + + //input + QColor foreground; + bool as_mask; + struct { + QPixmap pixmap; + const uchar *bytes; + } data; + QPaintDevice *pdev; + //output + CGImageRef image; +}; +static void qt_mac_draw_pattern(void *info, CGContextRef c) +{ + QMacPattern *pat = (QMacPattern*)info; + int w = 0, h = 0; + bool isBitmap = (pat->data.pixmap.depth() == 1); + if (!pat->image) { //lazy cache + if (pat->as_mask) { + Q_ASSERT(pat->data.bytes); + w = h = 8; +#if (QMACPATTERN_MASK_MULTIPLIER == 1) + CGDataProviderRef provider = CGDataProviderCreateWithData(0, pat->data.bytes, w*h, 0); + pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false); + CGDataProviderRelease(provider); +#else + const int numBytes = (w*h)/sizeof(uchar); + uchar xor_bytes[numBytes]; + for (int i = 0; i < numBytes; ++i) + xor_bytes[i] = pat->data.bytes[i] ^ 0xFF; + CGDataProviderRef provider = CGDataProviderCreateWithData(0, xor_bytes, w*h, 0); + CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false); + CGDataProviderRelease(provider); + + const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255); + QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER); + pm.fill(c0); + CGContextRef pm_ctx = qt_mac_cg_context(&pm); + CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev)); + CGRect rect = CGRectMake(0, 0, w, h); + for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) { + rect.origin.x = x * w; + for (int y = 0; y < QMACPATTERN_MASK_MULTIPLIER; ++y) { + rect.origin.y = y * h; + qt_mac_drawCGImage(pm_ctx, &rect, swatch); + } + } + pat->image = qt_mac_create_imagemask(pm, pm.rect()); + CGImageRelease(swatch); + CGContextRelease(pm_ctx); + w *= QMACPATTERN_MASK_MULTIPLIER; + h *= QMACPATTERN_MASK_MULTIPLIER; +#endif + } else { + w = pat->data.pixmap.width(); + h = pat->data.pixmap.height(); + if (isBitmap) + pat->image = qt_mac_create_imagemask(pat->data.pixmap, pat->data.pixmap.rect()); + else + pat->image = qt_mac_image_to_cgimage(pat->data.pixmap.toImage()); + } + } else { + w = CGImageGetWidth(pat->image); + h = CGImageGetHeight(pat->image); + } + + //draw + bool needRestore = false; + if (CGImageIsMask(pat->image)) { + CGContextSaveGState(c); + CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground, pat->pdev)); + } + CGRect rect = CGRectMake(0, 0, w, h); + qt_mac_drawCGImage(c, &rect, pat->image); + if (needRestore) + CGContextRestoreGState(c); +} +static void qt_mac_dispose_pattern(void *info) +{ + QMacPattern *pat = (QMacPattern*)info; + delete pat; +} + +/***************************************************************************** + QCoreGraphicsPaintEngine member functions + *****************************************************************************/ + +inline static QPaintEngine::PaintEngineFeatures qt_mac_cg_features() +{ + return QPaintEngine::PaintEngineFeatures(QPaintEngine::AllFeatures & ~QPaintEngine::PaintOutsidePaintEvent + & ~QPaintEngine::PerspectiveTransform + & ~QPaintEngine::ConicalGradientFill + & ~QPaintEngine::LinearGradientFill + & ~QPaintEngine::RadialGradientFill + & ~QPaintEngine::BrushStroke); +} + +QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine() +: QPaintEngine(*(new QCoreGraphicsPaintEnginePrivate), qt_mac_cg_features()) +{ +} + +QCoreGraphicsPaintEngine::QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr) +: QPaintEngine(dptr, qt_mac_cg_features()) +{ +} + +QCoreGraphicsPaintEngine::~QCoreGraphicsPaintEngine() +{ +} + +bool +QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev) +{ + Q_D(QCoreGraphicsPaintEngine); + if (isActive()) { // already active painting + qWarning("QCoreGraphicsPaintEngine::begin: Painter already active"); + return false; + } + + //initialization + d->pdev = pdev; + d->complexXForm = false; + d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticSetPenWidth; + d->cosmeticPenSize = 1; + d->current.clipEnabled = false; + d->pixelSize = QPoint(1,1); + d->hd = qt_mac_cg_context(pdev); + if (d->hd) { + d->saveGraphicsState(); + d->orig_xform = CGContextGetCTM(d->hd); + if (d->shading) { + CGShadingRelease(d->shading); + d->shading = 0; + } + d->setClip(0); //clear the context's clipping + } + + setActive(true); + + if (d->pdev->devType() == QInternal::Widget) { // device is a widget + QWidget *w = (QWidget*)d->pdev; + bool unclipped = w->testAttribute(Qt::WA_PaintUnclipped); + + if ((w->windowType() == Qt::Desktop)) { + if (!unclipped) + qWarning("QCoreGraphicsPaintEngine::begin: Does not support clipped desktop on Mac OS X"); + // ## need to do [qt_mac_window_for(w) makeKeyAndOrderFront]; (need to rename the file) + } else if (unclipped) { + qWarning("QCoreGraphicsPaintEngine::begin: Does not support unclipped painting"); + } + } else if (d->pdev->devType() == QInternal::Pixmap) { // device is a pixmap + QPixmap *pm = (QPixmap*)d->pdev; + if (pm->isNull()) { + qWarning("QCoreGraphicsPaintEngine::begin: Cannot paint null pixmap"); + end(); + return false; + } + } + + setDirty(QPaintEngine::DirtyPen); + setDirty(QPaintEngine::DirtyBrush); + setDirty(QPaintEngine::DirtyBackground); + setDirty(QPaintEngine::DirtyHints); + return true; +} + +bool +QCoreGraphicsPaintEngine::end() +{ + Q_D(QCoreGraphicsPaintEngine); + setActive(false); + if (d->pdev->devType() == QInternal::Widget && static_cast<QWidget*>(d->pdev)->windowType() == Qt::Desktop) { + // ### need to do [qt_mac_window_for(static_cast<QWidget *>(d->pdev)) orderOut]; (need to rename) + } + if (d->shading) { + CGShadingRelease(d->shading); + d->shading = 0; + } + d->pdev = 0; + if (d->hd) { + d->restoreGraphicsState(); + CGContextSynchronize(d->hd); + CGContextRelease(d->hd); + d->hd = 0; + } + return true; +} + +void +QCoreGraphicsPaintEngine::updateState(const QPaintEngineState &state) +{ + Q_D(QCoreGraphicsPaintEngine); + QPaintEngine::DirtyFlags flags = state.state(); + + if (flags & DirtyTransform) + updateMatrix(state.transform()); + + if (flags & DirtyClipEnabled) { + if (state.isClipEnabled()) + updateClipPath(painter()->clipPath(), Qt::ReplaceClip); + else + updateClipPath(QPainterPath(), Qt::NoClip); + } + + if (flags & DirtyClipPath) { + updateClipPath(state.clipPath(), state.clipOperation()); + } else if (flags & DirtyClipRegion) { + updateClipRegion(state.clipRegion(), state.clipOperation()); + } + + // If the clip has changed we need to update all other states + // too, since they are included in the system context on OSX, + // and changing the clip resets that context back to scratch. + if (flags & (DirtyClipPath | DirtyClipRegion | DirtyClipEnabled)) + flags |= AllDirty; + + if (flags & DirtyPen) + updatePen(state.pen()); + if (flags & (DirtyBrush|DirtyBrushOrigin)) + updateBrush(state.brush(), state.brushOrigin()); + if (flags & DirtyFont) + updateFont(state.font()); + if (flags & DirtyOpacity) + updateOpacity(state.opacity()); + if (flags & DirtyHints) + updateRenderHints(state.renderHints()); + if (flags & DirtyCompositionMode) + updateCompositionMode(state.compositionMode()); + + if (flags & (DirtyPen | DirtyTransform)) { + if (!d->current.pen.isCosmetic()) { + d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticNone; + } else if (d->current.transform.m11() < d->current.transform.m22()-1.0 || + d->current.transform.m11() > d->current.transform.m22()+1.0) { + d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticTransformPath; + d->cosmeticPenSize = d->adjustPenWidth(d->current.pen.widthF()); + if (!d->cosmeticPenSize) + d->cosmeticPenSize = 1.0; + } else { + d->cosmeticPen = QCoreGraphicsPaintEnginePrivate::CosmeticSetPenWidth; + static const float sqrt2 = sqrt(2); + qreal width = d->current.pen.widthF(); + if (!width) + width = 1; + d->cosmeticPenSize = sqrt(pow(d->pixelSize.y(), 2) + pow(d->pixelSize.x(), 2)) / sqrt2 * width; + } + } +} + +void +QCoreGraphicsPaintEngine::updatePen(const QPen &pen) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + d->current.pen = pen; + d->setStrokePen(pen); +} + +void +QCoreGraphicsPaintEngine::updateBrush(const QBrush &brush, const QPointF &brushOrigin) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + d->current.brush = brush; + +#ifdef QT_MAC_USE_NATIVE_GRADIENTS + // Quartz supports only pad spread + if (const QGradient *gradient = brush.gradient()) { + if (drawGradientNatively(gradient)) { + gccaps |= QPaintEngine::LinearGradientFill | QPaintEngine::RadialGradientFill; + } else { + gccaps &= ~(QPaintEngine::LinearGradientFill | QPaintEngine::RadialGradientFill); + } + } +#endif + + if (d->shading) { + CGShadingRelease(d->shading); + d->shading = 0; + } + d->setFillBrush(brushOrigin); +} + +void +QCoreGraphicsPaintEngine::updateOpacity(qreal opacity) +{ + Q_D(QCoreGraphicsPaintEngine); + CGContextSetAlpha(d->hd, opacity); +} + +void +QCoreGraphicsPaintEngine::updateFont(const QFont &) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + updatePen(d->current.pen); +} + +void +QCoreGraphicsPaintEngine::updateMatrix(const QTransform &transform) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (qt_is_nan(transform.m11()) || qt_is_nan(transform.m12()) || qt_is_nan(transform.m13()) + || qt_is_nan(transform.m21()) || qt_is_nan(transform.m22()) || qt_is_nan(transform.m23()) + || qt_is_nan(transform.m31()) || qt_is_nan(transform.m32()) || qt_is_nan(transform.m33())) + return; + + d->current.transform = transform; + d->setTransform(transform.isIdentity() ? 0 : &transform); + d->complexXForm = (transform.m11() != 1 || transform.m22() != 1 + || transform.m12() != 0 || transform.m21() != 0); + d->pixelSize = d->devicePixelSize(d->hd); +} + +void +QCoreGraphicsPaintEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperation op) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + if (op == Qt::NoClip) { + if (d->current.clipEnabled) { + d->current.clipEnabled = false; + d->current.clip = QRegion(); + d->setClip(0); + } + } else { + if (!d->current.clipEnabled) + op = Qt::ReplaceClip; + d->current.clipEnabled = true; + QRegion clipRegion(p.toFillPolygon().toPolygon(), p.fillRule()); + if (op == Qt::ReplaceClip) { + d->current.clip = clipRegion; + d->setClip(0); + if (p.isEmpty()) { + CGRect rect = CGRectMake(0, 0, 0, 0); + CGContextClipToRect(d->hd, rect); + } else { + CGMutablePathRef path = qt_mac_compose_path(p); + CGContextBeginPath(d->hd); + CGContextAddPath(d->hd, path); + if (p.fillRule() == Qt::WindingFill) + CGContextClip(d->hd); + else + CGContextEOClip(d->hd); + CGPathRelease(path); + } + } else if (op == Qt::IntersectClip) { + d->current.clip = d->current.clip.intersected(clipRegion); + d->setClip(&d->current.clip); + } + } +} + +void +QCoreGraphicsPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + if (op == Qt::NoClip) { + d->current.clipEnabled = false; + d->current.clip = QRegion(); + d->setClip(0); + } else { + if (!d->current.clipEnabled) + op = Qt::ReplaceClip; + d->current.clipEnabled = true; + if (op == Qt::IntersectClip) + d->current.clip = d->current.clip.intersected(clipRegion); + else if (op == Qt::ReplaceClip) + d->current.clip = clipRegion; + d->setClip(&d->current.clip); + } +} + +void +QCoreGraphicsPaintEngine::drawPath(const QPainterPath &p) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + CGMutablePathRef path = qt_mac_compose_path(p); + uchar ops = QCoreGraphicsPaintEnginePrivate::CGStroke; + if (p.fillRule() == Qt::WindingFill) + ops |= QCoreGraphicsPaintEnginePrivate::CGFill; + else + ops |= QCoreGraphicsPaintEnginePrivate::CGEOFill; + CGContextBeginPath(d->hd); + d->drawPath(ops, path); + CGPathRelease(path); +} + +void +QCoreGraphicsPaintEngine::drawRects(const QRectF *rects, int rectCount) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + for (int i=0; i<rectCount; ++i) { + QRectF r = rects[i]; + + CGMutablePathRef path = CGPathCreateMutable(); + CGPathAddRect(path, 0, qt_mac_compose_rect(r)); + d->drawPath(QCoreGraphicsPaintEnginePrivate::CGFill|QCoreGraphicsPaintEnginePrivate::CGStroke, + path); + CGPathRelease(path); + } +} + +void +QCoreGraphicsPaintEngine::drawPoints(const QPointF *points, int pointCount) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + if (d->current.pen.capStyle() == Qt::FlatCap) + CGContextSetLineCap(d->hd, kCGLineCapSquare); + + CGMutablePathRef path = CGPathCreateMutable(); + for (int i=0; i < pointCount; i++) { + float x = points[i].x(), y = points[i].y(); + CGPathMoveToPoint(path, 0, x, y); + CGPathAddLineToPoint(path, 0, x+0.001, y); + } + + bool doRestore = false; + if (d->cosmeticPen == QCoreGraphicsPaintEnginePrivate::CosmeticNone && !(state->renderHints() & QPainter::Antialiasing)) { + //we don't want adjusted pens for point rendering + doRestore = true; + d->saveGraphicsState(); + CGContextSetLineWidth(d->hd, d->current.pen.widthF()); + } + d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path); + if (doRestore) + d->restoreGraphicsState(); + CGPathRelease(path); + if (d->current.pen.capStyle() == Qt::FlatCap) + CGContextSetLineCap(d->hd, kCGLineCapButt); +} + +void +QCoreGraphicsPaintEngine::drawEllipse(const QRectF &r) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + CGMutablePathRef path = CGPathCreateMutable(); + CGAffineTransform transform = CGAffineTransformMakeScale(r.width() / r.height(), 1); + CGPathAddArc(path, &transform,(r.x() + (r.width() / 2)) / (r.width() / r.height()), + r.y() + (r.height() / 2), r.height() / 2, 0, (2 * M_PI), false); + d->drawPath(QCoreGraphicsPaintEnginePrivate::CGFill | QCoreGraphicsPaintEnginePrivate::CGStroke, + path); + CGPathRelease(path); +} + +void +QCoreGraphicsPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + CGMutablePathRef path = CGPathCreateMutable(); + CGPathMoveToPoint(path, 0, points[0].x(), points[0].y()); + for (int x = 1; x < pointCount; ++x) + CGPathAddLineToPoint(path, 0, points[x].x(), points[x].y()); + if (mode != PolylineMode && points[0] != points[pointCount-1]) + CGPathAddLineToPoint(path, 0, points[0].x(), points[0].y()); + uint op = QCoreGraphicsPaintEnginePrivate::CGStroke; + if (mode != PolylineMode) + op |= mode == OddEvenMode ? QCoreGraphicsPaintEnginePrivate::CGEOFill + : QCoreGraphicsPaintEnginePrivate::CGFill; + d->drawPath(op, path); + CGPathRelease(path); +} + +void +QCoreGraphicsPaintEngine::drawLines(const QLineF *lines, int lineCount) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + CGMutablePathRef path = CGPathCreateMutable(); + for (int i = 0; i < lineCount; i++) { + const QPointF start = lines[i].p1(), end = lines[i].p2(); + CGPathMoveToPoint(path, 0, start.x(), start.y()); + CGPathAddLineToPoint(path, 0, end.x(), end.y()); + } + d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path); + CGPathRelease(path); +} + +void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + if (pm.isNull()) + return; + + bool differentSize = (QRectF(0, 0, pm.width(), pm.height()) != sr), doRestore = false; + CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); + QCFType<CGImageRef> image; + bool isBitmap = (pm.depth() == 1); + if (isBitmap) { + doRestore = true; + d->saveGraphicsState(); + + const QColor &col = d->current.pen.color(); + CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev)); + image = qt_mac_create_imagemask(pm, sr); + } else if (differentSize) { + QCFType<CGImageRef> img = qt_mac_image_to_cgimage(pm.toImage()); + image = CGImageCreateWithImageInRect(img, CGRectMake(qRound(sr.x()), qRound(sr.y()), qRound(sr.width()), qRound(sr.height()))); + } else { + image = qt_mac_image_to_cgimage(pm.toImage()); + } + qt_mac_drawCGImage(d->hd, &rect, image); + if (doRestore) + d->restoreGraphicsState(); +} + +static void drawImageReleaseData (void *info, const void *, size_t) +{ + delete static_cast<QImage *>(info); +} + +CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0) +{ + QImage *image; + if (img.depth() != 32) + image = new QImage(img.convertToFormat(QImage::Format_ARGB32_Premultiplied)); + else + image = new QImage(img); + + uint cgflags = kCGImageAlphaNone; + switch (image->format()) { + case QImage::Format_ARGB32_Premultiplied: + cgflags = kCGImageAlphaPremultipliedFirst; + break; + case QImage::Format_ARGB32: + cgflags = kCGImageAlphaFirst; + break; + case QImage::Format_RGB32: + cgflags = kCGImageAlphaNoneSkipFirst; + default: + break; + } +#if defined(kCGBitmapByteOrder32Host) //only needed because CGImage.h added symbols in the minor version + cgflags |= kCGBitmapByteOrder32Host; +#endif + QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(image, + static_cast<const QImage *>(image)->bits(), + image->byteCount(), + drawImageReleaseData); + if (imagePtr) + *imagePtr = image; + return CGImageCreate(image->width(), image->height(), 8, 32, + image->bytesPerLine(), + QCoreGraphicsPaintEngine::macGenericColorSpace(), + cgflags, dataProvider, 0, false, kCGRenderingIntentDefault); + +} + +void QCoreGraphicsPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRectF &sr, + Qt::ImageConversionFlags flags) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_UNUSED(flags); + Q_ASSERT(isActive()); + + if (img.isNull() || state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + const QImage *image; + QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img, &image); + CGRect rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); + if (QRectF(0, 0, img.width(), img.height()) != sr) + cgimage = CGImageCreateWithImageInRect(cgimage, CGRectMake(sr.x(), sr.y(), + sr.width(), sr.height())); + qt_mac_drawCGImage(d->hd, &rect, cgimage); +} + +void QCoreGraphicsPaintEngine::initialize() +{ +} + +void QCoreGraphicsPaintEngine::cleanup() +{ +} + +CGContextRef +QCoreGraphicsPaintEngine::handle() const +{ + return d_func()->hd; +} + +void +QCoreGraphicsPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, + const QPointF &p) +{ + Q_D(QCoreGraphicsPaintEngine); + Q_ASSERT(isActive()); + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + //save the old state + d->saveGraphicsState(); + + //setup the pattern + QMacPattern *qpattern = new QMacPattern; + qpattern->data.pixmap = pixmap; + qpattern->foreground = d->current.pen.color(); + qpattern->pdev = d->pdev; + CGPatternCallbacks callbks; + callbks.version = 0; + callbks.drawPattern = qt_mac_draw_pattern; + callbks.releaseInfo = qt_mac_dispose_pattern; + const int width = qpattern->width(), height = qpattern->height(); + CGAffineTransform trans = CGContextGetCTM(d->hd); + CGPatternRef pat = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height), + trans, width, height, + kCGPatternTilingNoDistortion, true, &callbks); + CGColorSpaceRef cs = CGColorSpaceCreatePattern(0); + CGContextSetFillColorSpace(d->hd, cs); + CGFloat component = 1.0; //just one + CGContextSetFillPattern(d->hd, pat, &component); + CGSize phase = CGSizeApplyAffineTransform(CGSizeMake(-(p.x()-r.x()), -(p.y()-r.y())), trans); + CGContextSetPatternPhase(d->hd, phase); + + //fill the rectangle + CGRect mac_rect = CGRectMake(r.x(), r.y(), r.width(), r.height()); + CGContextFillRect(d->hd, mac_rect); + + //restore the state + d->restoreGraphicsState(); + //cleanup + CGColorSpaceRelease(cs); + CGPatternRelease(pat); +} + +void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &item) +{ + Q_D(QCoreGraphicsPaintEngine); + if (d->current.transform.type() == QTransform::TxProject +#ifndef QMAC_NATIVE_GRADIENTS + || painter()->pen().brush().gradient() //Just let the base engine "emulate" the gradient +#endif + ) { + QPaintEngine::drawTextItem(pos, item); + return; + } + + if (state->compositionMode() == QPainter::CompositionMode_Destination) + return; + + const QTextItemInt &ti = static_cast<const QTextItemInt &>(item); + + QPen oldPen = painter()->pen(); + QBrush oldBrush = painter()->brush(); + QPointF oldBrushOrigin = painter()->brushOrigin(); + updatePen(Qt::NoPen); + updateBrush(oldPen.brush(), QPointF(0, 0)); + + Q_ASSERT(type() == QPaintEngine::CoreGraphics); + + QFontEngine *fe = ti.fontEngine; + + const bool textAA = state->renderHints() & QPainter::TextAntialiasing && fe->fontDef.pointSize > qt_antialiasing_threshold && !(fe->fontDef.styleStrategy & QFont::NoAntialias); + const bool lineAA = state->renderHints() & QPainter::Antialiasing; + if (textAA != lineAA) + CGContextSetShouldAntialias(d->hd, textAA); + + if (ti.glyphs.numGlyphs) { + switch (fe->type()) { + case QFontEngine::Mac: + static_cast<QCoreTextFontEngine *>(fe)->draw(d->hd, pos.x(), pos.y(), ti, paintDevice()->height()); + break; + case QFontEngine::Box: + d->drawBoxTextItem(pos, ti); + break; + default: + break; + } + } + + if (textAA != lineAA) + CGContextSetShouldAntialias(d->hd, !textAA); + + updatePen(oldPen); + updateBrush(oldBrush, oldBrushOrigin); +} + +QPainter::RenderHints +QCoreGraphicsPaintEngine::supportedRenderHints() const +{ + return QPainter::RenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); +} +enum CGCompositeMode { + kCGCompositeModeClear = 0, + kCGCompositeModeCopy = 1, + kCGCompositeModeSourceOver = 2, + kCGCompositeModeSourceIn = 3, + kCGCompositeModeSourceOut = 4, + kCGCompositeModeSourceAtop = 5, + kCGCompositeModeDestinationOver = 6, + kCGCompositeModeDestinationIn = 7, + kCGCompositeModeDestinationOut = 8, + kCGCompositeModeDestinationAtop = 9, + kCGCompositeModeXOR = 10, + kCGCompositeModePlusDarker = 11, // (max (0, (1-d) + (1-s))) + kCGCompositeModePlusLighter = 12, // (min (1, s + d)) + }; +extern "C" { + extern void CGContextSetCompositeOperation(CGContextRef, int); +} // private function, but is in all versions of OS X. +void +QCoreGraphicsPaintEngine::updateCompositionMode(QPainter::CompositionMode mode) +{ +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { + int cg_mode = kCGBlendModeNormal; + switch (mode) { + case QPainter::CompositionMode_Multiply: + cg_mode = kCGBlendModeMultiply; + break; + case QPainter::CompositionMode_Screen: + cg_mode = kCGBlendModeScreen; + break; + case QPainter::CompositionMode_Overlay: + cg_mode = kCGBlendModeOverlay; + break; + case QPainter::CompositionMode_Darken: + cg_mode = kCGBlendModeDarken; + break; + case QPainter::CompositionMode_Lighten: + cg_mode = kCGBlendModeLighten; + break; + case QPainter::CompositionMode_ColorDodge: + cg_mode = kCGBlendModeColorDodge; + break; + case QPainter::CompositionMode_ColorBurn: + cg_mode = kCGBlendModeColorBurn; + break; + case QPainter::CompositionMode_HardLight: + cg_mode = kCGBlendModeHardLight; + break; + case QPainter::CompositionMode_SoftLight: + cg_mode = kCGBlendModeSoftLight; + break; + case QPainter::CompositionMode_Difference: + cg_mode = kCGBlendModeDifference; + break; + case QPainter::CompositionMode_Exclusion: + cg_mode = kCGBlendModeExclusion; + break; + case QPainter::CompositionMode_Plus: + cg_mode = kCGBlendModePlusLighter; + break; + case QPainter::CompositionMode_SourceOver: + cg_mode = kCGBlendModeNormal; + break; + case QPainter::CompositionMode_DestinationOver: + cg_mode = kCGBlendModeDestinationOver; + break; + case QPainter::CompositionMode_Clear: + cg_mode = kCGBlendModeClear; + break; + case QPainter::CompositionMode_Source: + cg_mode = kCGBlendModeCopy; + break; + case QPainter::CompositionMode_Destination: + cg_mode = -1; + break; + case QPainter::CompositionMode_SourceIn: + cg_mode = kCGBlendModeSourceIn; + break; + case QPainter::CompositionMode_DestinationIn: + cg_mode = kCGCompositeModeDestinationIn; + break; + case QPainter::CompositionMode_SourceOut: + cg_mode = kCGBlendModeSourceOut; + break; + case QPainter::CompositionMode_DestinationOut: + cg_mode = kCGBlendModeDestinationOver; + break; + case QPainter::CompositionMode_SourceAtop: + cg_mode = kCGBlendModeSourceAtop; + break; + case QPainter::CompositionMode_DestinationAtop: + cg_mode = kCGBlendModeDestinationAtop; + break; + case QPainter::CompositionMode_Xor: + cg_mode = kCGBlendModeXOR; + break; + default: + break; + } + if (cg_mode > -1) { + CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); + } + } else +#endif + // The standard porter duff ops. + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_3 + && mode <= QPainter::CompositionMode_Xor) { + int cg_mode = kCGCompositeModeCopy; + switch (mode) { + case QPainter::CompositionMode_SourceOver: + cg_mode = kCGCompositeModeSourceOver; + break; + case QPainter::CompositionMode_DestinationOver: + cg_mode = kCGCompositeModeDestinationOver; + break; + case QPainter::CompositionMode_Clear: + cg_mode = kCGCompositeModeClear; + break; + default: + qWarning("QCoreGraphicsPaintEngine: Unhandled composition mode %d", (int)mode); + break; + case QPainter::CompositionMode_Source: + cg_mode = kCGCompositeModeCopy; + break; + case QPainter::CompositionMode_Destination: + cg_mode = CGCompositeMode(-1); + break; + case QPainter::CompositionMode_SourceIn: + cg_mode = kCGCompositeModeSourceIn; + break; + case QPainter::CompositionMode_DestinationIn: + cg_mode = kCGCompositeModeDestinationIn; + break; + case QPainter::CompositionMode_SourceOut: + cg_mode = kCGCompositeModeSourceOut; + break; + case QPainter::CompositionMode_DestinationOut: + cg_mode = kCGCompositeModeDestinationOut; + break; + case QPainter::CompositionMode_SourceAtop: + cg_mode = kCGCompositeModeSourceAtop; + break; + case QPainter::CompositionMode_DestinationAtop: + cg_mode = kCGCompositeModeDestinationAtop; + break; + case QPainter::CompositionMode_Xor: + cg_mode = kCGCompositeModeXOR; + break; + } + if (cg_mode > -1) + CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); + } else { +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + bool needPrivateAPI = false; + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + int cg_mode = kCGBlendModeNormal; + switch (mode) { + case QPainter::CompositionMode_Multiply: + cg_mode = kCGBlendModeMultiply; + break; + case QPainter::CompositionMode_Screen: + cg_mode = kCGBlendModeScreen; + break; + case QPainter::CompositionMode_Overlay: + cg_mode = kCGBlendModeOverlay; + break; + case QPainter::CompositionMode_Darken: + cg_mode = kCGBlendModeDarken; + break; + case QPainter::CompositionMode_Lighten: + cg_mode = kCGBlendModeLighten; + break; + case QPainter::CompositionMode_ColorDodge: + cg_mode = kCGBlendModeColorDodge; + break; + case QPainter::CompositionMode_ColorBurn: + cg_mode = kCGBlendModeColorBurn; + break; + case QPainter::CompositionMode_HardLight: + cg_mode = kCGBlendModeHardLight; + break; + case QPainter::CompositionMode_SoftLight: + cg_mode = kCGBlendModeSoftLight; + break; + case QPainter::CompositionMode_Difference: + cg_mode = kCGBlendModeDifference; + break; + case QPainter::CompositionMode_Exclusion: + cg_mode = kCGBlendModeExclusion; + break; + case QPainter::CompositionMode_Plus: + needPrivateAPI = true; + cg_mode = kCGCompositeModePlusLighter; + break; + default: + break; + } + if (!needPrivateAPI) + CGContextSetBlendMode(d_func()->hd, CGBlendMode(cg_mode)); + else + CGContextSetCompositeOperation(d_func()->hd, CGCompositeMode(cg_mode)); + } +#endif + } +} + +void +QCoreGraphicsPaintEngine::updateRenderHints(QPainter::RenderHints hints) +{ + Q_D(QCoreGraphicsPaintEngine); + CGContextSetShouldAntialias(d->hd, hints & QPainter::Antialiasing); + static const CGFloat ScaleFactor = qt_mac_get_scalefactor(); + if (ScaleFactor > 1.) { + CGContextSetInterpolationQuality(d->hd, kCGInterpolationHigh); + } else { + CGContextSetInterpolationQuality(d->hd, (hints & QPainter::SmoothPixmapTransform) ? + kCGInterpolationHigh : kCGInterpolationNone); + } + bool textAntialiasing = (hints & QPainter::TextAntialiasing) == QPainter::TextAntialiasing; + if (!textAntialiasing || d->disabledSmoothFonts) { + d->disabledSmoothFonts = !textAntialiasing; + CGContextSetShouldSmoothFonts(d->hd, textAntialiasing); + } +} + +/* + Returns the size of one device pixel in user-space coordinates. +*/ +QPointF QCoreGraphicsPaintEnginePrivate::devicePixelSize(CGContextRef) +{ + QPointF p1 = current.transform.inverted().map(QPointF(0, 0)); + QPointF p2 = current.transform.inverted().map(QPointF(1, 1)); + return QPointF(qAbs(p2.x() - p1.x()), qAbs(p2.y() - p1.y())); +} + +/* + Adjusts the pen width so we get correct line widths in the + non-transformed, aliased case. +*/ +float QCoreGraphicsPaintEnginePrivate::adjustPenWidth(float penWidth) +{ + Q_Q(QCoreGraphicsPaintEngine); + float ret = penWidth; + if (!complexXForm && !(q->state->renderHints() & QPainter::Antialiasing)) { + if (penWidth < 2) + ret = 1; + else if (penWidth < 3) + ret = 1.5; + else + ret = penWidth -1; + } + return ret; +} + +void +QCoreGraphicsPaintEnginePrivate::setStrokePen(const QPen &pen) +{ + //pencap + CGLineCap cglinecap = kCGLineCapButt; + if (pen.capStyle() == Qt::SquareCap) + cglinecap = kCGLineCapSquare; + else if (pen.capStyle() == Qt::RoundCap) + cglinecap = kCGLineCapRound; + CGContextSetLineCap(hd, cglinecap); + CGContextSetLineWidth(hd, adjustPenWidth(pen.widthF())); + + //join + CGLineJoin cglinejoin = kCGLineJoinMiter; + if (pen.joinStyle() == Qt::BevelJoin) + cglinejoin = kCGLineJoinBevel; + else if (pen.joinStyle() == Qt::RoundJoin) + cglinejoin = kCGLineJoinRound; + CGContextSetLineJoin(hd, cglinejoin); +// CGContextSetMiterLimit(hd, pen.miterLimit()); + + //pen style + QVector<CGFloat> linedashes; + if (pen.style() == Qt::CustomDashLine) { + QVector<qreal> customs = pen.dashPattern(); + for (int i = 0; i < customs.size(); ++i) + linedashes.append(customs.at(i)); + } else if (pen.style() == Qt::DashLine) { + linedashes.append(4); + linedashes.append(2); + } else if (pen.style() == Qt::DotLine) { + linedashes.append(1); + linedashes.append(2); + } else if (pen.style() == Qt::DashDotLine) { + linedashes.append(4); + linedashes.append(2); + linedashes.append(1); + linedashes.append(2); + } else if (pen.style() == Qt::DashDotDotLine) { + linedashes.append(4); + linedashes.append(2); + linedashes.append(1); + linedashes.append(2); + linedashes.append(1); + linedashes.append(2); + } + const CGFloat cglinewidth = pen.widthF() <= 0.0f ? 1.0f : float(pen.widthF()); + for (int i = 0; i < linedashes.size(); ++i) { + linedashes[i] *= cglinewidth; + if (cglinewidth < 3 && (cglinecap == kCGLineCapSquare || cglinecap == kCGLineCapRound)) { + if ((i%2)) + linedashes[i] += cglinewidth/2; + else + linedashes[i] -= cglinewidth/2; + } + } + CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size()); + + // color + CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color(), pdev)); +} + +// Add our own patterns here to deal with the fact that the coordinate system +// is flipped vertically with Quartz2D. +static const uchar *qt_mac_patternForBrush(int brushStyle) +{ + Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern); + static const uchar dense1_pat[] = { 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00 }; + static const uchar dense2_pat[] = { 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }; + static const uchar dense3_pat[] = { 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa }; + static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; + static const uchar dense5_pat[] = { 0xee, 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55 }; + static const uchar dense6_pat[] = { 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 }; + static const uchar dense7_pat[] = { 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff }; + static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff }; + static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef }; + static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef }; + static const uchar fdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe }; + static const uchar bdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; + static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e }; + static const uchar *const pat_tbl[] = { + dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat, + dense6_pat, dense7_pat, + hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat }; + return pat_tbl[brushStyle - Qt::Dense1Pattern]; +} + +void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) +{ + // pattern + Qt::BrushStyle bs = current.brush.style(); +#ifdef QT_MAC_USE_NATIVE_GRADIENTS + if (bs == Qt::LinearGradientPattern || bs == Qt::RadialGradientPattern) { + const QGradient *grad = static_cast<const QGradient*>(current.brush.gradient()); + if (drawGradientNatively(grad)) { + Q_ASSERT(grad->spread() == QGradient::PadSpread); + + static const CGFloat domain[] = { 0.0f, +1.0f }; + static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, 0 }; + CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(¤t.brush), + 1, domain, 4, 0, &callbacks); + + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); + if (bs == Qt::LinearGradientPattern) { + const QLinearGradient *linearGrad = static_cast<const QLinearGradient *>(grad); + const QPointF start(linearGrad->start()); + const QPointF stop(linearGrad->finalStop()); + shading = CGShadingCreateAxial(colorspace, CGPointMake(start.x(), start.y()), + CGPointMake(stop.x(), stop.y()), fill_func, true, true); + } else { + Q_ASSERT(bs == Qt::RadialGradientPattern); + const QRadialGradient *radialGrad = static_cast<const QRadialGradient *>(grad); + QPointF center(radialGrad->center()); + QPointF focal(radialGrad->focalPoint()); + qreal radius = radialGrad->radius(); + qreal focalRadius = radialGrad->focalRadius(); + shading = CGShadingCreateRadial(colorspace, CGPointMake(focal.x(), focal.y()), + focalRadius, CGPointMake(center.x(), center.y()), radius, fill_func, false, true); + } + + CGFunctionRelease(fill_func); + } + } else +#endif + if (bs != Qt::SolidPattern && bs != Qt::NoBrush +#ifndef QT_MAC_USE_NATIVE_GRADIENTS + && (bs < Qt::LinearGradientPattern || bs > Qt::ConicalGradientPattern) +#endif + ) + { + QMacPattern *qpattern = new QMacPattern; + qpattern->pdev = pdev; + CGFloat components[4] = { 1.0, 1.0, 1.0, 1.0 }; + CGColorSpaceRef base_colorspace = 0; + if (bs == Qt::TexturePattern) { + qpattern->data.pixmap = current.brush.texture(); + if (qpattern->data.pixmap.isQBitmap()) { + const QColor &col = current.brush.color(); + components[0] = qt_mac_convert_color_to_cg(col.red()); + components[1] = qt_mac_convert_color_to_cg(col.green()); + components[2] = qt_mac_convert_color_to_cg(col.blue()); + base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); + } + } else { + qpattern->as_mask = true; + + qpattern->data.bytes = qt_mac_patternForBrush(bs); + const QColor &col = current.brush.color(); + components[0] = qt_mac_convert_color_to_cg(col.red()); + components[1] = qt_mac_convert_color_to_cg(col.green()); + components[2] = qt_mac_convert_color_to_cg(col.blue()); + base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); + } + int width = qpattern->width(), height = qpattern->height(); + qpattern->foreground = current.brush.color(); + + CGColorSpaceRef fill_colorspace = CGColorSpaceCreatePattern(base_colorspace); + CGContextSetFillColorSpace(hd, fill_colorspace); + + CGAffineTransform xform = CGContextGetCTM(hd); + xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(current.brush.transform()), xform); + xform = CGAffineTransformTranslate(xform, offset.x(), offset.y()); + + CGPatternCallbacks callbks; + callbks.version = 0; + callbks.drawPattern = qt_mac_draw_pattern; + callbks.releaseInfo = qt_mac_dispose_pattern; + CGPatternRef fill_pattern = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height), + xform, width, height, kCGPatternTilingNoDistortion, + !base_colorspace, &callbks); + CGContextSetFillPattern(hd, fill_pattern, components); + + CGPatternRelease(fill_pattern); + CGColorSpaceRelease(fill_colorspace); + } else if (bs != Qt::NoBrush) { + CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color(), pdev)); + } +} + +void +QCoreGraphicsPaintEnginePrivate::setClip(const QRegion *rgn) +{ + Q_Q(QCoreGraphicsPaintEngine); + if (hd) { + resetClip(); + QRegion sysClip = q->systemClip(); + if (!sysClip.isEmpty()) + qt_mac_clip_cg(hd, sysClip, &orig_xform); + if (rgn) + qt_mac_clip_cg(hd, *rgn, 0); + } +} + +struct qt_mac_cg_transform_path { + CGMutablePathRef path; + CGAffineTransform transform; +}; + +void qt_mac_cg_transform_path_apply(void *info, const CGPathElement *element) +{ + Q_ASSERT(info && element); + qt_mac_cg_transform_path *t = (qt_mac_cg_transform_path*)info; + switch (element->type) { + case kCGPathElementMoveToPoint: + CGPathMoveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y); + break; + case kCGPathElementAddLineToPoint: + CGPathAddLineToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y); + break; + case kCGPathElementAddQuadCurveToPoint: + CGPathAddQuadCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y, + element->points[1].x, element->points[1].y); + break; + case kCGPathElementAddCurveToPoint: + CGPathAddCurveToPoint(t->path, &t->transform, element->points[0].x, element->points[0].y, + element->points[1].x, element->points[1].y, + element->points[2].x, element->points[2].y); + break; + case kCGPathElementCloseSubpath: + CGPathCloseSubpath(t->path); + break; + default: + qDebug() << "Unhandled path transform type: " << element->type; + } +} + +void QCoreGraphicsPaintEnginePrivate::drawPath(uchar ops, CGMutablePathRef path) +{ + Q_Q(QCoreGraphicsPaintEngine); + Q_ASSERT((ops & (CGFill | CGEOFill)) != (CGFill | CGEOFill)); //can't really happen + if ((ops & (CGFill | CGEOFill))) { + if (shading) { + Q_ASSERT(path); + CGContextBeginPath(hd); + CGContextAddPath(hd, path); + saveGraphicsState(); + if (ops & CGFill) + CGContextClip(hd); + else if (ops & CGEOFill) + CGContextEOClip(hd); + if (current.brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) { + CGRect boundingBox = CGPathGetBoundingBox(path); + CGContextConcatCTM(hd, + CGAffineTransformMake(boundingBox.size.width, 0, + 0, boundingBox.size.height, + boundingBox.origin.x, boundingBox.origin.y)); + } + CGContextDrawShading(hd, shading); + restoreGraphicsState(); + ops &= ~CGFill; + ops &= ~CGEOFill; + } else if (current.brush.style() == Qt::NoBrush) { + ops &= ~CGFill; + ops &= ~CGEOFill; + } + } + if ((ops & CGStroke) && current.pen.style() == Qt::NoPen) + ops &= ~CGStroke; + + if (ops & (CGEOFill | CGFill)) { + CGContextBeginPath(hd); + CGContextAddPath(hd, path); + if (ops & CGEOFill) { + CGContextEOFillPath(hd); + } else { + CGContextFillPath(hd); + } + } + + // Avoid saving and restoring the context if we can. + const bool needContextSave = (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone || + !(q->state->renderHints() & QPainter::Antialiasing)); + if (ops & CGStroke) { + if (needContextSave) + saveGraphicsState(); + CGContextBeginPath(hd); + + // Translate a fraction of a pixel size in the y direction + // to make sure that primitives painted at pixel borders + // fills the right pixel. This is needed since the y xais + // in the Quartz coordinate system is inverted compared to Qt. + if (!(q->state->renderHints() & QPainter::Antialiasing)) { + if (current.pen.style() == Qt::SolidLine || current.pen.width() >= 3) + CGContextTranslateCTM(hd, double(pixelSize.x()) * 0.25, double(pixelSize.y()) * 0.25); + else if (current.pen.style() == Qt::DotLine && QSysInfo::MacintoshVersion == QSysInfo::MV_10_3) + ; // Do nothing. + else + CGContextTranslateCTM(hd, 0, double(pixelSize.y()) * 0.1); + } + + if (cosmeticPen != QCoreGraphicsPaintEnginePrivate::CosmeticNone) { + // If antialiazing is enabled, use the cosmetic pen size directly. + if (q->state->renderHints() & QPainter::Antialiasing) + CGContextSetLineWidth(hd, cosmeticPenSize); + else if (current.pen.widthF() <= 1) + CGContextSetLineWidth(hd, cosmeticPenSize * 0.9f); + else + CGContextSetLineWidth(hd, cosmeticPenSize); + } + if (cosmeticPen == QCoreGraphicsPaintEnginePrivate::CosmeticTransformPath) { + qt_mac_cg_transform_path t; + t.transform = qt_mac_convert_transform_to_cg(current.transform); + t.path = CGPathCreateMutable(); + CGPathApply(path, &t, qt_mac_cg_transform_path_apply); //transform the path + setTransform(0); //unset the context transform + CGContextSetLineWidth(hd, cosmeticPenSize); + CGContextAddPath(hd, t.path); + CGPathRelease(t.path); + } else { + CGContextAddPath(hd, path); + } + + CGContextStrokePath(hd); + if (needContextSave) + restoreGraphicsState(); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h new file mode 100644 index 0000000000..0987d921fc --- /dev/null +++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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_MAC_P_H +#define QPAINTENGINE_MAC_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 "private/qpaintengine_p.h" +#include "private/qpolygonclipper_p.h" +#include "private/qfont_p.h" +#include "QtCore/qhash.h" + +#include "qt_mac_p.h" + +typedef struct CGColorSpace *CGColorSpaceRef; +QT_BEGIN_NAMESPACE + +class QCoreGraphicsPaintEnginePrivate; +class QCoreGraphicsPaintEngine : public QPaintEngine +{ + Q_DECLARE_PRIVATE(QCoreGraphicsPaintEngine) + +public: + QCoreGraphicsPaintEngine(); + ~QCoreGraphicsPaintEngine(); + + bool begin(QPaintDevice *pdev); + bool end(); + static CGColorSpaceRef macGenericColorSpace(); + static CGColorSpaceRef macDisplayColorSpace(const QWidget *widget = 0); + + void updateState(const QPaintEngineState &state); + + void updatePen(const QPen &pen); + void updateBrush(const QBrush &brush, const QPointF &pt); + void updateFont(const QFont &font); + void updateOpacity(qreal opacity); + void updateMatrix(const QTransform &matrix); + void updateTransform(const QTransform &matrix); + void updateClipRegion(const QRegion ®ion, Qt::ClipOperation op); + void updateClipPath(const QPainterPath &path, Qt::ClipOperation op); + void updateCompositionMode(QPainter::CompositionMode mode); + void updateRenderHints(QPainter::RenderHints hints); + + void drawLines(const QLineF *lines, int lineCount); + void drawRects(const QRectF *rects, int rectCount); + void drawPoints(const QPointF *p, int pointCount); + void drawEllipse(const QRectF &r); + void drawPath(const QPainterPath &path); + + void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); + + void drawTextItem(const QPointF &pos, const QTextItem &item); + void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, + Qt::ImageConversionFlags flags = Qt::AutoColor); + + Type type() const { return QPaintEngine::CoreGraphics; } + + CGContextRef handle() const; + + static void initialize(); + static void cleanup(); + + QPainter::RenderHints supportedRenderHints() const; + + //avoid partial shadowed overload warnings... + void drawLines(const QLine *lines, int lineCount) { QPaintEngine::drawLines(lines, lineCount); } + void drawRects(const QRect *rects, int rectCount) { QPaintEngine::drawRects(rects, rectCount); } + void drawPoints(const QPoint *p, int pointCount) { QPaintEngine::drawPoints(p, pointCount); } + void drawEllipse(const QRect &r) { QPaintEngine::drawEllipse(r); } + void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) + { QPaintEngine::drawPolygon(points, pointCount, mode); } + + bool supportsTransformations(qreal, const QTransform &) const { return true; }; + +protected: + friend class QMacPrintEngine; + friend class QMacPrintEnginePrivate; + QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr); + +private: + static bool m_postRoutineRegistered; + static CGColorSpaceRef m_genericColorSpace; + static QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash; + static void cleanUpMacColorSpaces(); + Q_DISABLE_COPY(QCoreGraphicsPaintEngine) +}; + +/***************************************************************************** + Private data + *****************************************************************************/ +class QCoreGraphicsPaintEnginePrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QCoreGraphicsPaintEngine) +public: + QCoreGraphicsPaintEnginePrivate() + : hd(0), shading(0), stackCount(0), complexXForm(false), disabledSmoothFonts(false) + { + } + + struct { + QPen pen; + QBrush brush; + uint clipEnabled : 1; + QRegion clip; + QTransform transform; + } current; + + //state info (shared with QD) + CGAffineTransform orig_xform; + + //cg structures + CGContextRef hd; + CGShadingRef shading; + int stackCount; + bool complexXForm; + bool disabledSmoothFonts; + enum { CosmeticNone, CosmeticTransformPath, CosmeticSetPenWidth } cosmeticPen; + + // pixel and cosmetic pen size in user coordinates. + QPointF pixelSize; + float cosmeticPenSize; + + //internal functions + enum { CGStroke=0x01, CGEOFill=0x02, CGFill=0x04 }; + void drawPath(uchar ops, CGMutablePathRef path = 0); + void setClip(const QRegion *rgn=0); + void resetClip(); + void setFillBrush(const QPointF &origin=QPoint()); + void setStrokePen(const QPen &pen); + inline void saveGraphicsState(); + inline void restoreGraphicsState(); + float penOffset(); + QPointF devicePixelSize(CGContextRef context); + float adjustPenWidth(float penWidth); + inline void setTransform(const QTransform *matrix=0) + { + CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd))); + CGAffineTransform xform = orig_xform; + if (matrix) { + extern CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &); + xform = CGAffineTransformConcat(qt_mac_convert_transform_to_cg(*matrix), xform); + } + CGContextConcatCTM(hd, xform); + CGContextSetTextMatrix(hd, xform); + } +}; + +inline void QCoreGraphicsPaintEnginePrivate::saveGraphicsState() +{ + ++stackCount; + CGContextSaveGState(hd); +} + +inline void QCoreGraphicsPaintEnginePrivate::restoreGraphicsState() +{ + --stackCount; + Q_ASSERT(stackCount >= 0); + CGContextRestoreGState(hd); +} + +class QMacQuartzPaintDevice : public QPaintDevice +{ +public: + QMacQuartzPaintDevice(CGContextRef cg, int width, int height, int bytesPerLine) + : mCG(cg), mWidth(width), mHeight(height), mBytesPerLine(bytesPerLine) + { } + int devType() const { return QInternal::MacQuartz; } + CGContextRef cgContext() const { return mCG; } + int metric(PaintDeviceMetric metric) const { + switch (metric) { + case PdmWidth: + return mWidth; + case PdmHeight: + return mHeight; + case PdmWidthMM: + return (qt_defaultDpiX() * mWidth) / 2.54; + case PdmHeightMM: + return (qt_defaultDpiY() * mHeight) / 2.54; + case PdmNumColors: + return 0; + case PdmDepth: + return 32; + case PdmDpiX: + case PdmPhysicalDpiX: + return qt_defaultDpiX(); + case PdmDpiY: + case PdmPhysicalDpiY: + return qt_defaultDpiY(); + } + return 0; + } + QPaintEngine *paintEngine() const { qWarning("This function should never be called."); return 0; } +private: + CGContextRef mCG; + int mWidth; + int mHeight; + int mBytesPerLine; +}; + +QT_END_NAMESPACE + +#endif // QPAINTENGINE_MAC_P_H diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm new file mode 100644 index 0000000000..e432b12e67 --- /dev/null +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -0,0 +1,817 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 "qprintengine_mac_p.h" +#include <qdebug.h> +#include <qthread.h> +#include <QtCore/qcoreapplication.h> +#include <QtPrintSupport/QPlatformPrinterSupport> + +#include "qcocoaautoreleasepool.h" + +#ifndef QT_NO_PRINTER + +QT_BEGIN_NAMESPACE + +QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(new QMacPrintEnginePrivate)) +{ + Q_D(QMacPrintEngine); + d->mode = mode; + d->initialize(); +} + +bool QMacPrintEngine::begin(QPaintDevice *dev) +{ + Q_D(QMacPrintEngine); + + Q_ASSERT(dev && dev->devType() == QInternal::Printer); + if (!static_cast<QPrinter *>(dev)->isValid()) + return false; + + if (d->state == QPrinter::Idle && !d->isPrintSessionInitialized()) // Need to reinitialize + d->initialize(); + + d->paintEngine->state = state; + d->paintEngine->begin(dev); + Q_ASSERT_X(d->state == QPrinter::Idle, "QMacPrintEngine", "printer already active"); + + if (PMSessionValidatePrintSettings(d->session(), d->settings(), kPMDontWantBoolean) != noErr + || PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean) != noErr) { + d->state = QPrinter::Error; + return false; + } + + if (!d->outputFilename.isEmpty()) { + QCFType<CFURLRef> outFile = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, + QCFString(d->outputFilename), + kCFURLPOSIXPathStyle, + false); + if (PMSessionSetDestination(d->session(), d->settings(), kPMDestinationFile, + kPMDocumentFormatPDF, outFile) != noErr) { + qWarning("QMacPrintEngine::begin: Problem setting file [%s]", d->outputFilename.toUtf8().constData()); + return false; + } + } + + OSStatus status = PMSessionBeginCGDocumentNoDialog(d->session(), d->settings(), d->format()); + if (status != noErr) { + d->state = QPrinter::Error; + return false; + } + + d->state = QPrinter::Active; + setActive(true); + d->newPage_helper(); + return true; +} + +bool QMacPrintEngine::end() +{ + Q_D(QMacPrintEngine); + if (d->state == QPrinter::Aborted) + return true; // I was just here a function call ago :) + if (d->paintEngine->type() == QPaintEngine::CoreGraphics) { + // We dont need the paint engine to call restoreGraphicsState() + static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0; + static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0; + } + d->paintEngine->end(); + if (d->state != QPrinter::Idle) + d->releaseSession(); + d->state = QPrinter::Idle; + return true; +} + +QPaintEngine * +QMacPrintEngine::paintEngine() const +{ + return d_func()->paintEngine; +} + +Qt::HANDLE QMacPrintEngine::handle() const +{ + QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine()); + return cgEngine->d_func()->hd; +} + +QMacPrintEnginePrivate::~QMacPrintEnginePrivate() +{ + [printInfo release]; + delete paintEngine; +} + +void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps) +{ + Q_Q(QMacPrintEngine); + QSizeF newSize = QPlatformPrinterSupport::convertPaperSizeToQSizeF(ps); + QCFType<CFArrayRef> formats; + PMPrinter printer; + + if (PMSessionGetCurrentPrinter(session(), &printer) == noErr + && PMSessionCreatePageFormatList(session(), printer, &formats) == noErr) { + CFIndex total = CFArrayGetCount(formats); + PMPageFormat tmp; + PMRect paper; + for (CFIndex idx = 0; idx < total; ++idx) { + tmp = static_cast<PMPageFormat>( + const_cast<void *>(CFArrayGetValueAtIndex(formats, idx))); + PMGetUnadjustedPaperRect(tmp, &paper); + int wMM = int((paper.right - paper.left) / 72 * 25.4 + 0.5); + int hMM = int((paper.bottom - paper.top) / 72 * 25.4 + 0.5); + if (newSize.width() == wMM && newSize.height() == hMM) { + PMCopyPageFormat(tmp, format()); + // reset the orientation and resolution as they are lost in the copy. + q->setProperty(QPrintEngine::PPK_Orientation, orient); + if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) { + // Don't know, warn for the moment. + qWarning("QMacPrintEngine, problem setting format and resolution for this page size"); + } + break; + } + } + } +} + +QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const +{ + if (hasCustomPaperSize) + return QPrinter::Custom; + PMRect paper; + PMGetUnadjustedPaperRect(format(), &paper); + QSizeF sizef((paper.right - paper.left) / 72.0 * 25.4, (paper.bottom - paper.top) / 72.0 * 25.4); + return QPlatformPrinterSupport::convertQSizeFToPaperSize(sizef); +} + +QList<QVariant> QMacPrintEnginePrivate::supportedResolutions() const +{ + Q_ASSERT_X(printInfo, "QMacPrinterEngine::supportedResolutions", + "must have a valid printer session"); + UInt32 resCount; + QList<QVariant> resolutions; + PMPrinter printer; + if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { + PMResolution res; + OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount); + if (status == kPMNotImplemented) { +#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) + // *Sigh* we have to use the non-indexed version. + if (PMPrinterGetPrinterResolution(printer, kPMMinSquareResolution, &res) == noErr) + resolutions.append(int(res.hRes)); + if (PMPrinterGetPrinterResolution(printer, kPMMaxSquareResolution, &res) == noErr) { + QVariant var(int(res.hRes)); + if (!resolutions.contains(var)) + resolutions.append(var); + } + if (PMPrinterGetPrinterResolution(printer, kPMDefaultResolution, &res) == noErr) { + QVariant var(int(res.hRes)); + if (!resolutions.contains(var)) + resolutions.append(var); + } +#endif + } else if (status == noErr) { + // According to the docs, index start at 1. + for (UInt32 i = 1; i <= resCount; ++i) { + if (PMPrinterGetIndexedPrinterResolution(printer, i, &res) == noErr) + resolutions.append(QVariant(int(res.hRes))); + } + } else { + qWarning("QMacPrintEngine::supportedResolutions: Unexpected error: %ld", long(status)); + } + } + return resolutions; +} + +QPrinter::PrinterState QMacPrintEngine::printerState() const +{ + return d_func()->state; +} + +bool QMacPrintEngine::newPage() +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + OSStatus err = PMSessionEndPageNoDialog(d->session()); + if (err != noErr) { + if (err == kPMCancel) { + // User canceled, we need to abort! + abort(); + } else { + // Not sure what the problem is... + qWarning("QMacPrintEngine::newPage: Cannot end current page. %ld", long(err)); + d->state = QPrinter::Error; + } + return false; + } + return d->newPage_helper(); +} + +bool QMacPrintEngine::abort() +{ + Q_D(QMacPrintEngine); + if (d->state != QPrinter::Active) + return false; + bool ret = end(); + d->state = QPrinter::Aborted; + return ret; +} + +static inline int qt_get_PDMWidth(PMPageFormat pformat, bool fullPage, + const PMResolution &resolution) +{ + int val = 0; + PMRect r; + qreal hRatio = resolution.hRes / 72; + if (fullPage) { + if (PMGetAdjustedPaperRect(pformat, &r) == noErr) + val = qRound((r.right - r.left) * hRatio); + } else { + if (PMGetAdjustedPageRect(pformat, &r) == noErr) + val = qRound((r.right - r.left) * hRatio); + } + return val; +} + +static inline int qt_get_PDMHeight(PMPageFormat pformat, bool fullPage, + const PMResolution &resolution) +{ + int val = 0; + PMRect r; + qreal vRatio = resolution.vRes / 72; + if (fullPage) { + if (PMGetAdjustedPaperRect(pformat, &r) == noErr) + val = qRound((r.bottom - r.top) * vRatio); + } else { + if (PMGetAdjustedPageRect(pformat, &r) == noErr) + val = qRound((r.bottom - r.top) * vRatio); + } + return val; +} + + +int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const +{ + Q_D(const QMacPrintEngine); + int val = 1; + switch (m) { + case QPaintDevice::PdmWidth: + if (d->hasCustomPaperSize) { + val = qRound(d->customSize.width()); + if (d->hasCustomPageMargins) { + val -= qRound(d->leftMargin + d->rightMargin); + } else { + QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList(); + val -= qRound(margins.at(0).toDouble() + margins.at(2).toDouble()); + } + } else { + val = qt_get_PDMWidth(d->format(), property(PPK_FullPage).toBool(), d->resolution); + } + break; + case QPaintDevice::PdmHeight: + if (d->hasCustomPaperSize) { + val = qRound(d->customSize.height()); + if (d->hasCustomPageMargins) { + val -= qRound(d->topMargin + d->bottomMargin); + } else { + QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList(); + val -= qRound(margins.at(1).toDouble() + margins.at(3).toDouble()); + } + } else { + val = qt_get_PDMHeight(d->format(), property(PPK_FullPage).toBool(), d->resolution); + } + break; + case QPaintDevice::PdmWidthMM: + val = metric(QPaintDevice::PdmWidth); + val = int((val * 254 + 5 * d->resolution.hRes) / (10 * d->resolution.hRes)); + break; + case QPaintDevice::PdmHeightMM: + val = metric(QPaintDevice::PdmHeight); + val = int((val * 254 + 5 * d->resolution.vRes) / (10 * d->resolution.vRes)); + break; + case QPaintDevice::PdmPhysicalDpiX: + case QPaintDevice::PdmPhysicalDpiY: { + PMPrinter printer; + if (PMSessionGetCurrentPrinter(d->session(), &printer) == noErr) { + PMResolution resolution; + PMPrinterGetOutputResolution(printer, d->settings(), &resolution); + val = (int)resolution.vRes; + break; + } + //otherwise fall through + } + case QPaintDevice::PdmDpiY: + val = (int)d->resolution.vRes; + break; + case QPaintDevice::PdmDpiX: + val = (int)d->resolution.hRes; + break; + case QPaintDevice::PdmNumColors: + val = (1 << metric(QPaintDevice::PdmDepth)); + break; + case QPaintDevice::PdmDepth: + val = 24; + break; + default: + val = 0; + qWarning("QPrinter::metric: Invalid metric command"); + } + return val; +} + +void QMacPrintEnginePrivate::initialize() +{ + Q_Q(QMacPrintEngine); + + Q_ASSERT(!printInfo); + + if (!paintEngine) + paintEngine = new QCoreGraphicsPaintEngine(); + + q->gccaps = paintEngine->gccaps; + + fullPage = false; + + QCocoaAutoReleasePool pool; + printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]]; + + PMPrinter printer; + if (printInfo && PMSessionGetCurrentPrinter(session(), &printer) == noErr) { + QList<QVariant> resolutions = supportedResolutions(); + if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { + if (resolutions.count() > 1 && mode == QPrinter::HighResolution) { + int max = 0; + for (int i = 0; i < resolutions.count(); ++i) { + int value = resolutions.at(i).toInt(); + if (value > max) + max = value; + } + resolution.hRes = resolution.vRes = max; + } else { + resolution.hRes = resolution.vRes = resolutions.at(0).toInt(); + } + if (resolution.hRes == 0) + resolution.hRes = resolution.vRes = 600; + } else { + resolution.hRes = resolution.vRes = qt_defaultDpi(); + } + } + + QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant>::const_iterator propC; + for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) { + q->setProperty(propC.key(), propC.value()); + } +} + +void QMacPrintEnginePrivate::releaseSession() +{ + PMSessionEndPageNoDialog(session()); + PMSessionEndDocumentNoDialog(session()); + [printInfo release]; + printInfo = 0; +} + +bool QMacPrintEnginePrivate::newPage_helper() +{ + Q_Q(QMacPrintEngine); + Q_ASSERT(state == QPrinter::Active); + + if (PMSessionError(session()) != noErr) { + q->abort(); + return false; + } + + // pop the stack of saved graphic states, in case we get the same + // context back - either way, the stack count should be 0 when we + // get the new one + QCoreGraphicsPaintEngine *cgEngine = static_cast<QCoreGraphicsPaintEngine*>(paintEngine); + while (cgEngine->d_func()->stackCount > 0) + cgEngine->d_func()->restoreGraphicsState(); + + OSStatus status = PMSessionBeginPageNoDialog(session(), format(), 0); + if (status != noErr) { + state = QPrinter::Error; + return false; + } + + QRect page = q->property(QPrintEngine::PPK_PageRect).toRect(); + QRect paper = q->property(QPrintEngine::PPK_PaperRect).toRect(); + + CGContextRef cgContext; + OSStatus err = noErr; + err = PMSessionGetCGGraphicsContext(session(), &cgContext); + if (err != noErr) { + qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err)); + state = QPrinter::Error; + return false; + } + cgEngine->d_func()->hd = cgContext; + + // Set the resolution as a scaling ration of 72 (the default). + CGContextScaleCTM(cgContext, 72 / resolution.hRes, 72 / resolution.vRes); + + CGContextScaleCTM(cgContext, 1, -1); + CGContextTranslateCTM(cgContext, 0, -paper.height()); + if (!fullPage) + CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y()); + cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext); + cgEngine->d_func()->setClip(0); + cgEngine->state->dirtyFlags = QPaintEngine::DirtyFlag(QPaintEngine::AllDirty + & ~(QPaintEngine::DirtyClipEnabled + | QPaintEngine::DirtyClipRegion + | QPaintEngine::DirtyClipPath)); + if (cgEngine->painter()->hasClipping()) + cgEngine->state->dirtyFlags |= QPaintEngine::DirtyClipEnabled; + cgEngine->syncState(); + return true; +} + + +void QMacPrintEngine::updateState(const QPaintEngineState &state) +{ + d_func()->paintEngine->updateState(state); +} + +void QMacPrintEngine::drawRects(const QRectF *r, int num) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawRects(r, num); +} + +void QMacPrintEngine::drawPoints(const QPointF *points, int pointCount) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawPoints(points, pointCount); +} + +void QMacPrintEngine::drawEllipse(const QRectF &r) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawEllipse(r); +} + +void QMacPrintEngine::drawLines(const QLineF *lines, int lineCount) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawLines(lines, lineCount); +} + +void QMacPrintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawPolygon(points, pointCount, mode); +} + +void QMacPrintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawPixmap(r, pm, sr); +} + +void QMacPrintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawImage(r, pm, sr, flags); +} + +void QMacPrintEngine::drawTextItem(const QPointF &p, const QTextItem &ti) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawTextItem(p, ti); +} + +void QMacPrintEngine::drawTiledPixmap(const QRectF &dr, const QPixmap &pixmap, const QPointF &sr) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawTiledPixmap(dr, pixmap, sr); +} + +void QMacPrintEngine::drawPath(const QPainterPath &path) +{ + Q_D(QMacPrintEngine); + Q_ASSERT(d->state == QPrinter::Active); + d->paintEngine->drawPath(path); +} + + +void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value) +{ + Q_D(QMacPrintEngine); + + d->valueCache.insert(key, value); + if (!d->printInfo) + return; + + switch (key) { + case PPK_CollateCopies: + break; + case PPK_ColorMode: + break; + case PPK_Creator: + break; + case PPK_DocumentName: + break; + case PPK_PageOrder: + break; + case PPK_PaperSource: + break; + case PPK_SelectionOption: + break; + case PPK_Resolution: { + PMPrinter printer; + UInt32 count; + if (PMSessionGetCurrentPrinter(d->session(), &printer) != noErr) + break; + if (PMPrinterGetPrinterResolutionCount(printer, &count) != noErr) + break; + PMResolution resolution = { 0.0, 0.0 }; + PMResolution bestResolution = { 0.0, 0.0 }; + int dpi = value.toInt(); + int bestDistance = INT_MAX; + for (UInt32 i = 1; i <= count; ++i) { // Yes, it starts at 1 + if (PMPrinterGetIndexedPrinterResolution(printer, i, &resolution) == noErr) { + if (dpi == int(resolution.hRes)) { + bestResolution = resolution; + break; + } else { + int distance = qAbs(dpi - int(resolution.hRes)); + if (distance < bestDistance) { + bestDistance = distance; + bestResolution = resolution; + } + } + } + } + PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); + break; + } + + case PPK_FullPage: + d->fullPage = value.toBool(); + break; + case PPK_CopyCount: // fallthrough + case PPK_NumberOfCopies: + PMSetCopies(d->settings(), value.toInt(), false); + break; + case PPK_Orientation: { + if (d->state == QPrinter::Active) { + qWarning("QMacPrintEngine::setOrientation: Orientation cannot be changed during a print job, ignoring change"); + } else { + QPrinter::Orientation newOrientation = QPrinter::Orientation(value.toInt()); + if (d->hasCustomPaperSize && (d->orient != newOrientation)) + d->customSize = QSizeF(d->customSize.height(), d->customSize.width()); + d->orient = newOrientation; + PMOrientation o = d->orient == QPrinter::Portrait ? kPMPortrait : kPMLandscape; + PMSetOrientation(d->format(), o, false); + PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); + } + break; } + case PPK_OutputFileName: + d->outputFilename = value.toString(); + break; + case PPK_PaperSize: + d->setPaperSize(QPrinter::PaperSize(value.toInt())); + break; + case PPK_PrinterName: { + bool printerNameSet = false; + OSStatus status = noErr; + QCFType<CFArrayRef> printerList; + status = PMServerCreatePrinterList(kPMServerLocal, &printerList); + if (status == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i=0; i<count; ++i) { + PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i))); + QString name = QCFString::toQString(PMPrinterGetName(printer)); + if (name == value.toString()) { + status = PMSessionSetCurrentPMPrinter(d->session(), printer); + printerNameSet = true; + break; + } + } + } + if (status != noErr) + qWarning("QMacPrintEngine::setPrinterName: Error setting printer: %ld", long(status)); + if (!printerNameSet) { + qWarning("QMacPrintEngine::setPrinterName: Failed to set printer named '%s'.", qPrintable(value.toString())); + d->releaseSession(); + d->state = QPrinter::Idle; + } + break; } + case PPK_SuppressSystemPrintStatus: + break; + case PPK_CustomPaperSize: + { + PMOrientation orientation; + PMGetOrientation(d->format(), &orientation); + d->hasCustomPaperSize = true; + d->customSize = value.toSizeF(); + if (orientation != kPMPortrait) + d->customSize = QSizeF(d->customSize.height(), d->customSize.width()); + break; + } + case PPK_PageMargins: + { + QList<QVariant> margins(value.toList()); + Q_ASSERT(margins.size() == 4); + d->leftMargin = margins.at(0).toDouble(); + d->topMargin = margins.at(1).toDouble(); + d->rightMargin = margins.at(2).toDouble(); + d->bottomMargin = margins.at(3).toDouble(); + d->hasCustomPageMargins = true; + break; + } + + default: + break; + } +} + +QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const +{ + Q_D(const QMacPrintEngine); + QVariant ret; + + if (!d->printInfo && d->valueCache.contains(key)) + return *d->valueCache.find(key); + + switch (key) { + case PPK_CollateCopies: + ret = false; + break; + case PPK_ColorMode: + ret = QPrinter::Color; + break; + case PPK_Creator: + break; + case PPK_DocumentName: + break; + case PPK_FullPage: + ret = d->fullPage; + break; + case PPK_NumberOfCopies: + ret = 1; + break; + case PPK_CopyCount: { + UInt32 copies = 1; + PMGetCopies(d->settings(), &copies); + ret = (uint) copies; + break; + } + case PPK_SupportsMultipleCopies: + ret = true; + break; + case PPK_Orientation: + PMOrientation orientation; + PMGetOrientation(d->format(), &orientation); + ret = orientation == kPMPortrait ? QPrinter::Portrait : QPrinter::Landscape; + break; + case PPK_OutputFileName: + ret = d->outputFilename; + break; + case PPK_PageOrder: + break; + case PPK_PaperSource: + break; + case PPK_PageRect: { + // PageRect is returned in device pixels + QRect r; + PMRect macrect, macpaper; + qreal hRatio = d->resolution.hRes / 72; + qreal vRatio = d->resolution.vRes / 72; + if (d->hasCustomPaperSize) { + r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio)); + if (d->hasCustomPageMargins) { + r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), + -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio)); + } else { + QList<QVariant> margins = property(QPrintEngine::PPK_PageMargins).toList(); + r.adjust(qRound(margins.at(0).toDouble() * hRatio), + qRound(margins.at(1).toDouble() * vRatio), + -qRound(margins.at(2).toDouble() * hRatio), + -qRound(margins.at(3).toDouble()) * vRatio); + } + } else if (PMGetAdjustedPageRect(d->format(), ¯ect) == noErr + && PMGetAdjustedPaperRect(d->format(), &macpaper) == noErr) + { + if (d->fullPage || d->hasCustomPageMargins) { + r.setCoords(int(macpaper.left * hRatio), int(macpaper.top * vRatio), + int(macpaper.right * hRatio), int(macpaper.bottom * vRatio)); + r.translate(-r.x(), -r.y()); + if (d->hasCustomPageMargins) { + r.adjust(qRound(d->leftMargin * hRatio), qRound(d->topMargin * vRatio), + -qRound(d->rightMargin * hRatio), -qRound(d->bottomMargin * vRatio)); + } + } else { + r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio), + int(macrect.right * hRatio), int(macrect.bottom * vRatio)); + r.translate(int(-macpaper.left * hRatio), int(-macpaper.top * vRatio)); + } + } + ret = r; + break; } + case PPK_PaperSize: + ret = d->paperSize(); + break; + case PPK_PaperRect: { + QRect r; + PMRect macrect; + qreal hRatio = d->resolution.hRes / 72; + qreal vRatio = d->resolution.vRes / 72; + if (d->hasCustomPaperSize) { + r = QRect(0, 0, qRound(d->customSize.width() * hRatio), qRound(d->customSize.height() * vRatio)); + } else if (PMGetAdjustedPaperRect(d->format(), ¯ect) == noErr) { + r.setCoords(int(macrect.left * hRatio), int(macrect.top * vRatio), + int(macrect.right * hRatio), int(macrect.bottom * vRatio)); + r.translate(-r.x(), -r.y()); + } + ret = r; + break; } + case PPK_PrinterName: { + PMPrinter printer; + OSStatus status = PMSessionGetCurrentPrinter(d->session(), &printer); + if (status != noErr) + qWarning("QMacPrintEngine::printerName: Failed getting current PMPrinter: %ld", long(status)); + if (printer) + ret = QCFString::toQString(PMPrinterGetName(printer)); + break; } + case PPK_Resolution: { + ret = d->resolution.hRes; + break; + } + case PPK_SupportedResolutions: + ret = d->supportedResolutions(); + break; + case PPK_CustomPaperSize: + ret = d->customSize; + break; + case PPK_PageMargins: + { + QList<QVariant> margins; + if (d->hasCustomPageMargins) { + margins << d->leftMargin << d->topMargin + << d->rightMargin << d->bottomMargin; + } else { + PMPaperMargins paperMargins; + PMPaper paper; + PMGetPageFormatPaper(d->format(), &paper); + PMPaperGetMargins(paper, &paperMargins); + margins << paperMargins.left << paperMargins.top + << paperMargins.right << paperMargins.bottom; + } + ret = margins; + break; + } + default: + break; + } + return ret; +} + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h new file mode 100644 index 0000000000..2d37b43dfa --- /dev/null +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 QPRINTENGINE_MAC_P_H +#define QPRINTENGINE_MAC_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. +// + +#ifndef QT_NO_PRINTER + +#include <QtPrintSupport/qprinter.h> +#include <QtPrintSupport/qprintengine.h> +#include <QtGui/private/qpainter_p.h> + +#include "qpaintengine_mac_p.h" + +#ifdef __OBJC__ +@class NSPrintInfo; +#else +typedef void NSPrintInfo; +#endif + +QT_BEGIN_NAMESPACE + +class QPrinterPrivate; +class QMacPrintEnginePrivate; +class QMacPrintEngine : public QPaintEngine, public QPrintEngine +{ + Q_DECLARE_PRIVATE(QMacPrintEngine) +public: + QMacPrintEngine(QPrinter::PrinterMode mode); + + Qt::HANDLE handle() const; + + bool begin(QPaintDevice *dev); + bool end(); + virtual QPaintEngine::Type type() const { return QPaintEngine::MacPrinter; } + + QPaintEngine *paintEngine() const; + + void setProperty(PrintEnginePropertyKey key, const QVariant &value); + QVariant property(PrintEnginePropertyKey key) const; + + QPrinter::PrinterState printerState() const; + + bool newPage(); + bool abort(); + int metric(QPaintDevice::PaintDeviceMetric) const; + + //forwarded functions + + void updateState(const QPaintEngineState &state); + + virtual void drawLines(const QLineF *lines, int lineCount); + virtual void drawRects(const QRectF *r, int num); + virtual void drawPoints(const QPointF *p, int pointCount); + virtual void drawEllipse(const QRectF &r); + virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); + virtual void drawTextItem(const QPointF &p, const QTextItem &ti); + virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s); + virtual void drawPath(const QPainterPath &); + +private: + friend class QCocoaNativeInterface; +}; + +class QMacPrintEnginePrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QMacPrintEngine) +public: + QPrinter::PrinterMode mode; + QPrinter::PrinterState state; + QPrinter::Orientation orient; + NSPrintInfo *printInfo; + PMResolution resolution; + QString outputFilename; + bool fullPage; + QPaintEngine *paintEngine; + bool hasCustomPaperSize; + QSizeF customSize; + bool hasCustomPageMargins; + qreal leftMargin; + qreal topMargin; + qreal rightMargin; + qreal bottomMargin; + QHash<QMacPrintEngine::PrintEnginePropertyKey, QVariant> valueCache; + QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), + orient(QPrinter::Portrait), printInfo(0), paintEngine(0), + hasCustomPaperSize(false), hasCustomPageMargins(false) {} + ~QMacPrintEnginePrivate(); + void initialize(); + void releaseSession(); + bool newPage_helper(); + void setPaperSize(QPrinter::PaperSize ps); + QPrinter::PaperSize paperSize() const; + QList<QVariant> supportedResolutions() const; + inline bool isPrintSessionInitialized() const + { + return printInfo != 0; + } + + PMPageFormat format() const { return static_cast<PMPageFormat>([printInfo PMPageFormat]); } + PMPrintSession session() const { return static_cast<PMPrintSession>([printInfo PMPrintSession]); } + PMPrintSettings settings() const { return static_cast<PMPrintSettings>([printInfo PMPrintSettings]); } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER + +#endif // QPRINTENGINE_WIN_P_H diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h index b75e6e2bcb..f881965b32 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/cocoa/qt_mac_p.h @@ -159,7 +159,7 @@ class QMacCGContext { CGContextRef context; public: - QMacCGContext(QPainter *p); //qpaintengine_mac.cpp + QMacCGContext(QPainter *p); //qpaintengine_mac.mm inline QMacCGContext() { context = 0; } inline QMacCGContext(const QPaintDevice *pdev) { extern CGContextRef qt_mac_cg_context(const QPaintDevice *); diff --git a/src/plugins/platforms/eglfs/eglfs.json b/src/plugins/platforms/eglfs/eglfs.json new file mode 100644 index 0000000000..c1ad6ca028 --- /dev/null +++ b/src/plugins/platforms/eglfs/eglfs.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs" ] +} diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro index 291e09d6ed..ed8503b53c 100644 --- a/src/plugins/platforms/eglfs/eglfs.pro +++ b/src/plugins/platforms/eglfs/eglfs.pro @@ -1,6 +1,5 @@ TARGET = qeglfs -TEMPLATE = lib -CONFIG += plugin +load(qt_plugin) QT += core-private gui-private platformsupport-private @@ -29,3 +28,6 @@ CONFIG += qpa/genericunixfontdatabase target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target + +OTHER_FILES += \ + eglfs.json diff --git a/src/plugins/platforms/eglfs/main.cpp b/src/plugins/platforms/eglfs/main.cpp index e4167bf173..2ca2199619 100644 --- a/src/plugins/platforms/eglfs/main.cpp +++ b/src/plugins/platforms/eglfs/main.cpp @@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE class QEglIntegrationPlugin : public QPlatformIntegrationPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPlatformIntegrationFactoryInterface" FILE "eglfs.json") public: QStringList keys() const; QPlatformIntegration *create(const QString&, const QStringList&); @@ -67,6 +69,6 @@ QPlatformIntegration* QEglIntegrationPlugin::create(const QString& system, const return 0; } -Q_EXPORT_PLUGIN2(eglintegration, QEglIntegrationPlugin) - QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 9507b08ade..9c03af7594 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -60,7 +60,6 @@ QT_BEGIN_NAMESPACE class QQnxGLContext; class QQnxScreen; -class QPlatformGLContext; class QSurfaceFormat; class QQnxWindow : public QPlatformWindow diff --git a/src/plugins/platforms/uikit/README b/src/plugins/platforms/uikit/README deleted file mode 100644 index f878cce50e..0000000000 --- a/src/plugins/platforms/uikit/README +++ /dev/null @@ -1,45 +0,0 @@ -This is a proof-of-concept implemenation of a UIKit based -QPA plugin. Note that this is completely unsupported, and it is probable -that many parts of QtCore and other Qt Modules don't work properly. - -1) Build Qt - -The example Xcode project in the examples subdirectory requires that you do shadow -builds of Qt in qt-lighthouse-ios-simulator and qt-lighthouse-ios-device directories -parallel to the sources. To build for simulator make sure that both the Simulator -configuration *and* the simulator specific target are active. To build for device -make sure that both the Device configuration *and* the device specific target are -active. - -The setup is configured to use the iOS 4.2 SDKs, you might want to edit the mkspecs -to fit your need. - -After configuring and building Qt you need to also build src/plugins/platforms/uikit. - -Simulator: ----------- -configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations - -Device: -------- -configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations - -2) XCode setup: -- there are examples in the examples subdirectory of the platform plugin -- to create something fresh do something like: - - Xcode: Create a "View-based Appplication" - - remove the nibs and view controller and app controller files - - remove the reference to "Main nib file" from plist file - - create a main.mm like in the examples - - add the qmlapplicationviewer sources to your project (including the moc_*.h) - (best to link, not copy), the code for this is from the Qt Creator - mobile Qt Quick application template - - Add the Qt .a libraries, uikit platform plugin and libz (v1.2.3) to Frameworks - - add "$(SRCROOT)/../../../../qt-lighthouse-ios-device/include" (or -simulator) - to the include search paths. - - add "$(SRCROOT)/../qmltest" to the include search path if you didn't copy but - linked to the qmlapplicationviewer - - for device set the architecture to armv7 only - -3) Done: Build and Run. - diff --git a/src/plugins/platforms/uikit/examples/qmltest/main.mm b/src/plugins/platforms/uikit/examples/qmltest/main.mm deleted file mode 100644 index 68eef2a353..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/main.mm +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#import <UIKit/UIKit.h> - -#include "qmlapplicationviewer/qmlapplicationviewer.h" - -#include <QtGui/QApplication> -#include <QtCore/QtPlugin> -#include <QtDeclarative/QDeclarativeEngine> - -Q_IMPORT_PLUGIN(UIKit) - -static QString qStringFromNSString(NSString *nsstring) -{ - return QString::fromUtf8([nsstring UTF8String]); -} - -static QString documentsDirectory() -{ - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - return qStringFromNSString(documentsDirectory); -} - -int main(int argc, char *argv[]) { - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - - QApplication app(argc, argv); - QmlApplicationViewer viewer; - viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); - viewer.engine()->setOfflineStoragePath(documentsDirectory()); - NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; - viewer.setMainQmlFile(qStringFromNSString([resourcePath stringByAppendingPathComponent:@"qml/main.qml"])); - viewer.showMaximized(); - int retVal = app.exec(); - [pool release]; - return retVal; -} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qml/main.qml b/src/plugins/platforms/uikit/examples/qmltest/qml/main.qml deleted file mode 100644 index 07e8eb08a6..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qml/main.qml +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor -** the names of its contributors may be used to endorse or promote -** products derived from this software without specific prior written -** permission. -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 1.0 - -Rectangle { - id: box - width: 350; height: 250 - - Rectangle { - id: redSquare - width: 80; height: 80 - anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10 - color: "red" - - Text { text: "Click"; font.pixelSize: 16; anchors.centerIn: parent } - - MouseArea { - anchors.fill: parent - hoverEnabled: true - acceptedButtons: Qt.LeftButton | Qt.RightButton - - onEntered: info.text = 'Entered' - onExited: info.text = 'Exited (pressed=' + pressed + ')' - - onPressed: { - info.text = 'Pressed (button=' + (mouse.button == Qt.RightButton ? 'right' : 'left') - + ' shift=' + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')' - var posInBox = redSquare.mapToItem(box, mouse.x, mouse.y) - posInfo.text = + mouse.x + ',' + mouse.y + ' in square' - + ' (' + posInBox.x + ',' + posInBox.y + ' in window)' - } - - onReleased: { - info.text = 'Released (isClick=' + mouse.isClick + ' wasHeld=' + mouse.wasHeld + ')' - posInfo.text = '' - } - - onPressAndHold: info.text = 'Press and hold' - onClicked: info.text = 'Clicked (wasHeld=' + mouse.wasHeld + ')' - onDoubleClicked: info.text = 'Double clicked' - } - } - - Rectangle { - id: blueSquare - width: 80; height: 80 - x: box.width - width - 10; y: 10 // making this item draggable, so don't use anchors - color: "blue" - - Text { text: "Drag"; font.pixelSize: 16; color: "white"; anchors.centerIn: parent } - - MouseArea { - anchors.fill: parent - drag.target: blueSquare - drag.axis: Drag.XandYAxis - drag.minimumX: 0 - drag.maximumX: box.width - parent.width - drag.minimumY: 0 - drag.maximumY: box.height - parent.width - } - } - - Text { - id: info - anchors.bottom: posInfo.top; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 30 - - onTextChanged: console.log(text) - } - - Text { - id: posInfo - anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 30 - } -} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp deleted file mode 100644 index 2b36a87272..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -/**************************************************************************** -** Meta object code from reading C++ file 'qmlapplicationviewer.h' -** -** Created: Fri Feb 18 17:53:42 2011 -** by: The Qt Meta Object Compiler version 62 (Qt 4.7.2) -** -** WARNING! All changes made in this file will be lost! -*****************************************************************************/ - -#include "qmlapplicationviewer.h" -#if !defined(Q_MOC_OUTPUT_REVISION) -#error "The header file 'qmlapplicationviewer.h' doesn't include <QObject>." -#elif Q_MOC_OUTPUT_REVISION != 62 -#error "This file was generated using the moc from 4.7.2. It" -#error "cannot be used with the include files from this version of Qt." -#error "(The moc has changed too much.)" -#endif - -QT_BEGIN_MOC_NAMESPACE -static const uint qt_meta_data_QmlApplicationViewer[] = { - - // content: - 5, // revision - 0, // classname - 0, 0, // classinfo - 0, 0, // methods - 0, 0, // properties - 0, 0, // enums/sets - 0, 0, // constructors - 0, // flags - 0, // signalCount - - 0 // eod -}; - -static const char qt_meta_stringdata_QmlApplicationViewer[] = { - "QmlApplicationViewer\0" -}; - -const QMetaObject QmlApplicationViewer::staticMetaObject = { - { &QDeclarativeView::staticMetaObject, qt_meta_stringdata_QmlApplicationViewer, - qt_meta_data_QmlApplicationViewer, 0 } -}; - -#ifdef Q_NO_DATA_RELOCATION -const QMetaObject &QmlApplicationViewer::getStaticMetaObject() { return staticMetaObject; } -#endif //Q_NO_DATA_RELOCATION - -const QMetaObject *QmlApplicationViewer::metaObject() const -{ - return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; -} - -void *QmlApplicationViewer::qt_metacast(const char *_clname) -{ - if (!_clname) return 0; - if (!strcmp(_clname, qt_meta_stringdata_QmlApplicationViewer)) - return static_cast<void*>(const_cast< QmlApplicationViewer*>(this)); - return QDeclarativeView::qt_metacast(_clname); -} - -int QmlApplicationViewer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) -{ - _id = QDeclarativeView::qt_metacall(_c, _id, _a); - if (_id < 0) - return _id; - return _id; -} -QT_END_MOC_NAMESPACE diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp deleted file mode 100644 index aba9366d47..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -// checksum 0x17fa version 0x3000a -/* - This file was generated by the Qt Quick Application wizard of Qt Creator. - QmlApplicationViewer is a convenience class containing mobile device specific - code such as screen orientation handling. Also QML paths and debugging are - handled here. - It is recommended not to modify this file, since newer versions of Qt Creator - may offer an updated version of it. -*/ - -#include "qmlapplicationviewer.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QDir> -#include <QtCore/QFileInfo> -#include <QtDeclarative/QDeclarativeComponent> -#include <QtDeclarative/QDeclarativeEngine> -#include <QtDeclarative/QDeclarativeContext> - -#if defined(QMLJSDEBUGGER) -#include <qt_private/qdeclarativedebughelper_p.h> -#endif - -#if defined(QMLJSDEBUGGER) && !defined(NO_JSDEBUGGER) -#include <jsdebuggeragent.h> -#endif -#if defined(QMLJSDEBUGGER) && !defined(NO_QMLOBSERVER) -#include <qdeclarativeviewobserver.h> -#endif - -#if defined(QMLJSDEBUGGER) - -// Enable debugging before any QDeclarativeEngine is created -struct QmlJsDebuggingEnabler -{ - QmlJsDebuggingEnabler() - { - QDeclarativeDebugHelper::enableDebugging(); - } -}; - -// Execute code in constructor before first QDeclarativeEngine is instantiated -static QmlJsDebuggingEnabler enableDebuggingHelper; - -#endif // QMLJSDEBUGGER - -class QmlApplicationViewerPrivate -{ - QString mainQmlFile; - friend class QmlApplicationViewer; - static QString adjustPath(const QString &path); -}; - -QString QmlApplicationViewerPrivate::adjustPath(const QString &path) -{ -#ifdef Q_OS_UNIX -#ifdef Q_OS_MAC - if (!QDir::isAbsolutePath(path)) - return QCoreApplication::applicationDirPath() - + QLatin1String("/../Resources/") + path; -#else - const QString pathInShareDir = QCoreApplication::applicationDirPath() - + QLatin1String("/../share/") - + QFileInfo(QCoreApplication::applicationFilePath()).fileName() - + QLatin1Char('/') + path; - if (QFileInfo(pathInShareDir).exists()) - return pathInShareDir; -#endif -#endif - return path; -} - -QmlApplicationViewer::QmlApplicationViewer(QWidget *parent) : - QDeclarativeView(parent), - m_d(new QmlApplicationViewerPrivate) -{ - connect(engine(), SIGNAL(quit()), SLOT(close())); - setResizeMode(QDeclarativeView::SizeRootObjectToView); -#if defined(QMLJSDEBUGGER) && !defined(NO_JSDEBUGGER) - new QmlJSDebugger::JSDebuggerAgent(engine()); -#endif -#if defined(QMLJSDEBUGGER) && !defined(NO_QMLOBSERVER) - new QmlJSDebugger::QDeclarativeViewObserver(this, parent); -#endif -} - -QmlApplicationViewer::~QmlApplicationViewer() -{ - delete m_d; -} - -void QmlApplicationViewer::setMainQmlFile(const QString &file) -{ - m_d->mainQmlFile = QmlApplicationViewerPrivate::adjustPath(file); - setSource(QUrl::fromLocalFile(m_d->mainQmlFile)); -} - -void QmlApplicationViewer::addImportPath(const QString &path) -{ - engine()->addImportPath(QmlApplicationViewerPrivate::adjustPath(path)); -} - -void QmlApplicationViewer::setOrientation(ScreenOrientation orientation) -{ -// Qt::WidgetAttribute attribute; -// switch (orientation) { -//#if QT_VERSION < 0x040702 -// // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes -// case ScreenOrientationLockPortrait: -// attribute = static_cast<Qt::WidgetAttribute>(128); -// break; -// case ScreenOrientationLockLandscape: -// attribute = static_cast<Qt::WidgetAttribute>(129); -// break; -// default: -// case ScreenOrientationAuto: -// attribute = static_cast<Qt::WidgetAttribute>(130); -// break; -//#else // QT_VERSION < 0x040702 -// case ScreenOrientationLockPortrait: -// attribute = Qt::WA_LockPortraitOrientation; -// break; -// case ScreenOrientationLockLandscape: -// attribute = Qt::WA_LockLandscapeOrientation; -// break; -// default: -// case ScreenOrientationAuto: -// attribute = Qt::WA_AutoOrientation; -// break; -//#endif // QT_VERSION < 0x040702 -// }; -// setAttribute(attribute, true); -} - -void QmlApplicationViewer::showExpanded() -{ - show(); -} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h deleted file mode 100644 index e2ee5b5069..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -// checksum 0x5a59 version 0x3000a -/* - This file was generated by the Qt Quick Application wizard of Qt Creator. - QmlApplicationViewer is a convenience class containing mobile device specific - code such as screen orientation handling. Also QML paths and debugging are - handled here. - It is recommended not to modify this file, since newer versions of Qt Creator - may offer an updated version of it. -*/ - -#ifndef QMLAPPLICATIONVIEWER_H -#define QMLAPPLICATIONVIEWER_H - -#include <QtDeclarative/QDeclarativeView> - -class QmlApplicationViewer : public QDeclarativeView -{ - Q_OBJECT - -public: - enum ScreenOrientation { - ScreenOrientationLockPortrait, - ScreenOrientationLockLandscape, - ScreenOrientationAuto - }; - - explicit QmlApplicationViewer(QWidget *parent = 0); - virtual ~QmlApplicationViewer(); - - void setMainQmlFile(const QString &file); - void addImportPath(const QString &path); - void setOrientation(ScreenOrientation orientation); - void showExpanded(); - -private: - class QmlApplicationViewerPrivate *m_d; -}; - -#endif // QMLAPPLICATIONVIEWER_H diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist b/src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist deleted file mode 100644 index 15665856b0..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDevelopmentRegion</key> - <string>English</string> - <key>CFBundleDisplayName</key> - <string>${PRODUCT_NAME}</string> - <key>CFBundleExecutable</key> - <string>${EXECUTABLE_NAME}</string> - <key>CFBundleIconFile</key> - <string></string> - <key>CFBundleIdentifier</key> - <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>${PRODUCT_NAME}</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleVersion</key> - <string>1.0</string> - <key>LSRequiresIPhoneOS</key> - <true/> -</dict> -</plist> diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj deleted file mode 100755 index 10bb20fcb9..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj +++ /dev/null @@ -1,491 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 45; - objects = { - -/* Begin PBXBuildFile section */ - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - D316594E1338B29E00760B02 /* libQtXml_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D31659431338B21000760B02 /* libQtXml_debug.a */; }; - D316594F1338B29E00760B02 /* libQtXmlPatterns_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */; }; - D35784241345D8C90046D202 /* libQtOpenGL_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784231345D8C90046D202 /* libQtOpenGL_debug.a */; }; - D35784261345D9940046D202 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784251345D9940046D202 /* OpenGLES.framework */; }; - D35784281345D9E00046D202 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784271345D9E00046D202 /* QuartzCore.framework */; }; - D3578436134A09990046D202 /* libQtOpenGL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3578435134A09990046D202 /* libQtOpenGL.a */; }; - D3578439134A0AAE0046D202 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784251345D9940046D202 /* OpenGLES.framework */; }; - D357843A134A0AB10046D202 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D35784271345D9E00046D202 /* QuartzCore.framework */; }; - D3CAA7C813264AAD008BB877 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7C713264AAD008BB877 /* main.mm */; }; - D3CAA7E613264EA6008BB877 /* moc_qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */; }; - D3CAA7E713264EA6008BB877 /* qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */; }; - D3CAA7EC13264F52008BB877 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7C713264AAD008BB877 /* main.mm */; }; - D3CAA7ED13264F52008BB877 /* moc_qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */; }; - D3CAA7EE13264F52008BB877 /* qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */; }; - D3CAA7F013264F52008BB877 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; - D3CAA7F113264F52008BB877 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; - D3CAA7F213264F52008BB877 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; - D3CAA7FA13264F8A008BB877 /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */; }; - D3CAA81113264FF0008BB877 /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */; }; - D3CAA81B13265056008BB877 /* libQtCore_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81613265056008BB877 /* libQtCore_debug.a */; }; - D3CAA81C13265056008BB877 /* libQtDeclarative_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */; }; - D3CAA81D13265056008BB877 /* libQtGui_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81813265056008BB877 /* libQtGui_debug.a */; }; - D3CAA81E13265056008BB877 /* libQtScript_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81913265056008BB877 /* libQtScript_debug.a */; }; - D3CAA81F13265056008BB877 /* libQtSql_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81A13265056008BB877 /* libQtSql_debug.a */; }; - D3CAA8211326507D008BB877 /* libquikit_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA8201326507D008BB877 /* libquikit_debug.a */; }; - D3CAA82813265220008BB877 /* libQtNetwork_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA82713265220008BB877 /* libQtNetwork_debug.a */; }; - D3CAA88A132652E5008BB877 /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA836132652E5008BB877 /* fonts */; }; - D3CAA88B132652E5008BB877 /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA836132652E5008BB877 /* fonts */; }; - D3CAA89113265310008BB877 /* qml in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA88E13265310008BB877 /* qml */; }; - D3CAA89213265310008BB877 /* qml in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA88E13265310008BB877 /* qml */; }; - D3D817B2132A2CFD00CDE422 /* libQtCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AA132A2CFD00CDE422 /* libQtCore.a */; }; - D3D817B3132A2CFD00CDE422 /* libQtDeclarative.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */; }; - D3D817B4132A2CFD00CDE422 /* libQtGui.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AC132A2CFD00CDE422 /* libQtGui.a */; }; - D3D817B5132A2CFD00CDE422 /* libQtNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */; }; - D3D817B6132A2CFD00CDE422 /* libQtScript.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AE132A2CFD00CDE422 /* libQtScript.a */; }; - D3D817B7132A2CFD00CDE422 /* libQtSql.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AF132A2CFD00CDE422 /* libQtSql.a */; }; - D3D817B8132A2CFD00CDE422 /* libQtXml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817B0132A2CFD00CDE422 /* libQtXml.a */; }; - D3D817B9132A2CFD00CDE422 /* libQtXmlPatterns.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817B1132A2CFD00CDE422 /* libQtXmlPatterns.a */; }; - D3D817BB132A2D0E00CDE422 /* libquikit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817BA132A2D0E00CDE422 /* libquikit.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 1D6058910D05DD3D006BFB54 /* qmltest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = qmltest.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qmltest_Prefix.pch; sourceTree = "<group>"; }; - 8D1107310486CEB800E47090 /* qmltest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "qmltest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; }; - D31659431338B21000760B02 /* libQtXml_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXml_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtXml_debug.a"; sourceTree = SOURCE_ROOT; }; - D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXmlPatterns_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtXmlPatterns_debug.a"; sourceTree = SOURCE_ROOT; }; - D35784231345D8C90046D202 /* libQtOpenGL_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtOpenGL_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtOpenGL_debug.a"; sourceTree = "<group>"; }; - D35784251345D9940046D202 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; - D35784271345D9E00046D202 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - D3578435134A09990046D202 /* libQtOpenGL.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtOpenGL.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtOpenGL.a"; sourceTree = "<group>"; }; - D3CAA7C713264AAD008BB877 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; - D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_qmlapplicationviewer.cpp; path = qmlapplicationviewer/moc_qmlapplicationviewer.cpp; sourceTree = "<group>"; }; - D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qmlapplicationviewer.cpp; path = qmlapplicationviewer/qmlapplicationviewer.cpp; sourceTree = "<group>"; }; - D3CAA7E513264EA6008BB877 /* qmlapplicationviewer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qmlapplicationviewer.h; path = qmlapplicationviewer/qmlapplicationviewer.h; sourceTree = "<group>"; }; - D3CAA7F613264F52008BB877 /* qmltest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = qmltest.app; sourceTree = BUILT_PRODUCTS_DIR; }; - D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.2.3.dylib; path = usr/lib/libz.1.2.3.dylib; sourceTree = SDKROOT; }; - D3CAA81613265056008BB877 /* libQtCore_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtCore_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtCore_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtDeclarative_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtDeclarative_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA81813265056008BB877 /* libQtGui_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtGui_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtGui_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA81913265056008BB877 /* libQtScript_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtScript_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtScript_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA81A13265056008BB877 /* libQtSql_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtSql_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtSql_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA8201326507D008BB877 /* libquikit_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libquikit_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/plugins/platforms/libquikit_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA82713265220008BB877 /* libQtNetwork_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtNetwork_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtNetwork_debug.a"; sourceTree = SOURCE_ROOT; }; - D3CAA836132652E5008BB877 /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = fonts; path = ../../../../../../lib/fonts; sourceTree = SOURCE_ROOT; }; - D3CAA88E13265310008BB877 /* qml */ = {isa = PBXFileReference; lastKnownFileType = folder; path = qml; sourceTree = SOURCE_ROOT; }; - D3D817AA132A2CFD00CDE422 /* libQtCore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtCore.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtCore.a"; sourceTree = SOURCE_ROOT; }; - D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtDeclarative.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtDeclarative.a"; sourceTree = SOURCE_ROOT; }; - D3D817AC132A2CFD00CDE422 /* libQtGui.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtGui.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtGui.a"; sourceTree = SOURCE_ROOT; }; - D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtNetwork.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtNetwork.a"; sourceTree = SOURCE_ROOT; }; - D3D817AE132A2CFD00CDE422 /* libQtScript.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtScript.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtScript.a"; sourceTree = SOURCE_ROOT; }; - D3D817AF132A2CFD00CDE422 /* libQtSql.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtSql.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtSql.a"; sourceTree = SOURCE_ROOT; }; - D3D817B0132A2CFD00CDE422 /* libQtXml.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXml.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtXml.a"; sourceTree = SOURCE_ROOT; }; - D3D817B1132A2CFD00CDE422 /* libQtXmlPatterns.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXmlPatterns.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtXmlPatterns.a"; sourceTree = SOURCE_ROOT; }; - D3D817BA132A2D0E00CDE422 /* libquikit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libquikit.a; path = "../../../../../../../qt-lighthouse-ios-device/plugins/platforms/libquikit.a"; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D35784281345D9E00046D202 /* QuartzCore.framework in Frameworks */, - 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, - 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, - 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, - D35784261345D9940046D202 /* OpenGLES.framework in Frameworks */, - D3CAA7FA13264F8A008BB877 /* libz.1.2.3.dylib in Frameworks */, - D3CAA81B13265056008BB877 /* libQtCore_debug.a in Frameworks */, - D3CAA81C13265056008BB877 /* libQtDeclarative_debug.a in Frameworks */, - D3CAA81D13265056008BB877 /* libQtGui_debug.a in Frameworks */, - D3CAA81E13265056008BB877 /* libQtScript_debug.a in Frameworks */, - D3CAA81F13265056008BB877 /* libQtSql_debug.a in Frameworks */, - D3CAA8211326507D008BB877 /* libquikit_debug.a in Frameworks */, - D3CAA82813265220008BB877 /* libQtNetwork_debug.a in Frameworks */, - D316594E1338B29E00760B02 /* libQtXml_debug.a in Frameworks */, - D316594F1338B29E00760B02 /* libQtXmlPatterns_debug.a in Frameworks */, - D35784241345D8C90046D202 /* libQtOpenGL_debug.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D3CAA7EF13264F52008BB877 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D357843A134A0AB10046D202 /* QuartzCore.framework in Frameworks */, - D3578439134A0AAE0046D202 /* OpenGLES.framework in Frameworks */, - D3CAA7F013264F52008BB877 /* Foundation.framework in Frameworks */, - D3CAA7F113264F52008BB877 /* UIKit.framework in Frameworks */, - D3CAA7F213264F52008BB877 /* CoreGraphics.framework in Frameworks */, - D3CAA81113264FF0008BB877 /* libz.1.2.3.dylib in Frameworks */, - D3D817B2132A2CFD00CDE422 /* libQtCore.a in Frameworks */, - D3D817B3132A2CFD00CDE422 /* libQtDeclarative.a in Frameworks */, - D3D817B4132A2CFD00CDE422 /* libQtGui.a in Frameworks */, - D3D817B5132A2CFD00CDE422 /* libQtNetwork.a in Frameworks */, - D3D817B6132A2CFD00CDE422 /* libQtScript.a in Frameworks */, - D3D817B7132A2CFD00CDE422 /* libQtSql.a in Frameworks */, - D3D817B8132A2CFD00CDE422 /* libQtXml.a in Frameworks */, - D3D817B9132A2CFD00CDE422 /* libQtXmlPatterns.a in Frameworks */, - D3D817BB132A2D0E00CDE422 /* libquikit.a in Frameworks */, - D3578436134A09990046D202 /* libQtOpenGL.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 19C28FACFE9D520D11CA2CBB /* Products */ = { - isa = PBXGroup; - children = ( - 1D6058910D05DD3D006BFB54 /* qmltest.app */, - D3CAA7F613264F52008BB877 /* qmltest.app */, - ); - name = Products; - sourceTree = "<group>"; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - D3CAA7E213264E8C008BB877 /* QMLApplicationViewer */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = "<group>"; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */, - D3CAA7C713264AAD008BB877 /* main.mm */, - ); - name = "Other Sources"; - sourceTree = "<group>"; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - D3CAA88E13265310008BB877 /* qml */, - D3CAA836132652E5008BB877 /* fonts */, - 8D1107310486CEB800E47090 /* qmltest-Info.plist */, - ); - name = Resources; - sourceTree = "<group>"; - }; - 29B97323FDCFA39411CA2CEA /* Frameworks */ = { - isa = PBXGroup; - children = ( - D3CAA81513265035008BB877 /* Simulator */, - D3CAA8141326500A008BB877 /* Device */, - 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, - 1D30AB110D05D00D00671497 /* Foundation.framework */, - 288765A40DF7441C002DB57D /* CoreGraphics.framework */, - D35784251345D9940046D202 /* OpenGLES.framework */, - D35784271345D9E00046D202 /* QuartzCore.framework */, - D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */, - ); - name = Frameworks; - sourceTree = "<group>"; - }; - D3CAA7E213264E8C008BB877 /* QMLApplicationViewer */ = { - isa = PBXGroup; - children = ( - D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */, - D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */, - D3CAA7E513264EA6008BB877 /* qmlapplicationviewer.h */, - ); - name = QMLApplicationViewer; - sourceTree = "<group>"; - }; - D3CAA8141326500A008BB877 /* Device */ = { - isa = PBXGroup; - children = ( - D3D817BA132A2D0E00CDE422 /* libquikit.a */, - D3D817AA132A2CFD00CDE422 /* libQtCore.a */, - D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */, - D3D817AC132A2CFD00CDE422 /* libQtGui.a */, - D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */, - D3578435134A09990046D202 /* libQtOpenGL.a */, - D3D817AE132A2CFD00CDE422 /* libQtScript.a */, - D3D817AF132A2CFD00CDE422 /* libQtSql.a */, - D3D817B0132A2CFD00CDE422 /* libQtXml.a */, - D3D817B1132A2CFD00CDE422 /* libQtXmlPatterns.a */, - ); - name = Device; - sourceTree = "<group>"; - }; - D3CAA81513265035008BB877 /* Simulator */ = { - isa = PBXGroup; - children = ( - D3CAA8201326507D008BB877 /* libquikit_debug.a */, - D3CAA81613265056008BB877 /* libQtCore_debug.a */, - D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */, - D3CAA81813265056008BB877 /* libQtGui_debug.a */, - D3CAA82713265220008BB877 /* libQtNetwork_debug.a */, - D35784231345D8C90046D202 /* libQtOpenGL_debug.a */, - D3CAA81913265056008BB877 /* libQtScript_debug.a */, - D3CAA81A13265056008BB877 /* libQtSql_debug.a */, - D31659431338B21000760B02 /* libQtXml_debug.a */, - D31659441338B21000760B02 /* libQtXmlPatterns_debug.a */, - ); - name = Simulator; - sourceTree = "<group>"; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* qmltest simulator */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "qmltest simulator" */; - buildPhases = ( - 1D60588D0D05DD3D006BFB54 /* Resources */, - 1D60588E0D05DD3D006BFB54 /* Sources */, - 1D60588F0D05DD3D006BFB54 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "qmltest simulator"; - productName = qmltest; - productReference = 1D6058910D05DD3D006BFB54 /* qmltest.app */; - productType = "com.apple.product-type.application"; - }; - D3CAA7E813264F52008BB877 /* qmltest device */ = { - isa = PBXNativeTarget; - buildConfigurationList = D3CAA7F313264F52008BB877 /* Build configuration list for PBXNativeTarget "qmltest device" */; - buildPhases = ( - D3CAA7E913264F52008BB877 /* Resources */, - D3CAA7EB13264F52008BB877 /* Sources */, - D3CAA7EF13264F52008BB877 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "qmltest device"; - productName = qmltest; - productReference = D3CAA7F613264F52008BB877 /* qmltest.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 29B97313FDCFA39411CA2CEA /* Project object */ = { - isa = PBXProject; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "qmltest" */; - compatibilityVersion = "Xcode 3.1"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 1D6058900D05DD3D006BFB54 /* qmltest simulator */, - D3CAA7E813264F52008BB877 /* qmltest device */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 1D60588D0D05DD3D006BFB54 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D3CAA88A132652E5008BB877 /* fonts in Resources */, - D3CAA89113265310008BB877 /* qml in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D3CAA7E913264F52008BB877 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D3CAA88B132652E5008BB877 /* fonts in Resources */, - D3CAA89213265310008BB877 /* qml in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1D60588E0D05DD3D006BFB54 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D3CAA7C813264AAD008BB877 /* main.mm in Sources */, - D3CAA7E613264EA6008BB877 /* moc_qmlapplicationviewer.cpp in Sources */, - D3CAA7E713264EA6008BB877 /* qmlapplicationviewer.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D3CAA7EB13264F52008BB877 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D3CAA7EC13264F52008BB877 /* main.mm in Sources */, - D3CAA7ED13264F52008BB877 /* moc_qmlapplicationviewer.cpp in Sources */, - D3CAA7EE13264F52008BB877 /* qmlapplicationviewer.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 1D6058940D05DD3E006BFB54 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = qmltest_Prefix.pch; - HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/include\"/**"; - INFOPLIST_FILE = "qmltest-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/lib\"", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/plugins/platforms\"", - ); - PRODUCT_NAME = qmltest; - }; - name = Debug; - }; - 1D6058950D05DD3E006BFB54 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = qmltest_Prefix.pch; - HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/include\"/**"; - INFOPLIST_FILE = "qmltest-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/lib\"", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/plugins/platforms\"", - ); - PRODUCT_NAME = qmltest; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - C01FCF4F08A954540054247B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - PREBINDING = NO; - SDKROOT = iphoneos; - }; - name = Debug; - }; - C01FCF5008A954540054247B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; - PREBINDING = NO; - SDKROOT = iphoneos; - }; - name = Release; - }; - D3CAA7F413264F52008BB877 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = qmltest_Prefix.pch; - HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/include\"/**"; - INFOPLIST_FILE = "qmltest-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/lib\"", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/plugins/platforms\"", - ); - PRODUCT_NAME = qmltest; - }; - name = Debug; - }; - D3CAA7F513264F52008BB877 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; - COPY_PHASE_STRIP = YES; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = qmltest_Prefix.pch; - HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/include\"/**"; - INFOPLIST_FILE = "qmltest-Info.plist"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/lib\"", - "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/plugins/platforms\"", - ); - PRODUCT_NAME = qmltest; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "qmltest simulator" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1D6058940D05DD3E006BFB54 /* Debug */, - 1D6058950D05DD3E006BFB54 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "qmltest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C01FCF4F08A954540054247B /* Debug */, - C01FCF5008A954540054247B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D3CAA7F313264F52008BB877 /* Build configuration list for PBXNativeTarget "qmltest device" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D3CAA7F413264F52008BB877 /* Debug */, - D3CAA7F513264F52008BB877 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; -} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch b/src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch deleted file mode 100644 index c06715c661..0000000000 --- a/src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'qmltest' target in the 'qmltest' project -// - -#ifdef __OBJC__ - #import <Foundation/Foundation.h> - #import <UIKit/UIKit.h> -#endif diff --git a/src/plugins/platforms/uikit/quikiteventloop.mm b/src/plugins/platforms/uikit/quikiteventloop.mm deleted file mode 100644 index 43df46705d..0000000000 --- a/src/plugins/platforms/uikit/quikiteventloop.mm +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 "quikiteventloop.h" -#include "quikitwindow.h" -#include "quikitwindowsurface.h" - -#include <UIKit/UIKit.h> - -#include <QtGui/QApplication> -#include <QtGui/QWidget> -#include <QtDebug> - -@interface QUIKitAppDelegate : NSObject <UIApplicationDelegate> { -} -@end - -@interface EventLoopHelper : NSObject { - QUIKitEventLoop *mIntegration; -} - -- (id)initWithEventLoopIntegration:(QUIKitEventLoop *)integration; - -- (void)processEvents; -- (void)processEventsAndSchedule; - -@end - -@implementation QUIKitAppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - Q_UNUSED(launchOptions) - Q_UNUSED(application) - foreach (QWidget *widget, qApp->topLevelWidgets()) { - QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); - platformWindow->ensureNativeWindow(); - } - return YES; -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - Q_UNUSED(application) - // TODO this isn't called for some reason - qDebug() << "quit"; - qApp->quit(); -} - -@end - -@implementation EventLoopHelper - -- (id)initWithEventLoopIntegration:(QUIKitEventLoop *)integration -{ - if ((self = [self init])) { - mIntegration = integration; - } - return self; -} - -- (void)processEvents -{ - QPlatformEventLoopIntegration::processEvents(); -} - -- (void)processEventsAndSchedule -{ - QPlatformEventLoopIntegration::processEvents(); - qint64 nextTime = mIntegration->nextTimerEvent(); - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - NSDate *nextDate = [[NSDate date] dateByAddingTimeInterval:((double)nextTime/1000)]; - [mIntegration->mTimer setFireDate:nextDate]; - [pool release]; -} - -@end - -QT_BEGIN_NAMESPACE - -QUIKitEventLoop::QUIKitEventLoop() -{ - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - mInputHandler = new QUIKitSoftwareInputHandler; - mHelper = [[EventLoopHelper alloc] initWithEventLoopIntegration:this]; - mTimer = [[NSTimer timerWithTimeInterval:0.030 target:mHelper selector:@selector(processEventsAndSchedule) userInfo:nil repeats:YES] retain]; - [pool release]; -} - -QUIKitEventLoop::~QUIKitEventLoop() -{ - [mTimer release]; - [mHelper release]; - delete mInputHandler; -} - -void QUIKitEventLoop::startEventLoop() -{ - qApp->installEventFilter(mInputHandler); - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - [[NSRunLoop currentRunLoop] addTimer:[mTimer autorelease] forMode:NSDefaultRunLoopMode]; - UIApplicationMain(qApp->argc(), qApp->argv(), nil, @"QUIKitAppDelegate"); - [pool release]; -} - -void QUIKitEventLoop::quitEventLoop() -{ - -} - -void QUIKitEventLoop::qtNeedsToProcessEvents() -{ - [mHelper performSelectorOnMainThread:@selector(processEvents) withObject:nil waitUntilDone:NO]; -} - -bool QUIKitSoftwareInputHandler::eventFilter(QObject *obj, QEvent *event) -{ - if (event->type() == QEvent::RequestSoftwareInputPanel) { - QWidget *widget = qobject_cast<QWidget *>(obj); - if (widget) { - QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); - [platformWindow->nativeView() becomeFirstResponder]; - return true; - } - } else if (event->type() == QEvent::CloseSoftwareInputPanel) { - QWidget *widget = qobject_cast<QWidget *>(obj); - if (widget) { - QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); - [platformWindow->nativeView() resignFirstResponder]; - return true; - } - } - return false; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitintegration.mm b/src/plugins/platforms/uikit/quikitintegration.mm deleted file mode 100644 index 0c8579fc0f..0000000000 --- a/src/plugins/platforms/uikit/quikitintegration.mm +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 "quikitintegration.h" -#include "quikitwindow.h" -#include "quikitwindowsurface.h" -#include "quikitscreen.h" -#include "quikiteventloop.h" - -#include <QtGui/QApplication> - -#include <private/qpixmap_raster_p.h> - -#include <UIKit/UIKit.h> - -#include <QtDebug> - -QT_BEGIN_NAMESPACE - -QUIKitIntegration::QUIKitIntegration() -{ - mScreens << new QUIKitScreen(0); -} - -QUIKitIntegration::~QUIKitIntegration() -{ -} - -QPlatformPixmap *QUIKitIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const -{ - return new QRasterPlatformPixmap(type); -} - -QPlatformWindow *QUIKitIntegration::createPlatformWindow(QWidget *widget, WId winId) const -{ - Q_UNUSED(winId); - return new QUIKitWindow(widget); -} - -QList<QPlatformScreen *> QUIKitIntegration::screens() const -{ - return mScreens; -} - -QWindowSurface *QUIKitIntegration::createWindowSurface(QWidget *widget, WId winId) const -{ - Q_UNUSED(winId); - return new QUIKitWindowSurface(widget); -} - -QPlatformEventLoopIntegration *QUIKitIntegration::createEventLoopIntegration() const -{ - return new QUIKitEventLoop(); -} - -QPlatformFontDatabase * QUIKitIntegration::fontDatabase() const -{ - static bool initialized = false; - if (!initialized) { - initialized = true; - setenv("QT_QPA_FONTDIR",[[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"fonts"] UTF8String],1); - } - return QPlatformIntegration::fontDatabase(); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitscreen.mm b/src/plugins/platforms/uikit/quikitscreen.mm deleted file mode 100644 index 9569f95052..0000000000 --- a/src/plugins/platforms/uikit/quikitscreen.mm +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 "quikitscreen.h" - -#include <QtGui/QApplication> - -#include <QtDebug> - -QT_BEGIN_NAMESPACE - -QUIKitScreen::QUIKitScreen(int screenIndex) - : QPlatformScreen(), - m_index(screenIndex) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - UIScreen *screen = [[UIScreen screens] objectAtIndex:screenIndex]; - CGRect bounds = [screen bounds]; - m_geometry = QRect(bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height); - - m_format = QImage::Format_ARGB32; - - m_depth = 24; - - const qreal inch = 25.4; - qreal dpi = 160.; - int dragDistance = 12; - if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { - dpi = 132.; - dragDistance = 10; - } - m_physicalSize = QSizeF(bounds.size.width, bounds.size.height) * inch / dpi; - qApp->setStartDragDistance(dragDistance); - [pool release]; -} - -QUIKitScreen::~QUIKitScreen() -{ -} - -UIScreen *QUIKitScreen::uiScreen() const -{ - return [[UIScreen screens] objectAtIndex:m_index]; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindow.h b/src/plugins/platforms/uikit/quikitwindow.h deleted file mode 100644 index 7fe599f0cd..0000000000 --- a/src/plugins/platforms/uikit/quikitwindow.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 QUIKITWINDOW_H -#define QUIKITWINDOW_H - -#include <QPlatformWindow> - -#import <UIKit/UIKit.h> -#import <OpenGLES/ES1/gl.h> -#import <OpenGLES/ES1/glext.h> -#import <OpenGLES/ES2/gl.h> -#import <OpenGLES/ES2/glext.h> -#import <OpenGLES/EAGL.h> - -@interface EAGLView : UIView <UIKeyInput> -{ - QPlatformWindow *mWindow; - EAGLContext *mContext; - - GLint mFramebufferWidth; - GLint mFramebufferHeight; - - GLuint mFramebuffer, mColorRenderbuffer, mDepthRenderbuffer; - - id delegate; - // ------- Text Input ---------- - UITextAutocapitalizationType autocapitalizationType; - UITextAutocorrectionType autocorrectionType; - BOOL enablesReturnKeyAutomatically; - UIKeyboardAppearance keyboardAppearance; - UIKeyboardType keyboardType; - UIReturnKeyType returnKeyType; - BOOL secureTextEntry; -} - -- (void)setContext:(EAGLContext *)newContext; -- (void)presentFramebuffer; -- (void)deleteFramebuffer; -- (void)createFramebuffer; -- (void)makeCurrent; -- (void)setWindow:(QPlatformWindow *)window; -- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons; - -@property (readonly,getter=fbo) GLint fbo; -@property (nonatomic, assign) id delegate; - -// ------- Text Input ---------- - -@property(nonatomic) UITextAutocapitalizationType autocapitalizationType; -@property(nonatomic) UITextAutocorrectionType autocorrectionType; -@property(nonatomic) BOOL enablesReturnKeyAutomatically; -@property(nonatomic) UIKeyboardAppearance keyboardAppearance; -@property(nonatomic) UIKeyboardType keyboardType; -@property(nonatomic) UIReturnKeyType returnKeyType; -@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry; - -@end - -@protocol EAGLViewDelegate -- (void)eaglView:(EAGLView *)view usesFramebuffer:(GLuint)buffer; -@end - -class EAGLPlatformContext; - -QT_BEGIN_NAMESPACE - -class QUIKitScreen; - -class QUIKitWindow : public QPlatformWindow -{ -public: - explicit QUIKitWindow(QWidget *tlw); - ~QUIKitWindow(); - - UIWindow *nativeWindow() const { return mWindow; } - EAGLView *nativeView() const { return mView; } - void setGeometry(const QRect &rect); - - UIWindow *ensureNativeWindow(); - - QPlatformOpenGLContext *glContext() const; - -private: - QUIKitScreen *mScreen; - UIWindow *mWindow; - EAGLView *mView; - mutable EAGLPlatformContext *mContext; -}; - -QT_END_NAMESPACE - -#endif // QUIKITWINDOW_H diff --git a/src/plugins/platforms/uikit/quikitwindow.mm b/src/plugins/platforms/uikit/quikitwindow.mm deleted file mode 100644 index fb6711009a..0000000000 --- a/src/plugins/platforms/uikit/quikitwindow.mm +++ /dev/null @@ -1,392 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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$ -** -****************************************************************************/ - -#import <QuartzCore/CAEAGLLayer.h> - -#include "quikitwindow.h" - -#include "quikitscreen.h" - -#include <QtDebug> -#include <QtGui/QApplication> -#include <QtGui/QKeyEvent> -#include <QtGui/QPlatformOpenGLContext> -#include <QtGui/QWindowSystemInterface> - -#include <QtDebug> - -class EAGLPlatformContext : public QPlatformOpenGLContext -{ -public: - EAGLPlatformContext(EAGLView *view) - : mView(view) - { - mFormat.setWindowApi(QPlatformWindowFormat::OpenGL); - mFormat.setDepthBufferSize(24); - mFormat.setAccumBufferSize(0); - mFormat.setRedBufferSize(8); - mFormat.setGreenBufferSize(8); - mFormat.setBlueBufferSize(8); - mFormat.setAlphaBufferSize(8); - mFormat.setStencilBufferSize(8); - mFormat.setSampleBuffers(false); - mFormat.setSamples(1); -// mFormat.setSwapInterval(?) - mFormat.setDoubleBuffer(true); - mFormat.setDepth(true); - mFormat.setRgba(true); - mFormat.setAlpha(true); - mFormat.setAccum(false); - mFormat.setStencil(true); - mFormat.setStereo(false); - mFormat.setDirectRendering(false); - -#if defined(QT_OPENGL_ES_2) - EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; -#else - EAGLContext *aContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; -#endif - [mView setContext:aContext]; - } - - ~EAGLPlatformContext() { } - - void makeCurrent() - { - QPlatformOpenGLContext::makeCurrent(); - [mView makeCurrent]; - } - - void doneCurrent() - { - QPlatformOpenGLContext::doneCurrent(); - } - - void swapBuffers() - { - [mView presentFramebuffer]; - } - - void* getProcAddress(const QString& ) { return 0; } - - QPlatformWindowFormat platformWindowFormat() const - { - return mFormat; - } - -private: - EAGLView *mView; - - QPlatformWindowFormat mFormat; -}; - -@implementation EAGLView - -@synthesize delegate; - -+ (Class)layerClass -{ - return [CAEAGLLayer class]; -} - -- (id)initWithFrame:(CGRect)frame -{ - if ((self = [super initWithFrame:frame])) { - CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; - eaglLayer.opaque = TRUE; - eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking, - kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, - nil]; - autocapitalizationType = UITextAutocapitalizationTypeNone; - autocorrectionType = UITextAutocorrectionTypeNo; - enablesReturnKeyAutomatically = NO; - keyboardAppearance = UIKeyboardAppearanceDefault; - keyboardType = UIKeyboardTypeDefault; - returnKeyType = UIReturnKeyDone; - secureTextEntry = NO; - } - return self; -} - -- (void)setContext:(EAGLContext *)newContext -{ - if (mContext != newContext) - { - [self deleteFramebuffer]; - [mContext release]; - mContext = [newContext retain]; - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)presentFramebuffer -{ - if (mContext) { - [EAGLContext setCurrentContext:mContext]; - glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer); - [mContext presentRenderbuffer:GL_RENDERBUFFER]; - } -} - -- (void)deleteFramebuffer -{ - if (mContext) - { - [EAGLContext setCurrentContext:mContext]; - if (mFramebuffer) { - glDeleteFramebuffers(1, &mFramebuffer); - mFramebuffer = 0; - } - if (mColorRenderbuffer) { - glDeleteRenderbuffers(1, &mColorRenderbuffer); - mColorRenderbuffer = 0; - } - if (mDepthRenderbuffer) { - glDeleteRenderbuffers(1, &mDepthRenderbuffer); - mDepthRenderbuffer = 0; - } - } -} - -- (void)createFramebuffer -{ - if (mContext && !mFramebuffer) - { - [EAGLContext setCurrentContext:mContext]; - glGenFramebuffers(1, &mFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); - - glGenRenderbuffers(1, &mColorRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer); - [mContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer]; - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &mFramebufferWidth); - glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &mFramebufferHeight); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbuffer); - - glGenRenderbuffers(1, &mDepthRenderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, mFramebufferWidth, mFramebufferHeight); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbuffer); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); - if (delegate && [delegate respondsToSelector:@selector(eaglView:usesFramebuffer:)]) { - [delegate eaglView:self usesFramebuffer:mFramebuffer]; - } - } -} - -- (void)makeCurrent -{ - if (mContext) - { - [EAGLContext setCurrentContext:mContext]; - if (!mFramebuffer) - [self createFramebuffer]; - glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); - glViewport(0, 0, mFramebufferWidth, mFramebufferHeight); - } -} - -- (GLint)fbo -{ - return mFramebuffer; -} - -- (void)setWindow:(QPlatformWindow *)window -{ - mWindow = window; -} - -- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons -{ - UITouch *touch = [touches anyObject]; - CGPoint locationInView = [touch locationInView:self]; - QPoint p(locationInView.x, locationInView.y); - // TODO handle global touch point? for status bar? - QWindowSystemInterface::handleMouseEvent(mWindow->widget(), (ulong)(event.timestamp*1000), - p, p, buttons); -} - -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; -} - -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; -} - -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ - [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; -} - -// ------- Text Input ---------- - -@synthesize autocapitalizationType; -@synthesize autocorrectionType; -@synthesize enablesReturnKeyAutomatically; -@synthesize keyboardAppearance; -@synthesize keyboardType; -@synthesize returnKeyType; -@synthesize secureTextEntry; - -- (BOOL)canBecomeFirstResponder -{ - return YES; -} - -- (BOOL)hasText -{ - return YES; -} - -- (void)insertText:(NSString *)text -{ - QKeyEvent *ev; - int key = 0; - if ([text isEqualToString:@"\n"]) - key = (int)Qt::Key_Return; - ev = new QKeyEvent(QEvent::KeyPress, - key, - Qt::NoModifier, - QString::fromUtf8([text UTF8String]) - ); - qApp->postEvent(qApp->focusWidget(), ev); - ev = new QKeyEvent(QEvent::KeyRelease, - key, - Qt::NoModifier, - QString::fromUtf8([text UTF8String]) - ); - qApp->postEvent(qApp->focusWidget(), ev); -} - -- (void)deleteBackward -{ - QKeyEvent *ev; - ev = new QKeyEvent(QEvent::KeyPress, - (int)Qt::Key_Backspace, - Qt::NoModifier - ); - qApp->postEvent(qApp->focusWidget(), ev); - ev = new QKeyEvent(QEvent::KeyRelease, - (int)Qt::Key_Backspace, - Qt::NoModifier - ); - qApp->postEvent(qApp->focusWidget(), ev); -} - -@end - -QT_BEGIN_NAMESPACE - -QUIKitWindow::QUIKitWindow(QWidget *tlw) : - QPlatformWindow(tlw), - mWindow(nil), - mContext(0) -{ - mScreen = static_cast<QUIKitScreen *>(QPlatformScreen::platformScreenForWidget(tlw)); - CGRect screenBounds = [mScreen->uiScreen() bounds]; - QRect geom(screenBounds.origin.x, screenBounds.origin.y, screenBounds.size.width, screenBounds.size.height); - setGeometry(geom); - mView = [[EAGLView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; - // TODO ensure the native window if the application is already running -} - -QUIKitWindow::~QUIKitWindow() -{ - delete mContext; mContext = 0; - [mView release]; - [mWindow release]; -} - -void QUIKitWindow::setGeometry(const QRect &rect) -{ - if (mWindow && rect != geometry()) { - mWindow.frame = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); - mView.frame = CGRectMake(0, 0, rect.width(), rect.height()); - [mView deleteFramebuffer]; - [mWindow setNeedsDisplay]; - } - QPlatformWindow::setGeometry(rect); -} - -UIWindow *QUIKitWindow::ensureNativeWindow() -{ - if (!mWindow) { - // window - CGRect frame = [mScreen->uiScreen() applicationFrame]; - QRect geom = QRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); - widget()->setGeometry(geom); - mWindow = [[UIWindow alloc] init]; - mWindow.screen = mScreen->uiScreen(); - mWindow.frame = frame; // for some reason setting the screen resets frame.origin, so we need to set the frame afterwards - - // view - [mView deleteFramebuffer]; - mView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); // fill - [mView setMultipleTouchEnabled:YES]; - [mView setWindow:this]; - [mWindow addSubview:mView]; - [mWindow setNeedsDisplay]; - [mWindow makeKeyAndVisible]; - } - return mWindow; -} - -QPlatformOpenGLContext *QUIKitWindow::glContext() const -{ - if (!mContext) { - mContext = new EAGLPlatformContext(mView); - } - return mContext; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.mm b/src/plugins/platforms/uikit/quikitwindowsurface.mm deleted file mode 100644 index b7455b3bbe..0000000000 --- a/src/plugins/platforms/uikit/quikitwindowsurface.mm +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 "quikitwindowsurface.h" -#include "quikitwindow.h" - -#include <QtOpenGL/private/qgl_p.h> -#include <QtOpenGL/private/qglpaintdevice_p.h> - -#include <QtDebug> - -class EAGLPaintDevice; - -@interface PaintDeviceHelper : NSObject { - EAGLPaintDevice *device; -} - -@property (nonatomic, assign) EAGLPaintDevice *device; - -- (void)eaglView:(EAGLView *)view usesFramebuffer:(GLuint)buffer; - -@end - -class EAGLPaintDevice : public QGLPaintDevice -{ -public: - EAGLPaintDevice(QPlatformWindow *window) - :QGLPaintDevice(), mWindow(window) - { -#if defined(QT_OPENGL_ES_2) - helper = [[PaintDeviceHelper alloc] init]; - helper.device = this; - EAGLView *view = static_cast<QUIKitWindow *>(window)->nativeView(); - view.delegate = helper; - m_thisFBO = view.fbo; -#endif - } - - ~EAGLPaintDevice() - { -#if defined(QT_OPENGL_ES_2) - [helper release]; -#endif - } - - void setFramebuffer(GLuint buffer) { m_thisFBO = buffer; } - int devType() const { return QInternal::OpenGL; } - QSize size() const { return mWindow->geometry().size(); } - QGLContext* context() const { return QGLContext::fromPlatformGLContext(mWindow->glContext()); } - - QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } - -private: - QPlatformWindow *mWindow; - PaintDeviceHelper *helper; -}; - -@implementation PaintDeviceHelper -@synthesize device; - -- (void)eaglView:(EAGLView *)view usesFramebuffer:(GLuint)buffer -{ - Q_UNUSED(view) - if (device) - device->setFramebuffer(buffer); -} - -@end - -QT_BEGIN_NAMESPACE - -QUIKitWindowSurface::QUIKitWindowSurface(QWidget *window) - : QWindowSurface(window), mPaintDevice(new EAGLPaintDevice(window->platformWindow())) -{ -} - -QPaintDevice *QUIKitWindowSurface::paintDevice() -{ - return mPaintDevice; -} - -void QUIKitWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) -{ - Q_UNUSED(widget); - Q_UNUSED(region); - Q_UNUSED(offset); - widget->platformWindow()->glContext()->swapBuffers(); -} - -QWindowSurface::WindowSurfaceFeatures QUIKitWindowSurface::features() const -{ - return PartialUpdates; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/uikit.pro b/src/plugins/platforms/uikit/uikit.pro deleted file mode 100644 index 5e3a0e6b7c..0000000000 --- a/src/plugins/platforms/uikit/uikit.pro +++ /dev/null @@ -1,27 +0,0 @@ -TARGET = quikit -load(qpa/plugin) -QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms - -QT += opengl - -OBJECTIVE_SOURCES = main.mm \ - quikitintegration.mm \ - quikitwindow.mm \ - quikitscreen.mm \ - quikiteventloop.mm \ - quikitwindowsurface.mm - -OBJECTIVE_HEADERS = quikitintegration.h \ - quikitwindow.h \ - quikitscreen.h \ - quikiteventloop.h \ - quikitwindowsurface.h - -HEADERS = quikitsoftwareinputhandler.h - -#add libz for freetype. -LIBS += -lz - -#load(qpa/fontdatabases/basicunix) -target.path += $$[QT_INSTALL_PLUGINS]/platforms -INSTALLS += target diff --git a/src/plugins/platforms/vnc/qvnccursor.cpp b/src/plugins/platforms/vnc/qvnccursor.cpp deleted file mode 100644 index 52591bdc05..0000000000 --- a/src/plugins/platforms/vnc/qvnccursor.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 <QPainter> -#include <QTcpSocket> -#include <arpa/inet.h> -#include <QBitmap> -#include <QApplication> - -#include <QDebug> - -#include "qvnccursor.h" -#include "qvncserver.h" -#include "qvncintegration.h" - -QT_BEGIN_NAMESPACE - -QVNCCursor::QVNCCursor(QVNCServer * srvr, QVNCScreen *scr ) - :QPlatformSoftwareCursor(scr), useVncCursor(false), server(srvr) -{ -} - -void QVNCCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) -{ - QPlatformSoftwareCursor::changeCursor(widgetCursor, widget); - if (useVncCursor) { - server->setDirtyCursor(); - } else { - setDirty(); - } -} - -void QVNCCursor::setCursorMode(bool vnc) -{ - if (vnc) { - setDirty(); - server->setDirtyCursor(); - } else { - server->setDirtyCursor(); - } - useVncCursor = vnc; -} - -QRect QVNCCursor::drawCursor(QPainter & painter) -{ - if (useVncCursor) - return QRect(); - - return QPlatformSoftwareCursor::drawCursor(painter); -} - -void QVNCCursor::clearClientCursor() -{ - QTcpSocket *socket = server->clientSocket(); - if (!socket) { - return; - } - // FramebufferUpdate header - { - const quint16 tmp[6] = { htons(0), - htons(1), - htons(0), htons(0), - htons(0), - htons(0) }; - socket->write((char*)tmp, sizeof(tmp)); - - const quint32 encoding = htonl(-239); - socket->write((char*)(&encoding), sizeof(encoding)); - } -} - -void QVNCCursor::sendClientCursor() -{ - if (useVncCursor == false) { - clearClientCursor(); - return; - } - QImage *image = graphic->image(); - if (image->isNull()) - return; - QTcpSocket *socket = server->clientSocket(); - if (!socket) { - return; - } - // FramebufferUpdate header - { - const quint16 tmp[6] = { htons(0), - htons(1), - htons(graphic->hotspot().x()), htons(graphic->hotspot().y()), - htons(image->width()), - htons(image->height()) }; - socket->write((char*)tmp, sizeof(tmp)); - - const quint32 encoding = htonl(-239); - socket->write((char*)(&encoding), sizeof(encoding)); - } - - // write pixels - //Q_ASSERT(cursor->hasAlphaChannel()); - const QImage img = image->convertToFormat(QImage::Format_RGB32); - const int n = server->clientBytesPerPixel() * img.width(); - char *buffer = new char[n]; - for (int i = 0; i < img.height(); ++i) { - server->convertPixels(buffer, (const char*)img.scanLine(i), img.width()); - socket->write(buffer, n); - } - delete[] buffer; - - // write mask - const QImage bitmap = image->createAlphaMask().convertToFormat(QImage::Format_Mono); - Q_ASSERT(bitmap.depth() == 1); - Q_ASSERT(bitmap.size() == img.size()); - const int width = (bitmap.width() + 7) / 8; - for (int i = 0; i < bitmap.height(); ++i) - socket->write((const char*)bitmap.scanLine(i), width); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnccursor.h b/src/plugins/platforms/vnc/qvnccursor.h deleted file mode 100644 index 3428d71ac7..0000000000 --- a/src/plugins/platforms/vnc/qvnccursor.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 QVNCCURSOR_H -#define QVNCCURSOR_H - -#include "../fb_base/fb_base.h" -#include <QList> -#include <QImage> -#include <QMouseEvent> - -QT_BEGIN_NAMESPACE - -class QVNCScreen; -class QVNCServer; - -class QVNCCursor : public QPlatformSoftwareCursor { -public: - QVNCCursor(QVNCServer *, QVNCScreen *); - - // input methods - void setCursorMode(bool vnc); - void changeCursor(QCursor * widgetCursor, QWidget * widget); - - // output methods - QRect drawCursor(QPainter &); - - // VNC client communication - void sendClientCursor(); - void clearClientCursor(); -private: - bool useVncCursor; // VNC or local - - QVNCServer * server; // VNC server to get events from -}; - -QT_END_NAMESPACE - -#endif // QVNCCURSOR_H diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp deleted file mode 100644 index 8b653f7208..0000000000 --- a/src/plugins/platforms/vnc/qvncintegration.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 "qvncintegration.h" -#include "../fb_base/fb_base.h" -#include <private/qapplication_p.h> -#include <QtGui/private/qpixmap_raster_p.h> -#include <QtCore/qdebug.h> - -#include <qvncserver.h> -#include <QtGui/QPainter> - -#include <QtCore/QTimer> -#include "qgenericunixfontdatabase.h" - -QVNCScreen::QVNCScreen(QRect screenSize, int screenId) - : QFbScreen::QFbScreen() -{ - setGeometry(screenSize); - setDepth(32); - setFormat(QImage::Format_RGB32); - setPhysicalSize((geometry().size()*254)/720); - - - d_ptr = new QVNCScreenPrivate(this, screenId); - - cursor = new QVNCCursor(d_ptr->vncServer, this); - d_ptr->vncServer->setCursor(static_cast<QVNCCursor *>(cursor)); -} - -QVNCDirtyMap *QVNCScreen::dirtyMap() -{ - return d_ptr->dirty; -} - -QRegion QVNCScreen::doRedraw() -{ - QRegion touched; - touched = QFbScreen::doRedraw(); - - QVector<QRect> rects = touched.rects(); - for (int i = 0; i < rects.size(); i++) - d_ptr->setDirty(rects[i]); - return touched; -} - -static inline int defaultWidth() { return 800; } -static inline int defaultHeight() { return 600; } -static inline int defaultDisplay() { return 0; } - -static void usage() -{ - qWarning() << "VNC Platform Integration options:"; - qWarning() << " size=<Width>x<Height> - set the display width and height"; - qWarning() << " defaults to" << defaultWidth() << "x" << defaultHeight(); - qWarning() << " display=<ID> - set the VNC display port to ID + 5900"; - qWarning() << " defaults to" << defaultDisplay(); - qWarning() << " offset=<X>x<Y> - set the current screens offset"; - qWarning() << " vnc - start configuration of a new screen"; - qWarning() << " size and offset are inherited from the previous screen if not set"; - qWarning() << " display id is incremented from the previous screen if not set"; - qWarning() << " virtual - manage the set of screens as a virtual desktop"; -} - -QVNCIntegration::QVNCIntegration(const QStringList& paramList) - : virtualDesktop(false), fontDb(new QGenericUnixFontDatabase()) -{ - int sizeX = defaultWidth(); - int sizeY = defaultHeight(); - int offsetX = 0; - int offsetY = 0; - int display = defaultDisplay(); - bool showUsage = false; - - foreach(QString confString, paramList) { - if (confString.startsWith(QLatin1String("size="))) { - QString val = confString.section(QLatin1Char('='), 1, 1); - sizeX = val.section(QLatin1Char('x'), 0, 0).toInt(); - sizeY = val.section(QLatin1Char('x'), 1, 1).toInt(); - } - else if (confString.startsWith(QLatin1String("display="))) { - display = confString.section(QLatin1Char('='), 1, 1).toInt(); - } - else if (confString.startsWith(QLatin1String("offset="))) { - QString val = confString.section(QLatin1Char('='), 1, 1); - offsetX = val.section(QLatin1Char('x'), 0, 0).toInt(); - offsetY = val.section(QLatin1Char('x'), 1, 1).toInt(); - } - else if (confString == QLatin1String("vnc")) { - QRect screenRect(offsetX, offsetY, sizeX, sizeY); - QVNCScreen *screen = new QVNCScreen(screenRect, display); - mScreens.append(screen); - screen->setObjectName(QString("screen %1").arg(display)); - screen->setDirty(screenRect); - ++display; - } - else if (confString == QLatin1String("virtual")) { - virtualDesktop = true; - } - else { - qWarning() << "Unknown VNC option:" << confString; - showUsage = true; - } - } - - if (showUsage) - usage(); - - QRect screenRect(offsetX, offsetY, sizeX, sizeY); - QVNCScreen *screen = new QVNCScreen(screenRect, display); - mScreens.append(screen); - mPrimaryScreen = qobject_cast<QVNCScreen *>(mScreens.first()); - screen->setObjectName(QString("screen %1").arg(display)); - screen->setDirty(screenRect); -} - -bool QVNCIntegration::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case ThreadedPixmaps: return true; - default: return QPlatformIntegration::hasCapability(cap); - } -} - - -QPlatformPixmap *QVNCIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const -{ - return new QRasterPlatformPixmap(type); -} - -QWindowSurface *QVNCIntegration::createWindowSurface(QWidget *widget, WId) const -{ - QFbWindowSurface * surface; - surface = new QFbWindowSurface(mPrimaryScreen, widget); - return surface; -} - -QAbstractEventDispatcher *QVFbIntegration::createEventDispatcher() const -{ - return createUnixEventDispatcher(); -} - -QPlatformWindow *QVNCIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const -{ - QFbWindow *w = new QFbWindow(widget); - if (virtualDesktop) { - QList<QPlatformScreen *>::const_iterator i = mScreens.constBegin(); - QList<QPlatformScreen *>::const_iterator end = mScreens.constEnd(); - QFbScreen *screen; - while (i != end) { - screen = static_cast<QFbScreen *>(*i); - screen->addWindow(w); - ++i; - } - } - else - mPrimaryScreen->addWindow(w); - return w; -} - -QPixmap QVNCIntegration::grabWindow(WId window, int x, int y, int width, int height) const -{ -// qDebug() << "QVNCIntegration::grabWindow" << window << x << y << width << height; - - if (window == 0) { //desktop - QImage *desktopImage = mPrimaryScreen->image(); - if (x==0 && y == 0 && width < 0 && height < 0) { - return QPixmap::fromImage(*desktopImage); - } - if (width < 0) - width = desktopImage->width() - x; - if (height < 0) - height = desktopImage->height() - y; - int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp - QImage img(desktopImage->scanLine(y) + bytesPerPixel*x, width, height, desktopImage->bytesPerLine(), desktopImage->format()); - return QPixmap::fromImage(img); - } - QWidget *win = QWidget::find(window); - if (win) { - QRect r = win->geometry(); - if (width < 0) - width = r.width() - x; - if (height < 0) - height = r.height() - y; - QImage *desktopImage = mPrimaryScreen->image(); - int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp - - QImage img(desktopImage->scanLine(r.top() + y) + bytesPerPixel*(r.left()+x), width, height, desktopImage->bytesPerLine(), desktopImage->format()); - return QPixmap::fromImage(img); - } - return QPixmap(); -} - - -void QVNCIntegration::moveToScreen(QWidget *window, int screen) -{ - if (virtualDesktop) { // all windows exist on all screens in virtual desktop mode - return; - } - if (screen < 0 || screen > mScreens.size()) - return; - QVNCScreen * newScreen = qobject_cast<QVNCScreen *>(mScreens.at(screen)); - for(int i = 0; i < mScreens.size(); i++) { - QVNCScreen *oldScreen = qobject_cast<QVNCScreen *>(mScreens.at(i)); - if (oldScreen->windowStack.contains(static_cast<QFbWindow *>(window->platformWindow()))) { - oldScreen->removeWindow(static_cast<QFbWindow *>(window->platformWindow())); - break; - } - } - window->platformWindow()->setGeometry(window->geometry()); // this should be unified elsewhere - newScreen->addWindow(static_cast<QFbWindow *>(window->platformWindow())); -} - -QPlatformFontDatabase *QVNCIntegration::fontDatabase() const -{ - return fontDb; -} diff --git a/src/plugins/platforms/vnc/qvncintegration.h b/src/plugins/platforms/vnc/qvncintegration.h deleted file mode 100644 index a6baf0340e..0000000000 --- a/src/plugins/platforms/vnc/qvncintegration.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 QGRAPHICSSYSTEM_VNC_H -#define QGRAPHICSSYSTEM_VNC_H - -#include "qvnccursor.h" -#include "../fb_base/fb_base.h" -#include <QPlatformIntegration> -#include "qgenericunixfontdatabase.h" - -QT_BEGIN_NAMESPACE - -class QVNCServer; -class QVNCDirtyMap; - -class QVNCScreenPrivate; - -class QVNCScreen : public QFbScreen -{ - Q_OBJECT -public: - QVNCScreen(QRect screenSize, int screenId); - - int linestep() const { return image() ? image()->bytesPerLine() : 0; } - uchar *base() const { return image() ? image()->bits() : 0; } - QVNCDirtyMap *dirtyMap(); - -public: - QVNCScreenPrivate *d_ptr; - -private: - QVNCServer *server; - QRegion doRedraw(); - friend class QVNCIntegration; -}; - -class QVNCIntegrationPrivate; -class QAbstractEventDispatcher; - -class QVNCIntegration : public QPlatformIntegration -{ -public: - QVNCIntegration(const QStringList& paramList); - - bool hasCapability(QPlatformIntegration::Capability cap) const; - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; - QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; - QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; - QAbstractEventDispatcher createEventDispatcher() const; - - QPixmap grabWindow(WId window, int x, int y, int width, int height) const; - - QList<QPlatformScreen *> screens() const { return mScreens; } - - bool isVirtualDesktop() { return virtualDesktop; } - void moveToScreen(QWidget *window, int screen); - - QPlatformFontDatabase *fontDatabase() const; - -private: - QVNCScreen *mPrimaryScreen; - QList<QPlatformScreen *> mScreens; - bool virtualDesktop; - QPlatformFontDatabase *fontDb; -}; - - - -QT_END_NAMESPACE - -#endif //QGRAPHICSSYSTEM_VNC_H - diff --git a/src/plugins/platforms/vnc/qvncserver.cpp b/src/plugins/platforms/vnc/qvncserver.cpp deleted file mode 100644 index db49025c41..0000000000 --- a/src/plugins/platforms/vnc/qvncserver.cpp +++ /dev/null @@ -1,1935 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 "qvncserver.h" - -#include <QtCore/qtimer.h> -#include <QtCore/qregexp.h> -#include <QtWidgets/qwidget.h> -#include <QtGui/qpolygon.h> -#include <QtGui/qpainter.h> - -#include <QtGui/qevent.h> -#include <QWindowSystemInterface> - -#include <qplatformdefs.h> - -#include <qdebug.h> - -#include <stdlib.h> - - -#define QT_QWS_VNC_DEBUG -#define QT_NO_QWS_CURSOR //### - - -QT_BEGIN_NAMESPACE - - - -//copied from qscreen_qws.h -#ifndef QT_QWS_DEPTH16_RGB -#define QT_QWS_DEPTH16_RGB 565 -#endif -static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); -static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); -static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); -static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); -static const int qt_green_shift = qt_bbits-(8-qt_gbits); -static const int qt_neg_blue_shift = 8-qt_bbits; -static const int qt_blue_mask = (1<<qt_bbits)-1; -static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); -static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); - -static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; -static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; -static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; - - -inline QRgb qt_conv16ToRgb(ushort c) -{ - const int r=(c & qt_red_mask); - const int g=(c & qt_green_mask); - const int b=(c & qt_blue_mask); - const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; - const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; - const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; - - return qRgb(tr,tg,tb); -} - - - -//=========================================================================== - -static const struct { - int keysym; - int keycode; -} keyMap[] = { - { 0xff08, Qt::Key_Backspace }, - { 0xff09, Qt::Key_Tab }, - { 0xff0d, Qt::Key_Return }, - { 0xff1b, Qt::Key_Escape }, - { 0xff63, Qt::Key_Insert }, - { 0xffff, Qt::Key_Delete }, - { 0xff50, Qt::Key_Home }, - { 0xff57, Qt::Key_End }, - { 0xff55, Qt::Key_PageUp }, - { 0xff56, Qt::Key_PageDown }, - { 0xff51, Qt::Key_Left }, - { 0xff52, Qt::Key_Up }, - { 0xff53, Qt::Key_Right }, - { 0xff54, Qt::Key_Down }, - { 0xffbe, Qt::Key_F1 }, - { 0xffbf, Qt::Key_F2 }, - { 0xffc0, Qt::Key_F3 }, - { 0xffc1, Qt::Key_F4 }, - { 0xffc2, Qt::Key_F5 }, - { 0xffc3, Qt::Key_F6 }, - { 0xffc4, Qt::Key_F7 }, - { 0xffc5, Qt::Key_F8 }, - { 0xffc6, Qt::Key_F9 }, - { 0xffc7, Qt::Key_F10 }, - { 0xffc8, Qt::Key_F11 }, - { 0xffc9, Qt::Key_F12 }, - { 0xffe1, Qt::Key_Shift }, - { 0xffe2, Qt::Key_Shift }, - { 0xffe3, Qt::Key_Control }, - { 0xffe4, Qt::Key_Control }, - { 0xffe7, Qt::Key_Meta }, - { 0xffe8, Qt::Key_Meta }, - { 0xffe9, Qt::Key_Alt }, - { 0xffea, Qt::Key_Alt }, - { 0, 0 } -}; - -void QRfbRect::read(QTcpSocket *s) -{ - quint16 buf[4]; - s->read((char*)buf, 8); - x = ntohs(buf[0]); - y = ntohs(buf[1]); - w = ntohs(buf[2]); - h = ntohs(buf[3]); -} - -void QRfbRect::write(QTcpSocket *s) const -{ - quint16 buf[4]; - buf[0] = htons(x); - buf[1] = htons(y); - buf[2] = htons(w); - buf[3] = htons(h); - s->write((char*)buf, 8); -} - -void QRfbPixelFormat::read(QTcpSocket *s) -{ - char buf[16]; - s->read(buf, 16); - bitsPerPixel = buf[0]; - depth = buf[1]; - bigEndian = buf[2]; - trueColor = buf[3]; - - quint16 a = ntohs(*(quint16 *)(buf + 4)); - redBits = 0; - while (a) { a >>= 1; redBits++; } - - a = ntohs(*(quint16 *)(buf + 6)); - greenBits = 0; - while (a) { a >>= 1; greenBits++; } - - a = ntohs(*(quint16 *)(buf + 8)); - blueBits = 0; - while (a) { a >>= 1; blueBits++; } - - redShift = buf[10]; - greenShift = buf[11]; - blueShift = buf[12]; -} - -void QRfbPixelFormat::write(QTcpSocket *s) -{ - char buf[16]; - buf[0] = bitsPerPixel; - buf[1] = depth; - buf[2] = bigEndian; - buf[3] = trueColor; - - quint16 a = 0; - for (int i = 0; i < redBits; i++) a = (a << 1) | 1; - *(quint16 *)(buf + 4) = htons(a); - - a = 0; - for (int i = 0; i < greenBits; i++) a = (a << 1) | 1; - *(quint16 *)(buf + 6) = htons(a); - - a = 0; - for (int i = 0; i < blueBits; i++) a = (a << 1) | 1; - *(quint16 *)(buf + 8) = htons(a); - - buf[10] = redShift; - buf[11] = greenShift; - buf[12] = blueShift; - s->write(buf, 16); -} - - -void QRfbServerInit::setName(const char *n) -{ - delete[] name; - name = new char [strlen(n) + 1]; - strcpy(name, n); -} - -void QRfbServerInit::read(QTcpSocket *s) -{ - s->read((char *)&width, 2); - width = ntohs(width); - s->read((char *)&height, 2); - height = ntohs(height); - format.read(s); - - quint32 len; - s->read((char *)&len, 4); - len = ntohl(len); - - name = new char [len + 1]; - s->read(name, len); - name[len] = '\0'; -} - -void QRfbServerInit::write(QTcpSocket *s) -{ - quint16 t = htons(width); - s->write((char *)&t, 2); - t = htons(height); - s->write((char *)&t, 2); - format.write(s); - quint32 len = strlen(name); - len = htonl(len); - s->write((char *)&len, 4); - s->write(name, strlen(name)); -} - -bool QRfbSetEncodings::read(QTcpSocket *s) -{ - if (s->bytesAvailable() < 3) - return false; - - char tmp; - s->read(&tmp, 1); // padding - s->read((char *)&count, 2); - count = ntohs(count); - - return true; -} - -bool QRfbFrameBufferUpdateRequest::read(QTcpSocket *s) -{ - if (s->bytesAvailable() < 9) - return false; - - s->read(&incremental, 1); - rect.read(s); - - return true; -} - -bool QRfbKeyEvent::read(QTcpSocket *s) -{ - if (s->bytesAvailable() < 7) - return false; - - s->read(&down, 1); - quint16 tmp; - s->read((char *)&tmp, 2); // padding - - quint32 key; - s->read((char *)&key, 4); - key = ntohl(key); - - unicode = 0; - keycode = 0; - int i = 0; - while (keyMap[i].keysym && !keycode) { - if (keyMap[i].keysym == (int)key) - keycode = keyMap[i].keycode; - i++; - } - if (!keycode) { - if (key <= 0xff) { - unicode = key; - if (key >= 'a' && key <= 'z') - keycode = Qt::Key_A + key - 'a'; - else if (key >= ' ' && key <= '~') - keycode = Qt::Key_Space + key - ' '; - } - } - - return true; -} - -bool QRfbPointerEvent::read(QTcpSocket *s) -{ - if (s->bytesAvailable() < 5) - return false; - - char buttonMask; - s->read(&buttonMask, 1); - - buttons = Qt::NoButton; - wheelDirection = WheelNone; - if (buttonMask & 1) - buttons |= Qt::LeftButton; - if (buttonMask & 2) - buttons |= Qt::MidButton; - if (buttonMask & 4) - buttons |= Qt::RightButton; - if (buttonMask & 8) - wheelDirection = WheelUp; - if (buttonMask & 16) - wheelDirection = WheelDown; - if (buttonMask & 32) - wheelDirection = WheelLeft; - if (buttonMask & 64) - wheelDirection = WheelRight; - - quint16 tmp; - s->read((char *)&tmp, 2); - x = ntohs(tmp); - s->read((char *)&tmp, 2); - y = ntohs(tmp); - - return true; -} - -bool QRfbClientCutText::read(QTcpSocket *s) -{ - if (s->bytesAvailable() < 7) - return false; - - char tmp[3]; - s->read(tmp, 3); // padding - s->read((char *)&length, 4); - length = ntohl(length); - - return true; -} - -//=========================================================================== - -QVNCServer::QVNCServer(QVNCScreen *screen) - : qvnc_screen(screen), cursor(0) -{ - init(5900); -} - -QVNCServer::QVNCServer(QVNCScreen *screen, int id) - : qvnc_screen(screen), cursor(0) -{ - init(5900 + id); -} - -void QVNCServer::init(uint port) -{ - qDebug() << "QVNCServer::init" << port; - - handleMsg = false; - client = 0; - encodingsPending = 0; - cutTextPending = 0; - keymod = 0; - state = Unconnected; - dirtyCursor = false; - - refreshRate = 25; - timer = new QTimer(this); - timer->setSingleShot(true); - connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); - - serverSocket = new QTcpServer(this); - if (!serverSocket->listen(QHostAddress::Any, port)) - qDebug() << "QVNCServer could not connect:" << serverSocket->errorString(); - else - qDebug("QVNCServer created on port %d", port); - - connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection())); - -#ifndef QT_NO_QWS_CURSOR - qvnc_cursor = 0; -#endif - encoder = 0; -} - -QVNCServer::~QVNCServer() -{ - delete encoder; - encoder = 0; - delete client; - client = 0; -#ifndef QT_NO_QWS_CURSOR - delete qvnc_cursor; - qvnc_cursor = 0; -#endif -} - -void QVNCServer::setDirty() -{ - if (state == Connected && !timer->isActive() && - ((dirtyMap()->numDirty > 0) || dirtyCursor)) { - timer->start(); - } -} - -void QVNCServer::newConnection() -{ - if (client) - delete client; - - client = serverSocket->nextPendingConnection(); - connect(client,SIGNAL(readyRead()),this,SLOT(readClient())); - connect(client,SIGNAL(disconnected()),this,SLOT(discardClient())); - handleMsg = false; - encodingsPending = 0; - cutTextPending = 0; - supportHextile = false; - wantUpdate = false; - - timer->start(1000 / refreshRate); - dirtyMap()->reset(); - - // send protocol version - const char *proto = "RFB 003.003\n"; - client->write(proto, 12); - state = Protocol; - -// if (!qvnc_screen->screen()) -// QWSServer::instance()->enablePainting(true); -} - -void QVNCServer::readClient() -{ - switch (state) { - case Protocol: - if (client->bytesAvailable() >= 12) { - char proto[13]; - client->read(proto, 12); - proto[12] = '\0'; - qDebug("Client protocol version %s", proto); - // No authentication - quint32 auth = htonl(1); - client->write((char *) &auth, sizeof(auth)); - state = Init; - } - break; - - case Init: - if (client->bytesAvailable() >= 1) { - quint8 shared; - client->read((char *) &shared, 1); - - // Server Init msg - QRfbServerInit sim; - QRfbPixelFormat &format = sim.format; - switch (qvnc_screen->depth()) { - case 32: - format.bitsPerPixel = 32; - format.depth = 32; - format.bigEndian = 0; - format.trueColor = true; - format.redBits = 8; - format.greenBits = 8; - format.blueBits = 8; - format.redShift = 16; - format.greenShift = 8; - format.blueShift = 0; - break; - - case 24: - format.bitsPerPixel = 24; - format.depth = 24; - format.bigEndian = 0; - format.trueColor = true; - format.redBits = 8; - format.greenBits = 8; - format.blueBits = 8; - format.redShift = 16; - format.greenShift = 8; - format.blueShift = 0; - break; - - case 18: - format.bitsPerPixel = 24; - format.depth = 18; - format.bigEndian = 0; - format.trueColor = true; - format.redBits = 6; - format.greenBits = 6; - format.blueBits = 6; - format.redShift = 12; - format.greenShift = 6; - format.blueShift = 0; - break; - - case 16: - format.bitsPerPixel = 16; - format.depth = 16; - format.bigEndian = 0; - format.trueColor = true; - format.redBits = 5; - format.greenBits = 6; - format.blueBits = 5; - format.redShift = 11; - format.greenShift = 5; - format.blueShift = 0; - break; - - case 15: - format.bitsPerPixel = 16; - format.depth = 15; - format.bigEndian = 0; - format.trueColor = true; - format.redBits = 5; - format.greenBits = 5; - format.blueBits = 5; - format.redShift = 10; - format.greenShift = 5; - format.blueShift = 0; - break; - - case 12: - format.bitsPerPixel = 16; - format.depth = 12; - format.bigEndian = 0; - format.trueColor = true; - format.redBits = 4; - format.greenBits = 4; - format.blueBits = 4; - format.redShift = 8; - format.greenShift = 4; - format.blueShift = 0; - break; - - case 8: - case 4: - format.bitsPerPixel = 8; - format.depth = 8; - format.bigEndian = 0; - format.trueColor = false; - format.redBits = 0; - format.greenBits = 0; - format.blueBits = 0; - format.redShift = 0; - format.greenShift = 0; - format.blueShift = 0; - break; - - default: - qDebug("QVNC cannot drive depth %d", qvnc_screen->depth()); - discardClient(); - return; - } - sim.width = qvnc_screen->geometry().width(); - sim.height = qvnc_screen->geometry().height(); - sim.setName("Qt for Embedded Linux VNC Server"); - sim.write(client); - state = Connected; - } - break; - - case Connected: - do { - if (!handleMsg) { - client->read((char *)&msgType, 1); - handleMsg = true; - } - if (handleMsg) { - switch (msgType ) { - case SetPixelFormat: - setPixelFormat(); - break; - case FixColourMapEntries: - qDebug("Not supported: FixColourMapEntries"); - handleMsg = false; - break; - case SetEncodings: - setEncodings(); - break; - case FramebufferUpdateRequest: - frameBufferUpdateRequest(); - break; - case KeyEvent: - keyEvent(); - break; - case PointerEvent: - pointerEvent(); - break; - case ClientCutText: - clientCutText(); - break; - default: - qDebug("Unknown message type: %d", (int)msgType); - handleMsg = false; - } - } - } while (!handleMsg && client->bytesAvailable()); - break; - default: - break; - } -} - -#if 0//Q_BYTE_ORDER == Q_BIG_ENDIAN -bool QVNCScreen::swapBytes() const -{ - if (depth() != 16) - return false; - - if (screen()) - return screen()->frameBufferLittleEndian(); - return frameBufferLittleEndian(); -} -#endif - -void QVNCServer::setPixelFormat() -{ - if (client->bytesAvailable() >= 19) { - char buf[3]; - client->read(buf, 3); // just padding - pixelFormat.read(client); -#ifdef QT_QWS_VNC_DEBUG - qDebug("Want format: %d %d %d %d %d %d %d %d %d %d", - int(pixelFormat.bitsPerPixel), - int(pixelFormat.depth), - int(pixelFormat.bigEndian), - int(pixelFormat.trueColor), - int(pixelFormat.redBits), - int(pixelFormat.greenBits), - int(pixelFormat.blueBits), - int(pixelFormat.redShift), - int(pixelFormat.greenShift), - int(pixelFormat.blueShift)); -#endif - if (!pixelFormat.trueColor) { - qDebug("Can only handle true color clients"); - discardClient(); - } - handleMsg = false; - sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!pixelFormat.bigEndian; - needConversion = pixelConversionNeeded(); -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - swapBytes = qvnc_screen->swapBytes(); -#endif - } -} - -void QVNCServer::setEncodings() -{ - QRfbSetEncodings enc; - - if (!encodingsPending && enc.read(client)) { - encodingsPending = enc.count; - if (!encodingsPending) - handleMsg = false; - } - - if (encoder) { - delete encoder; - encoder = 0; - } - - enum Encodings { - Raw = 0, - CopyRect = 1, - RRE = 2, - CoRRE = 4, - Hextile = 5, - ZRLE = 16, - Cursor = -239, - DesktopSize = -223 - }; - - supportCursor = false; - - if (encodingsPending && (unsigned)client->bytesAvailable() >= - encodingsPending * sizeof(quint32)) { - for (int i = 0; i < encodingsPending; ++i) { - qint32 enc; - client->read((char *)&enc, sizeof(qint32)); - enc = ntohl(enc); -#ifdef QT_QWS_VNC_DEBUG - qDebug("QVNCServer::setEncodings: %d", enc); -#endif - switch (enc) { - case Raw: - if (!encoder) { - encoder = new QRfbRawEncoder(this); -#ifdef QT_QWS_VNC_DEBUG - qDebug("QVNCServer::setEncodings: using raw"); -#endif - } - break; - case CopyRect: - supportCopyRect = true; - break; - case RRE: - supportRRE = true; - break; - case CoRRE: - supportCoRRE = true; - break; - case Hextile: - supportHextile = true; - if (encoder) - break; - switch (qvnc_screen->depth()) { -#ifdef QT_QWS_DEPTH_8 - case 8: - encoder = new QRfbHextileEncoder<quint8>(this); - break; -#endif -#ifdef QT_QWS_DEPTH_12 - case 12: - encoder = new QRfbHextileEncoder<qrgb444>(this); - break; -#endif -#ifdef QT_QWS_DEPTH_15 - case 15: - encoder = new QRfbHextileEncoder<qrgb555>(this); - break; -#endif -#ifdef QT_QWS_DEPTH_16 - case 16: - encoder = new QRfbHextileEncoder<quint16>(this); - break; -#endif -#ifdef QT_QWS_DEPTH_18 - case 18: - encoder = new QRfbHextileEncoder<qrgb666>(this); - break; -#endif -#ifdef QT_QWS_DEPTH_24 - case 24: - encoder = new QRfbHextileEncoder<qrgb888>(this); - break; -#endif -#ifdef QT_QWS_DEPTH_32 - case 32: - encoder = new QRfbHextileEncoder<quint32>(this); - break; -#endif - default: - break; - } -#ifdef QT_QWS_VNC_DEBUG - qDebug("QVNCServer::setEncodings: using hextile"); -#endif - break; - case ZRLE: - supportZRLE = true; - break; - case Cursor: - supportCursor = true; -#ifndef QT_NO_QWS_CURSOR - if (!qvnc_screen->screen() || qt_screencursor->isAccelerated()) { - delete qvnc_cursor; - qvnc_cursor = new QVNCClientCursor(this); - } -#endif - break; - case DesktopSize: - supportDesktopSize = true; - break; - default: - break; - } - } - handleMsg = false; - encodingsPending = 0; - } - - if (!encoder) { - encoder = new QRfbRawEncoder(this); -#ifdef QT_QWS_VNC_DEBUG - qDebug("QVNCServer::setEncodings: fallback using raw"); -#endif - } - - if (cursor) - cursor->setCursorMode(supportCursor); -} - -void QVNCServer::frameBufferUpdateRequest() -{ - QRfbFrameBufferUpdateRequest ev; - - if (ev.read(client)) { - if (!ev.incremental) { - QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h); -////### r.translate(qvnc_screen->offset()); - qvnc_screen->d_ptr->setDirty(r, true); - } - wantUpdate = true; - checkUpdate(); - handleMsg = false; - } -} - -static bool buttonChange(Qt::MouseButtons before, Qt::MouseButtons after, Qt::MouseButton *button, bool *isPress) -{ - if (before == after) - return false; - for (int b = Qt::LeftButton; b <= Qt::MidButton; b<<=1) { - if ((before & b) != (after & b)) { - *button = static_cast<Qt::MouseButton>(b); - *isPress = (after & b); - return true; - } - } - return false; -} - -void QVNCServer::pointerEvent() -{ - QPoint screenOffset = this->screen()->geometry().topLeft(); - - QRfbPointerEvent ev; - if (ev.read(client)) { - QPoint eventPoint(ev.x, ev.y); - eventPoint += screenOffset; // local to global translation - - if (ev.wheelDirection == ev.WheelNone) { - QEvent::Type type = QEvent::MouseMove; - Qt::MouseButton button = Qt::NoButton; - bool isPress; - if (buttonChange(buttons, ev.buttons, &button, &isPress)) - type = isPress ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; - QWindowSystemInterface::handleMouseEvent(0, eventPoint, eventPoint, ev.buttons); - } else { - // No buttons or motion reported at the same time as wheel events - Qt::Orientation orientation; - if (ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelRight) - orientation = Qt::Horizontal; - else - orientation = Qt::Vertical; - int delta = 120 * ((ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelUp) ? 1 : -1); - QWindowSystemInterface::handleWheelEvent(0, eventPoint, eventPoint, delta, orientation); - } - handleMsg = false; - } -} - -void QVNCServer::keyEvent() -{ - QRfbKeyEvent ev; - - if (ev.read(client)) { - if (ev.keycode == Qt::Key_Shift) - keymod = ev.down ? keymod | Qt::ShiftModifier : - keymod & ~Qt::ShiftModifier; - else if (ev.keycode == Qt::Key_Control) - keymod = ev.down ? keymod | Qt::ControlModifier : - keymod & ~Qt::ControlModifier; - else if (ev.keycode == Qt::Key_Alt) - keymod = ev.down ? keymod | Qt::AltModifier : - keymod & ~Qt::AltModifier; - if (ev.unicode || ev.keycode) { -// qDebug() << "keyEvent" << hex << ev.unicode << ev.keycode << keymod << ev.down; - QEvent::Type type = ev.down ? QEvent::KeyPress : QEvent::KeyRelease; - QString str; - if (ev.unicode && ev.unicode != 0xffff) - str = QString(ev.unicode); - QWindowSystemInterface::handleKeyEvent(0, type, ev.keycode, keymod, str); - } - handleMsg = false; - } -} - -void QVNCServer::clientCutText() -{ - QRfbClientCutText ev; - - if (cutTextPending == 0 && ev.read(client)) { - cutTextPending = ev.length; - if (!cutTextPending) - handleMsg = false; - } - - if (cutTextPending && client->bytesAvailable() >= cutTextPending) { - char *text = new char [cutTextPending+1]; - client->read(text, cutTextPending); - delete [] text; - cutTextPending = 0; - handleMsg = false; - } -} - -// stride in bytes -template <class SRC> -bool QRfbSingleColorHextile<SRC>::read(const uchar *data, - int width, int height, int stride) -{ - const int depth = encoder->server->screen()->depth(); - if (width % (depth / 8)) // hw: should rather fallback to simple loop - return false; - - static int alwaysFalse = qgetenv("QT_VNC_NOCHECKFILL").toInt(); - if (alwaysFalse) - return false; - - switch (depth) { - case 4: { - const quint8 *data8 = reinterpret_cast<const quint8*>(data); - if ((data8[0] & 0xf) != (data8[0] >> 4)) - return false; - width /= 2; - } // fallthrough - case 8: { - const quint8 *data8 = reinterpret_cast<const quint8*>(data); - if (data8[0] != data8[1]) - return false; - width /= 2; - } // fallthrough - case 12: - case 15: - case 16: { - const quint16 *data16 = reinterpret_cast<const quint16*>(data); - if (data16[0] != data16[1]) - return false; - width /= 2; - } // fallthrough - case 18: - case 24: - case 32: { - const quint32 *data32 = reinterpret_cast<const quint32*>(data); - const quint32 first = data32[0]; - const int linestep = (stride / sizeof(quint32)) - width; - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - if (*(data32++) != first) - return false; - } - data32 += linestep; - } - break; - } - default: - return false; - } - - SRC color = reinterpret_cast<const SRC*>(data)[0]; - encoder->newBg |= (color != encoder->bg); - encoder->bg = color; - return true; -} - -template <class SRC> -void QRfbSingleColorHextile<SRC>::write(QTcpSocket *socket) const -{ - if (true || encoder->newBg) { - const int bpp = encoder->server->clientBytesPerPixel(); - const int padding = 3; - QVarLengthArray<char> buffer(padding + 1 + bpp); - buffer[padding] = 2; // BackgroundSpecified - encoder->server->convertPixels(buffer.data() + padding + 1, - reinterpret_cast<char*>(&encoder->bg), - 1); - socket->write(buffer.data() + padding, bpp + 1); -// encoder->newBg = false; - } else { - char subenc = 0; - socket->write(&subenc, 1); - } -} - -template <class SRC> -bool QRfbDualColorHextile<SRC>::read(const uchar *data, - int width, int height, int stride) -{ - const SRC *ptr = reinterpret_cast<const SRC*>(data); - const int linestep = (stride / sizeof(SRC)) - width; - - SRC c1; - SRC c2 = 0; - int n1 = 0; - int n2 = 0; - int x = 0; - int y = 0; - - c1 = *ptr; - - // find second color - while (y < height) { - while (x < width) { - if (*ptr == c1) { - ++n1; - } else { - c2 = *ptr; - goto found_second_color; - } - ++ptr; - ++x; - } - x = 0; - ptr += linestep; - ++y; - } - -found_second_color: - // finish counting - while (y < height) { - while (x < width) { - if (*ptr == c1) { - ++n1; - } else if (*ptr == c2) { - ++n2; - } else { - return false; - } - ++ptr; - ++x; - } - x = 0; - ptr += linestep; - ++y; - } - - if (n2 > n1) { - const quint32 tmpC = c1; - c1 = c2; - c2 = tmpC; - } - - encoder->newBg |= (c1 != encoder->bg); - encoder->newFg |= (c2 != encoder->fg); - - encoder->bg = c1; - encoder->fg = c2; - - // create map - bool inRect = false; - numRects = 0; - ptr = reinterpret_cast<const SRC*>(data); - for (y = 0; y < height; ++y) { - for (x = 0; x < width; ++x) { - if (inRect && *ptr == encoder->bg) { - // rect finished - setWidth(x - lastx()); - next(); - inRect = false; - } else if (!inRect && *ptr == encoder->fg) { - // rect start - setX(x); - setY(y); - setHeight(1); - inRect = true; - } - ++ptr; - } - if (inRect) { - // finish rect - setWidth(width - lastx()); - next(); - inRect = false; - } - ptr += linestep; - } - - return true; -} - -template <class SRC> -void QRfbDualColorHextile<SRC>::write(QTcpSocket *socket) const -{ - const int bpp = encoder->server->clientBytesPerPixel(); - const int padding = 3; - QVarLengthArray<char> buffer(padding + 2 * bpp + sizeof(char) + sizeof(numRects)); - char &subenc = buffer[padding]; - int n = padding + sizeof(subenc); - - subenc = 0x8; // AnySubrects - - if (encoder->newBg) { - subenc |= 0x2; // Background - encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->bg, 1); - n += bpp; -// encoder->newBg = false; - } - - if (encoder->newFg) { - subenc |= 0x4; // Foreground - encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->fg, 1); - n += bpp; -// encoder->newFg = false; - } - buffer[n] = numRects; - n += sizeof(numRects); - - socket->write(buffer.data() + padding, n - padding); - socket->write((char*)rects, numRects * sizeof(Rect)); -} - -template <class SRC> -void QRfbDualColorHextile<SRC>::next() -{ - for (int r = numRects - 1; r >= 0; --r) { - if (recty(r) == lasty()) - continue; - if (recty(r) < lasty() - 1) // only search previous scanline - break; - if (rectx(r) == lastx() && width(r) == width(numRects)) { - ++rects[r].wh; - return; - } - } - ++numRects; -} - -template <class SRC> -inline void QRfbMultiColorHextile<SRC>::setColor(SRC color) -{ - encoder->server->convertPixels(reinterpret_cast<char*>(rect(numRects)), - (const char*)&color, 1); -} - -template <class SRC> -inline bool QRfbMultiColorHextile<SRC>::beginRect() -{ - if ((rects.size() + bpp + 2) > maxRectsSize) - return false; - rects.resize(rects.size() + bpp + 2); - return true; -} - -template <class SRC> -inline void QRfbMultiColorHextile<SRC>::endRect() -{ - setHeight(numRects, 1); - ++numRects; -} - -template <class SRC> -bool QRfbMultiColorHextile<SRC>::read(const uchar *data, - int width, int height, int stride) -{ - const SRC *ptr = reinterpret_cast<const SRC*>(data); - const int linestep = (stride / sizeof(SRC)) - width; - - bpp = encoder->server->clientBytesPerPixel(); - - if (encoder->newBg) - encoder->bg = ptr[0]; - - const SRC bg = encoder->bg; - SRC color = bg; - bool inRect = false; - - numRects = 0; - rects.clear(); - - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - if (inRect && *ptr != color) { // end rect - setWidth(numRects, x - rectx(numRects)); - endRect(); - inRect = false; - } - - if (!inRect && *ptr != bg) { // begin rect - if (!beginRect()) - return false; - inRect = true; - color = *ptr; - setColor(color); - setX(numRects, x); - setY(numRects, y); - } - ++ptr; - } - if (inRect) { // end rect - setWidth(numRects, width - rectx(numRects)); - endRect(); - inRect = false; - } - ptr += linestep; - } - - return true; -} - -template <class SRC> -void QRfbMultiColorHextile<SRC>::write(QTcpSocket *socket) const -{ - const int padding = 3; - QVarLengthArray<quint8> buffer(bpp + padding + sizeof(quint8) + sizeof(numRects)); - - quint8 &subenc = buffer[padding]; - int n = padding + sizeof(quint8); - - subenc = 8 | 16; // AnySubrects | SubrectsColoured - - if (encoder->newBg) { - subenc |= 0x2; // Background - encoder->server->convertPixels(reinterpret_cast<char*>(buffer.data() + n), - reinterpret_cast<const char*>(&encoder->bg), - 1); - n += bpp; -// encoder->newBg = false; - } - - buffer[n] = numRects; - n += sizeof(numRects); - - socket->write(reinterpret_cast<const char*>(buffer.data() + padding), - n - padding); - socket->write(reinterpret_cast<const char*>(rects.constData()), - rects.size()); -} - -bool QVNCServer::pixelConversionNeeded() const -{ - if (!sameEndian) - return true; - -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - if (qvnc_screen->swapBytes()) - return true; -#endif - - const int screendepth = qvnc_screen->depth(); - if (screendepth != pixelFormat.bitsPerPixel) - return true; - - switch (screendepth) { - case 32: - case 24: - return false; - case 18: - return (pixelFormat.redBits == 6 - && pixelFormat.greenBits == 6 - && pixelFormat.blueBits == 6); - case 16: - return (pixelFormat.redBits == 5 - && pixelFormat.greenBits == 6 - && pixelFormat.blueBits == 5); - case 15: - return (pixelFormat.redBits == 5 - && pixelFormat.greenBits == 5 - && pixelFormat.blueBits == 5); - case 12: - return (pixelFormat.redBits == 4 - && pixelFormat.greenBits == 4 - && pixelFormat.blueBits == 4); - } - return true; -} - -// count: number of pixels -void QVNCServer::convertPixels(char *dst, const char *src, int count) const -{ - const int screendepth = qvnc_screen->depth(); - const bool isBgr = false; //### qvnc_screen->pixelType() == QScreen::BGRPixel; - - // cutoffs -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - if (!swapBytes) -#endif - if (sameEndian) { - if (screendepth == pixelFormat.bitsPerPixel) { // memcpy cutoffs - - switch (screendepth) { - case 32: - memcpy(dst, src, count * sizeof(quint32)); - return; - case 16: - if (pixelFormat.redBits == 5 - && pixelFormat.greenBits == 6 - && pixelFormat.blueBits == 5) - { - memcpy(dst, src, count * sizeof(quint16)); - return; - } - } - } else if (screendepth == 16 && pixelFormat.bitsPerPixel == 32) { -#if defined(__i386__) // Currently fails on ARM if dst is not 4 byte aligned - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - quint32 *dst32 = reinterpret_cast<quint32*>(dst); - int count32 = count * sizeof(quint16) / sizeof(quint32); - while (count32--) { - const quint32 s = *src32++; - quint32 result1; - quint32 result2; - - // red - result1 = ((s & 0xf8000000) | ((s & 0xe0000000) >> 5)) >> 8; - result2 = ((s & 0x0000f800) | ((s & 0x0000e000) >> 5)) << 8; - - // green - result1 |= ((s & 0x07e00000) | ((s & 0x06000000) >> 6)) >> 11; - result2 |= ((s & 0x000007e0) | ((s & 0x00000600) >> 6)) << 5; - - // blue - result1 |= ((s & 0x001f0000) | ((s & 0x001c0000) >> 5)) >> 13; - result2 |= ((s & 0x0000001f) | ((s & 0x0000001c) >> 5)) << 3; - - *dst32++ = result2; - *dst32++ = result1; - } - if (count & 0x1) { - const quint16 *src16 = reinterpret_cast<const quint16*>(src); - *dst32 = qt_conv16ToRgb(src16[count - 1]); - } - return; -#endif - } - } - - const int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) / 8; - -// nibble = 0; - - for (int i = 0; i < count; ++i) { - int r, g, b; - - switch (screendepth) { -#if 0 - case 4: { - if (!nibble) { - r = ((*src) & 0x0f) << 4; - } else { - r = (*src) & 0xf0; - src++; - } - nibble = !nibble; - g = b = r; - break; - } -#endif -#if 0 - case 8: { - QRgb rgb = qvnc_screen->clut()[int(*src)]; - r = qRed(rgb); - g = qGreen(rgb); - b = qBlue(rgb); - src++; - break; - } -#endif -#ifdef QT_QWS_DEPTH_12 - case 12: { - quint32 p = quint32(*reinterpret_cast<const qrgb444*>(src)); - r = qRed(p); - g = qGreen(p); - b = qBlue(p); - src += sizeof(qrgb444); - break; - } -#endif -#ifdef QT_QWS_DEPTH_15 - case 15: { - quint32 p = quint32(*reinterpret_cast<const qrgb555*>(src)); - r = qRed(p); - g = qGreen(p); - b = qBlue(p); - src += sizeof(qrgb555); - break; - } -#endif - case 16: { - quint16 p = *reinterpret_cast<const quint16*>(src); -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - if (swapBytes) - p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8); -#endif - r = (p >> 11) & 0x1f; - g = (p >> 5) & 0x3f; - b = p & 0x1f; - r <<= 3; - g <<= 2; - b <<= 3; - src += sizeof(quint16); - break; - } -#ifdef QT_QWS_DEPTH_18 - case 18: { - quint32 p = quint32(*reinterpret_cast<const qrgb666*>(src)); - r = qRed(p); - g = qGreen(p); - b = qBlue(p); - src += sizeof(qrgb666); - break; - } -#endif -#ifdef QT_QWS_DEPTH_24 - case 24: { - quint32 p = quint32(*reinterpret_cast<const qrgb888*>(src)); - r = qRed(p); - g = qGreen(p); - b = qBlue(p); - src += sizeof(qrgb888); - break; - } -#endif - case 32: { - quint32 p = *reinterpret_cast<const quint32*>(src); - r = (p >> 16) & 0xff; - g = (p >> 8) & 0xff; - b = p & 0xff; - src += sizeof(quint32); - break; - } - default: { - r = g = b = 0; - qDebug("QVNCServer: don't support %dbpp display", screendepth); - return; - } - } - -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - if (swapBytes ^ isBgr) -#else - if (isBgr) -#endif - qSwap(r, b); - - r >>= (8 - pixelFormat.redBits); - g >>= (8 - pixelFormat.greenBits); - b >>= (8 - pixelFormat.blueBits); - - int pixel = (r << pixelFormat.redShift) | - (g << pixelFormat.greenShift) | - (b << pixelFormat.blueShift); - - if (sameEndian || pixelFormat.bitsPerPixel == 8) { - memcpy(dst, &pixel, bytesPerPixel); // XXX: do a simple for-loop instead? - dst += bytesPerPixel; - continue; - } - - - if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { - switch (pixelFormat.bitsPerPixel) { - case 16: - pixel = (((pixel & 0x0000ff00) << 8) | - ((pixel & 0x000000ff) << 24)); - break; - case 32: - pixel = (((pixel & 0xff000000) >> 24) | - ((pixel & 0x00ff0000) >> 8) | - ((pixel & 0x0000ff00) << 8) | - ((pixel & 0x000000ff) << 24)); - break; - default: - qDebug("Cannot handle %d bpp client", pixelFormat.bitsPerPixel); - } - } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian - switch (pixelFormat.bitsPerPixel) { - case 16: - pixel = (((pixel & 0xff000000) >> 8) | - ((pixel & 0x00ff0000) << 8)); - break; - case 32: - pixel = (((pixel & 0xff000000) >> 24) | - ((pixel & 0x00ff0000) >> 8) | - ((pixel & 0x0000ff00) << 8) | - ((pixel & 0x000000ff) << 24)); - break; - default: - qDebug("Cannot handle %d bpp client", - pixelFormat.bitsPerPixel); - break; - } - } - memcpy(dst, &pixel, bytesPerPixel); // XXX: simple for-loop instead? - dst += bytesPerPixel; - } -} - -#ifndef QT_NO_QWS_CURSOR -static void blendCursor(QImage &image, const QRect &imageRect) -{ - const QRect cursorRect = qt_screencursor->boundingRect(); - const QRect intersection = (cursorRect & imageRect); - const QRect destRect = intersection.translated(-imageRect.topLeft()); - const QRect srcRect = intersection.translated(-cursorRect.topLeft()); - - QPainter painter(&image); - painter.drawImage(destRect, qt_screencursor->image(), srcRect); - painter.end(); -} -#endif // QT_NO_QWS_CURSOR - -QVNCDirtyMap::QVNCDirtyMap(QVNCScreen *s) - : bytesPerPixel(0), numDirty(0), screen(s) -{ - bytesPerPixel = (screen->depth() + 7) / 8; - QSize screenSize = screen->geometry().size(); - bufferWidth = screenSize.width(); - bufferHeight = screenSize.height(); - bufferStride = bufferWidth * bytesPerPixel; - buffer = new uchar[bufferHeight * bufferStride]; - - mapWidth = (bufferWidth + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; - mapHeight = (bufferHeight + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; - numTiles = mapWidth * mapHeight; - map = new uchar[numTiles]; -} - -QVNCDirtyMap::~QVNCDirtyMap() -{ - delete[] map; - delete[] buffer; -} - -void QVNCDirtyMap::reset() -{ - memset(map, 1, numTiles); - memset(buffer, 0, bufferHeight * bufferStride); - numDirty = numTiles; -} - -inline bool QVNCDirtyMap::dirty(int x, int y) const -{ - return map[y * mapWidth + x]; -} - -inline void QVNCDirtyMap::setClean(int x, int y) -{ - map[y * mapWidth + x] = 0; - --numDirty; -} - -template <class T> -void QVNCDirtyMapOptimized<T>::setDirty(int tileX, int tileY, bool force) -{ - static bool alwaysForce = qgetenv("QT_VNC_NO_COMPAREBUFFER").toInt(); - if (alwaysForce) - force = true; - - bool changed = false; - - if (!force) { - const int lstep = screen->linestep(); - const int startX = tileX * MAP_TILE_SIZE; - const int startY = tileY * MAP_TILE_SIZE; - const uchar *scrn = screen->base() - + startY * lstep + startX * bytesPerPixel; - uchar *old = buffer + startY * bufferStride + startX * sizeof(T); - - const int tileHeight = (startY + MAP_TILE_SIZE > bufferHeight ? - bufferHeight - startY : MAP_TILE_SIZE); - const int tileWidth = (startX + MAP_TILE_SIZE > bufferWidth ? - bufferWidth - startX : MAP_TILE_SIZE); - const bool doInlines = (tileWidth == MAP_TILE_SIZE); - - int y = tileHeight; - - if (doInlines) { // hw: memcmp/memcpy is inlined when using constants - while (y) { - if (memcmp(old, scrn, sizeof(T) * MAP_TILE_SIZE)) { - changed = true; - break; - } - scrn += lstep; - old += bufferStride; - --y; - } - - while (y) { - memcpy(old, scrn, sizeof(T) * MAP_TILE_SIZE); - scrn += lstep; - old += bufferStride; - --y; - } - } else { - while (y) { - if (memcmp(old, scrn, sizeof(T) * tileWidth)) { - changed = true; - break; - } - scrn += lstep; - old += bufferStride; - --y; - } - - while (y) { - memcpy(old, scrn, sizeof(T) * tileWidth); - scrn += lstep; - old += bufferStride; - --y; - } - } - } - - const int mapIndex = tileY * mapWidth + tileX; - if ((force || changed) && !map[mapIndex]) { - map[mapIndex] = 1; - ++numDirty; - } -} - -template <class SRC> -QRfbHextileEncoder<SRC>::QRfbHextileEncoder(QVNCServer *s) - : QRfbEncoder(s), - singleColorHextile(this), dualColorHextile(this), multiColorHextile(this) -{ -} - -/* - \internal - Send dirty rects using hextile encoding. -*/ -template <class SRC> -void QRfbHextileEncoder<SRC>::write() -{ -// QWSDisplay::grab(true); - - QVNCDirtyMap *map = server->dirtyMap(); - QTcpSocket *socket = server->clientSocket(); - - const quint32 encoding = htonl(5); // hextile encoding - const int bytesPerPixel = server->clientBytesPerPixel(); - - { - const char tmp[2] = { 0, 0 }; // msg type, padding - socket->write(tmp, sizeof(tmp)); - } - { - const quint16 count = htons(map->numDirty); - socket->write((char *)&count, sizeof(count)); - } - - if (map->numDirty <= 0) { -// QWSDisplay::ungrab(); - return; - } - - newBg = true; - newFg = true; - - const QImage screenImage = server->screenImage(); - QRfbRect rect(0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE); - - QSize screenSize = server->screen()->geometry().size(); - - for (int y = 0; y < map->mapHeight; ++y) { - if (rect.y + MAP_TILE_SIZE > screenSize.height()) - rect.h = screenSize.height() - rect.y; - rect.w = MAP_TILE_SIZE; - for (int x = 0; x < map->mapWidth; ++x) { - if (!map->dirty(x, y)) - continue; - map->setClean(x, y); - - rect.x = x * MAP_TILE_SIZE; - if (rect.x + MAP_TILE_SIZE > screenSize.width()) //###deviceWidth ??? - rect.w = screenSize.width() - rect.x; - rect.write(socket); - - socket->write((char *)&encoding, sizeof(encoding)); - - const uchar *screendata = screenImage.scanLine(rect.y) - + rect.x * screenImage.depth() / 8; - int linestep = screenImage.bytesPerLine(); - -#ifndef QT_NO_QWS_CURSOR - // hardware cursors must be blended with the screen memory - const bool doBlendCursor = qt_screencursor - && !server->hasClientCursor() - && qt_screencursor->isAccelerated(); - QImage tileImage; - if (doBlendCursor) { - const QRect tileRect(rect.x, rect.y, rect.w, rect.h); - const QRect cursorRect = qt_screencursor->boundingRect() - .translated(-server->screen()->offset()); - if (tileRect.intersects(cursorRect)) { - tileImage = screenImage.copy(tileRect); - blendCursor(tileImage, - tileRect.translated(server->screen()->offset())); - screendata = tileImage.bits(); - linestep = tileImage.bytesPerLine(); - } - } -#endif // QT_NO_QWS_CURSOR - - if (singleColorHextile.read(screendata, rect.w, rect.h, linestep)) { - singleColorHextile.write(socket); - } else if (dualColorHextile.read(screendata, rect.w, rect.h, linestep)) { - dualColorHextile.write(socket); - } else if (multiColorHextile.read(screendata, rect.w, rect.h, linestep)) { - multiColorHextile.write(socket); - } else if (server->doPixelConversion()) { - const int bufferSize = rect.w * rect.h * bytesPerPixel + 1; - const int padding = sizeof(quint32) - sizeof(char); - buffer.resize(bufferSize + padding); - - buffer[padding] = 1; // Raw subencoding - - // convert pixels - char *b = buffer.data() + padding + 1; - const int bstep = rect.w * bytesPerPixel; - for (int i = 0; i < rect.h; ++i) { - server->convertPixels(b, (const char*)screendata, rect.w); - screendata += linestep; - b += bstep; - } - socket->write(buffer.constData() + padding, bufferSize); - } else { - quint8 subenc = 1; // Raw subencoding - socket->write((char *)&subenc, 1); - - // send pixels - for (int i = 0; i < rect.h; ++i) { - socket->write((const char*)screendata, - rect.w * bytesPerPixel); - screendata += linestep; - } - } - } - if (socket->state() == QAbstractSocket::UnconnectedState) - break; - rect.y += MAP_TILE_SIZE; - } - socket->flush(); - Q_ASSERT(map->numDirty == 0); - -// QWSDisplay::ungrab(); -} - -void QRfbRawEncoder::write() -{ -// QWSDisplay::grab(false); - - QVNCDirtyMap *map = server->dirtyMap(); - QTcpSocket *socket = server->clientSocket(); - - const int bytesPerPixel = server->clientBytesPerPixel(); - QSize screenSize = server->screen()->geometry().size(); - - // create a region from the dirty rects and send the region's merged rects. - QRegion rgn; - if (map) { - for (int y = 0; y < map->mapHeight; ++y) { - for (int x = 0; x < map->mapWidth; ++x) { - if (!map->dirty(x, y)) - continue; - rgn += QRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, - MAP_TILE_SIZE, MAP_TILE_SIZE); - map->setClean(x, y); - } - } - - rgn &= QRect(0, 0, screenSize.width(), - screenSize.height()); - } - const QVector<QRect> rects = rgn.rects(); - - { - const char tmp[2] = { 0, 0 }; // msg type, padding - socket->write(tmp, sizeof(tmp)); - } - - { - const quint16 count = htons(rects.size()); - socket->write((char *)&count, sizeof(count)); - } - - if (rects.size() <= 0) { -// QWSDisplay::ungrab(); - return; - } - - const QImage *screenImage = server->screenImage(); - - for (int i = 0; i < rects.size(); ++i) { - const QRect tileRect = rects.at(i); - const QRfbRect rect(tileRect.x(), tileRect.y(), - tileRect.width(), tileRect.height()); - rect.write(socket); - - const quint32 encoding = htonl(0); // raw encoding - socket->write((char *)&encoding, sizeof(encoding)); - - int linestep = screenImage->bytesPerLine(); - const uchar *screendata = screenImage->scanLine(rect.y) - + rect.x * screenImage->depth() / 8; - -#ifndef QT_NO_QWS_CURSOR - // hardware cursors must be blended with the screen memory - const bool doBlendCursor = qt_screencursor - && !server->hasClientCursor() - && qt_screencursor->isAccelerated(); - QImage tileImage; - if (doBlendCursor) { - const QRect cursorRect = qt_screencursor->boundingRect() - .translated(-server->screen()->offset()); - if (tileRect.intersects(cursorRect)) { - tileImage = screenImage->copy(tileRect); - blendCursor(tileImage, - tileRect.translated(server->screen()->offset())); - screendata = tileImage.bits(); - linestep = tileImage.bytesPerLine(); - } - } -#endif // QT_NO_QWS_CURSOR - - if (server->doPixelConversion()) { - const int bufferSize = rect.w * rect.h * bytesPerPixel; - if (bufferSize > buffer.size()) - buffer.resize(bufferSize); - - // convert pixels - char *b = buffer.data(); - const int bstep = rect.w * bytesPerPixel; - for (int i = 0; i < rect.h; ++i) { - server->convertPixels(b, (const char*)screendata, rect.w); - screendata += linestep; - b += bstep; - } - socket->write(buffer.constData(), bufferSize); - } else { - for (int i = 0; i < rect.h; ++i) { - socket->write((const char*)screendata, rect.w * bytesPerPixel); - screendata += linestep; - } - } - if (socket->state() == QAbstractSocket::UnconnectedState) - break; - } - socket->flush(); - -// QWSDisplay::ungrab(); -} - -inline QImage *QVNCServer::screenImage() const -{ - return qvnc_screen->image(); -} - -void QVNCServer::checkUpdate() -{ - if (!wantUpdate) - return; - - if (dirtyCursor) { -#ifndef QT_NO_QWS_CURSOR - Q_ASSERT(qvnc_cursor); - qvnc_cursor->write(); -#endif - cursor->sendClientCursor(); - dirtyCursor = false; - wantUpdate = false; - return; - } - - if (dirtyMap()->numDirty > 0) { - if (encoder) - encoder->write(); - wantUpdate = false; - } -} - -void QVNCServer::discardClient() -{ - timer->stop(); - state = Unconnected; - delete encoder; - encoder = 0; -#ifndef QT_NO_QWS_CURSOR - delete qvnc_cursor; - qvnc_cursor = 0; -#endif -// if (!qvnc_screen->screen()) -// QWSServer::instance()->enablePainting(false); -} - - - -QVNCScreenPrivate::QVNCScreenPrivate(QVNCScreen *parent, int screenId) - : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25), - vncServer(0), q_ptr(parent) -{ -#if 0//ndef QT_NO_QWS_SIGNALHANDLER - QWSSignalHandler::instance()->addObject(this); -#endif - - vncServer = new QVNCServer(q_ptr, screenId); - vncServer->setRefreshRate(refreshRate); - - - Q_ASSERT(q_ptr->depth() == 32); - - dirty = new QVNCDirtyMapOptimized<quint32>(q_ptr); -} - -QVNCScreenPrivate::~QVNCScreenPrivate() -{ -} - - -void QVNCScreenPrivate::setDirty(const QRect& rect, bool force) -{ - if (rect.isEmpty()) - return; - -// if (q_ptr->screen()) -// q_ptr->screen()->setDirty(rect); - - if (!vncServer || !vncServer->isConnected()) { -// qDebug() << "QVNCScreenPrivate::setDirty() - Not connected"; - return; - } - const QRect r = rect; // .translated(-q_ptr->offset()); - const int x1 = r.x() / MAP_TILE_SIZE; - int y = r.y() / MAP_TILE_SIZE; - for (; (y <= r.bottom() / MAP_TILE_SIZE) && y < dirty->mapHeight; y++) - for (int x = x1; (x <= r.right() / MAP_TILE_SIZE) && x < dirty->mapWidth; x++) - dirty->setDirty(x, y, force); - - vncServer->setDirty(); -} - - - - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvncserver.h b/src/plugins/platforms/vnc/qvncserver.h deleted file mode 100644 index e8b093764f..0000000000 --- a/src/plugins/platforms/vnc/qvncserver.h +++ /dev/null @@ -1,533 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the plugins 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 QSCREENVNC_P_H -#define QSCREENVNC_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 "qvncintegration.h" -#include "qvnccursor.h" -#define QT_NO_QWS_CURSOR - -#ifndef QT_NO_QWS_VNC - -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qsharedmemory.h> -#include <QtNetwork/qtcpsocket.h> -#include <QtNetwork/qtcpserver.h> - -QT_BEGIN_NAMESPACE - -class QVNCServer; - -#ifndef QT_NO_QWS_CURSOR -class QVNCCursor : public QProxyScreenCursor -{ -public: - QVNCCursor(QVNCScreen *s); - ~QVNCCursor(); - - void hide(); - void show(); - void set(const QImage &image, int hotx, int hoty); - void move(int x, int y); - -private: - void setDirty(const QRect &r) const; - QVNCScreen *screen; -}; - -class QVNCClientCursor : public QProxyScreenCursor -{ -public: - QVNCClientCursor(QVNCServer *s); - ~QVNCClientCursor(); - - void set(const QImage &image, int hotx, int hoty); - void write() const; - -private: - QVNCServer *server; -}; -#endif // QT_NO_QWS_CURSOR - -#define MAP_TILE_SIZE 16 -#define MAP_WIDTH 1280 / MAP_TILE_SIZE -#define MAP_HEIGHT 1024 / MAP_TILE_SIZE - -class QVNCDirtyMap -{ -public: - QVNCDirtyMap(QVNCScreen *screen); - virtual ~QVNCDirtyMap(); - - void reset(); - bool dirty(int x, int y) const; - virtual void setDirty(int x, int y, bool force = false) = 0; - void setClean(int x, int y); - - int bytesPerPixel; - - int numDirty; - int mapWidth; - int mapHeight; - -protected: - uchar *map; - QVNCScreen *screen; - uchar *buffer; - int bufferWidth; - int bufferHeight; - int bufferStride; - int numTiles; -}; - -template <class T> -class QVNCDirtyMapOptimized : public QVNCDirtyMap -{ -public: - QVNCDirtyMapOptimized(QVNCScreen *screen) : QVNCDirtyMap(screen) {} - ~QVNCDirtyMapOptimized() {} - - void setDirty(int x, int y, bool force = false); -}; - -class QRfbRect -{ -public: - QRfbRect() {} - QRfbRect(quint16 _x, quint16 _y, quint16 _w, quint16 _h) { - x = _x; y = _y; w = _w; h = _h; - } - - void read(QTcpSocket *s); - void write(QTcpSocket *s) const; - - quint16 x; - quint16 y; - quint16 w; - quint16 h; -}; - -class QRfbPixelFormat -{ -public: - static int size() { return 16; } - - void read(QTcpSocket *s); - void write(QTcpSocket *s); - - int bitsPerPixel; - int depth; - bool bigEndian; - bool trueColor; - int redBits; - int greenBits; - int blueBits; - int redShift; - int greenShift; - int blueShift; -}; - -class QRfbServerInit -{ -public: - QRfbServerInit() { name = 0; } - ~QRfbServerInit() { delete[] name; } - - int size() const { return QRfbPixelFormat::size() + 8 + strlen(name); } - void setName(const char *n); - - void read(QTcpSocket *s); - void write(QTcpSocket *s); - - quint16 width; - quint16 height; - QRfbPixelFormat format; - char *name; -}; - -class QRfbSetEncodings -{ -public: - bool read(QTcpSocket *s); - - quint16 count; -}; - -class QRfbFrameBufferUpdateRequest -{ -public: - bool read(QTcpSocket *s); - - char incremental; - QRfbRect rect; -}; - -class QRfbKeyEvent -{ -public: - bool read(QTcpSocket *s); - - char down; - int keycode; - int unicode; -}; - -class QRfbPointerEvent -{ -public: - bool read(QTcpSocket *s); - - Qt::MouseButtons buttons; - enum { WheelNone, - WheelUp, - WheelDown, - WheelLeft, - WheelRight - } wheelDirection; - quint16 x; - quint16 y; -}; - -class QRfbClientCutText -{ -public: - bool read(QTcpSocket *s); - - quint32 length; -}; - -class QVNCScreenPrivate : public QObject -{ -public: - QVNCScreenPrivate(QVNCScreen *parent, int screenId); - ~QVNCScreenPrivate(); - - void setDirty(const QRect &rect, bool force = false); - void configure(); - - qreal dpiX; - qreal dpiY; - bool doOnScreenSurface; - QVNCDirtyMap *dirty; - int refreshRate; - QVNCServer *vncServer; - -#if !defined(QT_NO_SHAREDMEMORY) - QSharedMemory shm; -#endif - - QVNCScreen *q_ptr; -}; - -class QRfbEncoder -{ -public: - QRfbEncoder(QVNCServer *s) : server(s) {} - virtual ~QRfbEncoder() {} - - virtual void write() = 0; - -protected: - QVNCServer *server; -}; - -class QRfbRawEncoder : public QRfbEncoder -{ -public: - QRfbRawEncoder(QVNCServer *s) : QRfbEncoder(s) {} - - void write(); - -private: - QByteArray buffer; -}; - -template <class SRC> class QRfbHextileEncoder; - -template <class SRC> -class QRfbSingleColorHextile -{ -public: - QRfbSingleColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} - bool read(const uchar *data, int width, int height, int stride); - void write(QTcpSocket *socket) const; - -private: - QRfbHextileEncoder<SRC> *encoder; -}; - -template <class SRC> -class QRfbDualColorHextile -{ -public: - QRfbDualColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} - bool read(const uchar *data, int width, int height, int stride); - void write(QTcpSocket *socket) const; - -private: - struct Rect { - quint8 xy; - quint8 wh; - } Q_PACKED rects[8 * 16]; - - quint8 numRects; - QRfbHextileEncoder<SRC> *encoder; - -private: - inline int lastx() const { return rectx(numRects); } - inline int lasty() const { return recty(numRects); } - inline int rectx(int r) const { return rects[r].xy >> 4; } - inline int recty(int r) const { return rects[r].xy & 0x0f; } - inline int width(int r) const { return (rects[r].wh >> 4) + 1; } - inline int height(int r) const { return (rects[r].wh & 0x0f) + 1; } - - inline void setX(int r, int x) { - rects[r].xy = (x << 4) | (rects[r].xy & 0x0f); - } - inline void setY(int r, int y) { - rects[r].xy = (rects[r].xy & 0xf0) | y; - } - inline void setWidth(int r, int width) { - rects[r].wh = ((width - 1) << 4) | (rects[r].wh & 0x0f); - } - inline void setHeight(int r, int height) { - rects[r].wh = (rects[r].wh & 0xf0) | (height - 1); - } - - inline void setWidth(int width) { setWidth(numRects, width); } - inline void setHeight(int height) { setHeight(numRects, height); } - inline void setX(int x) { setX(numRects, x); } - inline void setY(int y) { setY(numRects, y); } - void next(); -}; - -template <class SRC> -class QRfbMultiColorHextile -{ -public: - QRfbMultiColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} - bool read(const uchar *data, int width, int height, int stride); - void write(QTcpSocket *socket) const; - -private: - inline quint8* rect(int r) { - return rects.data() + r * (bpp + 2); - } - inline const quint8* rect(int r) const { - return rects.constData() + r * (bpp + 2); - } - inline void setX(int r, int x) { - quint8 *ptr = rect(r) + bpp; - *ptr = (x << 4) | (*ptr & 0x0f); - } - inline void setY(int r, int y) { - quint8 *ptr = rect(r) + bpp; - *ptr = (*ptr & 0xf0) | y; - } - void setColor(SRC color); - inline int rectx(int r) const { - const quint8 *ptr = rect(r) + bpp; - return *ptr >> 4; - } - inline int recty(int r) const { - const quint8 *ptr = rect(r) + bpp; - return *ptr & 0x0f; - } - inline void setWidth(int r, int width) { - quint8 *ptr = rect(r) + bpp + 1; - *ptr = ((width - 1) << 4) | (*ptr & 0x0f); - } - inline void setHeight(int r, int height) { - quint8 *ptr = rect(r) + bpp + 1; - *ptr = (*ptr & 0xf0) | (height - 1); - } - - bool beginRect(); - void endRect(); - - static const int maxRectsSize = 16 * 16; - QVarLengthArray<quint8, maxRectsSize> rects; - - quint8 bpp; - quint8 numRects; - QRfbHextileEncoder<SRC> *encoder; -}; - -template <class SRC> -class QRfbHextileEncoder : public QRfbEncoder -{ -public: - QRfbHextileEncoder(QVNCServer *s); - void write(); - -private: - enum SubEncoding { - Raw = 1, - BackgroundSpecified = 2, - ForegroundSpecified = 4, - AnySubrects = 8, - SubrectsColoured = 16 - }; - - QByteArray buffer; - QRfbSingleColorHextile<SRC> singleColorHextile; - QRfbDualColorHextile<SRC> dualColorHextile; - QRfbMultiColorHextile<SRC> multiColorHextile; - - SRC bg; - SRC fg; - bool newBg; - bool newFg; - - friend class QRfbSingleColorHextile<SRC>; - friend class QRfbDualColorHextile<SRC>; - friend class QRfbMultiColorHextile<SRC>; -}; - -class QVNCServer : public QObject -{ - Q_OBJECT -public: - QVNCServer(QVNCScreen *screen); - QVNCServer(QVNCScreen *screen, int id); - ~QVNCServer(); - - void setDirty(); - void setDirtyCursor() { dirtyCursor = true; setDirty(); } - inline bool isConnected() const { return state == Connected; } - inline void setRefreshRate(int rate) { refreshRate = rate; } - - enum ClientMsg { SetPixelFormat = 0, - FixColourMapEntries = 1, - SetEncodings = 2, - FramebufferUpdateRequest = 3, - KeyEvent = 4, - PointerEvent = 5, - ClientCutText = 6 }; - - enum ServerMsg { FramebufferUpdate = 0, - SetColourMapEntries = 1 }; - - void convertPixels(char *dst, const char *src, int count) const; - - inline int clientBytesPerPixel() const { - return pixelFormat.bitsPerPixel / 8; - } - - inline QVNCScreen* screen() const { return qvnc_screen; } - inline QVNCDirtyMap* dirtyMap() const { return qvnc_screen->dirtyMap(); } - inline QTcpSocket* clientSocket() const { return client; } - QImage *screenImage() const; - inline bool doPixelConversion() const { return needConversion; } -#ifndef QT_NO_QWS_CURSOR - inline bool hasClientCursor() const { return qvnc_cursor != 0; } -#endif - - void setCursor(QVNCCursor * c) { cursor = c; } -private: - void setPixelFormat(); - void setEncodings(); - void frameBufferUpdateRequest(); - void pointerEvent(); - void keyEvent(); - void clientCutText(); - bool pixelConversionNeeded() const; - -private slots: - void newConnection(); - void readClient(); - void checkUpdate(); - void discardClient(); - -private: - void init(uint port); - enum ClientState { Unconnected, Protocol, Init, Connected }; - QTimer *timer; - QTcpServer *serverSocket; - QTcpSocket *client; - ClientState state; - quint8 msgType; - bool handleMsg; - QRfbPixelFormat pixelFormat; - Qt::KeyboardModifiers keymod; - Qt::MouseButtons buttons; - int encodingsPending; - int cutTextPending; - uint supportCopyRect : 1; - uint supportRRE : 1; - uint supportCoRRE : 1; - uint supportHextile : 1; - uint supportZRLE : 1; - uint supportCursor : 1; - uint supportDesktopSize : 1; - bool wantUpdate; - bool sameEndian; - bool needConversion; -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - bool swapBytes; -#endif - bool dirtyCursor; - int refreshRate; - QVNCScreen *qvnc_screen; -#ifndef QT_NO_QWS_CURSOR - QVNCClientCursor *qvnc_cursor; -#endif - - QRfbEncoder *encoder; - QVNCCursor *cursor; -}; - - -QT_END_NAMESPACE -#endif // QT_NO_QWS_VNC -#endif // QSCREENVNC_P_H diff --git a/src/plugins/platforms/vnc/vnc.pro b/src/plugins/platforms/vnc/vnc.pro deleted file mode 100644 index 637ed82385..0000000000 --- a/src/plugins/platforms/vnc/vnc.pro +++ /dev/null @@ -1,22 +0,0 @@ -TARGET = qvncgraphicssystem -load(qt_plugin) - -QT += network core-private gui-private platformsupport-private - -DESTDIR = $$QT.gui.plugins/platforms - -SOURCES = main.cpp qvncintegration.cpp -HEADERS = qvncintegration.h - -HEADERS += qvncserver.h -SOURCES += qvncserver.cpp - -HEADERS += qvnccursor.h -SOURCES += qvnccursor.cpp - -include(../fb_base/fb_base.pri) -CONFIG += qpa/genericunixfontdatabase - -target.path += $$[QT_INSTALL_PLUGINS]/platforms - -INSTALLS += target diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri new file mode 100644 index 0000000000..1671c67d17 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -0,0 +1,19 @@ +SOURCES += \ + $$PWD/qwindowsaccessibility.cpp + +HEADERS += \ + $$PWD/qwindowsaccessibility.h + +!*g++* { + SOURCES += \ + $$PWD/qwindowsmsaaaccessible.cpp \ + $$PWD/iaccessible2.cpp \ + $$PWD/comutils.cpp + + HEADERS += \ + $$PWD/qwindowsmsaaaccessible.h \ + $$PWD/iaccessible2.h \ + $$PWD/comutils.h + + include(../../../../3rdparty/iaccessible2/iaccessible2.pri) +} # !g++ diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp new file mode 100644 index 0000000000..9a0fce20b8 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/comutils.cpp @@ -0,0 +1,641 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 <ocidl.h> +#include <olectl.h> + +#include "comutils.h" +#include <QtCore/qdatetime.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qfont.h> + + +#include <QtCore/qvariant.h> +#include <QtCore/qbytearray.h> +#include <QtGui/qcolor.h> + +static DATE QDateTimeToDATE(const QDateTime &dt) +{ + if (!dt.isValid() || dt.isNull()) + return 949998; // Special value for no date (01/01/4501) + + SYSTEMTIME stime; + memset(&stime, 0, sizeof(stime)); + QDate date = dt.date(); + QTime time = dt.time(); + if (date.isValid() && !date.isNull()) { + stime.wDay = date.day(); + stime.wMonth = date.month(); + stime.wYear = date.year(); + } + if (time.isValid() && !time.isNull()) { + stime.wMilliseconds = time.msec(); + stime.wSecond = time.second(); + stime.wMinute = time.minute(); + stime.wHour = time.hour(); + } + + double vtime; + SystemTimeToVariantTime(&stime, &vtime); + + return vtime; +} + +inline uint QColorToOLEColor(const QColor &col) +{ + return qRgba(col.blue(), col.green(), col.red(), 0x00); +} + +bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out) +{ + QVariant qvar = var; + // "type" is the expected type, so coerce if necessary + QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName); + if (proptype == QVariant::UserType && !typeName.isEmpty()) { + if (typeName == "short" || typeName == "char") + proptype = QVariant::Int; + else if (typeName == "float") + proptype = QVariant::Double; + } + if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) { + if (qvar.canConvert(proptype)) + qvar.convert(proptype); + else + qvar = QVariant(proptype); + } + + if (out && arg.vt == (VT_VARIANT|VT_BYREF) && arg.pvarVal) { + return QVariantToVARIANT(var, *arg.pvarVal, typeName, false); + } + + if (out && proptype == QVariant::UserType && typeName == "QVariant") { + VARIANT *pVariant = new VARIANT; + QVariantToVARIANT(var, *pVariant, QByteArray(), false); + arg.vt = VT_VARIANT|VT_BYREF; + arg.pvarVal = pVariant; + return true; + } + + switch ((int)qvar.type()) { + case QVariant::String: + if (out && arg.vt == (VT_BSTR|VT_BYREF)) { + if (*arg.pbstrVal) + SysFreeString(*arg.pbstrVal); + *arg.pbstrVal = QStringToBSTR(qvar.toString()); + arg.vt = VT_BSTR|VT_BYREF; + } else { + arg.vt = VT_BSTR; + arg.bstrVal = QStringToBSTR(qvar.toString()); + if (out) { + arg.pbstrVal = new BSTR(arg.bstrVal); + arg.vt |= VT_BYREF; + } + } + break; + + case QVariant::Int: + if (out && arg.vt == (VT_I4|VT_BYREF)) { + *arg.plVal = qvar.toInt(); + } else { + arg.vt = VT_I4; + arg.lVal = qvar.toInt(); + if (out) { + if (typeName == "short") { + arg.vt = VT_I2; + arg.piVal = new short(arg.lVal); + } else if (typeName == "char") { + arg.vt = VT_I1; + arg.pcVal= new char(arg.lVal); + } else { + arg.plVal = new long(arg.lVal); + } + arg.vt |= VT_BYREF; + } + } + break; + + case QVariant::UInt: + if (out && (arg.vt == (VT_UINT|VT_BYREF) || arg.vt == (VT_I4|VT_BYREF))) { + *arg.puintVal = qvar.toUInt(); + } else { + arg.vt = VT_UINT; + arg.uintVal = qvar.toUInt(); + if (out) { + arg.puintVal = new uint(arg.uintVal); + arg.vt |= VT_BYREF; + } + } + break; + + case QVariant::LongLong: + if (out && arg.vt == (VT_CY|VT_BYREF)) { + arg.pcyVal->int64 = qvar.toLongLong(); +#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400 + } else if (out && arg.vt == (VT_I8|VT_BYREF)) { + *arg.pllVal = qvar.toLongLong(); + } else { + arg.vt = VT_I8; + arg.llVal = qvar.toLongLong(); + if (out) { + arg.pllVal = new LONGLONG(arg.llVal); + arg.vt |= VT_BYREF; + } + } +#else + } else { + arg.vt = VT_CY; + arg.cyVal.int64 = qvar.toLongLong(); + if (out) { + arg.pcyVal = new CY(arg.cyVal); + arg.vt |= VT_BYREF; + } + } +#endif + break; + + case QVariant::ULongLong: + if (out && arg.vt == (VT_CY|VT_BYREF)) { + arg.pcyVal->int64 = qvar.toULongLong(); +#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400 + } else if (out && arg.vt == (VT_UI8|VT_BYREF)) { + *arg.pullVal = qvar.toULongLong(); + } else { + arg.vt = VT_UI8; + arg.ullVal = qvar.toULongLong(); + if (out) { + arg.pullVal = new ULONGLONG(arg.ullVal); + arg.vt |= VT_BYREF; + } + } +#else + } else { + arg.vt = VT_CY; + arg.cyVal.int64 = qvar.toULongLong(); + if (out) { + arg.pcyVal = new CY(arg.cyVal); + arg.vt |= VT_BYREF; + } + } + +#endif + + break; + + case QVariant::Bool: + if (out && arg.vt == (VT_BOOL|VT_BYREF)) { + *arg.pboolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE; + } else { + arg.vt = VT_BOOL; + arg.boolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE; + if (out) { + arg.pboolVal = new short(arg.boolVal); + arg.vt |= VT_BYREF; + } + } + break; + case QVariant::Double: + if (out && arg.vt == (VT_R8|VT_BYREF)) { + *arg.pdblVal = qvar.toDouble(); + } else { + arg.vt = VT_R8; + arg.dblVal = qvar.toDouble(); + if (out) { + if (typeName == "float") { + arg.vt = VT_R4; + arg.pfltVal = new float(arg.dblVal); + } else { + arg.pdblVal = new double(arg.dblVal); + } + arg.vt |= VT_BYREF; + } + } + break; + case QVariant::Color: + if (out && arg.vt == (VT_COLOR|VT_BYREF)) { + + *arg.plVal = QColorToOLEColor(qvariant_cast<QColor>(qvar)); + } else { + arg.vt = VT_COLOR; + arg.lVal = QColorToOLEColor(qvariant_cast<QColor>(qvar)); + if (out) { + arg.plVal = new long(arg.lVal); + arg.vt |= VT_BYREF; + } + } + break; + + case QVariant::Date: + case QVariant::Time: + case QVariant::DateTime: + if (out && arg.vt == (VT_DATE|VT_BYREF)) { + *arg.pdate = QDateTimeToDATE(qvar.toDateTime()); + } else { + arg.vt = VT_DATE; + arg.date = QDateTimeToDATE(qvar.toDateTime()); + if (out) { + arg.pdate = new DATE(arg.date); + arg.vt |= VT_BYREF; + } + } + break; +#if 0 // not a value with min/max semantics + case QVariant::Font: + if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { + if (*arg.ppdispVal) + (*arg.ppdispVal)->Release(); + *arg.ppdispVal = QFontToIFont(qvariant_cast<QFont>(qvar)); + } else { + arg.vt = VT_DISPATCH; + arg.pdispVal = QFontToIFont(qvariant_cast<QFont>(qvar)); + if (out) { + arg.ppdispVal = new IDispatch*(arg.pdispVal); + arg.vt |= VT_BYREF; + } + } + break; + case QVariant::Pixmap: + if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) { + if (*arg.ppdispVal) + (*arg.ppdispVal)->Release(); + *arg.ppdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar)); + } else { + arg.vt = VT_DISPATCH; + arg.pdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar)); + if (out) { + arg.ppdispVal = new IDispatch*(arg.pdispVal); + arg.vt |= VT_BYREF; + } + } + break; + case QVariant::Cursor: + { +#ifndef QT_NO_CURSOR + int shape = qvariant_cast<QCursor>(qvar).shape(); + if (out && (arg.vt & VT_BYREF)) { + switch (arg.vt & ~VT_BYREF) { + case VT_I4: + *arg.plVal = shape; + break; + case VT_I2: + *arg.piVal = shape; + break; + case VT_UI4: + *arg.pulVal = shape; + break; + case VT_UI2: + *arg.puiVal = shape; + break; + case VT_INT: + *arg.pintVal = shape; + break; + case VT_UINT: + *arg.puintVal = shape; + break; + } + } else { + arg.vt = VT_I4; + arg.lVal = shape; + if (out) { + arg.plVal = new long(arg.lVal); + arg.vt |= VT_BYREF; + } + } +#endif + } + break; + + case QVariant::List: + { + const QList<QVariant> list = qvar.toList(); + const int count = list.count(); + VARTYPE vt = VT_VARIANT; + QVariant::Type listType = QVariant::LastType; // == QVariant + if (!typeName.isEmpty() && typeName.startsWith("QList<")) { + const QByteArray listTypeName = typeName.mid(6, typeName.length() - 7); // QList<int> -> int + listType = QVariant::nameToType(listTypeName); + } + + VARIANT variant; + void *pElement = &variant; + switch (listType) { + case QVariant::Int: + vt = VT_I4; + pElement = &variant.lVal; + break; + case QVariant::Double: + vt = VT_R8; + pElement = &variant.dblVal; + break; + case QVariant::DateTime: + vt = VT_DATE; + pElement = &variant.date; + break; + case QVariant::Bool: + vt = VT_BOOL; + pElement = &variant.boolVal; + break; + case QVariant::LongLong: +#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400 + vt = VT_I8; + pElement = &variant.llVal; +#else + vt = VT_CY; + pElement = &variant.cyVal; +#endif + break; + default: + break; + } + SAFEARRAY *array = 0; + bool is2D = false; + // If the first element in the array is a list the whole list is + // treated as a 2D array. The column count is taken from the 1st element. + if (count) { + QVariantList col = list.at(0).toList(); + int maxColumns = col.count(); + if (maxColumns) { + is2D = true; + SAFEARRAYBOUND rgsabound[2] = { {0} }; + rgsabound[0].cElements = count; + rgsabound[1].cElements = maxColumns; + array = SafeArrayCreate(VT_VARIANT, 2, rgsabound); + LONG rgIndices[2]; + for (LONG i = 0; i < count; ++i) { + rgIndices[0] = i; + QVariantList columns = list.at(i).toList(); + int columnCount = qMin(maxColumns, columns.count()); + for (LONG j = 0; j < columnCount; ++j) { + QVariant elem = columns.at(j); + VariantInit(&variant); + QVariantToVARIANT(elem, variant, elem.typeName()); + rgIndices[1] = j; + SafeArrayPutElement(array, rgIndices, pElement); + clearVARIANT(&variant); + } + } + + } + } + if (!is2D) { + array = SafeArrayCreateVector(vt, 0, count); + for (LONG index = 0; index < count; ++index) { + QVariant elem = list.at(index); + if (listType != QVariant::LastType) + elem.convert(listType); + VariantInit(&variant); + QVariantToVARIANT(elem, variant, elem.typeName()); + SafeArrayPutElement(array, &index, pElement); + clearVARIANT(&variant); + } + } + if (out && arg.vt == (VT_ARRAY|vt|VT_BYREF)) { + if (*arg.pparray) + SafeArrayDestroy(*arg.pparray); + *arg.pparray = array; + } else { + arg.vt = VT_ARRAY|vt; + arg.parray = array; + if (out) { + arg.pparray = new SAFEARRAY*(arg.parray); + arg.vt |= VT_BYREF; + } + } + } + break; + + case QVariant::StringList: + { + const QStringList list = qvar.toStringList(); + const int count = list.count(); + SAFEARRAY *array = SafeArrayCreateVector(VT_BSTR, 0, count); + for (LONG index = 0; index < count; ++index) { + QString elem = list.at(index); + BSTR bstr = QStringToBSTR(elem); + SafeArrayPutElement(array, &index, bstr); + SysFreeString(bstr); + } + + if (out && arg.vt == (VT_ARRAY|VT_BSTR|VT_BYREF)) { + if (*arg.pparray) + SafeArrayDestroy(*arg.pparray); + *arg.pparray = array; + } else { + arg.vt = VT_ARRAY|VT_BSTR; + arg.parray = array; + if (out) { + arg.pparray = new SAFEARRAY*(arg.parray); + arg.vt |= VT_BYREF; + } + } + } + break; + + case QVariant::ByteArray: + { + const QByteArray bytes = qvar.toByteArray(); + const uint count = bytes.count(); + SAFEARRAY *array = SafeArrayCreateVector(VT_UI1, 0, count); + if (count) { + const char *data = bytes.constData(); + char *dest; + SafeArrayAccessData(array, (void **)&dest); + memcpy(dest, data, count); + SafeArrayUnaccessData(array); + } + + if (out && arg.vt == (VT_ARRAY|VT_UI1|VT_BYREF)) { + if (*arg.pparray) + SafeArrayDestroy(*arg.pparray); + *arg.pparray = array; + } else { + arg.vt = VT_ARRAY|VT_UI1; + arg.parray = array; + if (out) { + arg.pparray = new SAFEARRAY*(arg.parray); + arg.vt |= VT_BYREF; + } + } + } + break; + +#ifdef QAX_SERVER + case QVariant::Rect: + case QVariant::Size: + case QVariant::Point: + { + typedef HRESULT(WINAPI* PGetRecordInfoFromTypeInfo)(ITypeInfo *, IRecordInfo **); + static PGetRecordInfoFromTypeInfo pGetRecordInfoFromTypeInfo = 0; + static bool resolved = false; + if (!resolved) { + QSystemLibrary oleaut32(QLatin1String("oleaut32")); + pGetRecordInfoFromTypeInfo = (PGetRecordInfoFromTypeInfo)oleaut32.resolve("GetRecordInfoFromTypeInfo"); + resolved = true; + } + if (!pGetRecordInfoFromTypeInfo) + break; + + ITypeInfo *typeInfo = 0; + IRecordInfo *recordInfo = 0; + CLSID clsid = qvar.type() == QVariant::Rect ? CLSID_QRect + :qvar.type() == QVariant::Size ? CLSID_QSize + :CLSID_QPoint; + qAxTypeLibrary->GetTypeInfoOfGuid(clsid, &typeInfo); + if (!typeInfo) + break; + pGetRecordInfoFromTypeInfo(typeInfo, &recordInfo); + typeInfo->Release(); + if (!recordInfo) + break; + + void *record = 0; + switch (qvar.type()) { + case QVariant::Rect: + { + QRect qrect(qvar.toRect()); + recordInfo->RecordCreateCopy(&qrect, &record); + } + break; + case QVariant::Size: + { + QSize qsize(qvar.toSize()); + recordInfo->RecordCreateCopy(&qsize, &record); + } + break; + case QVariant::Point: + { + QPoint qpoint(qvar.toPoint()); + recordInfo->RecordCreateCopy(&qpoint, &record); + } + break; + } + + arg.vt = VT_RECORD; + arg.pRecInfo = recordInfo, + arg.pvRecord = record; + if (out) { + qWarning("QVariantToVARIANT: out-parameter not supported for records"); + return false; + } + } + break; +#endif // QAX_SERVER + case QVariant::UserType: + { + QByteArray subType = qvar.typeName(); +#ifdef QAX_SERVER + if (subType.endsWith('*')) + subType.truncate(subType.length() - 1); +#endif + if (!qstrcmp(qvar.typeName(), "IDispatch*")) { + arg.vt = VT_DISPATCH; + arg.pdispVal = *(IDispatch**)qvar.data(); + if (arg.pdispVal) + arg.pdispVal->AddRef(); + if (out) { + qWarning("QVariantToVARIANT: out-parameter not supported for IDispatch"); + return false; + } + } else if (!qstrcmp(qvar.typeName(), "IDispatch**")) { + arg.vt = VT_DISPATCH; + arg.ppdispVal = *(IDispatch***)qvar.data(); + if (out) + arg.vt |= VT_BYREF; + } else if (!qstrcmp(qvar.typeName(), "IUnknown*")) { + arg.vt = VT_UNKNOWN; + arg.punkVal = *(IUnknown**)qvar.data(); + if (arg.punkVal) + arg.punkVal->AddRef(); + if (out) { + qWarning("QVariantToVARIANT: out-parameter not supported for IUnknown"); + return false; + } +#ifdef QAX_SERVER + } else if (qAxFactory()->metaObject(QString::fromLatin1(subType.constData()))) { + arg.vt = VT_DISPATCH; + void *user = *(void**)qvar.constData(); +// qVariantGet(qvar, user, qvar.typeName()); + if (!user) { + arg.pdispVal = 0; + } else { + qAxFactory()->createObjectWrapper(static_cast<QObject*>(user), &arg.pdispVal); + } + if (out) { + qWarning("QVariantToVARIANT: out-parameter not supported for subtype"); + return false; + } +#else + } else if (QMetaType::type(subType)) { + QAxObject *object = *(QAxObject**)qvar.constData(); +// qVariantGet(qvar, object, subType); + arg.vt = VT_DISPATCH; + object->queryInterface(IID_IDispatch, (void**)&arg.pdispVal); + if (out) { + qWarning("QVariantToVARIANT: out-parameter not supported for subtype"); + return false; + } +#endif + } else { + return false; + } + } + break; +#endif + + case QVariant::Invalid: // default-parameters not set + if (out && arg.vt == (VT_ERROR|VT_BYREF)) { + *arg.plVal = DISP_E_PARAMNOTFOUND; + } else { + arg.vt = VT_ERROR; + arg.lVal = DISP_E_PARAMNOTFOUND; + if (out) { + arg.plVal = new long(arg.lVal); + arg.vt |= VT_BYREF; + } + } + break; + + default: + return false; + } + + Q_ASSERT(!out || (arg.vt & VT_BYREF)); + return true; +} + diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.h b/src/plugins/platforms/windows/accessible/comutils.h index 6ea1b2ad3c..08420cc46c 100644 --- a/src/plugins/platforms/uikit/quikitwindowsurface.h +++ b/src/plugins/platforms/windows/accessible/comutils.h @@ -38,27 +38,24 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef COMUTILS_H +#define COMUTILS_H -#ifndef QUIKITWINDOWSURFACE_H -#define QUIKITWINDOWSURFACE_H +#if !defined(_WINDOWS_) && !defined(_WINDOWS_H) && !defined(__WINDOWS__) +#error Must include windows.h first! +#endif -#include <QtGui/QPlatformIntegration> +#include <ocidl.h> +#include <QtCore/qstring.h> -QT_BEGIN_NAMESPACE +class QVariant; -class QUIKitWindowSurface : public QWindowSurface -{ -public: - QUIKitWindowSurface(QWidget *window); - - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - WindowSurfaceFeatures features() const; +bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out); -private: - QPaintDevice *mPaintDevice; -}; +inline BSTR QStringToBSTR(const QString &str) +{ + return SysAllocStringLen((OLECHAR*)str.unicode(), str.length()); +} -QT_END_NAMESPACE +#endif // COMUTILS_H -#endif // QUIKITWINDOWSURFACE_H diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp new file mode 100644 index 0000000000..f22349714f --- /dev/null +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -0,0 +1,1467 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 <QtCore/QtConfig> +#ifndef QT_NO_ACCESSIBILITY + +#include "iaccessible2.h" +#include "qwindowsaccessibility.h" + +#include <QtGui/qaccessible2.h> +#include <QtWidgets/qapplication.h> +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +/**************************************************************\ + * AccessibleApplication * + **************************************************************/ +// IUnknown +HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface) +{ + *iface = 0; + if (id == IID_IUnknown) { + accessibleDebug("AccessibleApplication::QI(): IID_IUnknown"); + *iface = (IUnknown*)this; + } else if (id == IID_IAccessibleApplication) { + accessibleDebug("AccessibleApplication::QI(): IID_IAccessibleApplication"); + *iface = static_cast<IAccessibleApplication*>(this); + } + + if (*iface) { + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef() +{ + return ++m_ref; +} + +ULONG STDMETHODCALLTYPE AccessibleApplication::Release() +{ + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; +} + +/* IAccessibleApplication */ +HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name) +{ + const QString appName = QGuiApplication::applicationName(); + *name = QStringToBSTR(appName); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appVersion(/* [retval][out] */ BSTR *version) +{ + const QString appName = QGuiApplication::applicationVersion(); + *version = QStringToBSTR(appName); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out] */ BSTR *name) +{ + *name = ::SysAllocString(L"Qt"); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version) +{ + *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR)); + return S_OK; +} + + + +/*! + \internal + Client allocates and deallocates array + (see "Special Consideration when using Arrays", in Accessible2.idl) + */ +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target( + /* [in] */ long targetIndex, + /* [retval][out] */ IUnknown **target) +{ + if (targetIndex >= 0 && targetIndex < m_targets.count()) { + QAccessibleInterface *iface = m_targets.at(targetIndex); + *target = QWindowsAccessibility::wrap(iface); + if (*target) + return S_OK; + return E_FAIL; + } + return E_INVALIDARG; +} + +/*! + \internal + Client allocates and deallocates \a targets array + (see "Special Consideration when using Arrays", in Accessible2.idl) + */ +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( + /* [in] */ long maxTargets, // Hmmm, ignore ??? + /* [length_is][size_is][out] */ IUnknown **targets, + /* [retval][out] */ long *nTargets) +{ + + const int numTargets = qMin((int)maxTargets, m_targets.count()); + for (int i = 0; i < numTargets; ++i) { + QAccessibleInterface *iface = m_targets.at(i); + IAccessible *iacc = QWindowsAccessibility::wrap(iface); + if (!iacc) + return E_FAIL; + *targets = iacc; + ++targets; + } + *nTargets = numTargets; + // \a targets array is allocated by client. + return numTargets > 0 ? S_OK : S_FALSE; +} + + +/**************************************************************\ + * * + * IUnknown * + * * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface) +{ + *iface = 0; + + QByteArray strIID = IIDToString(id); + if (!strIID.isEmpty()) { + QString ss; QDebug dbg(&ss); dbg << accessible; + accessibleDebug("QWindowsIA2Accessible::QI() - IID:%s, iface:%s ", strIID.constData(), qPrintable(ss)); + } + if (id == IID_IUnknown) { + *iface = (IUnknown*)(IDispatch*)this; + } else if (id == IID_IDispatch) { + *iface = (IDispatch*)this; + } else if (id == IID_IAccessible) { + *iface = (IAccessible*)this; + } else if (id == IID_IOleWindow) { + *iface = (IOleWindow*)this; + } else if (id == IID_IServiceProvider) { + *iface = (IServiceProvider*)this; + } else if (id == IID_IAccessible2) { + *iface = (IAccessible2*)this; + } else if (id == IID_IAccessibleAction) { + if (accessible->actionInterface()) + *iface = (IAccessibleAction*)this; + } else if (id == IID_IAccessibleComponent) { + *iface = (IAccessibleComponent*)this; + } else if (id == IID_IAccessibleEditableText) { + //if (accessible->editableTextInterface()) { + //*iface = (IAccessibleEditableText*)this; + //} + } else if (id == IID_IAccessibleHyperlink) { + //*iface = (IAccessibleHyperlink*)this; + } else if (id == IID_IAccessibleHypertext) { + //*iface = (IAccessibleHypertext*)this; + } else if (id == IID_IAccessibleImage) { + //*iface = (IAccessibleImage*)this; + } else if (id == IID_IAccessibleRelation) { + *iface = (IAccessibleRelation*)this; + } else if (id == IID_IAccessibleTable) { + //*iface = (IAccessibleTable*)this; // not supported + } else if (id == IID_IAccessibleTable2) { + if (accessible->tableInterface()) + *iface = (IAccessibleTable2*)this; + } else if (id == IID_IAccessibleTableCell) { + if (accessible->tableCellInterface()) + *iface = (IAccessibleTableCell*)this; + } else if (id == IID_IAccessibleText) { + if (accessible->textInterface()) + *iface = (IAccessibleText*)this; + } else if (id == IID_IAccessibleValue) { + if (accessible->valueInterface()) + *iface = (IAccessibleValue*)this; + } + if (*iface) { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef() +{ + return ++ref; +} + +ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release() +{ + if (!--ref) { + delete this; + return 0; + } + return ref; +} + + + +/**************************************************************\ + * * + * IAccessible2 * + * * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations) +{ + accessibleDebugClientCalls(accessible); + if (!nRelations) + return E_INVALIDARG; + if (!accessible->isValid()) + return E_FAIL; + + return getRelationsHelper(0, 0, 0, nRelations); +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation) +{ + accessibleDebugClientCalls(accessible); + if (!relation) + return E_INVALIDARG; + if (!accessible->isValid()) + return E_FAIL; + + return getRelationsHelper(relation, relationIndex, 1); +} + +/*! + \internal + Client allocates and deallocates array + (see "Special Consideration when using Arrays", in Accessible2.idl) + */ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations, + IAccessibleRelation **relations, + long *nRelations) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + return getRelationsHelper(relations, 0, maxRelations, nRelations); +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role) +{ + accessibleDebugClientCalls(accessible); + //### Change QAccessibleInterface::role() to return both MSAA and IA2 roles. + // When that is completed, we must patch the MSAA bridge not not return any + // IA2-specific roles from get_accRole(). + if (!accessible->isValid()) + return E_FAIL; + + *ia2role = accessible->role(); + return S_OK; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollTo(enum IA2ScrollType /*scrollType*/) +{ + //### Ignore for now + return E_NOTIMPL; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollToPoint(enum IA2CoordinateType /*coordinateType*/, long /*x*/, long /*y*/) +{ + //### Ignore for now + return E_NOTIMPL; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLevel, + long *similarItemsInGroup, + long *positionInGroup) +{ + // ### Ignore for now. Not sure what this is used for..... + *groupLevel = 0; // Not applicable + *similarItemsInGroup = 0; // Not applicable + *positionInGroup = 0; // Not applicable + return S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + if (!states) + return E_POINTER; + QAccessible::State st = accessible->state(); + AccessibleStates ia2states = 0; + if (st.active) + ia2states |= IA2_STATE_ACTIVE; + if (st.invalid) + ia2states |= IA2_STATE_DEFUNCT; + if (st.editable) + ia2states |= IA2_STATE_EDITABLE; + if (st.multiLine) + ia2states |= IA2_STATE_MULTI_LINE; + if (st.selectableText) + ia2states |= IA2_STATE_SELECTABLE_TEXT; + if (st.supportsAutoCompletion) + ia2states |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; + + *states = ia2states; + return S_OK; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedRole(BSTR *extendedRole) +{ + //### + *extendedRole = 0; + return E_NOTIMPL; // mozilla does this + //return S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedRole(BSTR *localizedExtendedRole) +{ + //### + *localizedExtendedRole = 0; + return E_NOTIMPL; // mozilla does this + //return S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nExtendedStates(long *nExtendedStates) +{ + // Who will ever intepret these values into something meaningful?? + *nExtendedStates = 0; + return E_NOTIMPL; // mozilla does this + //return S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedStates(long /*maxExtendedStates*/, + BSTR **extendedStates, + long *nExtendedStates) +{ + *extendedStates = 0; + *nExtendedStates = 0; + return E_NOTIMPL; // mozilla does this + //return S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(long /*maxLocalizedExtendedStates*/, + BSTR **localizedExtendedStates, + long *nLocalizedExtendedStates) +{ + *localizedExtendedStates = 0; + *nLocalizedExtendedStates = 0; + return E_NOTIMPL; // mozilla does this + //return S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + // ### FIXME SERIOUSLY, NOT A STABLE SOLUTION IF NODES ARE DELETED ETC + // Return 0 if no object and no parent. This is really an error case. + uint uid = uniqueID(); + accessibleDebug("uniqueID: %08x", uid); + + *outUniqueID = (long)uid; + return uid ? S_OK : S_FALSE; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + return GetWindow(windowHandle); +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + if (!indexInParent) + return E_INVALIDARG; + QAccessibleInterface *par = accessible->parent(); + if (!par) { + *indexInParent = -1; + return S_FALSE; + } + int indexOfChild = par->indexOfChild(accessible); + delete par; + Q_ASSERT(indexOfChild >= 0); + *indexInParent = indexOfChild; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + IA2Locale res; + QLocale l; + res.country = QStringToBSTR(QLocale::countryToString(l.country())); + res.language = QStringToBSTR(QLocale::languageToString(l.language())); + *locale = res; + return S_OK; +} + + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *attributes = 0;//QStringToBSTR(QString()); + return S_FALSE; +} + +/**************************************************************\ + * IAccessibleAction * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *nActions = 0; + + if (QAccessibleActionInterface *actionIface = actionInterface()) + *nActions = actionIface->actionNames().count(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + if (QAccessibleActionInterface *actionIface = actionInterface()) { + const QStringList actionNames = actionIface->actionNames(); + if (actionIndex < 0 || actionIndex >= actionNames.count()) + return E_INVALIDARG; + const QString actionName = actionNames.at(actionIndex); + actionIface->doAction(actionName); + return S_OK; + } + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *description = 0; + if (QAccessibleActionInterface *actionIface = actionInterface()) { + const QStringList actionNames = actionIface->actionNames(); + if (actionIndex < 0 || actionIndex >= actionNames.count()) + return E_INVALIDARG; + const QString actionName = actionNames.at(actionIndex); + *description = QStringToBSTR(actionIface->localizedActionDescription(actionName)); + } + return *description ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + Q_UNUSED(nMaxBindings); + BSTR *arrayOfBindingsToReturn = 0; + int numBindings = 0; + if (QAccessibleActionInterface *actionIface = actionInterface()) { + const QStringList actionNames = actionIface->actionNames(); + if (actionIndex < 0 || actionIndex >= actionNames.count()) + return E_INVALIDARG; + const QString actionName = actionNames.at(actionIndex); + const QStringList keyBindings = actionIface->keyBindingsForAction(actionName); + numBindings = keyBindings.count(); + if (numBindings > 0) { + // The IDL documents that the client must free with CoTaskMemFree + arrayOfBindingsToReturn = (BSTR*)::CoTaskMemAlloc(sizeof(BSTR) * numBindings); + for (int i = 0; i < numBindings; ++i) + arrayOfBindingsToReturn[i] = QStringToBSTR(keyBindings.at(i)); + } + } + *keyBindings = arrayOfBindingsToReturn; + *nBindings = numBindings; + + return numBindings ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *name = 0; + if (QAccessibleActionInterface *actionIface = actionInterface()) { + const QStringList actionNames = actionIface->actionNames(); + if (actionIndex < 0 || actionIndex >= actionNames.count()) + return E_INVALIDARG; + const QString actionName = actionNames.at(actionIndex); + *name = QStringToBSTR(actionName); + } + return *name ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *localizedName = 0; + if (QAccessibleActionInterface *actionIface = actionInterface()) { + const QStringList actionNames = actionIface->actionNames(); + if (actionIndex < 0 || actionIndex >= actionNames.count()) + return E_INVALIDARG; + + const QString actionName = actionNames.at(actionIndex); + *localizedName = QStringToBSTR(actionIface->localizedActionName(actionName)); + } + return *localizedName ? S_OK : S_FALSE; +} + +/**************************************************************\ + * IAccessibleComponent * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QPoint topLeft = accessible->rect().topLeft(); + + if (QAccessibleInterface *parentIface = accessible->parent()) + topLeft -= parentIface->rect().topLeft(); + + *x = topLeft.x(); + *y = topLeft.y(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + // IA2Color is a typedef for long + *foreground = (IA2Color)accessible->foregroundColor().rgb(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + // IA2Color is a typedef for long + *background = (IA2Color)accessible->backgroundColor().rgb(); + return S_OK; +} + +/**************************************************************\ + * IAccessibleTable2 * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *cell = 0; + if (QAccessibleTableInterface *tableIface = tableInterface()) { + if (QAccessibleInterface *qtCell = tableIface->cellAt(row, column)) { + *cell = QWindowsAccessibility::wrap(qtCell); + } + } + accessibleDebug("found cell? %p", *cell); + return *cell ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *captionInterface = 0; + if (QAccessibleTableInterface *tableIface = tableInterface()) { + if (QAccessibleInterface *iface = tableIface->caption()) + *captionInterface = QWindowsAccessibility::wrap(iface); + } + return *captionInterface ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *description = 0; + if (QAccessibleTableInterface *tableIface = tableInterface()) { + const QString qtDesc = tableIface->columnDescription(column); + if (!qtDesc.isEmpty()) + *description = QStringToBSTR(qtDesc); + } + return *description ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *columnCount = tableIface->columnCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *rowCount = tableIface->rowCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *cellCount = tableIface->selectedCellCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *columnCount = tableIface->selectedColumnCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *rowCount = tableIface->selectedRowCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *description = 0; + if (QAccessibleTableInterface *tableIface = tableInterface()) { + const QString qtDesc = tableIface->columnDescription(row); + if (!qtDesc.isEmpty()) + *description = QStringToBSTR(qtDesc); + } + return *description ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells) +{ + accessibleDebugClientCalls(accessible); + Q_UNUSED(cells); + Q_UNUSED(nSelectedCells); + if (!accessible->isValid()) + return E_FAIL; + + QList<QAccessibleInterface*> selectedCells = tableInterface()->selectedCells(); + return wrapListOfCells(selectedCells, cells, nSelectedCells); +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + const QList<int> selectedIndices = tableIface->selectedColumns(); + const int &count = selectedIndices.count(); + long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0); + for (int i = 0; i < count; ++i) + selected[i] = selectedIndices.at(i); + *selectedColumns = selected; + *nColumns = count; + return count ? S_OK : S_FALSE; + } + return E_FAIL; + +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + const QList<int> selectedIndices = tableIface->selectedRows(); + const int &count = selectedIndices.count(); + long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0); + for (int i = 0; i < count; ++i) + selected[i] = selectedIndices.at(i); + *selectedRows = selected; + *nRows = count; + return count ? S_OK : S_FALSE; + } + return E_FAIL; + +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *summaryInterface = 0; + if (QAccessibleTableInterface *tableIface = tableInterface()) { + if (QAccessibleInterface *iface = tableIface->summary()) + *summaryInterface = QWindowsAccessibility::wrap(iface); + } + return *summaryInterface ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *isSelected = tableIface->isColumnSelected(column); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + *isSelected = tableIface->isRowSelected(row); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + bool ok = tableIface->selectRow(row); + return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + bool ok = tableIface->selectColumn(column); + return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + bool ok = tableIface->unselectRow(row); + return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleTableInterface *tableIface = tableInterface()) { + bool ok = tableIface->unselectColumn(column); + return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails??? + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + return E_NOTIMPL; +} + +/**************************************************************\ + * IAccessibleTableCell * +\**************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *nColumnsSpanned = tableCellInterface()->columnExtent(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles, + long *nColumnHeaderCells) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + const QList<QAccessibleInterface*> headerCells = tableCellInterface()->columnHeaderCells(); + return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells); +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *columnIndex = tableCellInterface()->columnIndex(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *nRowsSpanned = tableCellInterface()->rowExtent(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles, + long *nRowHeaderCells) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + const QList<QAccessibleInterface*> headerCells = tableCellInterface()->rowHeaderCells(); + return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells); +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *rowIndex = tableCellInterface()->rowIndex(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + *isSelected = tableCellInterface()->isSelected(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *column, + long *rowExtents, long *columnExtents, + boolean *isSelected) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + tableCellInterface()->rowColumnExtents((int*)row, (int*)column, (int*)rowExtents, (int*)columnExtents, (bool*)isSelected); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QAccessibleInterface *tableIface = tableCellInterface()->table(); + + *table = QWindowsAccessibility::wrap(tableIface); + return S_OK; +} + +/**************************************************************\ + * IAccessibleText * +\**************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset, + long endOffset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + text->addSelection(startOffset, endOffset); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset, + long *startOffset, + long *endOffset, + BSTR *textAttributes) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset); + *textAttributes = QStringToBSTR(attrs); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + *offset = text->cursorPosition(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset, + enum IA2CoordinateType coordType, + long *x, + long *y, + long *width, + long *height) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + const QRect rect = text->characterRect(offset, (QAccessible2::CoordinateType)coordType); + *x = rect.x(); + *y = rect.y(); + *width = rect.width(); + *height = rect.height(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + *nSelections = text->selectionCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x, + long y, + enum IA2CoordinateType coordType, + long *offset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + *offset = text->offsetAtPoint(QPoint(x,y), (QAccessible2::CoordinateType)coordType); + return (*offset >=0 ? S_OK : S_FALSE); + } + return E_FAIL; + +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex, + long *startOffset, + long *endOffset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *text = textInterface()) { + text->selection(selectionIndex, (int*)startOffset, (int*)endOffset); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset, + long endOffset, + BSTR *text) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textif = textInterface()) { + const QString t = textif->text(startOffset, endOffset); + if (!t.isEmpty()) { + *text = QStringToBSTR(t); + return S_OK; + } + return E_INVALIDARG; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset, + enum IA2TextBoundaryType boundaryType, + long *startOffset, + long *endOffset, + BSTR *text) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + const QString txt = textIface->textBeforeOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + if (!txt.isEmpty()) { + *text = QStringToBSTR(txt); + return S_OK; + } + return S_FALSE; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset( + long offset, + enum IA2TextBoundaryType boundaryType, + long *startOffset, + long *endOffset, + BSTR *text) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + const QString txt = textIface->textAfterOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + if (!txt.isEmpty()) { + *text = QStringToBSTR(txt); + return S_OK; + } + return S_FALSE; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset, + enum IA2TextBoundaryType boundaryType, + long *startOffset, + long *endOffset, + BSTR *text) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + const QString txt = textIface->textAtOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + if (!txt.isEmpty()) { + *text = QStringToBSTR(txt); + return S_OK; + } + return S_FALSE; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + textIface->removeSelection(selectionIndex); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + textIface->setCursorPosition(offset); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex, + long startOffset, + long endOffset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + textIface->setSelection(selectionIndex, startOffset, endOffset); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + *nCharacters = textIface->characterCount(); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex, + long endIndex, + enum IA2ScrollType scrollType) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleTextInterface *textIface = textInterface()) { + Q_UNUSED(scrollType); //### + textIface->scrollToSubstring(startIndex, endIndex); + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex, + long endIndex, + enum IA2CoordinateType coordinateType, + long x, + long y) +{ + Q_UNUSED(startIndex); + Q_UNUSED(endIndex); + Q_UNUSED(coordinateType); + Q_UNUSED(x); + Q_UNUSED(y); + + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText) +{ + Q_UNUSED(newText); + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText) +{ + Q_UNUSED(oldText); + return E_NOTIMPL; +} + +/**************************************************************\ + * IAccessibleValue * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + if (QAccessibleValueInterface *valueIface = valueInterface()) { + const QVariant var = valueIface->currentValue(); + if (QVariantToVARIANT(var, *currentValue, QByteArray(), false)) + return S_OK; + + } + currentValue->vt = VT_EMPTY; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + HRESULT hr = S_FALSE; + if (QAccessibleValueInterface *valueIface = valueInterface()) { + hr = VariantChangeType(&value, &value, 0, VT_R8); + if (SUCCEEDED(hr)) { + // ### works only for numbers (not date, strings, etc) + valueIface->setCurrentValue(QVariant(value.dblVal)); + } + } + return hr; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + if (QAccessibleValueInterface *valueIface = valueInterface()) { + const QVariant var = valueIface->maximumValue(); + if (QVariantToVARIANT(var, *maximumValue, QByteArray(), false)) + return S_OK; + } + maximumValue->vt = VT_EMPTY; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + if (QAccessibleValueInterface *valueIface = valueInterface()) { + const QVariant var = valueIface->minimumValue(); + if (QVariantToVARIANT(var, *minimumValue, QByteArray(), false)) + return S_OK; + } + minimumValue->vt = VT_EMPTY; + return S_FALSE; +} + + +/**************************************************************\ + * IServiceProvider * + **************************************************************/ +/*! + \internal + Reimplemented from IServiceProvider +*/ +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface) +{ + if (!iface) + return E_POINTER; + Q_UNUSED(guidService); + *iface = 0; + accessibleDebug("QWindowsIA2Accessible::QS(): %s", IIDToString(riid).constData()); + if (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch) { + *iface = static_cast<IAccessible*>(this); + } else if (/*guidService == IID_IAccessible && */riid == IID_IAccessible2) { + *iface = static_cast<IAccessible2*>(this); + } else if (riid == IID_IAccessibleApplication) { + *iface = new AccessibleApplication; + return S_OK; + } else { + QueryInterface(riid, iface); + } + if (*iface) { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + + +/*! + \internal + private function.. + \a maxRelations max number of relations to return in \a relations + \a relations the array of relations matching + \a startIndex Index to start to return from, + it will return only that specific relation in \a relations + + If \a relations is null, \a startIndex and \a maxRelations are ignored, causing + it to return the number of relations in \a nRelations +*/ +HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/) +{ + if (nRelations) + *nRelations = 0; + typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry; + QVector<RelationEntry> rels = accessible->relations(); + QMap<QAccessible::Relation, QAccessibleInterface *> relationMap; + for (QVector<RelationEntry>::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it) + { + RelationEntry e = *it; + relationMap.insertMulti(e.second, e.first); + } + + QList<QAccessible::Relation> keys = relationMap.keys(); + const int numRelations = keys.count(); + if (relations) { + for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) { + QAccessible::Relation relation = keys.at(i); + QList<QAccessibleInterface*> targets = relationMap.values(relation); + AccessibleRelation *rel = new AccessibleRelation(targets, relation); + *relations = rel; + ++relations; + } + } + if (nRelations) + *nRelations = numRelations; + + return numRelations > 0 ? S_OK : S_FALSE; +} + + + + +/*! + \internal + helper to wrap a QList<QAccessibleInterface*> inside an array of IAccessible* + The IAccessible* array is returned as a IUnknown* +*/ +HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount) +{ + const int count = inputCells.count(); + // Server allocates array + IUnknown **outputCells = count ? (IUnknown**)::CoTaskMemAlloc(sizeof(IUnknown*) * count ) : (IUnknown**)0; + for (int i = 0; i < count; ++i) + outputCells[i] = QWindowsAccessibility::wrap(inputCells.at(i)); + + *outputAccessibles = outputCells; + *nCellCount = count; + return count > 0 ? S_OK : S_FALSE; +} + +uint QWindowsIA2Accessible::uniqueID() const +{ + uint uid = 0; + if (QObject *obj = accessible->object()) + uid = qHash(obj); + + if (!uid) { + QAccessibleInterface *acc = accessible; + QVector<int> indexOfNodes; + while (acc && !acc->object()) { + QAccessibleInterface *par = acc->parent(); + indexOfNodes.append(par->indexOfChild(acc)); + if (acc != accessible) + delete acc; + acc = par; + } + if (acc) { + if (acc->object()) { + uid = qHash(acc->object()); + for (int i = 0; i < indexOfNodes.count(); ++i) + uid = qHash(uid + indexOfNodes.at(i)); + + } + if (acc != accessible) + delete acc; + } + } + return uid; +} + + +#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid) + +QByteArray QWindowsIA2Accessible::IIDToString(REFIID id) +{ + IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText); + IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue); + + // else... + QByteArray strGuid; +#if 0 // Can be useful for debugging, but normally we'd like to reduce the noise a bit... + OLECHAR szGuid[39]={0}; + ::StringFromGUID2(id, szGuid, 39); + strGuid.reserve(40); + ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL); + strGuid[38] = '\0'; +#endif + return strGuid; +} + + +QT_END_NAMESPACE + +#endif //QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h new file mode 100644 index 0000000000..a59263fba1 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -0,0 +1,379 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 IACCESSIBLE2_H +#define IACCESSIBLE2_H + +#include <QtCore/QtConfig> +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsmsaaaccessible.h" +#include "comutils.h" + +#include "Accessible2.h" +#include "AccessibleAction.h" +#include "AccessibleApplication.h" +#include "AccessibleComponent.h" +#include "AccessibleEditableText.h" +#include "AccessibleHyperlink.h" +#include "AccessibleHypertext.h" +#include "AccessibleImage.h" +#include "AccessibleRelation.h" +#include "AccessibleTable.h" +#include "AccessibleTable2.h" +#include "AccessibleTableCell.h" +#include "AccessibleText.h" +#include "AccessibleValue.h" + +#include "AccessibleEventID.h" +#include "AccessibleRole.h" +#include "AccessibleStates.h" + +#ifdef Q_CC_MINGW +# include <servprov.h> +#endif + +QT_BEGIN_NAMESPACE + +class QWindowsIA2Accessible : public QWindowsMsaaAccessible, + public IAccessibleAction, + public IAccessibleComponent, + /*public IAccessibleEditableText,*/ + public IAccessibleTable2, + public IAccessibleTableCell, + public IAccessibleText, + public IAccessibleValue, + public IServiceProvider +{ +public: + QWindowsIA2Accessible(QAccessibleInterface *a) : QWindowsMsaaAccessible(a) {} + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + /* IAccessible2 */ + HRESULT STDMETHODCALLTYPE get_nRelations(long *nRelations); + HRESULT STDMETHODCALLTYPE get_relation(long relationIndex, IAccessibleRelation **relation); + HRESULT STDMETHODCALLTYPE get_relations(long maxRelations, IAccessibleRelation **relations, long *nRelations); + HRESULT STDMETHODCALLTYPE role(long *role); + HRESULT STDMETHODCALLTYPE scrollTo(enum IA2ScrollType scrollType); + HRESULT STDMETHODCALLTYPE scrollToPoint(enum IA2CoordinateType coordinateType, long x, long y); + HRESULT STDMETHODCALLTYPE get_groupPosition(long *groupLevel, long *similarItemsInGroup, long *positionInGroup); + HRESULT STDMETHODCALLTYPE get_states(AccessibleStates *states); + HRESULT STDMETHODCALLTYPE get_extendedRole(BSTR *extendedRole); + HRESULT STDMETHODCALLTYPE get_localizedExtendedRole(BSTR *localizedExtendedRole); + HRESULT STDMETHODCALLTYPE get_nExtendedStates(long *nExtendedStates); + HRESULT STDMETHODCALLTYPE get_extendedStates(long maxExtendedStates, BSTR **extendedStates, long *nExtendedStates); + HRESULT STDMETHODCALLTYPE get_localizedExtendedStates(long maxLocalizedExtendedStates, BSTR **localizedExtendedStates, long *nLocalizedExtendedStates); + HRESULT STDMETHODCALLTYPE get_uniqueID(long *uniqueID); + HRESULT STDMETHODCALLTYPE get_windowHandle(HWND *windowHandle); + HRESULT STDMETHODCALLTYPE get_indexInParent(long *indexInParent); + HRESULT STDMETHODCALLTYPE get_locale(IA2Locale *locale); + HRESULT STDMETHODCALLTYPE get_attributes(BSTR *attributes); + + /* IAccessibleAction */ + HRESULT STDMETHODCALLTYPE nActions(long *nActions); + HRESULT STDMETHODCALLTYPE doAction(long actionIndex); + HRESULT STDMETHODCALLTYPE get_description(long actionIndex, BSTR *description); + HRESULT STDMETHODCALLTYPE get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings); + HRESULT STDMETHODCALLTYPE get_name(long actionIndex, BSTR *name); + HRESULT STDMETHODCALLTYPE get_localizedName(long actionIndex, BSTR *localizedName); + + /* IAccessibleComponent */ + HRESULT STDMETHODCALLTYPE get_locationInParent(long *x,long *y); + HRESULT STDMETHODCALLTYPE get_foreground(IA2Color *foreground); + HRESULT STDMETHODCALLTYPE get_background(IA2Color *background); + + /* IAccessibleEditableText */ + /* + HRESULT STDMETHODCALLTYPE copyText(long startOffset, long endOffset); + HRESULT STDMETHODCALLTYPE deleteText(long startOffset, long endOffset); + HRESULT STDMETHODCALLTYPE insertText(long offset, BSTR *text); + HRESULT STDMETHODCALLTYPE cutText(long startOffset, long endOffset); + HRESULT STDMETHODCALLTYPE pasteText(long offset); + HRESULT STDMETHODCALLTYPE replaceText(long startOffset, long endOffset, BSTR *text); + HRESULT STDMETHODCALLTYPE setAttributes(long startOffset, long endOffset, BSTR *attributes); + */ + + /* IAccessibleTable2 */ + HRESULT STDMETHODCALLTYPE get_cellAt( long row, long column, IUnknown **cell); + HRESULT STDMETHODCALLTYPE get_caption( IUnknown **accessible); + HRESULT STDMETHODCALLTYPE get_columnDescription( long column, BSTR *description); + HRESULT STDMETHODCALLTYPE get_nColumns( long *columnCount); + HRESULT STDMETHODCALLTYPE get_nRows( long *rowCount); + HRESULT STDMETHODCALLTYPE get_nSelectedCells( long *cellCount); + HRESULT STDMETHODCALLTYPE get_nSelectedColumns( long *columnCount); + HRESULT STDMETHODCALLTYPE get_nSelectedRows( long *rowCount); + HRESULT STDMETHODCALLTYPE get_rowDescription( long row, BSTR *description); + HRESULT STDMETHODCALLTYPE get_selectedCells( IUnknown ***cells, long *nSelectedCells); + HRESULT STDMETHODCALLTYPE get_selectedColumns( long **selectedColumns, long *nColumns); + HRESULT STDMETHODCALLTYPE get_selectedRows( long **selectedRows, long *nRows); + HRESULT STDMETHODCALLTYPE get_summary( IUnknown **accessible); + HRESULT STDMETHODCALLTYPE get_isColumnSelected( long column, boolean *isSelected); + HRESULT STDMETHODCALLTYPE get_isRowSelected( long row, boolean *isSelected); + HRESULT STDMETHODCALLTYPE selectRow( long row); + HRESULT STDMETHODCALLTYPE selectColumn( long column); + HRESULT STDMETHODCALLTYPE unselectRow( long row); + HRESULT STDMETHODCALLTYPE unselectColumn( long column); + HRESULT STDMETHODCALLTYPE get_modelChange( IA2TableModelChange *modelChange); + + /* IAccessibleTableCell */ + HRESULT STDMETHODCALLTYPE get_columnExtent(long *nColumnsSpanned); + HRESULT STDMETHODCALLTYPE get_columnHeaderCells(IUnknown ***cellAccessibles, long *nColumnHeaderCells); + HRESULT STDMETHODCALLTYPE get_columnIndex(long *columnIndex); + HRESULT STDMETHODCALLTYPE get_rowExtent(long *nRowsSpanned); + HRESULT STDMETHODCALLTYPE get_rowHeaderCells(IUnknown ***cellAccessibles, long *nRowHeaderCells); + HRESULT STDMETHODCALLTYPE get_rowIndex(long *rowIndex); + HRESULT STDMETHODCALLTYPE get_isSelected( boolean *isSelected); + HRESULT STDMETHODCALLTYPE get_rowColumnExtents(long *row, long *column, + long *rowExtents, long *columnExtents, + boolean *isSelected); + HRESULT STDMETHODCALLTYPE get_table(IUnknown **table); + + + /* IAccessibleText */ + HRESULT STDMETHODCALLTYPE addSelection(long startOffset, long endOffset); + HRESULT STDMETHODCALLTYPE get_attributes(long offset, long *startOffset, + long *endOffset, BSTR *textAttributes); + HRESULT STDMETHODCALLTYPE get_caretOffset(long *offset); + HRESULT STDMETHODCALLTYPE get_characterExtents(long offset, enum IA2CoordinateType coordType, + long *x, long *y, + long *width, long *height); + HRESULT STDMETHODCALLTYPE get_nSelections(long *nSelections); + HRESULT STDMETHODCALLTYPE get_offsetAtPoint(long x, long y, enum IA2CoordinateType coordType, long *offset); + HRESULT STDMETHODCALLTYPE get_selection(long selectionIndex, long *startOffset, long *endOffset); + HRESULT STDMETHODCALLTYPE get_text(long startOffset, long endOffset, BSTR *text); + HRESULT STDMETHODCALLTYPE get_textBeforeOffset(long offset, enum IA2TextBoundaryType boundaryType, + long *startOffset, long *endOffset, BSTR *text); + HRESULT STDMETHODCALLTYPE get_textAfterOffset(long offset, enum IA2TextBoundaryType boundaryType, + long *startOffset, long *endOffset, BSTR *text); + HRESULT STDMETHODCALLTYPE get_textAtOffset(long offset, enum IA2TextBoundaryType boundaryType, + long *startOffset, long *endOffset, BSTR *text); + HRESULT STDMETHODCALLTYPE removeSelection(long selectionIndex); + HRESULT STDMETHODCALLTYPE setCaretOffset(long offset); + HRESULT STDMETHODCALLTYPE setSelection(long selectionIndex, long startOffset, long endOffset); + HRESULT STDMETHODCALLTYPE get_nCharacters(long *nCharacters); + HRESULT STDMETHODCALLTYPE scrollSubstringTo(long startIndex, long endIndex, enum IA2ScrollType scrollType); + HRESULT STDMETHODCALLTYPE scrollSubstringToPoint(long startIndex, long endIndex, + enum IA2CoordinateType coordinateType, long x, long y); + HRESULT STDMETHODCALLTYPE get_newText(IA2TextSegment *newText); + HRESULT STDMETHODCALLTYPE get_oldText(IA2TextSegment *oldText); + + /* IAccessibleValue */ + HRESULT STDMETHODCALLTYPE get_currentValue(VARIANT *currentValue); + HRESULT STDMETHODCALLTYPE setCurrentValue(VARIANT value); + HRESULT STDMETHODCALLTYPE get_maximumValue(VARIANT *maximumValue); + HRESULT STDMETHODCALLTYPE get_minimumValue(VARIANT *minimumValue); + + /* IServiceProvider */ + HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppv); + + /* private helper functions */ +private: + inline QAccessibleTextInterface *textInterface() const { + return accessible->isValid() ? accessible->textInterface() : static_cast<QAccessibleTextInterface *>(0); + } + + inline QAccessibleActionInterface *actionInterface() const { + return accessible->actionInterface(); + } + + inline QAccessibleValueInterface *valueInterface() const { + return accessible->valueInterface(); + } + + inline QAccessibleTableInterface *tableInterface() const { + return accessible->tableInterface(); + } + + inline QAccessibleTableCellInterface *tableCellInterface() const { + return accessible->tableCellInterface(); + } + + HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0); + HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount); + uint uniqueID() const; + QByteArray IIDToString(REFIID id); + +private: + ULONG ref; + +}; + +/**************************************************************\ + * AccessibleApplication * + **************************************************************/ +class AccessibleApplication : public IAccessibleApplication +{ +public: + AccessibleApplication() : m_ref(1) + { + + } + + virtual ~AccessibleApplication() {} + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + /* IAccessibleApplication */ + HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name); + HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version); + HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name); + HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version); +private: + ULONG m_ref; +}; + + + +/**************************************************************\ + * IAccessibleRelation * + **************************************************************/ +struct AccessibleRelation : public IAccessibleRelation +{ + AccessibleRelation(const QList<QAccessibleInterface *> &targets, + QAccessible::Relation relation) + : m_targets(targets), m_relation(relation), m_ref(1) + { + Q_ASSERT(m_targets.count()); + } + + + /* IUnknown */ + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) + { + *iface = 0; + if (id == IID_IUnknown) + *iface = (IUnknown*)this; + + if (*iface) { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef() + { + return ++m_ref; + } + + ULONG STDMETHODCALLTYPE Release() + { + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; + } + + /* IAccessibleRelation */ + HRESULT STDMETHODCALLTYPE get_relationType( + /* [retval][out] */ BSTR *relationType) + { + *relationType = relationToBSTR(m_relation); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE get_localizedRelationType( + /* [retval][out] */ BSTR *localizedRelationType) + { + // Who ever needs this??? + *localizedRelationType = relationToBSTR(m_relation); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE get_nTargets( + /* [retval][out] */ long *nTargets) + { + // ### always one target + *nTargets = m_targets.count(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE get_target(long targetIndex, IUnknown **target); + + + /*! + \internal + Client allocates and deallocates \a targets array + (see "Special Consideration when using Arrays", in Accessible2.idl) + */ + HRESULT STDMETHODCALLTYPE get_targets( + /* [in] */ long maxTargets, // Hmmm, ignore ??? + /* [length_is][size_is][out] */ IUnknown **targets, + /* [retval][out] */ long *nTargets); + +private: + static BSTR relationToBSTR(QAccessible::Relation relation) + { + wchar_t *constRelationString = 0; + switch (relation) { + case QAccessible::Controlled: + constRelationString = IA2_RELATION_CONTROLLED_BY; + break; + } + + if (constRelationString) { + BSTR bstrVal; + const UINT wlen = (UINT)wcslen(constRelationString); + bstrVal = ::SysAllocStringLen(constRelationString, wlen); + return bstrVal; + } + return 0; + } + + + QList<QAccessibleInterface *> m_targets; + QAccessible::Relation m_relation; + ULONG m_ref; +}; + +QT_END_NAMESPACE + +#endif //QT_NO_ACCESSIBILITY + +#endif // IACCESSIBLE2_H diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp new file mode 100644 index 0000000000..4f92b910b2 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 <QtCore/QtConfig> +#ifndef QT_NO_ACCESSIBILITY + + +#include <private/qsystemlibrary_p.h> + +#include <QtCore/qlocale.h> +#include <QtCore/qmap.h> +#include <QtCore/qpair.h> +#include <QtCore/qsettings.h> +#include <QtGui/qaccessible.h> +#include <QtGui/qaccessible2.h> +#include <QtGui/qplatformnativeinterface_qpa.h> +#include <QtGui/qwindow.h> +#include <QtGui/qguiapplication.h> + +#include "qwindowsaccessibility.h" + +#ifndef Q_CC_MINGW +# include "iaccessible2.h" +#endif // !Q_CC_MINGW + +#include "comutils.h" + +#include <oleacc.h> + +//#include <uiautomationcoreapi.h> +#ifndef UiaRootObjectId +#define UiaRootObjectId -25 +#endif + +#include <winuser.h> +#if !defined(WINABLEAPI) +# if defined(Q_OS_WINCE) +# include <bldver.h> +# endif +# include <winable.h> +#endif + +#include <oleacc.h> +#include <servprov.h> +#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) +#include <comdef.h> +#endif + +#ifdef Q_OS_WINCE +#include "../qguifunctions_wince.h" +#endif + +#include "../qtwindows_additional.h" + + +// This stuff is used for widgets/items with no window handle: +typedef QMap<int, QPair<QObject*,int> > NotifyMap; +Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents) + + +QT_BEGIN_NAMESPACE + + +/*! + \!internal + \class QWindowsAccessibility + + Implements QPlatformAccessibility + +*/ +QWindowsAccessibility::QWindowsAccessibility() +{ +} + +void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &event) +{ + QString soundName; + switch (event.type()) { + case QAccessible::PopupMenuStart: + soundName = QLatin1String("MenuPopup"); + break; + + case QAccessible::MenuCommand: + soundName = QLatin1String("MenuCommand"); + break; + + case QAccessible::Alert: + { + /* ### FIXME +#ifndef QT_NO_MESSAGEBOX + QMessageBox *mb = qobject_cast<QMessageBox*>(o); + if (mb) { + switch (mb->icon()) { + case QMessageBox::Warning: + soundName = QLatin1String("SystemExclamation"); + break; + case QMessageBox::Critical: + soundName = QLatin1String("SystemHand"); + break; + case QMessageBox::Information: + soundName = QLatin1String("SystemAsterisk"); + break; + default: + break; + } + } else +#endif // QT_NO_MESSAGEBOX +*/ + { + soundName = QLatin1String("SystemAsterisk"); + } + + } + break; + default: + break; + } + + if (!soundName.isEmpty()) { +#ifndef QT_NO_SETTINGS + QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + soundName, + QSettings::NativeFormat); + QString file = settings.value(QLatin1String(".Current/.")).toString(); +#else + QString file; +#endif + if (!file.isEmpty()) { + PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT); + } + } + + typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG); + +#if defined(Q_OS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0 + // There is no user32.lib nor NotifyWinEvent for CE + return; +#else + static PtrNotifyWinEvent ptrNotifyWinEvent = 0; + static bool resolvedNWE = false; + if (!resolvedNWE) { + resolvedNWE = true; + ptrNotifyWinEvent = (PtrNotifyWinEvent)QSystemLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent"); + } + if (!ptrNotifyWinEvent) + return; + + // An event has to be associated with a window, + // so find the first parent that is a widget and that has a WId + QAccessibleInterface *iface = event.accessibleInterface(); + QWindow *window = iface ? QWindowsAccessibility::windowHelper(iface) : 0; + delete iface; + + if (!window) { + window = QGuiApplication::activeWindow(); + if (!window) + return; + } + + QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); + HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window); + + static int eventNum = 0; + if (event.type() != QAccessible::MenuCommand) { // MenuCommand is faked + // See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE" + eventNum %= 50; //[0..49] + int eventId = - (eventNum - 1); + + qAccessibleRecentSentEvents()->insert(eventId, qMakePair(event.object(), event.child())); + ptrNotifyWinEvent(event.type(), hWnd, OBJID_CLIENT, eventId ); + + ++eventNum; + } +#endif // Q_OS_WINCE +} + +QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) +{ + QWindow *window = iface->window(); + if (!window) { + QAccessibleInterface *acc = iface->parent(); + while (acc && !window) { + window = acc->window(); + QAccessibleInterface *par = acc->parent(); + delete acc; + acc = par; + } + } + return window; +} + +/*! + \internal + helper to wrap a QAccessibleInterface inside a IAccessible* +*/ +IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) +{ +#ifdef Q_CC_MINGW + return 0; +#else + if (!acc) + return 0; + QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); + IAccessible *iacc = 0; + wacc->QueryInterface(IID_IAccessible, (void**)&iacc); + return iacc; +#endif +} + +/*! + \internal +*/ +QPair<QObject*, int> QWindowsAccessibility::getCachedObject(int entryId) +{ + return qAccessibleRecentSentEvents()->value(entryId); +} + +/* +void QWindowsAccessibility::setRootObject(QObject *o) +{ + +} + +void QWindowsAccessibility::initialize() +{ + +} + +void QWindowsAccessibility::cleanup() +{ + +} + +*/ + +bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) +{ + if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) { + /* For UI Automation */ + } else if ((DWORD)lParam == OBJID_CLIENT) { +#if 1 + // Ignoring all requests while starting up + // ### Maybe QPA takes care of this??? + if (QCoreApplication::startingUp() || QCoreApplication::closingDown()) + return false; +#endif + + 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) { + QWindow *window = QWindowsContext::instance()->findWindow(hwnd); + if (window) { + QAccessibleInterface *acc = window->accessibleRoot(); + if (acc) { + if (IAccessible *iface = wrap(acc)) { + *lResult = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2 + if (*lResult) { + iface->Release(); // the client will release the object again, and then it will destroy itself + } + return true; + } else { + delete acc; + } + } + } + } + } + return false; +} + +QT_END_NAMESPACE + +#endif //QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h index 9294f23565..0c3aca0a03 100644 --- a/src/plugins/platforms/windows/qwindowsaccessibility.h +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h @@ -42,9 +42,12 @@ #ifndef QWINDOWSACCESSIBILITY_H #define QWINDOWSACCESSIBILITY_H -#include "qtwindowsglobal.h" +#include "../qtwindowsglobal.h" +#include "../qwindowscontext.h" #include <QtGui/QPlatformAccessibility> +#include <oleacc.h> + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -59,6 +62,10 @@ public: virtual void initialize(); virtual void cleanup(); */ + static IAccessible *wrap(QAccessibleInterface *acc); + static QWindow *windowHelper(const QAccessibleInterface *iface); + + static QPair<QObject*, int> getCachedObject(int entryId); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 134b1c81ce..8791bbdcfb 100644 --- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -42,104 +42,44 @@ #include <QtCore/QtConfig> #ifndef QT_NO_ACCESSIBILITY - +#include "qwindowsmsaaaccessible.h" #include "qwindowsaccessibility.h" -#include "qwindowscontext.h" - -#include <private/qsystemlibrary_p.h> +#include <oleacc.h> +#include <servprov.h> +#include <winuser.h> +#include "comutils.h" +#include <QtCore/qdebug.h> #include <QtCore/qmap.h> -#include <QtCore/qsettings.h> -#include <QtCore/qsharedpointer.h> #include <QtCore/qpair.h> -#include <QtWidgets/qapplication.h> -#include <QtWidgets/qmessagebox.h> -#include <QtWidgets/qgraphicsitem.h> -#include <QtWidgets/qgraphicsview.h> +#include <QtCore/qsettings.h> #include <QtGui/qaccessible.h> +#include <QtGui/qaccessible2.h> +#include <QtGui/qguiapplication.h> #include <QtGui/qplatformnativeinterface_qpa.h> #include <QtGui/qwindow.h> -#include <QtGui/qaccessible2.h> -#include <oleacc.h> +#include <QtWidgets/qapplication.h> +#include <QtWidgets/qgraphicsitem.h> +#include <QtWidgets/qgraphicsview.h> +#include <QtWidgets/qmessagebox.h> //#include <uiautomationcoreapi.h> #ifndef UiaRootObjectId #define UiaRootObjectId -25 #endif -#include <winuser.h> -#if !defined(WINABLEAPI) -# if defined(Q_OS_WINCE) -# include <bldver.h> -# endif -# include <winable.h> -#endif - -#include <oleacc.h> #if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) #include <comdef.h> #endif #ifdef Q_OS_WINCE -#include "qguifunctions_wince.h" +#include "../qguifunctions_wince.h" #endif -#include "qtwindows_additional.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_DEBUG -QT_BEGIN_INCLUDE_NAMESPACE -# include <qdebug.h> -QT_END_INCLUDE_NAMESPACE -static inline bool debug_accessibility() -{ - static signed int debugging = -1; - if (debugging == -1) - debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt(); - return !!debugging; -} -# define accessibleDebug !debug_accessibility() ? (void)0 : qDebug -#else -# define accessibleDebug() -#endif - -//#define DEBUG_SHOW_ATCLIENT_COMMANDS -#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS) -void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface) -{ - QString str; - QDebug dbg(&str); - dbg << iface << QLatin1String(funcName); - accessibleDebug("%s", qPrintable(str)); -} -# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface) -#else -# define accessibleDebugClientCalls(iface) -#endif - - -typedef QSharedPointer<QAccessibleInterface> QAIPointer; - -static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other) -{ - if (one == other) return true; - if (!one || !other) return false; - - if (one->object() && other->object() && (one->object() == other->object())) - return true; - QAIPointer onePar(one->parent()); - QAIPointer otherPar(other->parent()); +#include "../qtwindows_additional.h" - if (compareAccessible(onePar.data(), otherPar.data())) - return onePar->indexOfChild(one) == otherPar->indexOfChild(other); - return false; -} -// This stuff is used for widgets/items with no window handle: -typedef QMap<int, QPair<QObject*,int> > NotifyMap; -Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents) -static int eventNum = 0; +QT_BEGIN_NAMESPACE class QWindowsEnumerate : public IEnumVARIANT { @@ -249,140 +189,60 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) return S_OK; } -/* -*/ -class QWindowsAccessible : public IAccessible, IOleWindow -{ -public: - QWindowsAccessible(QAccessibleInterface *a) - : ref(0), accessible(a) - { - } - - virtual ~QWindowsAccessible() - { - delete accessible; - } - - /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - /* IDispatch */ - HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *); - HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **); - HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *); - HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *); - - /* IAccessible */ - HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID); - HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID); - HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd); - HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch** ppdispChild); - HRESULT STDMETHODCALLTYPE get_accChildCount(long* pcountChildren); - HRESULT STDMETHODCALLTYPE get_accParent(IDispatch** ppdispParent); - - HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID); - HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction); - HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR* pszDescription); - HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp); - HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic); - HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut); - HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR* pszName); - HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName); - HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole); - HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState); - HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR* pszValue); - HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue); - - HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID); - HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID); - HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren); - - /* IOleWindow */ - HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd); - HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); - -private: - ULONG ref; - QAccessibleInterface *accessible; - - QAIPointer childPointer(VARIANT varID) - { - return QAIPointer(accessible->child(varID.lVal - 1)); - } -}; - -static inline BSTR QStringToBSTR(const QString &str) +static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other) { - BSTR bstrVal; - - int wlen = str.length()+1; - bstrVal = SysAllocStringByteLen(0, wlen*2); - memcpy(bstrVal, str.unicode(), sizeof(QChar)*(wlen)); - bstrVal[wlen] = 0; - - return bstrVal; -} - -/* -*/ + if (one == other) return true; + if (!one || !other) return false; -/* - IUnknown -*/ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown) - *iface = (IUnknown*)(IDispatch*)this; - else if (id == IID_IDispatch) - *iface = (IDispatch*)this; - else if (id == IID_IAccessible) - *iface = (IAccessible*)this; - else if (id == IID_IOleWindow) - *iface = (IOleWindow*)this; - else - return E_NOINTERFACE; + if (one->object() && other->object() && (one->object() == other->object())) + return true; + QAIPointer onePar(one->parent()); + QAIPointer otherPar(other->parent()); - AddRef(); - return S_OK; + if (compareAccessible(onePar.data(), otherPar.data())) + return onePar->indexOfChild(one) == otherPar->indexOfChild(other); + return false; } -ULONG STDMETHODCALLTYPE QWindowsAccessible::AddRef() +#ifndef QT_NO_DEBUG +bool debug_accessibility() { - return ++ref; + static int debugging = -1; + if (debugging == -1) + debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt(); + return !!debugging; } +#endif -ULONG STDMETHODCALLTYPE QWindowsAccessible::Release() +#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS) +void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface) { - if (!--ref) { - delete this; - return 0; - } - return ref; + QString str; + QDebug dbg(&str); + dbg << iface << QLatin1String(funcName); + accessibleDebug("%s", qPrintable(str)); } +#endif /* IDispatch */ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfoCount(unsigned int * pctinfo) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfoCount(unsigned int * pctinfo) { // We don't use a type library *pctinfo = 0; return S_OK; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo) { // We don't use a type library *pptinfo = 0; return S_OK; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid) { #if !defined(Q_CC_BOR) && !defined(Q_CC_GNU) // PROPERTIES: Hierarchical @@ -440,7 +300,13 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetIDsOfNames(const _GUID &, wchar #endif } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::Invoke(long dispIdMember, const _GUID &, unsigned long, unsigned short wFlags, tagDISPPARAMS *pDispParams, tagVARIANT *pVarResult, tagEXCEPINFO *, unsigned int *) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::Invoke(long dispIdMember, + const _GUID &, + unsigned long, + unsigned short wFlags, + tagDISPPARAMS *pDispParams, + tagVARIANT *pVarResult, + tagEXCEPINFO *, unsigned int *) { HRESULT hr = DISP_E_MEMBERNOTFOUND; @@ -621,9 +487,8 @@ IAccessible::accHitTest documents the value returned in pvarID like this: | | | interface pointer | +--------------------------------------------------------+-------------+-------------------------+ */ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { - accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -637,9 +502,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, return S_OK; } } else { - QWindowsAccessible* wacc = new QWindowsAccessible(child); - IDispatch *iface = 0; - wacc->QueryInterface(IID_IDispatch, (void**)&iface); + IAccessible *iface = QWindowsAccessibility::wrap(child); if (iface) { (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; @@ -662,7 +525,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, can be ignored. All stuff prefixed with "moz" are information from that page. */ // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -686,7 +549,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *py } // moz: [important, but no need to implement up/down/left/right] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -809,16 +672,14 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v (*pvarEnd).vt = VT_EMPTY; return S_FALSE; } - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - IDispatch *iface = 0; - wacc->QueryInterface(IID_IDispatch, (void**)&iface); - if (iface) { + if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { (*pvarEnd).vt = VT_DISPATCH; (*pvarEnd).pdispVal = iface; return S_OK; } else { - delete wacc; + if (acc != accessible) + delete acc; } (*pvarEnd).vt = VT_EMPTY; @@ -826,13 +687,13 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; - if (varChildID.vt == VT_EMPTY) + if (varChildID.vt != VT_I4) return E_INVALIDARG; @@ -841,7 +702,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I if (childIndex < 0) { const int entry = childIndex; - QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entry); + QPair<QObject*, int> ref = QWindowsAccessibility::getCachedObject(entry); if (ref.first) { acc = QAccessible::queryAccessibleInterface(ref.first); if (acc && ref.second >= 0) { @@ -851,6 +712,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I return E_INVALIDARG; acc = res; } + } else { + qWarning("get_accChild got a negative varChildID, but did not find it in cache"); } } else { if (childIndex) { @@ -868,17 +731,15 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I } if (acc) { - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - wacc->QueryInterface(IID_IDispatch, (void**)ppdispChild); + *ppdispChild = QWindowsAccessibility::wrap(acc); return S_OK; } - *ppdispChild = 0; - return S_FALSE; + return E_FAIL; } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -889,7 +750,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChil } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdispParent) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -897,11 +758,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispPa QAccessibleInterface *acc = accessible->parent(); if (acc) { - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - wacc->QueryInterface(IID_IDispatch, (void**)ppdispParent); - - if (*ppdispParent) + if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { + *ppdispParent = iface; return S_OK; + } else { + delete acc; + } } *ppdispParent = 0; @@ -911,7 +773,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispPa /* Properties and methods */ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT varID) { Q_UNUSED(varID); accessibleDebugClientCalls(accessible); @@ -928,7 +790,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) { Q_UNUSED(varID); accessibleDebugClientCalls(accessible); @@ -944,7 +806,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID return *pszDefaultAction ? S_OK : S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -969,7 +831,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -993,12 +855,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *p return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT, long *) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelpTopic(BSTR *, VARIANT, long *) { return DISP_E_MEMBERNOTFOUND; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) { Q_UNUSED(varID); accessibleDebugClientCalls(accessible); @@ -1029,7 +891,7 @@ static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAcce } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BSTR* pszName) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -1065,14 +927,14 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* p return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR) { accessibleDebugClientCalls(accessible); return DISP_E_MEMBERNOTFOUND; } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -1100,7 +962,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VARIANT *pvarState) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -1176,11 +1038,15 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue) { accessibleDebugClientCalls(accessible); - if (!accessible->isValid() || varID.lVal) + if (varID.vt != VT_I4) + return E_INVALIDARG; + + if (!accessible->isValid() || varID.lVal) { return E_FAIL; + } QString value; if (accessible->valueInterface()) { @@ -1194,17 +1060,18 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* } *pszValue = 0; + accessibleDebug("return S_FALSE"); return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR) { accessibleDebugClientCalls(accessible); return DISP_E_MEMBERNOTFOUND; } // moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VARIANT varID) { Q_UNUSED(flagsSelect); Q_UNUSED(varID); @@ -1250,7 +1117,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN +-------------+------------------------------------------------------------------------------+ moz: [important] */ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -1263,12 +1130,11 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) delete acc; return S_OK; } else { - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - IDispatch *iface = 0; - wacc->QueryInterface(IID_IDispatch, (void**)&iface); - (*pvarID).vt = VT_DISPATCH; - (*pvarID).pdispVal = iface; - return S_OK; + if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { + (*pvarID).vt = VT_DISPATCH; + (*pvarID).pdispVal = iface; + return S_OK; + } } delete acc; } @@ -1276,7 +1142,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvarChildren) { accessibleDebugClientCalls(accessible); if (!accessible->isValid()) @@ -1314,212 +1180,34 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChil return S_OK; } -static QWindow *window_helper(const QAccessibleInterface *iface) -{ - QWindow *window = iface->window(); - if (!window) { - QAccessibleInterface *acc = iface->parent(); - while (acc && !window) { - window = acc->window(); - QAccessibleInterface *par = acc->parent(); - delete acc; - acc = par; - } - } - return window; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd) +/**************************************************************\ + * IOleWindow * + **************************************************************/ +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetWindow(HWND *phwnd) { *phwnd = 0; + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; if (!accessible->isValid()) return E_UNEXPECTED; - QWindow *window = window_helper(accessible); + QWindow *window = QWindowsAccessibility::windowHelper(accessible); if (!window) return E_FAIL; QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); Q_ASSERT(platform); *phwnd = (HWND)platform->nativeResourceForWindow("handle", window); + accessibleDebug("QWindowsAccessible::GetWindow(): %p", *phwnd); return S_OK; } -HRESULT STDMETHODCALLTYPE QWindowsAccessible::ContextSensitiveHelp(BOOL) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL) { return S_OK; } - -QWindowsAccessibility::QWindowsAccessibility() -{ -} - - -void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &event) -{ - QString soundName; - switch (event.type()) { - case QAccessible::PopupMenuStart: - soundName = QLatin1String("MenuPopup"); - break; - - case QAccessible::MenuCommand: - soundName = QLatin1String("MenuCommand"); - break; - - case QAccessible::Alert: - { - /* ### FIXME -#ifndef QT_NO_MESSAGEBOX - QMessageBox *mb = qobject_cast<QMessageBox*>(o); - if (mb) { - switch (mb->icon()) { - case QMessageBox::Warning: - soundName = QLatin1String("SystemExclamation"); - break; - case QMessageBox::Critical: - soundName = QLatin1String("SystemHand"); - break; - case QMessageBox::Information: - soundName = QLatin1String("SystemAsterisk"); - break; - default: - break; - } - } else -#endif // QT_NO_MESSAGEBOX -*/ - { - soundName = QLatin1String("SystemAsterisk"); - } - - } - break; - default: - break; - } - - if (!soundName.isEmpty()) { -#ifndef QT_NO_SETTINGS - QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + soundName, - QSettings::NativeFormat); - QString file = settings.value(QLatin1String(".Current/.")).toString(); -#else - QString file; -#endif - if (!file.isEmpty()) { - PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT); - } - } - - typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG); - -#if defined(Q_OS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0 - // There is no user32.lib nor NotifyWinEvent for CE - return; -#else - static PtrNotifyWinEvent ptrNotifyWinEvent = 0; - static bool resolvedNWE = false; - if (!resolvedNWE) { - resolvedNWE = true; - ptrNotifyWinEvent = (PtrNotifyWinEvent)QSystemLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent"); - } - if (!ptrNotifyWinEvent) - return; - - // An event has to be associated with a window, - // so find the first parent that is a widget and that has a WId - QAccessibleInterface *iface = event.accessibleInterface(); - QWindow *window = iface ? window_helper(iface) : 0; - delete iface; - - if (!window) { - window = QGuiApplication::activeWindow(); - if (!window) - return; - } - - QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); - HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window); - - if (event.type() != QAccessible::MenuCommand) { // MenuCommand is faked - // See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE" - eventNum %= 50; //[0..49] - int eventId = - eventNum - 1; - - qAccessibleRecentSentEvents()->insert(eventId, qMakePair(event.object(), event.child())); - ptrNotifyWinEvent(event.type(), hWnd, OBJID_CLIENT, eventId ); - - ++eventNum; - } -#endif // Q_OS_WINCE -} - -/* -void QWindowsAccessibility::setRootObject(QObject *o) -{ - -} - -void QWindowsAccessibility::initialize() -{ - -} - -void QWindowsAccessibility::cleanup() -{ - -} - -*/ - -bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) -{ - if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) { - /* For UI Automation - */ - } else if ((DWORD)lParam == OBJID_CLIENT) { -#if 1 - // Ignoring all requests while starting up - // ### Maybe QPA takes care of this??? - if (QApplication::startingUp() || QApplication::closingDown()) - return false; -#endif - - 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) { - QWindow *window = QWindowsContext::instance()->findWindow(hwnd); - if (window) { - QAccessibleInterface *acc = window->accessibleRoot(); - if (acc) { - QWindowsAccessible *winacc = new QWindowsAccessible(acc); - IAccessible *iface; - HRESULT hr = winacc->QueryInterface(IID_IAccessible, (void**)&iface); - if (SUCCEEDED(hr)) { - *lResult = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2 - if (*lResult) { - iface->Release(); // the client will release the object again, and then it will destroy itself - } - return true; - } - } - } - } - } - return false; -} - QT_END_NAMESPACE #endif //QT_NO_ACCESSIBILITY diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h new file mode 100644 index 0000000000..9cb56c954c --- /dev/null +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins 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 QWINDOWSMSAAACCESSIBLE_H +#define QWINDOWSMSAAACCESSIBLE_H + +#include <QtCore/QtConfig> +#ifndef QT_NO_ACCESSIBILITY + +#include "../qtwindows_additional.h" +#include <oleacc.h> +#include "Accessible2.h" +#include <QtCore/qsharedpointer.h> +#include <QtGui/qaccessible.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_DEBUG +bool debug_accessibility(); +# define accessibleDebug !debug_accessibility() ? (void)0 : qDebug +#else +# define accessibleDebug +#endif + +#define DEBUG_SHOW_ATCLIENT_COMMANDS +#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS) +void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface); +# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface) +#else +# define accessibleDebugClientCalls(iface) +#endif + +typedef QSharedPointer<QAccessibleInterface> QAIPointer; + +QWindow *window_helper(const QAccessibleInterface *iface); + +/**************************************************************\ + * QWindowsAccessible * + **************************************************************/ +class QWindowsMsaaAccessible : public IAccessible2, public IOleWindow +{ +public: + QWindowsMsaaAccessible(QAccessibleInterface *a) + : accessible(a) + { + } + + virtual ~QWindowsMsaaAccessible() + { + delete accessible; + } + + + /* IDispatch */ + HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *); + HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **); + HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *); + HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *); + + /* IAccessible */ + HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID); + HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID); + HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd); + HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch** ppdispChild); + HRESULT STDMETHODCALLTYPE get_accChildCount(long* pcountChildren); + HRESULT STDMETHODCALLTYPE get_accParent(IDispatch** ppdispParent); + + HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID); + HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction); + HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR* pszDescription); + HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp); + HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic); + HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut); + HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR* pszName); + HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName); + HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole); + HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState); + HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR* pszValue); + HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue); + + HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID); + HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID); + HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren); + + /* IOleWindow */ + HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd); + HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); + +protected: + QAccessibleInterface *accessible; + + QAIPointer childPointer(VARIANT varID) + { + return QAIPointer(accessible->child(varID.lVal - 1)); + } +}; + +QT_END_NAMESPACE + +#endif //QT_NO_ACCESSIBILITY + +#endif // QWINDOWSMSAAACCESSIBLE_H diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h index ac768e2dab..3465d4ab1e 100644 --- a/src/plugins/platforms/windows/qtwindows_additional.h +++ b/src/plugins/platforms/windows/qtwindows_additional.h @@ -71,6 +71,16 @@ #define IFACEMETHODIMP STDMETHODIMP #define IFACEMETHODIMP_(type) STDMETHODIMP_(type) +// For accessibility: +#ifdef __cplusplus + #define EXTERN_C extern "C" +#else + #define EXTERN_C extern +#endif + +#define CHILDID_SELF 0 +#define WM_GETOBJECT 0x003D + #if !defined(__MINGW64_VERSION_MAJOR) #define STATE_SYSTEM_HASPOPUP 0x40000000 diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2706e02cf8..f61e40ef77 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -47,7 +47,7 @@ #include "qtwindowsglobal.h" #include "qwindowsmime.h" #include "qwindowsinputcontext.h" -#include "qwindowsaccessibility.h" +#include "accessible/qwindowsaccessibility.h" #include "qwindowsscreen.h" #include "qwindowstheme.h" @@ -788,7 +788,8 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, QWindowSystemInterface::handleCloseEvent(platformWindow->window()); return true; case QtWindows::ThemeChanged: // ### fixme: Compress these events? - QWindowsTheme::instance()->windowsThemeChanged(platformWindow->window()); + if (QWindowsTheme *theme = QWindowsTheme::instance()) + theme->windowsThemeChanged(platformWindow->window()); return true; default: break; diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 5094ad9dc3..e0be731b53 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1065,9 +1065,17 @@ static inline int verticalDPI() return GetDeviceCaps(QWindowsContext::instance()->displayContext(), LOGPIXELSY); } -QFont QWindowsFontDatabase::defaultFont() const +QFont QWindowsFontDatabase::systemDefaultFont() { - return QWindowsFontDatabaseFT::systemDefaultFont(); + LOGFONT lf; + GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); + QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(lf); + // "MS Shell Dlg 2" is the correct system font >= Win2k + if (systemFont.family() == QStringLiteral("MS Shell Dlg")) + systemFont.setFamily(QStringLiteral("MS Shell Dlg 2")); + if (QWindowsContext::verboseFonts) + qDebug() << __FUNCTION__ << systemFont; + return systemFont; } QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index 04d6ccdd91..f8f2a1eb85 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -85,7 +85,8 @@ public: virtual void releaseHandle(void *handle); virtual QString fontDir() const; - virtual QFont defaultFont() const; + virtual QFont defaultFont() const { return systemDefaultFont(); } + static QFont systemDefaultFont(); static QFontEngine *createEngine(int script, const QFontDef &request, HDC fontHdc, int dpi, bool rawMode, diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index fcce87d0bd..f90a880cd3 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qwindowsfontdatabase_ft.h" +#include "qwindowsfontdatabase.h" #include "qwindowscontext.h" #include <ft2build.h> @@ -460,17 +461,9 @@ static inline int verticalDPI() return GetDeviceCaps(QWindowsContext::instance()->displayContext(), LOGPIXELSY); } -QFont QWindowsFontDatabaseFT::systemDefaultFont() +QFont QWindowsFontDatabaseFT::defaultFont() const { - LOGFONT lf; - GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); - QFont systemFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(lf); - // "MS Shell Dlg 2" is the correct system font >= Win2k - if (systemFont.family() == QStringLiteral("MS Shell Dlg")) - systemFont.setFamily(QStringLiteral("MS Shell Dlg 2")); - if (QWindowsContext::verboseFonts) - qDebug() << __FUNCTION__ << systemFont; - return systemFont; + return QWindowsFontDatabase::systemDefaultFont(); } QFont QWindowsFontDatabaseFT::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h index 4136b75dd8..24810c9202 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h @@ -59,8 +59,7 @@ public: QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); virtual QString fontDir() const; - virtual QFont defaultFont() const { return systemDefaultFont(); } - static QFont systemDefaultFont(); + virtual QFont defaultFont() const; static HFONT systemFont(); static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 3c2ece58d0..ee58a19ca9 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -55,8 +55,8 @@ #include "qwindowsclipboard.h" #include "qwindowsdrag.h" #include "qwindowsinputcontext.h" -#include "qwindowsaccessibility.h" #include "qwindowskeymapper.h" +#include "accessible/qwindowsaccessibility.h" #include <QtGui/QPlatformNativeInterface> #include <QtGui/QWindowSystemInterface> @@ -183,7 +183,6 @@ struct QWindowsIntegrationPrivate QOpenGLStaticContextPtr m_staticOpenGLContext; QWindowsInputContext m_inputContext; QWindowsAccessibility m_accessibility; - QWindowsTheme m_theme; QWindowsServices m_services; }; @@ -362,9 +361,16 @@ QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const return d->m_eventDispatcher; } -QPlatformTheme *QWindowsIntegration::platformTheme() const +QStringList QWindowsIntegration::themeNames() const { - return &d->m_theme; + return QStringList(QLatin1String(QWindowsTheme::name)); +} + +QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) const +{ + if (name == QLatin1String(QWindowsTheme::name)) + return new QWindowsTheme; + return QPlatformIntegration::createPlatformTheme(name); } QPlatformServices *QWindowsIntegration::services() const diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 6dd65a02e4..20fd790bfe 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -69,7 +69,8 @@ public: virtual QPlatformAccessibility *accessibility() const; virtual QPlatformNativeInterface *nativeInterface() const; virtual QPlatformFontDatabase *fontDatabase() const; - virtual QPlatformTheme *platformTheme() const; + virtual QStringList themeNames() const; + virtual QPlatformTheme *createPlatformTheme(const QString &name) const; QPlatformServices *services() const; virtual QVariant styleHint(StyleHint hint) const; diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 10b4682ad8..f3a9d91d00 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -44,7 +44,7 @@ #include "qwindowscontext.h" #include "qwindowsintegration.h" #include "qt_windows.h" -#include "qwindowsfontdatabase_ft.h" +#include "qwindowsfontdatabase.h" #include <QtCore/QVariant> #include <QtCore/QCoreApplication> @@ -229,8 +229,12 @@ static inline QPalette *menuBarPalette(const QPalette &menuPalette) return result; } +const char *QWindowsTheme::name = "windows"; +QWindowsTheme *QWindowsTheme::m_instance = 0; + QWindowsTheme::QWindowsTheme() { + m_instance = this; qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0)); qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0)); refresh(); @@ -240,11 +244,7 @@ QWindowsTheme::~QWindowsTheme() { clearPalettes(); clearFonts(); -} - -QWindowsTheme *QWindowsTheme::instance() -{ - return static_cast<QWindowsTheme *>(QWindowsIntegration::instance()->platformTheme()); + m_instance = 0; } static inline QStringList iconThemeSearchPaths() @@ -325,16 +325,16 @@ void QWindowsTheme::refreshFonts() ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - const QFont menuFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMenuFont); - const QFont messageBoxFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMessageFont); - const QFont statusFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfStatusFont); - const QFont titleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfCaptionFont); + const QFont menuFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMenuFont); + const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont); + const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont); + const QFont titleFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfCaptionFont); LOGFONT lfIconTitleFont; SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - const QFont iconTitleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(lfIconTitleFont); + const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont); - m_fonts[SystemFont] = new QFont(QWindowsFontDatabaseFT::systemDefaultFont()); + m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont()); m_fonts[MenuFont] = new QFont(menuFont); m_fonts[MenuBarFont] = new QFont(menuFont); m_fonts[MessageBoxFont] = new QFont(messageBoxFont); diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index 37346eed3a..7515a13a72 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -57,7 +57,7 @@ public: QWindowsTheme(); ~QWindowsTheme(); - static QWindowsTheme *instance(); + static QWindowsTheme *instance() { return m_instance; } virtual bool usePlatformNativeDialog(DialogType type) const; virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const; @@ -69,6 +69,8 @@ public: void windowsThemeChanged(QWindow *window); + static const char *name; + private: void refresh() { refreshPalettes(); refreshFonts(); } void clearPalettes(); @@ -76,6 +78,7 @@ private: void clearFonts(); void refreshFonts(); + static QWindowsTheme *m_instance; QPalette *m_palettes[NPalettes]; QFont *m_fonts[NFonts]; }; diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index bb41fe87fc..87bc7245c4 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -45,7 +45,6 @@ SOURCES += \ qwindowsdrag.cpp \ qwindowscursor.cpp \ qwindowsinputcontext.cpp \ - qwindowsaccessibility.cpp \ qwindowstheme.cpp \ qwindowsdialoghelpers.cpp \ qwindowsservices.cpp @@ -73,7 +72,6 @@ HEADERS += \ qwindowscursor.h \ array.h \ qwindowsinputcontext.h \ - qwindowsaccessibility.h \ qwindowstheme.h \ qwindowsdialoghelpers.h \ qwindowsservices.h @@ -151,5 +149,6 @@ contains(QT_CONFIG, freetype) { OTHER_FILES += windows.json +include(accessible/accessible.pri) target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index fe33bd7153..50d3c4f1b5 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -82,14 +82,15 @@ #include <QtGui/QOpenGLContext> #include <QtGui/QScreen> +#ifndef QT_NO_ACCESSIBILITY #include <QtGui/QPlatformAccessibility> +#endif QT_BEGIN_NAMESPACE QXcbIntegration::QXcbIntegration(const QStringList ¶meters) : m_eventDispatcher(createUnixEventDispatcher()), - m_services(new QGenericUnixServices), - m_theme(QGenericUnixTheme::createUnixTheme()) + m_services(new QGenericUnixServices) { QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher); @@ -114,7 +115,9 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters) m_fontDatabase.reset(new QGenericUnixFontDatabase()); m_inputContext.reset(QPlatformInputContextFactory::create()); +#ifndef QT_NO_ACCESSIBILITY m_accessibility.reset(new QPlatformAccessibility()); +#endif #if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE) m_sharedGraphicsCache.reset(new QXcbSharedGraphicsCache); @@ -247,10 +250,12 @@ QPlatformInputContext *QXcbIntegration::inputContext() const return m_inputContext.data(); } +#ifndef QT_NO_ACCESSIBILITY QPlatformAccessibility *QXcbIntegration::accessibility() const { return m_accessibility.data(); } +#endif #if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE) static bool sharedGraphicsCacheDisabled() @@ -277,9 +282,14 @@ QPlatformServices *QXcbIntegration::services() const return m_services.data(); } -QPlatformTheme *QXcbIntegration::platformTheme() const +QStringList QXcbIntegration::themeNames() const +{ + return QGenericUnixTheme::themeNames(); +} + +QPlatformTheme *QXcbIntegration::createPlatformTheme(const QString &name) const { - return m_theme.data(); + return QGenericUnixTheme::createUnixTheme(name); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 457f90d6e0..58eebfe716 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -77,7 +77,9 @@ public: QPlatformInputContext *inputContext() const; +#ifndef QT_NO_ACCESSIBILITY QPlatformAccessibility *accessibility() const; +#endif #if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE) QPlatformSharedGraphicsCache *createPlatformSharedGraphicsCache(const char *cacheId) const; @@ -85,7 +87,8 @@ public: QPlatformServices *services() const; - QPlatformTheme *platformTheme() const; + QStringList themeNames() const; + QPlatformTheme *createPlatformTheme(const QString &name) const; private: QList<QXcbConnection *> m_connections; @@ -96,14 +99,15 @@ private: QScopedPointer<QPlatformInputContext> m_inputContext; QAbstractEventDispatcher *m_eventDispatcher; +#ifndef QT_NO_ACCESSIBILITY QScopedPointer<QPlatformAccessibility> m_accessibility; +#endif #if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE) QScopedPointer<QPlatformSharedGraphicsCache> m_sharedGraphicsCache; #endif QScopedPointer<QPlatformServices> m_services; - QScopedPointer<QPlatformTheme> m_theme; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 055defde08..4de3734c22 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -549,7 +549,8 @@ void QXcbWindow::show() updateNetWmStateBeforeMap(); } - updateNetWmUserTime(connection()->time()); + if (connection()->time() != CurrentTime) + updateNetWmUserTime(connection()->time()); Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); xcb_flush(xcb_connection()); @@ -1306,7 +1307,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * { bool fromSendEvent = (event->response_type & 0x80); QPoint pos(event->x, event->y); - if (!fromSendEvent) { + if (!parent() && !fromSendEvent) { // Do not trust the position, query it instead. xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), m_screen->root(), 0, 0); diff --git a/src/plugins/platforms/xlib/qglxintegration.cpp b/src/plugins/platforms/xlib/qglxintegration.cpp index 51621408b9..b2d44cf084 100644 --- a/src/plugins/platforms/xlib/qglxintegration.cpp +++ b/src/plugins/platforms/xlib/qglxintegration.cpp @@ -41,7 +41,6 @@ #include <QDebug> #include <QLibrary> -#include <QGLFormat> #include "qxlibwindow.h" #include "qxlibscreen.h" diff --git a/src/plugins/platforms/xlib/qxlibkeyboard.cpp b/src/plugins/platforms/xlib/qxlibkeyboard.cpp index 590d582661..1ebf22b7ba 100644 --- a/src/plugins/platforms/xlib/qxlibkeyboard.cpp +++ b/src/plugins/platforms/xlib/qxlibkeyboard.cpp @@ -48,6 +48,10 @@ #include <QtCore/QTextCodec> +#if defined(QT_LINUXBASE) +# include <X11/keysymdef.h> +#endif + #ifndef XK_ISO_Left_Tab #define XK_ISO_Left_Tab 0xFE20 #endif diff --git a/src/plugins/platforms/xlib/qxlibwindow.cpp b/src/plugins/platforms/xlib/qxlibwindow.cpp index 94c4332e65..00403aed64 100644 --- a/src/plugins/platforms/xlib/qxlibwindow.cpp +++ b/src/plugins/platforms/xlib/qxlibwindow.cpp @@ -62,7 +62,8 @@ #include <QtGui/QWindowSystemInterface> #include <QSocketNotifier> -#include <QApplication> +#include <QGuiApplication> +#include <QStyleHints> #include <QDebug> //#define MYX11_DEBUG @@ -379,10 +380,11 @@ void QXlibWindow::mousePressEvent(XButtonEvent *e) QEvent::Type type = QEvent::MouseButtonPress; - if (e->window == prevWindow && long(e->time) - prevTime < QApplication::doubleClickInterval() + const int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval(); + if (e->window == prevWindow && long(e->time) - prevTime < doubleClickInterval && qAbs(e->x - prevX) < 5 && qAbs(e->y - prevY) < 5) { type = QEvent::MouseButtonDblClick; - prevTime = e->time - QApplication::doubleClickInterval(); //no double click next time + prevTime = e->time - doubleClickInterval; //no double click next time } else { prevTime = e->time; } @@ -724,7 +726,7 @@ void QXlibWindow::doSizeHints() s.flags |= USSize; s.flags |= PSize; s.flags |= PWinGravity; - s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; + s.win_gravity = QGuiApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; XSetWMNormalHints(mScreen->display()->nativeDisplay(), x_window, &s); } diff --git a/src/plugins/platforms/xlib/xlib.pro b/src/plugins/platforms/xlib/xlib.pro index 463130a64b..a4e006f837 100644 --- a/src/plugins/platforms/xlib/xlib.pro +++ b/src/plugins/platforms/xlib/xlib.pro @@ -43,7 +43,6 @@ mac { CONFIG += qpa/genericunixfontdatabase contains(QT_CONFIG, opengl) { - QT += opengl !contains(QT_CONFIG, opengles2) { # load(qpa/glx/convenience) HEADERS += qglxintegration.h diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 177f64c71b..0855847177 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -2,7 +2,7 @@ TEMPLATE = subdirs SUBDIRS *= sqldrivers bearer !contains(QT_CONFIG, no-gui): SUBDIRS *= imageformats -!isEmpty(QT.widgets.name): SUBDIRS += accessible +!contains(QT_CONFIG, no-widgets): SUBDIRS += accessible SUBDIRS += platforms platforminputcontexts generic diff --git a/src/plugins/printsupport/cocoa/cocoa.json b/src/plugins/printsupport/cocoa/cocoa.json new file mode 100644 index 0000000000..85c38c42be --- /dev/null +++ b/src/plugins/printsupport/cocoa/cocoa.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "cocoaprintersupport" ] +} diff --git a/src/plugins/printsupport/cocoa/cocoa.pro b/src/plugins/printsupport/cocoa/cocoa.pro new file mode 100644 index 0000000000..353094cbae --- /dev/null +++ b/src/plugins/printsupport/cocoa/cocoa.pro @@ -0,0 +1,13 @@ +TARGET = cocoaprintersupport +load(qt_plugin) +DESTDIR = $$QT.gui.plugins/printsupport + +QT += printsupport +LIBS += -framework Cocoa + +SOURCES += main.cpp + +OTHER_FILES += cocoa.json + +target.path += $$[QT_INSTALL_PLUGINS]/printsupport +INSTALLS += target diff --git a/src/plugins/platforms/vnc/main.cpp b/src/plugins/printsupport/cocoa/main.cpp index 7ec780af53..bc8f2e072c 100644 --- a/src/plugins/platforms/vnc/main.cpp +++ b/src/plugins/printsupport/cocoa/main.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** -** This file is part of the plugins of the Qt Toolkit. +** This file is part of the QtPrintSupport module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage @@ -39,35 +39,46 @@ ** ****************************************************************************/ -#include "qvncintegration.h" -#include <qstringlist.h> -#include <QtGui/QPlatformIntegrationPlugin> +#include <QtCore/QMetaMethod> +#include <QtGui/QGuiApplication> +#include <QtGui/QPlatformNativeInterface> +#include <QtPrintSupport/QPlatformPrinterSupportPlugin> QT_BEGIN_NAMESPACE -class QVNCIntegrationPlugin : public QPlatformIntegrationPlugin +class QCocoaPrinterSupportPlugin : public QPlatformPrinterSupportPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.QPlatformPrinterSupportFactoryInterface" FILE "cocoa.json") + public: QStringList keys() const; - QPlatformIntegration *create(const QString&, const QStringList &); + QPlatformPrinterSupport *create(const QString &); }; -QStringList QVNCIntegrationPlugin::keys() const +QStringList QCocoaPrinterSupportPlugin::keys() const { - QStringList list; - list << "VNC"; - return list; + return QStringList(QStringLiteral("cocoaprintersupport")); } -QPlatformIntegration* QVNCIntegrationPlugin::create(const QString& system, const QStringList& paramList) +QPlatformPrinterSupport *QCocoaPrinterSupportPlugin::create(const QString &key) { - Q_UNUSED(paramList); - if (system.toLower() == "vnc") - return new QVNCIntegration(paramList); - - return 0; + if (key.compare(key, QStringLiteral("cocoaprintersupport"), Qt::CaseInsensitive) != 0) + return 0; + QGuiApplication *app = qobject_cast<QGuiApplication *>(QCoreApplication::instance()); + if (!app) + return 0; + QPlatformNativeInterface *platformNativeInterface = app->platformNativeInterface(); + int at = platformNativeInterface->metaObject()->indexOfMethod("createPlatformPrinterSupport()"); + if (at == -1) + return 0; + QMetaMethod createPlatformPrinterSupport = platformNativeInterface->metaObject()->method(at); + QPlatformPrinterSupport *platformPrinterSupport = 0; + if (!createPlatformPrinterSupport.invoke(platformNativeInterface, Q_RETURN_ARG(QPlatformPrinterSupport *, platformPrinterSupport))) + return 0; + return platformPrinterSupport; } -Q_EXPORT_PLUGIN2(vnc, QVNCIntegrationPlugin) - QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/printsupport/printsupport.pro b/src/plugins/printsupport/printsupport.pro index 9298e7981f..547ac42c9e 100644 --- a/src/plugins/printsupport/printsupport.pro +++ b/src/plugins/printsupport/printsupport.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs +mac: SUBDIRS += cocoa win32: SUBDIRS += windows |