From 412dbdf410c765e75c60d1f48143dd6c02a69493 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Wed, 29 Feb 2012 13:32:20 +0900 Subject: Input method on Mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restore input method implimentation in Qt4 Task-number: QTBUG-23867 Change-Id: I5d405ccc8b0a73c399d992f6474a0cc38d191157 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/cocoa.pro | 2 + src/plugins/platforms/cocoa/qcocoahelpers.h | 2 + src/plugins/platforms/cocoa/qcocoahelpers.mm | 19 ++ src/plugins/platforms/cocoa/qcocoainputcontext.h | 70 +++++++ src/plugins/platforms/cocoa/qcocoainputcontext.mm | 122 +++++++++++ src/plugins/platforms/cocoa/qcocoaintegration.h | 2 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 7 + .../platforms/cocoa/qcocoanativeinterface.h | 1 + src/plugins/platforms/cocoa/qnsview.h | 4 +- src/plugins/platforms/cocoa/qnsview.mm | 233 ++++++++++++++++++++- 10 files changed, 457 insertions(+), 5 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoainputcontext.h create mode 100644 src/plugins/platforms/cocoa/qcocoainputcontext.mm (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index b953210720..bd70a415d0 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -31,6 +31,7 @@ OBJECTIVE_SOURCES += main.mm \ qmacclipboard.mm \ qmacmime.mm \ qcocoasystemsettings.mm \ + qcocoainputcontext.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -59,6 +60,7 @@ HEADERS += qcocoaintegration.h \ qmacclipboard.h \ qmacmime.h \ qcocoasystemsettings.h \ + qcocoainputcontext.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui RESOURCES += qcocoaresources.qrc diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 3e3e8fa507..e5fe664731 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -74,6 +74,8 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm); NSSize qt_mac_toNSSize(const QSize &qtSize); +QColor qt_mac_toQColor(const NSColor *color); + 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..e41ddf4a9f 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -137,6 +137,25 @@ 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 diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.h b/src/plugins/platforms/cocoa/qcocoainputcontext.h new file mode 100644 index 0000000000..172c87e2dc --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 QCOCOAINPUTCONTEXT_H +#define QCOCOAINPUTCONTEXT_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QCocoaInputContext : public QPlatformInputContext +{ + Q_OBJECT +public: + explicit QCocoaInputContext(); + ~QCocoaInputContext(); + + virtual bool isValid() const { return true; } + + virtual void reset(); + +private Q_SLOTS: + void inputItemChanged(); + +private: + QPointer mWindow; +}; + +QT_END_NAMESPACE + +#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 +#include +#include + +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(QGuiApplication::platformNativeInterface()); + if (!nativeInterface) return; + + QNSView *view = static_cast(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..2389fc2a55 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -89,6 +89,7 @@ public: QPlatformFontDatabase *fontDatabase() const; QPlatformNativeInterface *nativeInterface() const; + QPlatformInputContext *inputContext() const; QPlatformAccessibility *accessibility() const; QPlatformDrag *drag() const; @@ -98,6 +99,7 @@ private: QScopedPointer mFontDb; QAbstractEventDispatcher *mEventDispatcher; + QScopedPointer mInputContext; QScopedPointer mAccessibility; QScopedPointer mPlatformTheme; QList mScreens; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 8411a795c1..d490495be4 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 @@ -90,6 +91,7 @@ QCocoaScreen::~QCocoaScreen() QCocoaIntegration::QCocoaIntegration() : mFontDb(new QCoreTextFontDatabase()) , mEventDispatcher(new QCocoaEventDispatcher()) + , mInputContext(new QCocoaInputContext) , mAccessibility(new QPlatformAccessibility) , mPlatformTheme(new QCocoaTheme) , mCocoaDrag(new QCocoaDrag) @@ -195,6 +197,11 @@ QPlatformNativeInterface *QCocoaIntegration::nativeInterface() const return new QCocoaNativeInterface(); } +QPlatformInputContext *QCocoaIntegration::inputContext() const +{ + return mInputContext.data(); +} + QPlatformAccessibility *QCocoaIntegration::accessibility() const { return mAccessibility.data(); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 7c6fb38577..d277cb2964 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -48,6 +48,7 @@ class QWidget; class QCocoaNativeInterface : public QPlatformNativeInterface { + Q_OBJECT public: void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); }; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 1a1a1cd3b9..b21e9e342f 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -51,12 +51,14 @@ QT_BEGIN_NAMESPACE class QCocoaWindow; QT_END_NAMESPACE -@interface QNSView : NSView { +@interface QNSView : NSView { 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..6206d53423 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -51,6 +51,7 @@ #include "qcocoadrag.h" #include +#include #include #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 @@ -272,8 +274,15 @@ static QTouchDevice *touchDevice = 0; - (void)mouseDown:(NSEvent *)theEvent { - m_buttons |= Qt::LeftButton; - [self handleMouseEvent:theEvent]; + 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 @@ -467,12 +476,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(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([aString string])); + } else { + commitString = QCFString::toQString(reinterpret_cast(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 attrs; + attrs<([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<(aString)); + } + + if (attrs.isEmpty()) { + QTextCharFormat format; + format.setFontUnderline(true); + attrs<((CFStringRef)string); + return [[[NSAttributedString alloc] initWithString:const_cast(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 -- cgit v1.2.3 From 0bb95b183b28208a9ecf88e25cc22b8086201a2b Mon Sep 17 00:00:00 2001 From: Rick Stockton Date: Thu, 8 Mar 2012 14:33:15 -0800 Subject: Cocoa platform plugin: Add support for up to 16 mouse buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OS-X provides a buttonNumber within Event data for otherMouseDown: and otherMouseUp: Events. Instead of mapping all occurences of these event types to Qt::MiddleButton, this Update uses that data to support a total of 16 mouse buttons. Task-number: QTBUG-24702 Change-Id: I3cffb32498f98ea182509d7c42f3fc6634155ebb Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qnsview.mm | 96 +++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 6206d53423..4ab5e32a8e 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -336,7 +336,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]; } @@ -349,7 +395,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]; } -- cgit v1.2.3 From 02d75eaaf9f2e4984f39b1e081e841966d1dde0c Mon Sep 17 00:00:00 2001 From: Jan-Arve Saether Date: Thu, 6 Oct 2011 09:41:34 +0200 Subject: Add support for IAccessible2 on Windows Change-Id: Ia955ab46dc5037ed1c74e0acc525e98b02552c97 Reviewed-by: Frederik Gladhorn --- .../platforms/windows/accessible/accessible.pri | 15 + .../platforms/windows/accessible/comutils.cpp | 641 ++++++++ .../platforms/windows/accessible/comutils.h | 61 + .../platforms/windows/accessible/iaccessible2.cpp | 1467 +++++++++++++++++++ .../platforms/windows/accessible/iaccessible2.h | 375 +++++ .../windows/accessible/qwindowsaccessibility.cpp | 301 ++++ .../windows/accessible/qwindowsaccessibility.h | 73 + .../windows/accessible/qwindowsmsaaaccessible.cpp | 1228 ++++++++++++++++ .../windows/accessible/qwindowsmsaaaccessible.h | 138 ++ .../platforms/windows/qwindowsaccessibility.cpp | 1525 -------------------- .../platforms/windows/qwindowsaccessibility.h | 67 - src/plugins/platforms/windows/qwindowscontext.cpp | 2 +- .../platforms/windows/qwindowsintegration.cpp | 2 +- src/plugins/platforms/windows/windows.pro | 3 +- 14 files changed, 4302 insertions(+), 1596 deletions(-) create mode 100644 src/plugins/platforms/windows/accessible/accessible.pri create mode 100644 src/plugins/platforms/windows/accessible/comutils.cpp create mode 100644 src/plugins/platforms/windows/accessible/comutils.h create mode 100644 src/plugins/platforms/windows/accessible/iaccessible2.cpp create mode 100644 src/plugins/platforms/windows/accessible/iaccessible2.h create mode 100644 src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp create mode 100644 src/plugins/platforms/windows/accessible/qwindowsaccessibility.h create mode 100644 src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp create mode 100644 src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h delete mode 100644 src/plugins/platforms/windows/qwindowsaccessibility.cpp delete mode 100644 src/plugins/platforms/windows/qwindowsaccessibility.h (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri new file mode 100644 index 0000000000..bf25ad870c --- /dev/null +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -0,0 +1,15 @@ + +SOURCES += \ + $$PWD/qwindowsmsaaaccessible.cpp \ + $$PWD/qwindowsaccessibility.cpp \ + $$PWD/iaccessible2.cpp \ + $$PWD/comutils.cpp + +HEADERS += \ + $$PWD/qwindowsmsaaaccessible.h \ + $$PWD/qwindowsaccessibility.h \ + $$PWD/iaccessible2.h \ + $$PWD/comutils.h + + +include(../../../../3rdparty/iaccessible2/iaccessible2.pri) 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 +#include + +#include "comutils.h" +#include +#include +#include + + +#include +#include +#include + +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(qvar)); + } else { + arg.vt = VT_COLOR; + arg.lVal = QColorToOLEColor(qvariant_cast(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(qvar)); + } else { + arg.vt = VT_DISPATCH; + arg.pdispVal = QFontToIFont(qvariant_cast(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(qvar)); + } else { + arg.vt = VT_DISPATCH; + arg.pdispVal = QPixmapToIPicture(qvariant_cast(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(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 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 + 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(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/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h new file mode 100644 index 0000000000..08420cc46c --- /dev/null +++ b/src/plugins/platforms/windows/accessible/comutils.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 COMUTILS_H +#define COMUTILS_H + +#if !defined(_WINDOWS_) && !defined(_WINDOWS_H) && !defined(__WINDOWS__) +#error Must include windows.h first! +#endif + +#include +#include + +class QVariant; + +bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out); + +inline BSTR QStringToBSTR(const QString &str) +{ + return SysAllocStringLen((OLECHAR*)str.unicode(), str.length()); +} + +#endif // COMUTILS_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 +#ifndef QT_NO_ACCESSIBILITY + +#include "iaccessible2.h" +#include "qwindowsaccessibility.h" + +#include +#include +#include + +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(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 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 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 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 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 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(this); + } else if (/*guidService == IID_IAccessible && */riid == IID_IAccessible2) { + *iface = static_cast(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 RelationEntry; + QVector rels = accessible->relations(); + QMap relationMap; + for (QVector::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it) + { + RelationEntry e = *it; + relationMap.insertMulti(e.second, e.first); + } + + QList 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 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 inside an array of IAccessible* + The IAccessible* array is returned as a IUnknown* +*/ +HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList &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 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..11889df9ec --- /dev/null +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -0,0 +1,375 @@ +/**************************************************************************** +** +** 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 +#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" + +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(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 &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 &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 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..f409730600 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -0,0 +1,301 @@ +/**************************************************************************** +** +** 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 +#ifndef QT_NO_ACCESSIBILITY + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qwindowsaccessibility.h" +#include "iaccessible2.h" +#include "comutils.h" + +#include + +//#include +#ifndef UiaRootObjectId +#define UiaRootObjectId -25 +#endif + +#include +#if !defined(WINABLEAPI) +# if defined(Q_OS_WINCE) +# include +# endif +# include +#endif + +#include +#include +#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) +#include +#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 > 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(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(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); + + 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 +} + + +/*! + \internal + helper to wrap a QAccessibleInterface inside a IAccessible* +*/ +IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) +{ + if (!acc) + return 0; + QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); + IAccessible *iacc = 0; + wacc->QueryInterface(IID_IAccessible, (void**)&iacc); + return iacc; +} + +/*! + \internal +*/ +QPair 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(lParam) == static_cast(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) { + 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/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h new file mode 100644 index 0000000000..3b7069570b --- /dev/null +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 QWINDOWSACCESSIBILITY_H +#define QWINDOWSACCESSIBILITY_H + +#include "../qtwindowsglobal.h" +#include "../qwindowscontext.h" +#include + +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QWindowsAccessibility : public QPlatformAccessibility +{ +public: + QWindowsAccessibility(); + static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult); + virtual void notifyAccessibilityUpdate(const QAccessibleEvent &event); + /* + virtual void setRootObject(QObject *o); + virtual void initialize(); + virtual void cleanup(); + */ + static IAccessible *wrap(QAccessibleInterface *acc); + + static QPair getCachedObject(int entryId); +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QWINDOWSACCESSIBILITY_H diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp new file mode 100644 index 0000000000..ca3ce0a614 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -0,0 +1,1228 @@ +/**************************************************************************** +** +** 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 +#ifndef QT_NO_ACCESSIBILITY + +#include "qwindowsmsaaaccessible.h" +#include "qwindowsaccessibility.h" +#include +#include +#include +#include "comutils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include +#ifndef UiaRootObjectId +#define UiaRootObjectId -25 +#endif + +#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) +#include +#endif + +#ifdef Q_OS_WINCE +#include "../qguifunctions_wince.h" +#endif + +#include "../qtwindows_additional.h" + + +QT_BEGIN_NAMESPACE + +class QWindowsEnumerate : public IEnumVARIANT +{ +public: + QWindowsEnumerate(const QVector &a) + : ref(0), current(0),array(a) + { + } + + virtual ~QWindowsEnumerate() {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum); + HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched); + HRESULT STDMETHODCALLTYPE Reset(); + HRESULT STDMETHODCALLTYPE Skip(unsigned long celt); + +private: + ULONG ref; + ULONG current; + QVector array; +}; + +HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface) +{ + *iface = 0; + if (id == IID_IUnknown) + *iface = (IUnknown*)this; + else if (id == IID_IEnumVARIANT) + *iface = (IEnumVARIANT*)this; + + if (*iface) { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef() +{ + return ++ref; +} + +ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release() +{ + if (!--ref) { + delete this; + return 0; + } + return ref; +} + +HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum) +{ + QWindowsEnumerate *penum = 0; + *ppEnum = 0; + + penum = new QWindowsEnumerate(array); + if (!penum) + return E_OUTOFMEMORY; + penum->current = current; + penum->array = array; + penum->AddRef(); + *ppEnum = penum; + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched) +{ + if (pCeltFetched) + *pCeltFetched = 0; + + ULONG l; + for (l = 0; l < celt; l++) { + VariantInit(&rgVar[l]); + if ((current+1) > (ULONG)array.size()) { + *pCeltFetched = l; + return S_FALSE; + } + + rgVar[l].vt = VT_I4; + rgVar[l].lVal = array[(int)current]; + ++current; + } + *pCeltFetched = l; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset() +{ + current = 0; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) +{ + current += celt; + if (current > (ULONG)array.size()) { + current = array.size(); + return S_FALSE; + } + return S_OK; +} + +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()); + + if (compareAccessible(onePar.data(), otherPar.data())) + return onePar->indexOfChild(one) == otherPar->indexOfChild(other); + return false; +} + +#ifndef QT_NO_DEBUG +bool debug_accessibility() +{ + static int debugging = -1; + if (debugging == -1) + debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt(); + return !!debugging; +} +#endif + +#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)); +} +#endif + +/* + IDispatch +*/ + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfoCount(unsigned int * pctinfo) +{ + // We don't use a type library + *pctinfo = 0; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo) +{ + // We don't use a type library + *pptinfo = 0; + return S_OK; +} + +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 + if (_bstr_t(rgszNames[0]) == _bstr_t(L"accParent")) + rgdispid[0] = DISPID_ACC_PARENT; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChildCount")) + rgdispid[0] = DISPID_ACC_CHILDCOUNT; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChild")) + rgdispid[0] = DISPID_ACC_CHILD; + + // PROPERTIES: Descriptional + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accName(")) + rgdispid[0] = DISPID_ACC_NAME; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accValue")) + rgdispid[0] = DISPID_ACC_VALUE; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDescription")) + rgdispid[0] = DISPID_ACC_DESCRIPTION; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accRole")) + rgdispid[0] = DISPID_ACC_ROLE; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accState")) + rgdispid[0] = DISPID_ACC_STATE; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelp")) + rgdispid[0] = DISPID_ACC_HELP; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelpTopic")) + rgdispid[0] = DISPID_ACC_HELPTOPIC; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accKeyboardShortcut")) + rgdispid[0] = DISPID_ACC_KEYBOARDSHORTCUT; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accFocus")) + rgdispid[0] = DISPID_ACC_FOCUS; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelection")) + rgdispid[0] = DISPID_ACC_SELECTION; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDefaultAction")) + rgdispid[0] = DISPID_ACC_DEFAULTACTION; + + // METHODS + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelect")) + rgdispid[0] = DISPID_ACC_SELECT; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accLocation")) + rgdispid[0] = DISPID_ACC_LOCATION; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accNavigate")) + rgdispid[0] = DISPID_ACC_NAVIGATE; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHitTest")) + rgdispid[0] = DISPID_ACC_HITTEST; + else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDoDefaultAction")) + rgdispid[0] = DISPID_ACC_DODEFAULTACTION; + else + return DISP_E_UNKNOWNINTERFACE; + + return S_OK; +#else + Q_UNUSED(rgszNames); + Q_UNUSED(rgdispid); + + return DISP_E_MEMBERNOTFOUND; +#endif +} + +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; + + switch (dispIdMember) + { + case DISPID_ACC_PARENT: + if (wFlags == DISPATCH_PROPERTYGET) { + if (!pVarResult) + return E_INVALIDARG; + hr = get_accParent(&pVarResult->pdispVal); + } else { + hr = DISP_E_MEMBERNOTFOUND; + } + break; + + case DISPID_ACC_CHILDCOUNT: + if (wFlags == DISPATCH_PROPERTYGET) { + if (!pVarResult) + return E_INVALIDARG; + hr = get_accChildCount(&pVarResult->lVal); + } else { + hr = DISP_E_MEMBERNOTFOUND; + } + break; + + case DISPID_ACC_CHILD: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accChild(pDispParams->rgvarg[0], &pVarResult->pdispVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_NAME: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accName(pDispParams->rgvarg[0], &pVarResult->bstrVal); + else if (wFlags == DISPATCH_PROPERTYPUT) + hr = put_accName(pDispParams->rgvarg[0], pVarResult->bstrVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_VALUE: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accValue(pDispParams->rgvarg[0], &pVarResult->bstrVal); + else if (wFlags == DISPATCH_PROPERTYPUT) + hr = put_accValue(pDispParams->rgvarg[0], pVarResult->bstrVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_DESCRIPTION: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accDescription(pDispParams->rgvarg[0], &pVarResult->bstrVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_ROLE: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accRole(pDispParams->rgvarg[0], pVarResult); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_STATE: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accState(pDispParams->rgvarg[0], pVarResult); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_HELP: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accHelp(pDispParams->rgvarg[0], &pVarResult->bstrVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_HELPTOPIC: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accHelpTopic(&pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_KEYBOARDSHORTCUT: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accKeyboardShortcut(pDispParams->rgvarg[0], &pVarResult->bstrVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_FOCUS: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accFocus(pVarResult); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_SELECTION: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accSelection(pVarResult); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_DEFAULTACTION: + if (wFlags == DISPATCH_PROPERTYGET) + hr = get_accDefaultAction(pDispParams->rgvarg[0], &pVarResult->bstrVal); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_SELECT: + if (wFlags == DISPATCH_METHOD) + hr = accSelect(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_LOCATION: + if (wFlags == DISPATCH_METHOD) + hr = accLocation(&pDispParams->rgvarg[4].lVal, &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_NAVIGATE: + if (wFlags == DISPATCH_METHOD) + hr = accNavigate(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0], pVarResult); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_HITTEST: + if (wFlags == DISPATCH_METHOD) + hr = accHitTest(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal, pVarResult); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + case DISPID_ACC_DODEFAULTACTION: + if (wFlags == DISPATCH_METHOD) + hr = accDoDefaultAction(pDispParams->rgvarg[0]); + else + hr = DISP_E_MEMBERNOTFOUND; + break; + + default: + hr = DISP_E_MEMBERNOTFOUND; + break; + } + + if (!SUCCEEDED(hr)) { + return hr; + } + return hr; +} + +/* + IAccessible + +IAccessible::accHitTest documents the value returned in pvarID like this: + +| *Point location* | *vt member* | *Value member* | ++========================================================+=============+=========================+ +| Outside of the object's boundaries, and either inside | VT_EMPTY | None. | +| or outside of the object's bounding rectangle. | | | ++--------------------------------------------------------+-------------+-------------------------+ +| Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF | +| child object. | | | ++--------------------------------------------------------+-------------+-------------------------+ +| Within a child element. | VT_I4 | lVal contains | +| | | the child ID. | ++--------------------------------------------------------+-------------+-------------------------+ +| Within a child object. | VT_DISPATCH | pdispVal is set to the | +| | | child object's IDispatch| +| | | interface pointer | ++--------------------------------------------------------+-------------+-------------------------+ +*/ +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QAccessibleInterface *child = accessible->childAt(xLeft, yTop); + if (child == 0) { + // no child found, return this item if it contains the coordinates + if (accessible->rect().contains(xLeft, yTop)) { + (*pvarID).vt = VT_I4; + (*pvarID).lVal = CHILDID_SELF; + return S_OK; + } + } else { + IAccessible *iface = QWindowsAccessibility::wrap(child); + if (iface) { + (*pvarID).vt = VT_DISPATCH; + (*pvarID).pdispVal = iface; + return S_OK; + } + } + + // Did not find anything + (*pvarID).vt = VT_EMPTY; + return S_FALSE; +} + +/* + It is recommended to read + "Implementing a Microsoft Active Accessibility (MSAA) Server. + Practical Tips for Developers and How Mozilla Does It" + (https://developer.mozilla.org/En/Accessibility/Implementing_an_MSAA_Server) + + to get an overview of what's important to implement and what parts of MSAA + can be ignored. All stuff prefixed with "moz" are information from that page. +*/ +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QRect rect; + if (varID.lVal) { + QAIPointer child = QAIPointer(accessible->child(varID.lVal - 1)); + if (child->isValid()) + rect = child->rect(); + } else { + rect = accessible->rect(); + } + + *pxLeft = rect.x(); + *pyTop = rect.y(); + *pcxWidth = rect.width(); + *pcyHeight = rect.height(); + + return S_OK; +} + +// moz: [important, but no need to implement up/down/left/right] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QAccessibleInterface *acc = 0; + switch (navDir) { + case NAVDIR_FIRSTCHILD: + acc = accessible->child(0); + break; + case NAVDIR_LASTCHILD: + acc = accessible->child(accessible->childCount() - 1); + break; + case NAVDIR_NEXT: + case NAVDIR_PREVIOUS: + if (!varStart.lVal){ + QAccessibleInterface *parent = accessible->parent(); + if (parent) { + int index = parent->indexOfChild(accessible); + index += (navDir == NAVDIR_NEXT) ? 1 : -1; + if (index >= 0 && index < parent->childCount()) + acc = parent->child(index); + delete parent; + } + } else { + int index = varStart.lVal; + index += (navDir == NAVDIR_NEXT) ? 1 : -1; + if (index > 0 && index <= accessible->childCount()) + acc = accessible->child(index - 1); + } + break; + + // Geometrical + case NAVDIR_UP: + case NAVDIR_DOWN: + case NAVDIR_LEFT: + case NAVDIR_RIGHT: + if (QAccessibleInterface *pIface = accessible->parent()) { + const int indexOfOurself = pIface->indexOfChild(accessible); + QRect startg = accessible->rect(); + QPoint startc = startg.center(); + QAccessibleInterface *candidate = 0; + unsigned mindist = UINT_MAX; // will work on screen sizes at least up to 46340x46340 + const int sibCount = pIface->childCount(); + for (int i = 0; i < sibCount; ++i) { + QAccessibleInterface *sibling = 0; + sibling = pIface->child(i); + Q_ASSERT(sibling); + if (i == indexOfOurself || sibling->state().invisible) { + //ignore ourself and invisible siblings + delete sibling; + continue; + } + + QRect sibg = sibling->rect(); + QPoint sibc = sibg.center(); + QPoint sibp; + QPoint startp; + QPoint distp; + switch (navDir) { + case NAVDIR_LEFT: + startp = QPoint(startg.left(), startg.top() + startg.height() / 2); + sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2); + if (QPoint(sibc - startc).x() >= 0) { + delete sibling; + continue; + } + distp = sibp - startp; + break; + case NAVDIR_RIGHT: + startp = QPoint(startg.right(), startg.top() + startg.height() / 2); + sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2); + if (QPoint(sibc - startc).x() <= 0) { + delete sibling; + continue; + } + distp = sibp - startp; + break; + case NAVDIR_UP: + startp = QPoint(startg.left() + startg.width() / 2, startg.top()); + sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom()); + if (QPoint(sibc - startc).y() >= 0) { + delete sibling; + continue; + } + distp = sibp - startp; + break; + case NAVDIR_DOWN: + startp = QPoint(startg.left() + startg.width() / 2, startg.bottom()); + sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top()); + if (QPoint(sibc - startc).y() <= 0) { + delete sibling; + continue; + } + distp = sibp - startp; + break; + default: + break; + } + + // Since we're *comparing* (and not measuring) distances, we can compare the + // squared distance, (thus, no need to take the sqrt()). + unsigned dist = distp.x() * distp.x() + distp.y() * distp.y(); + if (dist < mindist) { + delete candidate; + candidate = sibling; + mindist = dist; + } else { + delete sibling; + } + } + delete pIface; + acc = candidate; + } + break; + default: + break; + } + if (!acc) { + (*pvarEnd).vt = VT_EMPTY; + return S_FALSE; + } + + if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { + (*pvarEnd).vt = VT_DISPATCH; + (*pvarEnd).pdispVal = iface; + return S_OK; + } else { + if (acc != accessible) + delete acc; + } + + (*pvarEnd).vt = VT_EMPTY; + return S_FALSE; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (varChildID.vt != VT_I4) + return E_INVALIDARG; + + + int childIndex = varChildID.lVal; + QAccessibleInterface *acc = 0; + + if (childIndex < 0) { + const int entry = childIndex; + QPair ref = QWindowsAccessibility::getCachedObject(entry); + if (ref.first) { + acc = QAccessible::queryAccessibleInterface(ref.first); + if (acc && ref.second >= 0) { + QAccessibleInterface *res = acc->child(ref.second); + delete acc; + if (!res) + return E_INVALIDARG; + acc = res; + } + } else { + qWarning("get_accChild got a negative varChildID, but did not find it in cache"); + } + } else { + if (childIndex) { + acc = accessible->child(childIndex - 1); + } else { + // Yes, some AT clients (Active Accessibility Object Inspector) + // actually ask for the same object. As a consequence, we need to clone ourselves: + if (QAccessibleInterface *par = accessible->parent()) { + const int indexOf = par->indexOfChild(accessible); + QAccessibleInterface *clone = par->child(indexOf); + delete par; + acc = clone; + } + } + } + + if (acc) { + *ppdispChild = QWindowsAccessibility::wrap(acc); + return S_OK; + } + + return E_FAIL; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *pcountChildren = accessible->childCount(); + return S_OK; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdispParent) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QAccessibleInterface *acc = accessible->parent(); + if (acc) { + if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { + *ppdispParent = iface; + return S_OK; + } else { + delete acc; + } + } + + *ppdispParent = 0; + return S_FALSE; +} + +/* + Properties and methods +*/ +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT varID) +{ + Q_UNUSED(varID); + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { + const QString def = actionIface->actionNames().value(0); + if (!def.isEmpty()) { + actionIface->doAction(def); + return S_OK; + } + } + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) +{ + Q_UNUSED(varID); + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *pszDefaultAction = 0; + if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { + const QString def = actionIface->actionNames().value(0); + if (!def.isEmpty()) + *pszDefaultAction = QStringToBSTR(def); + } + return *pszDefaultAction ? S_OK : S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + + QString descr; + if (varID.lVal) { + QAIPointer child = childPointer(varID); + if (!child) + return E_FAIL; + descr = child->text(QAccessible::Description); + } else { + descr = accessible->text(QAccessible::Description); + } + if (descr.size()) { + *pszDescription = QStringToBSTR(descr); + return S_OK; + } + + *pszDescription = 0; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QString help; + if (varID.lVal) { + QAIPointer child = childPointer(varID); + if (!child) + return E_FAIL; + help = child->text(QAccessible::Help); + } else { + help = accessible->text(QAccessible::Help); + } + if (help.size()) { + *pszHelp = QStringToBSTR(help); + return S_OK; + } + + *pszHelp = 0; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelpTopic(BSTR *, VARIANT, long *) +{ + return DISP_E_MEMBERNOTFOUND; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) +{ + Q_UNUSED(varID); + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + *pszKeyboardShortcut = 0; + if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { + const QString def = actionIface->actionNames().value(0); + if (!def.isEmpty()) { + const QString keyBoardShortCut = actionIface->keyBindingsForAction(def).value(0); + if (!keyBoardShortCut.isEmpty()) + *pszKeyboardShortcut = QStringToBSTR(keyBoardShortCut); + } + } + return *pszKeyboardShortcut ? S_OK : S_FALSE; +} + +static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAccessible::RelationFlag flag) +{ + typedef QPair RelationPair; + QVector rels = iface->relations(flag); + + for (int i = 1; i < rels.count(); ++i) + delete rels.at(i).first; + + return rels.value(0).first; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BSTR* pszName) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QString name; + if (varID.lVal) { + QAIPointer child = childPointer(varID); + if (!child) + return E_FAIL; + name = child->text(QAccessible::Name); + if (name.isEmpty()) { + if (QAccessibleInterface *labelInterface = relatedInterface(child.data(), QAccessible::Label)) { + name = labelInterface->text(QAccessible::Name); + delete labelInterface; + } + } + } else { + name = accessible->text(QAccessible::Name); + if (name.isEmpty()) { + if (QAccessibleInterface *labelInterface = relatedInterface(accessible, QAccessible::Label)) { + name = labelInterface->text(QAccessible::Name); + delete labelInterface; + } + } + } + if (name.size()) { + *pszName = QStringToBSTR(name); + return S_OK; + } + + *pszName = 0; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR) +{ + accessibleDebugClientCalls(accessible); + return DISP_E_MEMBERNOTFOUND; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QAccessible::Role role; + if (varID.lVal) { + QAIPointer child = childPointer(varID); + if (!child) + return E_FAIL; + role = child->role(); + } else { + role = accessible->role(); + } + + if (role != QAccessible::NoRole) { + if (role == QAccessible::LayeredPane) + role = QAccessible::Pane; + (*pvarRole).vt = VT_I4; + (*pvarRole).lVal = role; + } else { + (*pvarRole).vt = VT_EMPTY; + } + return S_OK; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VARIANT *pvarState) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + QAccessible::State state; + if (varID.lVal) { + QAIPointer child = childPointer(varID); + if (!child.data()) + return E_FAIL; + state = child->state(); + } else { + state = accessible->state(); + } + + LONG st = 0; + if (state.animated) + st |= STATE_SYSTEM_ANIMATED; + if (state.busy) + st |= STATE_SYSTEM_BUSY; + if (state.checked) + st |= STATE_SYSTEM_CHECKED; + if (state.collapsed) + st |= STATE_SYSTEM_COLLAPSED; + if (state.defaultButton) + st |= STATE_SYSTEM_DEFAULT; + if (state.expanded) + st |= STATE_SYSTEM_EXPANDED; + if (state.extSelectable) + st |= STATE_SYSTEM_EXTSELECTABLE; + if (state.focusable) + st |= STATE_SYSTEM_FOCUSABLE; + if (state.focused) + st |= STATE_SYSTEM_FOCUSED; + if (state.hasPopup) + st |= STATE_SYSTEM_HASPOPUP; + if (state.hotTracked) + st |= STATE_SYSTEM_HOTTRACKED; + if (state.invisible) + st |= STATE_SYSTEM_INVISIBLE; + if (state.linked) + st |= STATE_SYSTEM_LINKED; + if (state.marqueed) + st |= STATE_SYSTEM_MARQUEED; + if (state.checkStateMixed) + st |= STATE_SYSTEM_MIXED; + if (state.movable) + st |= STATE_SYSTEM_MOVEABLE; + if (state.multiSelectable) + st |= STATE_SYSTEM_MULTISELECTABLE; + if (state.offscreen) + st |= STATE_SYSTEM_OFFSCREEN; + if (state.pressed) + st |= STATE_SYSTEM_PRESSED; + if (state.passwordEdit) + st |= STATE_SYSTEM_PROTECTED; + if (state.readOnly) + st |= STATE_SYSTEM_READONLY; + if (state.selectable) + st |= STATE_SYSTEM_SELECTABLE; + if (state.selected) + st |= STATE_SYSTEM_SELECTED; + if (state.selfVoicing) + st |= STATE_SYSTEM_SELFVOICING; + if (state.sizeable) + st |= STATE_SYSTEM_SIZEABLE; + if (state.traversed) + st |= STATE_SYSTEM_TRAVERSED; + + (*pvarState).vt = VT_I4; + (*pvarState).lVal = st; + return S_OK; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue) +{ + accessibleDebugClientCalls(accessible); + if (varID.vt != VT_I4) + return E_INVALIDARG; + + if (!accessible->isValid() || varID.lVal) { + return E_FAIL; + } + + QString value; + if (accessible->valueInterface()) { + value = QString::number(accessible->valueInterface()->currentValue().toDouble()); + } else { + value = accessible->text(QAccessible::Value); + } + if (!value.isNull()) { + *pszValue = QStringToBSTR(value); + return S_OK; + } + + *pszValue = 0; + accessibleDebug("return S_FALSE"); + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR) +{ + accessibleDebugClientCalls(accessible); + return DISP_E_MEMBERNOTFOUND; +} + +// moz: [important] +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VARIANT varID) +{ + Q_UNUSED(flagsSelect); + Q_UNUSED(varID); + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + bool res = false; + +/* + ### Check for accessibleTableInterface() or accessibleTextInterface() + + ### and if there are no ia2 interfaces we should do nothing?? + if (flagsSelect & SELFLAG_TAKEFOCUS) + res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); + if (flagsSelect & SELFLAG_TAKESELECTION) { + accessible->doAction(ClearSelection, 0, QVariantList()); + res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); + } + if (flagsSelect & SELFLAG_EXTENDSELECTION) + res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); + if (flagsSelect & SELFLAG_ADDSELECTION) + res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); + if (flagsSelect & SELFLAG_REMOVESELECTION) + res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); +*/ + return res ? S_OK : S_FALSE; +} + +/*! + \internal + Can return: + + +-------------+------------------------------------------------------------------------------+ + | VT_EMPTY | None. Neither this object nor any of its children has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + | VT_I4 | lVal is CHILDID_SELF. The object itself has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + | VT_I4 | lVal contains the child ID of the child element that has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + | VT_DISPATCH | pdispVal member is the address of the IDispatch interface for the child | + | | object that has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + moz: [important] +*/ +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + if (QAccessibleInterface *acc = accessible->focusChild()) { + if (compareAccessible(acc, accessible)) { + (*pvarID).vt = VT_I4; + (*pvarID).lVal = CHILDID_SELF; + delete acc; + return S_OK; + } else { + if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) { + (*pvarID).vt = VT_DISPATCH; + (*pvarID).pdispVal = iface; + return S_OK; + } + } + delete acc; + } + (*pvarID).vt = VT_EMPTY; + return S_FALSE; +} + +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvarChildren) +{ + accessibleDebugClientCalls(accessible); + if (!accessible->isValid()) + return E_FAIL; + + int cc = accessible->childCount(); + QVector sel(cc); + int selIndex = 0; + for (int i = 0; i < cc; ++i) { + bool isSelected = false; + QAccessibleInterface *child = accessible->child(i); + if (child) { + isSelected = child->state().selected; + delete child; + } + if (isSelected) + sel[selIndex++] = i+1; + } + sel.resize(selIndex); + if (sel.isEmpty()) { + (*pvarChildren).vt = VT_EMPTY; + return S_FALSE; + } + if (sel.size() == 1) { + (*pvarChildren).vt = VT_I4; + (*pvarChildren).lVal = sel[0]; + return S_OK; + } + IEnumVARIANT *iface = new QWindowsEnumerate(sel); + IUnknown *uiface; + iface->QueryInterface(IID_IUnknown, (void**)&uiface); + (*pvarChildren).vt = VT_UNKNOWN; + (*pvarChildren).punkVal = uiface; + + return S_OK; +} + +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; +} + +/**************************************************************\ + * 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); + 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 QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL) +{ + return S_OK; +} + +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..609f57b398 --- /dev/null +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -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 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 +#ifndef QT_NO_ACCESSIBILITY + +#include +#include "Accessible2.h" +#include +#include + +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 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/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp deleted file mode 100644 index 134b1c81ce..0000000000 --- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp +++ /dev/null @@ -1,1525 +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 -#ifndef QT_NO_ACCESSIBILITY - - -#include "qwindowsaccessibility.h" -#include "qwindowscontext.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#include -#ifndef UiaRootObjectId -#define UiaRootObjectId -25 -#endif - -#include -#if !defined(WINABLEAPI) -# if defined(Q_OS_WINCE) -# include -# endif -# include -#endif - -#include -#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU) -#include -#endif - -#ifdef Q_OS_WINCE -#include "qguifunctions_wince.h" -#endif - -#include "qtwindows_additional.h" - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_DEBUG -QT_BEGIN_INCLUDE_NAMESPACE -# include -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 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()); - - 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 > NotifyMap; -Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents) -static int eventNum = 0; - -class QWindowsEnumerate : public IEnumVARIANT -{ -public: - QWindowsEnumerate(const QVector &a) - : ref(0), current(0),array(a) - { - } - - virtual ~QWindowsEnumerate() {} - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum); - HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched); - HRESULT STDMETHODCALLTYPE Reset(); - HRESULT STDMETHODCALLTYPE Skip(unsigned long celt); - -private: - ULONG ref; - ULONG current; - QVector array; -}; - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface) -{ - *iface = 0; - if (id == IID_IUnknown) - *iface = (IUnknown*)this; - else if (id == IID_IEnumVARIANT) - *iface = (IEnumVARIANT*)this; - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef() -{ - return ++ref; -} - -ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release() -{ - if (!--ref) { - delete this; - return 0; - } - return ref; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum) -{ - QWindowsEnumerate *penum = 0; - *ppEnum = 0; - - penum = new QWindowsEnumerate(array); - if (!penum) - return E_OUTOFMEMORY; - penum->current = current; - penum->array = array; - penum->AddRef(); - *ppEnum = penum; - - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched) -{ - if (pCeltFetched) - *pCeltFetched = 0; - - ULONG l; - for (l = 0; l < celt; l++) { - VariantInit(&rgVar[l]); - if ((current+1) > (ULONG)array.size()) { - *pCeltFetched = l; - return S_FALSE; - } - - rgVar[l].vt = VT_I4; - rgVar[l].lVal = array[(int)current]; - ++current; - } - *pCeltFetched = l; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset() -{ - current = 0; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) -{ - current += celt; - if (current > (ULONG)array.size()) { - current = array.size(); - return S_FALSE; - } - 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) -{ - BSTR bstrVal; - - int wlen = str.length()+1; - bstrVal = SysAllocStringByteLen(0, wlen*2); - memcpy(bstrVal, str.unicode(), sizeof(QChar)*(wlen)); - bstrVal[wlen] = 0; - - return bstrVal; -} - -/* -*/ - -/* - 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; - - AddRef(); - return S_OK; -} - -ULONG STDMETHODCALLTYPE QWindowsAccessible::AddRef() -{ - return ++ref; -} - -ULONG STDMETHODCALLTYPE QWindowsAccessible::Release() -{ - if (!--ref) { - delete this; - return 0; - } - return ref; -} - -/* - IDispatch -*/ - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::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) -{ - // 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) -{ -#if !defined(Q_CC_BOR) && !defined(Q_CC_GNU) - // PROPERTIES: Hierarchical - if (_bstr_t(rgszNames[0]) == _bstr_t(L"accParent")) - rgdispid[0] = DISPID_ACC_PARENT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChildCount")) - rgdispid[0] = DISPID_ACC_CHILDCOUNT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accChild")) - rgdispid[0] = DISPID_ACC_CHILD; - - // PROPERTIES: Descriptional - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accName(")) - rgdispid[0] = DISPID_ACC_NAME; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accValue")) - rgdispid[0] = DISPID_ACC_VALUE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDescription")) - rgdispid[0] = DISPID_ACC_DESCRIPTION; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accRole")) - rgdispid[0] = DISPID_ACC_ROLE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accState")) - rgdispid[0] = DISPID_ACC_STATE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelp")) - rgdispid[0] = DISPID_ACC_HELP; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHelpTopic")) - rgdispid[0] = DISPID_ACC_HELPTOPIC; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accKeyboardShortcut")) - rgdispid[0] = DISPID_ACC_KEYBOARDSHORTCUT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accFocus")) - rgdispid[0] = DISPID_ACC_FOCUS; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelection")) - rgdispid[0] = DISPID_ACC_SELECTION; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDefaultAction")) - rgdispid[0] = DISPID_ACC_DEFAULTACTION; - - // METHODS - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accSelect")) - rgdispid[0] = DISPID_ACC_SELECT; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accLocation")) - rgdispid[0] = DISPID_ACC_LOCATION; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accNavigate")) - rgdispid[0] = DISPID_ACC_NAVIGATE; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accHitTest")) - rgdispid[0] = DISPID_ACC_HITTEST; - else if (_bstr_t(rgszNames[0]) == _bstr_t(L"accDoDefaultAction")) - rgdispid[0] = DISPID_ACC_DODEFAULTACTION; - else - return DISP_E_UNKNOWNINTERFACE; - - return S_OK; -#else - Q_UNUSED(rgszNames); - Q_UNUSED(rgdispid); - - return DISP_E_MEMBERNOTFOUND; -#endif -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::Invoke(long dispIdMember, const _GUID &, unsigned long, unsigned short wFlags, tagDISPPARAMS *pDispParams, tagVARIANT *pVarResult, tagEXCEPINFO *, unsigned int *) -{ - HRESULT hr = DISP_E_MEMBERNOTFOUND; - - switch (dispIdMember) - { - case DISPID_ACC_PARENT: - if (wFlags == DISPATCH_PROPERTYGET) { - if (!pVarResult) - return E_INVALIDARG; - hr = get_accParent(&pVarResult->pdispVal); - } else { - hr = DISP_E_MEMBERNOTFOUND; - } - break; - - case DISPID_ACC_CHILDCOUNT: - if (wFlags == DISPATCH_PROPERTYGET) { - if (!pVarResult) - return E_INVALIDARG; - hr = get_accChildCount(&pVarResult->lVal); - } else { - hr = DISP_E_MEMBERNOTFOUND; - } - break; - - case DISPID_ACC_CHILD: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accChild(pDispParams->rgvarg[0], &pVarResult->pdispVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_NAME: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accName(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else if (wFlags == DISPATCH_PROPERTYPUT) - hr = put_accName(pDispParams->rgvarg[0], pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_VALUE: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accValue(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else if (wFlags == DISPATCH_PROPERTYPUT) - hr = put_accValue(pDispParams->rgvarg[0], pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_DESCRIPTION: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accDescription(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_ROLE: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accRole(pDispParams->rgvarg[0], pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_STATE: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accState(pDispParams->rgvarg[0], pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_HELP: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accHelp(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_HELPTOPIC: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accHelpTopic(&pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_KEYBOARDSHORTCUT: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accKeyboardShortcut(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_FOCUS: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accFocus(pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_SELECTION: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accSelection(pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_DEFAULTACTION: - if (wFlags == DISPATCH_PROPERTYGET) - hr = get_accDefaultAction(pDispParams->rgvarg[0], &pVarResult->bstrVal); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_SELECT: - if (wFlags == DISPATCH_METHOD) - hr = accSelect(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_LOCATION: - if (wFlags == DISPATCH_METHOD) - hr = accLocation(&pDispParams->rgvarg[4].lVal, &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_NAVIGATE: - if (wFlags == DISPATCH_METHOD) - hr = accNavigate(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0], pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_HITTEST: - if (wFlags == DISPATCH_METHOD) - hr = accHitTest(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal, pVarResult); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - case DISPID_ACC_DODEFAULTACTION: - if (wFlags == DISPATCH_METHOD) - hr = accDoDefaultAction(pDispParams->rgvarg[0]); - else - hr = DISP_E_MEMBERNOTFOUND; - break; - - default: - hr = DISP_E_MEMBERNOTFOUND; - break; - } - - if (!SUCCEEDED(hr)) { - return hr; - } - return hr; -} - -/* - IAccessible - -IAccessible::accHitTest documents the value returned in pvarID like this: - -| *Point location* | *vt member* | *Value member* | -+========================================================+=============+=========================+ -| Outside of the object's boundaries, and either inside | VT_EMPTY | None. | -| or outside of the object's bounding rectangle. | | | -+--------------------------------------------------------+-------------+-------------------------+ -| Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF | -| child object. | | | -+--------------------------------------------------------+-------------+-------------------------+ -| Within a child element. | VT_I4 | lVal contains | -| | | the child ID. | -+--------------------------------------------------------+-------------+-------------------------+ -| Within a child object. | VT_DISPATCH | pdispVal is set to the | -| | | child object's IDispatch| -| | | interface pointer | -+--------------------------------------------------------+-------------+-------------------------+ -*/ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) -{ - - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QAccessibleInterface *child = accessible->childAt(xLeft, yTop); - if (child == 0) { - // no child found, return this item if it contains the coordinates - if (accessible->rect().contains(xLeft, yTop)) { - (*pvarID).vt = VT_I4; - (*pvarID).lVal = CHILDID_SELF; - return S_OK; - } - } else { - QWindowsAccessible* wacc = new QWindowsAccessible(child); - IDispatch *iface = 0; - wacc->QueryInterface(IID_IDispatch, (void**)&iface); - if (iface) { - (*pvarID).vt = VT_DISPATCH; - (*pvarID).pdispVal = iface; - return S_OK; - } - } - - // Did not find anything - (*pvarID).vt = VT_EMPTY; - return S_FALSE; -} - -/* - It is recommended to read - "Implementing a Microsoft Active Accessibility (MSAA) Server. - Practical Tips for Developers and How Mozilla Does It" - (https://developer.mozilla.org/En/Accessibility/Implementing_an_MSAA_Server) - - to get an overview of what's important to implement and what parts of MSAA - 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) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QRect rect; - if (varID.lVal) { - QAIPointer child = QAIPointer(accessible->child(varID.lVal - 1)); - if (child->isValid()) - rect = child->rect(); - } else { - rect = accessible->rect(); - } - - *pxLeft = rect.x(); - *pyTop = rect.y(); - *pcxWidth = rect.width(); - *pcyHeight = rect.height(); - - return S_OK; -} - -// moz: [important, but no need to implement up/down/left/right] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QAccessibleInterface *acc = 0; - switch (navDir) { - case NAVDIR_FIRSTCHILD: - acc = accessible->child(0); - break; - case NAVDIR_LASTCHILD: - acc = accessible->child(accessible->childCount() - 1); - break; - case NAVDIR_NEXT: - case NAVDIR_PREVIOUS: - if (!varStart.lVal){ - QAccessibleInterface *parent = accessible->parent(); - if (parent) { - int index = parent->indexOfChild(accessible); - index += (navDir == NAVDIR_NEXT) ? 1 : -1; - if (index >= 0 && index < parent->childCount()) - acc = parent->child(index); - delete parent; - } - } else { - int index = varStart.lVal; - index += (navDir == NAVDIR_NEXT) ? 1 : -1; - if (index > 0 && index <= accessible->childCount()) - acc = accessible->child(index - 1); - } - break; - - // Geometrical - case NAVDIR_UP: - case NAVDIR_DOWN: - case NAVDIR_LEFT: - case NAVDIR_RIGHT: - if (QAccessibleInterface *pIface = accessible->parent()) { - const int indexOfOurself = pIface->indexOfChild(accessible); - QRect startg = accessible->rect(); - QPoint startc = startg.center(); - QAccessibleInterface *candidate = 0; - unsigned mindist = UINT_MAX; // will work on screen sizes at least up to 46340x46340 - const int sibCount = pIface->childCount(); - for (int i = 0; i < sibCount; ++i) { - QAccessibleInterface *sibling = 0; - sibling = pIface->child(i); - Q_ASSERT(sibling); - if (i == indexOfOurself || sibling->state().invisible) { - //ignore ourself and invisible siblings - delete sibling; - continue; - } - - QRect sibg = sibling->rect(); - QPoint sibc = sibg.center(); - QPoint sibp; - QPoint startp; - QPoint distp; - switch (navDir) { - case NAVDIR_LEFT: - startp = QPoint(startg.left(), startg.top() + startg.height() / 2); - sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2); - if (QPoint(sibc - startc).x() >= 0) { - delete sibling; - continue; - } - distp = sibp - startp; - break; - case NAVDIR_RIGHT: - startp = QPoint(startg.right(), startg.top() + startg.height() / 2); - sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2); - if (QPoint(sibc - startc).x() <= 0) { - delete sibling; - continue; - } - distp = sibp - startp; - break; - case NAVDIR_UP: - startp = QPoint(startg.left() + startg.width() / 2, startg.top()); - sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom()); - if (QPoint(sibc - startc).y() >= 0) { - delete sibling; - continue; - } - distp = sibp - startp; - break; - case NAVDIR_DOWN: - startp = QPoint(startg.left() + startg.width() / 2, startg.bottom()); - sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top()); - if (QPoint(sibc - startc).y() <= 0) { - delete sibling; - continue; - } - distp = sibp - startp; - break; - default: - break; - } - - // Since we're *comparing* (and not measuring) distances, we can compare the - // squared distance, (thus, no need to take the sqrt()). - unsigned dist = distp.x() * distp.x() + distp.y() * distp.y(); - if (dist < mindist) { - delete candidate; - candidate = sibling; - mindist = dist; - } else { - delete sibling; - } - } - delete pIface; - acc = candidate; - } - break; - default: - break; - } - if (!acc) { - (*pvarEnd).vt = VT_EMPTY; - return S_FALSE; - } - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - - IDispatch *iface = 0; - wacc->QueryInterface(IID_IDispatch, (void**)&iface); - if (iface) { - (*pvarEnd).vt = VT_DISPATCH; - (*pvarEnd).pdispVal = iface; - return S_OK; - } else { - delete wacc; - } - - (*pvarEnd).vt = VT_EMPTY; - return S_FALSE; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - if (varChildID.vt == VT_EMPTY) - return E_INVALIDARG; - - - int childIndex = varChildID.lVal; - QAccessibleInterface *acc = 0; - - if (childIndex < 0) { - const int entry = childIndex; - QPair ref = qAccessibleRecentSentEvents()->value(entry); - if (ref.first) { - acc = QAccessible::queryAccessibleInterface(ref.first); - if (acc && ref.second >= 0) { - QAccessibleInterface *res = acc->child(ref.second); - delete acc; - if (!res) - return E_INVALIDARG; - acc = res; - } - } - } else { - if (childIndex) { - acc = accessible->child(childIndex - 1); - } else { - // Yes, some AT clients (Active Accessibility Object Inspector) - // actually ask for the same object. As a consequence, we need to clone ourselves: - if (QAccessibleInterface *par = accessible->parent()) { - const int indexOf = par->indexOfChild(accessible); - QAccessibleInterface *clone = par->child(indexOf); - delete par; - acc = clone; - } - } - } - - if (acc) { - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - wacc->QueryInterface(IID_IDispatch, (void**)ppdispChild); - return S_OK; - } - - *ppdispChild = 0; - return S_FALSE; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - *pcountChildren = accessible->childCount(); - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QAccessibleInterface *acc = accessible->parent(); - if (acc) { - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - wacc->QueryInterface(IID_IDispatch, (void**)ppdispParent); - - if (*ppdispParent) - return S_OK; - } - - *ppdispParent = 0; - return S_FALSE; -} - -/* - Properties and methods -*/ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) -{ - Q_UNUSED(varID); - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { - const QString def = actionIface->actionNames().value(0); - if (!def.isEmpty()) { - actionIface->doAction(def); - return S_OK; - } - } - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) -{ - Q_UNUSED(varID); - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - *pszDefaultAction = 0; - if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { - const QString def = actionIface->actionNames().value(0); - if (!def.isEmpty()) - *pszDefaultAction = QStringToBSTR(def); - } - return *pszDefaultAction ? S_OK : S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - - QString descr; - if (varID.lVal) { - QAIPointer child = childPointer(varID); - if (!child) - return E_FAIL; - descr = child->text(QAccessible::Description); - } else { - descr = accessible->text(QAccessible::Description); - } - if (descr.size()) { - *pszDescription = QStringToBSTR(descr); - return S_OK; - } - - *pszDescription = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QString help; - if (varID.lVal) { - QAIPointer child = childPointer(varID); - if (!child) - return E_FAIL; - help = child->text(QAccessible::Help); - } else { - help = accessible->text(QAccessible::Help); - } - if (help.size()) { - *pszHelp = QStringToBSTR(help); - return S_OK; - } - - *pszHelp = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT, long *) -{ - return DISP_E_MEMBERNOTFOUND; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) -{ - Q_UNUSED(varID); - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - *pszKeyboardShortcut = 0; - if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { - const QString def = actionIface->actionNames().value(0); - if (!def.isEmpty()) { - const QString keyBoardShortCut = actionIface->keyBindingsForAction(def).value(0); - if (!keyBoardShortCut.isEmpty()) - *pszKeyboardShortcut = QStringToBSTR(keyBoardShortCut); - } - } - return *pszKeyboardShortcut ? S_OK : S_FALSE; -} - -static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAccessible::RelationFlag flag) -{ - typedef QPair RelationPair; - QVector rels = iface->relations(flag); - - for (int i = 1; i < rels.count(); ++i) - delete rels.at(i).first; - - return rels.value(0).first; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QString name; - if (varID.lVal) { - QAIPointer child = childPointer(varID); - if (!child) - return E_FAIL; - name = child->text(QAccessible::Name); - if (name.isEmpty()) { - if (QAccessibleInterface *labelInterface = relatedInterface(child.data(), QAccessible::Label)) { - name = labelInterface->text(QAccessible::Name); - delete labelInterface; - } - } - } else { - name = accessible->text(QAccessible::Name); - if (name.isEmpty()) { - if (QAccessibleInterface *labelInterface = relatedInterface(accessible, QAccessible::Label)) { - name = labelInterface->text(QAccessible::Name); - delete labelInterface; - } - } - } - if (name.size()) { - *pszName = QStringToBSTR(name); - return S_OK; - } - - *pszName = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR) -{ - accessibleDebugClientCalls(accessible); - return DISP_E_MEMBERNOTFOUND; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QAccessible::Role role; - if (varID.lVal) { - QAIPointer child = childPointer(varID); - if (!child) - return E_FAIL; - role = child->role(); - } else { - role = accessible->role(); - } - - if (role != QAccessible::NoRole) { - if (role == QAccessible::LayeredPane) - role = QAccessible::Pane; - (*pvarRole).vt = VT_I4; - (*pvarRole).lVal = role; - } else { - (*pvarRole).vt = VT_EMPTY; - } - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - QAccessible::State state; - if (varID.lVal) { - QAIPointer child = childPointer(varID); - if (!child.data()) - return E_FAIL; - state = child->state(); - } else { - state = accessible->state(); - } - - LONG st = 0; - if (state.animated) - st |= STATE_SYSTEM_ANIMATED; - if (state.busy) - st |= STATE_SYSTEM_BUSY; - if (state.checked) - st |= STATE_SYSTEM_CHECKED; - if (state.collapsed) - st |= STATE_SYSTEM_COLLAPSED; - if (state.defaultButton) - st |= STATE_SYSTEM_DEFAULT; - if (state.expanded) - st |= STATE_SYSTEM_EXPANDED; - if (state.extSelectable) - st |= STATE_SYSTEM_EXTSELECTABLE; - if (state.focusable) - st |= STATE_SYSTEM_FOCUSABLE; - if (state.focused) - st |= STATE_SYSTEM_FOCUSED; - if (state.hasPopup) - st |= STATE_SYSTEM_HASPOPUP; - if (state.hotTracked) - st |= STATE_SYSTEM_HOTTRACKED; - if (state.invisible) - st |= STATE_SYSTEM_INVISIBLE; - if (state.linked) - st |= STATE_SYSTEM_LINKED; - if (state.marqueed) - st |= STATE_SYSTEM_MARQUEED; - if (state.checkStateMixed) - st |= STATE_SYSTEM_MIXED; - if (state.movable) - st |= STATE_SYSTEM_MOVEABLE; - if (state.multiSelectable) - st |= STATE_SYSTEM_MULTISELECTABLE; - if (state.offscreen) - st |= STATE_SYSTEM_OFFSCREEN; - if (state.pressed) - st |= STATE_SYSTEM_PRESSED; - if (state.passwordEdit) - st |= STATE_SYSTEM_PROTECTED; - if (state.readOnly) - st |= STATE_SYSTEM_READONLY; - if (state.selectable) - st |= STATE_SYSTEM_SELECTABLE; - if (state.selected) - st |= STATE_SYSTEM_SELECTED; - if (state.selfVoicing) - st |= STATE_SYSTEM_SELFVOICING; - if (state.sizeable) - st |= STATE_SYSTEM_SIZEABLE; - if (state.traversed) - st |= STATE_SYSTEM_TRAVERSED; - - (*pvarState).vt = VT_I4; - (*pvarState).lVal = st; - return S_OK; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid() || varID.lVal) - return E_FAIL; - - QString value; - if (accessible->valueInterface()) { - value = QString::number(accessible->valueInterface()->currentValue().toDouble()); - } else { - value = accessible->text(QAccessible::Value); - } - if (!value.isNull()) { - *pszValue = QStringToBSTR(value); - return S_OK; - } - - *pszValue = 0; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR) -{ - accessibleDebugClientCalls(accessible); - return DISP_E_MEMBERNOTFOUND; -} - -// moz: [important] -HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID) -{ - Q_UNUSED(flagsSelect); - Q_UNUSED(varID); - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - bool res = false; - -/* - ### Check for accessibleTableInterface() or accessibleTextInterface() - - ### and if there are no ia2 interfaces we should do nothing?? - if (flagsSelect & SELFLAG_TAKEFOCUS) - res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_TAKESELECTION) { - accessible->doAction(ClearSelection, 0, QVariantList()); - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); - } - if (flagsSelect & SELFLAG_EXTENDSELECTION) - res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_ADDSELECTION) - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_REMOVESELECTION) - res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); -*/ - return res ? S_OK : S_FALSE; -} - -/*! - \internal - Can return: - - +-------------+------------------------------------------------------------------------------+ - | VT_EMPTY | None. Neither this object nor any of its children has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - | VT_I4 | lVal is CHILDID_SELF. The object itself has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - | VT_I4 | lVal contains the child ID of the child element that has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - | VT_DISPATCH | pdispVal member is the address of the IDispatch interface for the child | - | | object that has the keyboard focus. | - +-------------+------------------------------------------------------------------------------+ - moz: [important] -*/ -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - if (QAccessibleInterface *acc = accessible->focusChild()) { - if (compareAccessible(acc, accessible)) { - (*pvarID).vt = VT_I4; - (*pvarID).lVal = CHILDID_SELF; - 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; - } - delete acc; - } - (*pvarID).vt = VT_EMPTY; - return S_FALSE; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren) -{ - accessibleDebugClientCalls(accessible); - if (!accessible->isValid()) - return E_FAIL; - - int cc = accessible->childCount(); - QVector sel(cc); - int selIndex = 0; - for (int i = 0; i < cc; ++i) { - bool isSelected = false; - QAccessibleInterface *child = accessible->child(i); - if (child) { - isSelected = child->state().selected; - delete child; - } - if (isSelected) - sel[selIndex++] = i+1; - } - sel.resize(selIndex); - if (sel.isEmpty()) { - (*pvarChildren).vt = VT_EMPTY; - return S_FALSE; - } - if (sel.size() == 1) { - (*pvarChildren).vt = VT_I4; - (*pvarChildren).lVal = sel[0]; - return S_OK; - } - IEnumVARIANT *iface = new QWindowsEnumerate(sel); - IUnknown *uiface; - iface->QueryInterface(IID_IUnknown, (void**)&uiface); - (*pvarChildren).vt = VT_UNKNOWN; - (*pvarChildren).punkVal = uiface; - - 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) -{ - *phwnd = 0; - if (!accessible->isValid()) - return E_UNEXPECTED; - - QWindow *window = window_helper(accessible); - if (!window) - return E_FAIL; - - QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); - Q_ASSERT(platform); - *phwnd = (HWND)platform->nativeResourceForWindow("handle", window); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE QWindowsAccessible::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(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(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(lParam) == static_cast(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/qwindowsaccessibility.h b/src/plugins/platforms/windows/qwindowsaccessibility.h deleted file mode 100644 index 9294f23565..0000000000 --- a/src/plugins/platforms/windows/qwindowsaccessibility.h +++ /dev/null @@ -1,67 +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 QWINDOWSACCESSIBILITY_H -#define QWINDOWSACCESSIBILITY_H - -#include "qtwindowsglobal.h" -#include - -QT_BEGIN_HEADER -QT_BEGIN_NAMESPACE - -class QWindowsAccessibility : public QPlatformAccessibility -{ -public: - QWindowsAccessibility(); - static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult); - virtual void notifyAccessibilityUpdate(const QAccessibleEvent &event); - /* - virtual void setRootObject(QObject *o); - virtual void initialize(); - virtual void cleanup(); - */ -}; - -QT_END_NAMESPACE -QT_END_HEADER - -#endif // QWINDOWSACCESSIBILITY_H diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2706e02cf8..e8050d5027 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" diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 3c2ece58d0..7510cded50 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 #include 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 -- cgit v1.2.3 From 9a68dd015674a6c23764640977d83c272336d9c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 13 Mar 2012 16:50:05 +0100 Subject: Made sure first created xcb window still receives focus. Change 50ca45f059524293790 caused mapped windows to not receive focus by default. The _NET_WM_USER_TIME spec says that if the user time is set to 0 (or CurrentTime), the window will not be initially focused. Thus, if the connection time has not yet been set, we skip this part to restore the old behavior. Change-Id: I19de3602c78629ad2bc65f5e1976313949c82c4c Reviewed-by: Jan Arne Petersen Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 055defde08..54b3b214b1 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()); -- cgit v1.2.3 From 255079124a5378c71ec25726eee9ba3d648c56c6 Mon Sep 17 00:00:00 2001 From: jian liang Date: Tue, 13 Mar 2012 22:52:51 +0800 Subject: build fix for -no-freetype in Windows Don't use QWindowsFontDatabaseFT::systemDefaultFont() and QWindowsFontDatabaseFT::LOGFONT_to_QFont() in qwindowsfontdatabase.cpp and qwindowstheme.cpp because it is not available when building with -no-freetype. Change-Id: I11075475ff435c55b0c641540f95a4d3861b79da Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsfontdatabase.cpp | 12 ++++++++++-- src/plugins/platforms/windows/qwindowsfontdatabase.h | 3 ++- src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp | 13 +++---------- src/plugins/platforms/windows/qwindowsfontdatabase_ft.h | 3 +-- src/plugins/platforms/windows/qwindowstheme.cpp | 14 +++++++------- 5 files changed, 23 insertions(+), 22 deletions(-) (limited to 'src/plugins/platforms') 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 @@ -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/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 10b4682ad8..f10595fa79 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 #include @@ -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); -- cgit v1.2.3 From a3420b127e14787d6679c7431464ac6a26c6464b Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Sat, 10 Mar 2012 17:50:35 +0000 Subject: Remove unused forward declaration. Change-Id: Ib207e0036226dd7131195244bf49bbfae142cd22 Reviewed-by: Sean Harmer Reviewed-by: Kevin Krammer Reviewed-by: Harald Fernengel --- src/plugins/platforms/qnx/qqnxwindow.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/plugins/platforms') 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 -- cgit v1.2.3 From 087d6c21b853f0802df882c3e1545a7b97e0c898 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 14 Mar 2012 12:17:11 +0100 Subject: Fix compilation of the Windows accessibility code for MinGW. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Temporarily disable the code for MinGW. Change-Id: I435305167e06af05b9a78901e6e3a35347c5c3f5 Reviewed-by: Jan-Arve Sæther --- .../platforms/windows/accessible/accessible.pri | 24 +++++++++------- .../platforms/windows/accessible/iaccessible2.h | 4 +++ .../windows/accessible/qwindowsaccessibility.cpp | 32 +++++++++++++++++----- .../windows/accessible/qwindowsaccessibility.h | 1 + .../windows/accessible/qwindowsmsaaaccessible.cpp | 17 +----------- .../windows/accessible/qwindowsmsaaaccessible.h | 3 +- .../platforms/windows/qtwindows_additional.h | 10 +++++++ 7 files changed, 57 insertions(+), 34 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri index bf25ad870c..1671c67d17 100644 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -1,15 +1,19 @@ - SOURCES += \ - $$PWD/qwindowsmsaaaccessible.cpp \ - $$PWD/qwindowsaccessibility.cpp \ - $$PWD/iaccessible2.cpp \ - $$PWD/comutils.cpp + $$PWD/qwindowsaccessibility.cpp HEADERS += \ - $$PWD/qwindowsmsaaaccessible.h \ - $$PWD/qwindowsaccessibility.h \ - $$PWD/iaccessible2.h \ - $$PWD/comutils.h + $$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) + include(../../../../3rdparty/iaccessible2/iaccessible2.pri) +} # !g++ diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 11889df9ec..a59263fba1 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -66,6 +66,10 @@ #include "AccessibleRole.h" #include "AccessibleStates.h" +#ifdef Q_CC_MINGW +# include +#endif + QT_BEGIN_NAMESPACE class QWindowsIA2Accessible : public QWindowsMsaaAccessible, diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index f409730600..4f92b910b2 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -54,13 +54,13 @@ #include #include #include -#include -#include -#include -#include #include "qwindowsaccessibility.h" -#include "iaccessible2.h" + +#ifndef Q_CC_MINGW +# include "iaccessible2.h" +#endif // !Q_CC_MINGW + #include "comutils.h" #include @@ -185,7 +185,7 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &ev // 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; + QWindow *window = iface ? QWindowsAccessibility::windowHelper(iface) : 0; delete iface; if (!window) { @@ -211,6 +211,20 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &ev #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 @@ -218,12 +232,16 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &ev */ 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 } /*! @@ -260,7 +278,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W #if 1 // Ignoring all requests while starting up // ### Maybe QPA takes care of this??? - if (QApplication::startingUp() || QApplication::closingDown()) + if (QCoreApplication::startingUp() || QCoreApplication::closingDown()) return false; #endif diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h index 3b7069570b..0c3aca0a03 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h @@ -63,6 +63,7 @@ public: virtual void cleanup(); */ static IAccessible *wrap(QAccessibleInterface *acc); + static QWindow *windowHelper(const QAccessibleInterface *iface); static QPair getCachedObject(int entryId); }; diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index ca3ce0a614..8791bbdcfb 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -1180,21 +1180,6 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvar return S_OK; } -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; -} - /**************************************************************\ * IOleWindow * **************************************************************/ @@ -1207,7 +1192,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetWindow(HWND *phwnd) if (!accessible->isValid()) return E_UNEXPECTED; - QWindow *window = window_helper(accessible); + QWindow *window = QWindowsAccessibility::windowHelper(accessible); if (!window) return E_FAIL; diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h index 609f57b398..9cb56c954c 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -44,6 +44,7 @@ #include #ifndef QT_NO_ACCESSIBILITY +#include "../qtwindows_additional.h" #include #include "Accessible2.h" #include @@ -55,7 +56,7 @@ QT_BEGIN_NAMESPACE bool debug_accessibility(); # define accessibleDebug !debug_accessibility() ? (void)0 : qDebug #else -# define accessibleDebug() +# define accessibleDebug #endif #define DEBUG_SHOW_ATCLIENT_COMMANDS 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 -- cgit v1.2.3 From d6311a06515221e41edb69722b571080c08d11ce Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Fri, 16 Dec 2011 13:12:39 +0100 Subject: Cocoa: Improve basic window handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor NSWindow creation into createNSWindow and setNSWindow. This is necessary to support QMacNativeWidget where we re-use an already created window. Implement popup window handling. Make sure the window is displayed correctly and closes when it should. Take control over window activation in order to prevent infinite loops involving the QtCreator "cmd-k" window. Activation events are for now not sent to popup-type windows. There is now a different set of test failures: add and remove some QEXPECT_FAILs. Change-Id: I229761b59f90c9815b968eacc2cbc9c20cc5047e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.h | 22 +- src/plugins/platforms/cocoa/qcocoawindow.mm | 318 ++++++++++------------- src/plugins/platforms/cocoa/qnsview.h | 1 + src/plugins/platforms/cocoa/qnsview.mm | 20 +- src/plugins/platforms/cocoa/qnswindowdelegate.mm | 8 + 5 files changed, 183 insertions(+), 186 deletions(-) (limited to 'src/plugins/platforms') 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 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(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(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/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index b21e9e342f..f09c9331f6 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -44,6 +44,7 @@ #include +#include #include #include diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 4ab5e32a8e..a28c5959ce 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -146,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); @@ -268,12 +281,15 @@ 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 { + 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]) { 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); -- cgit v1.2.3 From f7957f39937c42aadecc6ad2b73d006559514e00 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 14 Mar 2012 13:50:14 +0100 Subject: Refactor theme plugin loading. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the old implementation, the QPlatformIntegration was asked for the theme first, so there was no way of overriding that by a custom plugin. Also, there was a memory leak in case the platform theme was actually created by a plugin. QGuiApplication now asks the QPlatformIntegration for a list of potential theme names first, tries to load them using the plugin loader and finally invokes a factory method of QPlatformIntegration in case that fails. The theme is now owned by QGuiApplication. In the XCB plugin, the environment variable DESKTOP_SESSION is queried and appended to the list of themes, making it possible to load plugins for other session types. Change-Id: I1a4b4e061815bca16c65b23e591bb7563a3e44e2 Reviewed-by: Samuel Rødal --- src/plugins/platforms/cocoa/qcocoaintegration.h | 4 +++- src/plugins/platforms/cocoa/qcocoaintegration.mm | 12 +++++++++--- src/plugins/platforms/cocoa/qcocoatheme.h | 3 +++ src/plugins/platforms/cocoa/qcocoatheme.mm | 2 ++ src/plugins/platforms/windows/qwindowscontext.cpp | 3 ++- src/plugins/platforms/windows/qwindowsintegration.cpp | 12 +++++++++--- src/plugins/platforms/windows/qwindowsintegration.h | 3 ++- src/plugins/platforms/windows/qwindowstheme.cpp | 10 +++++----- src/plugins/platforms/windows/qwindowstheme.h | 5 ++++- src/plugins/platforms/xcb/qxcbintegration.cpp | 12 ++++++++---- src/plugins/platforms/xcb/qxcbintegration.h | 4 ++-- 11 files changed, 49 insertions(+), 21 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 2389fc2a55..9248df0d37 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -93,7 +93,9 @@ public: QPlatformAccessibility *accessibility() const; QPlatformDrag *drag() const; - QPlatformTheme *platformTheme() const; + QStringList themeNames() const; + QPlatformTheme *createPlatformTheme(const QString &name) const; + private: QScopedPointer mFontDb; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index d490495be4..96027e0925 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -93,7 +93,6 @@ QCocoaIntegration::QCocoaIntegration() , mEventDispatcher(new QCocoaEventDispatcher()) , mInputContext(new QCocoaInputContext) , mAccessibility(new QPlatformAccessibility) - , mPlatformTheme(new QCocoaTheme) , mCocoaDrag(new QCocoaDrag) { QCocoaAutoReleasePool pool; @@ -212,9 +211,16 @@ QPlatformDrag *QCocoaIntegration::drag() const return mCocoaDrag.data(); } -QPlatformTheme *QCocoaIntegration::platformTheme() const +QStringList QCocoaIntegration::themeNames() const { - return mPlatformTheme.data(); + return QStringList(QLatin1String(QCocoaTheme::name)); +} + +QPlatformTheme *QCocoaIntegration::createPlatformTheme(const QString &name) const +{ + if (name == QLatin1String(QCocoaTheme::name)) + return new QCocoaTheme; + return QPlatformIntegration::createPlatformTheme(name); } QT_END_NAMESPACE 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 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/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index e8050d5027..f61e40ef77 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -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/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 7510cded50..ee58a19ca9 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -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 f10595fa79..f3a9d91d00 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -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(0)); qFill(m_palettes, m_palettes + NPalettes, static_cast(0)); refresh(); @@ -240,11 +244,7 @@ QWindowsTheme::~QWindowsTheme() { clearPalettes(); clearFonts(); -} - -QWindowsTheme *QWindowsTheme::instance() -{ - return static_cast(QWindowsIntegration::instance()->platformTheme()); + m_instance = 0; } static inline QStringList iconThemeSearchPaths() 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/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index fe33bd7153..0db9ef9e64 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -88,8 +88,7 @@ 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); @@ -277,9 +276,14 @@ QPlatformServices *QXcbIntegration::services() const return m_services.data(); } -QPlatformTheme *QXcbIntegration::platformTheme() const +QStringList QXcbIntegration::themeNames() const { - return m_theme.data(); + return QGenericUnixTheme::themeNames(); +} + +QPlatformTheme *QXcbIntegration::createPlatformTheme(const QString &name) const +{ + 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..4c335f2f06 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -85,7 +85,8 @@ public: QPlatformServices *services() const; - QPlatformTheme *platformTheme() const; + QStringList themeNames() const; + QPlatformTheme *createPlatformTheme(const QString &name) const; private: QList m_connections; @@ -103,7 +104,6 @@ private: #endif QScopedPointer m_services; - QScopedPointer m_theme; }; QT_END_NAMESPACE -- cgit v1.2.3 From f2826292242cb2412ddc7e068e668089bfa89f36 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Tue, 13 Mar 2012 20:59:59 +0100 Subject: LSB requires an explicit header include MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the plugin build in the LSB environment Change-Id: Ic9a54b984f7fc1f393853ec01e32886f49a041c6 Reviewed-by: Samuel Rødal --- src/plugins/platforms/xlib/qxlibkeyboard.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins/platforms') 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 +#if defined(QT_LINUXBASE) +# include +#endif + #ifndef XK_ISO_Left_Tab #define XK_ISO_Left_Tab 0xFE20 #endif -- cgit v1.2.3 From 8a79e8b645bfaa2f9ed00976466198223f6db6dd Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Tue, 6 Mar 2012 12:23:31 +0100 Subject: Remove unmaintained and broken VNC platform plugin Change-Id: Ie0a07c3a6822870b095a20d997b63fb1635f20be Reviewed-by: Oswald Buddenhagen Reviewed-by: Robert Griebl Reviewed-by: Girish Ramakrishnan --- src/plugins/platforms/vnc/main.cpp | 73 - src/plugins/platforms/vnc/qvnccursor.cpp | 156 -- src/plugins/platforms/vnc/qvnccursor.h | 76 - src/plugins/platforms/vnc/qvncintegration.cpp | 255 ---- src/plugins/platforms/vnc/qvncintegration.h | 111 -- src/plugins/platforms/vnc/qvncserver.cpp | 1935 ------------------------- src/plugins/platforms/vnc/qvncserver.h | 533 ------- src/plugins/platforms/vnc/vnc.pro | 22 - 8 files changed, 3161 deletions(-) delete mode 100644 src/plugins/platforms/vnc/main.cpp delete mode 100644 src/plugins/platforms/vnc/qvnccursor.cpp delete mode 100644 src/plugins/platforms/vnc/qvnccursor.h delete mode 100644 src/plugins/platforms/vnc/qvncintegration.cpp delete mode 100644 src/plugins/platforms/vnc/qvncintegration.h delete mode 100644 src/plugins/platforms/vnc/qvncserver.cpp delete mode 100644 src/plugins/platforms/vnc/qvncserver.h delete mode 100644 src/plugins/platforms/vnc/vnc.pro (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/vnc/main.cpp b/src/plugins/platforms/vnc/main.cpp deleted file mode 100644 index 7ec780af53..0000000000 --- a/src/plugins/platforms/vnc/main.cpp +++ /dev/null @@ -1,73 +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 -#include - -QT_BEGIN_NAMESPACE - -class QVNCIntegrationPlugin : public QPlatformIntegrationPlugin -{ -public: - QStringList keys() const; - QPlatformIntegration *create(const QString&, const QStringList &); -}; - -QStringList QVNCIntegrationPlugin::keys() const -{ - QStringList list; - list << "VNC"; - return list; -} - -QPlatformIntegration* QVNCIntegrationPlugin::create(const QString& system, const QStringList& paramList) -{ - Q_UNUSED(paramList); - if (system.toLower() == "vnc") - return new QVNCIntegration(paramList); - - return 0; -} - -Q_EXPORT_PLUGIN2(vnc, QVNCIntegrationPlugin) - -QT_END_NAMESPACE 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 -#include -#include -#include -#include - -#include - -#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 -#include -#include - -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 -#include -#include - -#include -#include - -#include -#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(cursor)); -} - -QVNCDirtyMap *QVNCScreen::dirtyMap() -{ - return d_ptr->dirty; -} - -QRegion QVNCScreen::doRedraw() -{ - QRegion touched; - touched = QFbScreen::doRedraw(); - - QVector 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=x - set the display width and height"; - qWarning() << " defaults to" << defaultWidth() << "x" << defaultHeight(); - qWarning() << " display= - set the VNC display port to ID + 5900"; - qWarning() << " defaults to" << defaultDisplay(); - qWarning() << " offset=x - 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(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::const_iterator i = mScreens.constBegin(); - QList::const_iterator end = mScreens.constEnd(); - QFbScreen *screen; - while (i != end) { - screen = static_cast(*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(mScreens.at(screen)); - for(int i = 0; i < mScreens.size(); i++) { - QVNCScreen *oldScreen = qobject_cast(mScreens.at(i)); - if (oldScreen->windowStack.contains(static_cast(window->platformWindow()))) { - oldScreen->removeWindow(static_cast(window->platformWindow())); - break; - } - } - window->platformWindow()->setGeometry(window->geometry()); // this should be unified elsewhere - newScreen->addWindow(static_cast(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 -#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 screens() const { return mScreens; } - - bool isVirtualDesktop() { return virtualDesktop; } - void moveToScreen(QWidget *window, int screen); - - QPlatformFontDatabase *fontDatabase() const; - -private: - QVNCScreen *mPrimaryScreen; - QList 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 -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include - - -#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_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(this); - break; -#endif -#ifdef QT_QWS_DEPTH_12 - case 12: - encoder = new QRfbHextileEncoder(this); - break; -#endif -#ifdef QT_QWS_DEPTH_15 - case 15: - encoder = new QRfbHextileEncoder(this); - break; -#endif -#ifdef QT_QWS_DEPTH_16 - case 16: - encoder = new QRfbHextileEncoder(this); - break; -#endif -#ifdef QT_QWS_DEPTH_18 - case 18: - encoder = new QRfbHextileEncoder(this); - break; -#endif -#ifdef QT_QWS_DEPTH_24 - case 24: - encoder = new QRfbHextileEncoder(this); - break; -#endif -#ifdef QT_QWS_DEPTH_32 - case 32: - encoder = new QRfbHextileEncoder(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(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 -bool QRfbSingleColorHextile::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(data); - if ((data8[0] & 0xf) != (data8[0] >> 4)) - return false; - width /= 2; - } // fallthrough - case 8: { - const quint8 *data8 = reinterpret_cast(data); - if (data8[0] != data8[1]) - return false; - width /= 2; - } // fallthrough - case 12: - case 15: - case 16: { - const quint16 *data16 = reinterpret_cast(data); - if (data16[0] != data16[1]) - return false; - width /= 2; - } // fallthrough - case 18: - case 24: - case 32: { - const quint32 *data32 = reinterpret_cast(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(data)[0]; - encoder->newBg |= (color != encoder->bg); - encoder->bg = color; - return true; -} - -template -void QRfbSingleColorHextile::write(QTcpSocket *socket) const -{ - if (true || encoder->newBg) { - const int bpp = encoder->server->clientBytesPerPixel(); - const int padding = 3; - QVarLengthArray buffer(padding + 1 + bpp); - buffer[padding] = 2; // BackgroundSpecified - encoder->server->convertPixels(buffer.data() + padding + 1, - reinterpret_cast(&encoder->bg), - 1); - socket->write(buffer.data() + padding, bpp + 1); -// encoder->newBg = false; - } else { - char subenc = 0; - socket->write(&subenc, 1); - } -} - -template -bool QRfbDualColorHextile::read(const uchar *data, - int width, int height, int stride) -{ - const SRC *ptr = reinterpret_cast(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(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 -void QRfbDualColorHextile::write(QTcpSocket *socket) const -{ - const int bpp = encoder->server->clientBytesPerPixel(); - const int padding = 3; - QVarLengthArray 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 -void QRfbDualColorHextile::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 -inline void QRfbMultiColorHextile::setColor(SRC color) -{ - encoder->server->convertPixels(reinterpret_cast(rect(numRects)), - (const char*)&color, 1); -} - -template -inline bool QRfbMultiColorHextile::beginRect() -{ - if ((rects.size() + bpp + 2) > maxRectsSize) - return false; - rects.resize(rects.size() + bpp + 2); - return true; -} - -template -inline void QRfbMultiColorHextile::endRect() -{ - setHeight(numRects, 1); - ++numRects; -} - -template -bool QRfbMultiColorHextile::read(const uchar *data, - int width, int height, int stride) -{ - const SRC *ptr = reinterpret_cast(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 -void QRfbMultiColorHextile::write(QTcpSocket *socket) const -{ - const int padding = 3; - QVarLengthArray 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(buffer.data() + n), - reinterpret_cast(&encoder->bg), - 1); - n += bpp; -// encoder->newBg = false; - } - - buffer[n] = numRects; - n += sizeof(numRects); - - socket->write(reinterpret_cast(buffer.data() + padding), - n - padding); - socket->write(reinterpret_cast(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(src); - quint32 *dst32 = reinterpret_cast(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(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(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(src)); - r = qRed(p); - g = qGreen(p); - b = qBlue(p); - src += sizeof(qrgb555); - break; - } -#endif - case 16: { - quint16 p = *reinterpret_cast(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(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(src)); - r = qRed(p); - g = qGreen(p); - b = qBlue(p); - src += sizeof(qrgb888); - break; - } -#endif - case 32: { - quint32 p = *reinterpret_cast(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 -void QVNCDirtyMapOptimized::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 -QRfbHextileEncoder::QRfbHextileEncoder(QVNCServer *s) - : QRfbEncoder(s), - singleColorHextile(this), dualColorHextile(this), multiColorHextile(this) -{ -} - -/* - \internal - Send dirty rects using hextile encoding. -*/ -template -void QRfbHextileEncoder::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 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(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 -#include -#include -#include - -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 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 QRfbHextileEncoder; - -template -class QRfbSingleColorHextile -{ -public: - QRfbSingleColorHextile(QRfbHextileEncoder *e) : encoder(e) {} - bool read(const uchar *data, int width, int height, int stride); - void write(QTcpSocket *socket) const; - -private: - QRfbHextileEncoder *encoder; -}; - -template -class QRfbDualColorHextile -{ -public: - QRfbDualColorHextile(QRfbHextileEncoder *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 *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 QRfbMultiColorHextile -{ -public: - QRfbMultiColorHextile(QRfbHextileEncoder *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 rects; - - quint8 bpp; - quint8 numRects; - QRfbHextileEncoder *encoder; -}; - -template -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 singleColorHextile; - QRfbDualColorHextile dualColorHextile; - QRfbMultiColorHextile multiColorHextile; - - SRC bg; - SRC fg; - bool newBg; - bool newFg; - - friend class QRfbSingleColorHextile; - friend class QRfbDualColorHextile; - friend class QRfbMultiColorHextile; -}; - -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 -- cgit v1.2.3 From 91752c43b8d7880a139d2bc7555571700a638cc9 Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Tue, 13 Mar 2012 17:46:22 +0100 Subject: Add new plugin metadata description and eglfs.json file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia594c18ba24e5fccf9fa59b9be6efcbeae00fad6 Reviewed-by: Girish Ramakrishnan Reviewed-by: Samuel Rødal --- src/plugins/platforms/eglfs/eglfs.json | 3 +++ src/plugins/platforms/eglfs/eglfs.pro | 6 ++++-- src/plugins/platforms/eglfs/main.cpp | 6 ++++-- 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 src/plugins/platforms/eglfs/eglfs.json (limited to 'src/plugins/platforms') 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" -- cgit v1.2.3 From cad51669d83ff649fae70842abf095acb5b72abc Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Tue, 13 Mar 2012 21:00:57 +0100 Subject: Remove QtWidgets dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove references to libQtOpenGL, and use QGuiApplication instead of QApplication Change-Id: If8f652223492cf758175a260c27b687f3af1c4ad Reviewed-by: Samuel Rødal --- src/plugins/platforms/xlib/qglxintegration.cpp | 1 - src/plugins/platforms/xlib/qxlibwindow.cpp | 10 ++++++---- src/plugins/platforms/xlib/xlib.pro | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/plugins/platforms') 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 #include -#include #include "qxlibwindow.h" #include "qxlibscreen.h" 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 #include -#include +#include +#include #include //#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 -- cgit v1.2.3 From 7e3c632e96dbbd6f577c2ba98464a54176c5b7b0 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 2 Mar 2012 12:17:24 +0100 Subject: Port QMacPrintEngine and QCoreGraphicsPaintEngine from Qt 4 to Qt 5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copy qprintengine_mac_p.h, qprintengine_mac.mm, qpaintengine_mac_p.h, and qpaintengine_mac.cpp (as qpaintengine_mac.mm) from src/gui/painting/ in the 4.8 branch of http://git.gitorious.org/qt/qt.git at commit e6bd33d4aef0e4538d7918e7ab130624c911b553. The following changes are necessary to port these files to the Qt 5 API: - The copyright notice on these files has been updated to match the header.LGPL template. - Fix #includes for qprintengine_mac* and qpaintengine_mac*, as some headers have moved in Qt 5. - Remove extern forward declarations for functions that no longer exist. - Remove friend declarations for classes/functions that are not part of the Cocoa platform plugin. - Remove QT_MAC_USE_COCOA blocks. Qt is always using Cocoa now, there is no need to keep the non-Cocoa code paths anymore. The QMacPrintEngine::shouldSuppressStatus() method was also removed, since it is no longer used. - Do not use Qt::UniteClip, it was removed in commit 01b72952c38b9193138eabdab6bdab632cd75ebd - Use QCocoaAutoReleasePool in qprintengine_mac.mm - Use QPlatformPrintSupport::convert*() functions in QMacPrintEngine, since we cannot use non-exported functions from QtPrintSupport in the Cocoa plugin. - Use qt_mac_image_to_cg_image() to convert QPixmap to CGImageRef. First convert QPixmap to QImage (cheap, since the Cocoa platform plugin uses QRasterPlatformPixmap), and then convert the QImage to CFImageRef using the existing helper function. - Copy qt_mac_cg_context() to the Cocoa platform plugin from qmacstyle_mac.mm, adding a note at each location about the duplication. - Add qt_mac_QRegionToHIMutableShape() helper. Adapt the Qt 4.x code for QRegion::toHIMutableShape(), and use this in QCoreGraphicsPaintEngine. - Add qt_mac_drawCGImage() and qt_mac_get_scalefactor() helper. These functions are copied directly from the 4.8 branch of http://git.gitorious.org/qt/qt.git at the same revision shown above. - Add qt_mac_create_imagemask() helper in qpaintengine_mac.cpp. This helper is based on the function with the same name from the 4.8 branch of http://git.gitorious.org/qt/qt.git at the same revision shown above. The correctness of the implementation has not yet been verified. Since these files use the QPrinter API from QtPrintSupport, the Cocoa plugin now needs to link to that library as well. Change-Id: I90b9bbe201327489ef9e1b3294e68e91ddda27bd Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/cocoa.pro | 6 +- src/plugins/platforms/cocoa/qcocoahelpers.h | 7 + src/plugins/platforms/cocoa/qcocoahelpers.mm | 43 + src/plugins/platforms/cocoa/qpaintengine_mac.mm | 1788 ++++++++++++++++++++++ src/plugins/platforms/cocoa/qpaintengine_mac_p.h | 254 +++ src/plugins/platforms/cocoa/qprintengine_mac.mm | 823 ++++++++++ src/plugins/platforms/cocoa/qprintengine_mac_p.h | 157 ++ src/plugins/platforms/cocoa/qt_mac_p.h | 2 +- 8 files changed, 3078 insertions(+), 2 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qpaintengine_mac.mm create mode 100644 src/plugins/platforms/cocoa/qpaintengine_mac_p.h create mode 100644 src/plugins/platforms/cocoa/qprintengine_mac.mm create mode 100644 src/plugins/platforms/cocoa/qprintengine_mac_p.h (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index bd70a415d0..9aca393a10 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -32,6 +32,8 @@ OBJECTIVE_SOURCES += main.mm \ qmacmime.mm \ qcocoasystemsettings.mm \ qcocoainputcontext.mm \ + qpaintengine_mac.mm \ + qprintengine_mac.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -61,13 +63,15 @@ HEADERS += qcocoaintegration.h \ qmacmime.h \ qcocoasystemsettings.h \ qcocoainputcontext.h \ + qpaintengine_mac_p.h \ + qprintengine_mac_p.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/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index e5fe664731..5113aca3f7 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -76,6 +76,13 @@ 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 e41ddf4a9f..60590b966e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -132,6 +132,22 @@ 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 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()); @@ -538,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/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qcocoahelpers.h" + +#include + +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 shape = qt_mac_QRegionToHIMutableShape(rgn); + Q_ASSERT(!HIShapeIsEmpty(shape)); + HIShapeReplacePathInCGContext(shape, hd); + } else +#endif + { + QVector 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(paintDevice) + : 0); +} + +// Implemented for qt_mac_p.h +QMacCGContext::QMacCGContext(QPainter *p) +{ + QPaintEngine *pe = p->paintEngine(); + if (pe->type() == QPaintEngine::MacPrinter) + pe = static_cast(pe)->paintEngine(); + pe->syncState(); + context = 0; + if (pe->type() == QPaintEngine::CoreGraphics) + context = static_cast(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(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(malloc(nbytes)); + quint32 *sptr = reinterpret_cast(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 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(pdev); + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); + uint flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; + CGContextRef ret = 0; + + QPlatformPixmap *data = const_cast(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(static_cast(pdev)->macCGHandle()); + ///CGContextRetain(ret); + //return ret; + qDebug() << "qt_mac_cg_context: not implemented: Widget class"; + return 0; + } + return 0; +} + +inline static QCFType 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(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 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 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::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(d->pdev)->windowType() == Qt::Desktop) { + // ### need to do [qt_mac_window_for(static_cast(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; idrawPath(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 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 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(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 dataProvider = CGDataProviderCreateWithData(image, + static_cast(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 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(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(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 linedashes; + if (pen.style() == Qt::CustomDashLine) { + QVector 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(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(¤t.brush), + 1, domain, 4, 0, &callbacks); + + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); + if (bs == Qt::LinearGradientPattern) { + const QLinearGradient *linearGrad = static_cast(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(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 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..51b1de6e58 --- /dev/null +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -0,0 +1,823 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include + +#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(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 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(d->paintEngine)->d_func()->stackCount = 0; + static_cast(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(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 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( + const_cast(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 QMacPrintEnginePrivate::supportedResolutions() const +{ + Q_ASSERT_X(session, "QMacPrinterEngine::supportedResolutions", + "must have a valid printer session"); + UInt32 resCount; + QList 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 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 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]]; + session = static_cast([printInfo PMPrintSession]); + + PMPrinter printer; + if (session && PMSessionGetCurrentPrinter(session, &printer) == noErr) { + QList 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(); + } + } + + settings = static_cast([printInfo PMPrintSettings]); + format = static_cast([printInfo PMPageFormat]); + + QHash::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; + session = 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(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->session) + 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 printerList; + status = PMServerCreatePrinterList(kPMServerLocal, &printerList); + if (status == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i=0; i(const_cast(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 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->session && 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 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 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..38bce4ff67 --- /dev/null +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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 +#include +#include + +#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 &); +}; + +class QMacPrintEnginePrivate : public QPaintEnginePrivate +{ + Q_DECLARE_PUBLIC(QMacPrintEngine) +public: + QPrinter::PrinterMode mode; + QPrinter::PrinterState state; + QPrinter::Orientation orient; + NSPrintInfo *printInfo; + PMPageFormat format; + PMPrintSettings settings; + PMPrintSession session; + PMResolution resolution; + QString outputFilename; + bool fullPage; + QPaintEngine *paintEngine; + bool hasCustomPaperSize; + QSizeF customSize; + bool hasCustomPageMargins; + qreal leftMargin; + qreal topMargin; + qreal rightMargin; + qreal bottomMargin; + QHash valueCache; + QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), + orient(QPrinter::Portrait), printInfo(0), format(0), settings(0), + session(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 supportedResolutions() const; + inline bool isPrintSessionInitialized() const + { + return printInfo != 0; + } +}; + +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 *); -- cgit v1.2.3 From 4f246bceb5958cb7ae86d7c5d59c78cad25bdd56 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 29 Feb 2012 15:23:22 +0100 Subject: Add a QPlatformPrinterSupportPlugin for Cocoa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is used to create the actual QPrintEngine and to query the system about printer information. The QCocoaPrinterSupport actually lives in the Cocoa platform plugin, so the QCocoaPrinterSupportPlugin uses the createPlatformPrinterSupport() function in the QPlatformNativeInterface (since the latter is a QObject). This is done to avoid adding a printing related virtual function to QPlatformIntegration (since we have plans to do a new printing API in the future). Change-Id: I8bf9be668ff8ae1d07840e2af1e0846dc3299334 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/cocoa.pro | 2 + .../platforms/cocoa/qcocoanativeinterface.h | 15 +++ .../platforms/cocoa/qcocoanativeinterface.mm | 7 ++ src/plugins/platforms/cocoa/qcocoaprintersupport.h | 60 +++++++++++ .../platforms/cocoa/qcocoaprintersupport.mm | 116 +++++++++++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 src/plugins/platforms/cocoa/qcocoaprintersupport.h create mode 100644 src/plugins/platforms/cocoa/qcocoaprintersupport.mm (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 9aca393a10..c42932520f 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -34,6 +34,7 @@ OBJECTIVE_SOURCES += main.mm \ qcocoainputcontext.mm \ qpaintengine_mac.mm \ qprintengine_mac.mm \ + qcocoaprintersupport.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -65,6 +66,7 @@ HEADERS += qcocoaintegration.h \ qcocoainputcontext.h \ qpaintengine_mac_p.h \ qprintengine_mac_p.h \ + qcocoaprintersupport.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui RESOURCES += qcocoaresources.qrc diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index d277cb2964..2665768edc 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -43,6 +43,7 @@ #define QCOCOANATIVEINTERFACE_H #include +#include class QWidget; @@ -51,6 +52,20 @@ 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(); }; #endif // QCOCOANATIVEINTERFACE_H diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 443369df75..7767254e11 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 #include #include "qplatformwindow_qpa.h" @@ -66,3 +68,8 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS } return 0; } + +QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport() +{ + return new QCocoaPrinterSupport(); +} diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h new file mode 100644 index 0000000000..db473dfabb --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QCOCOAPRINTERSUPPORT_H +#define QCOCOAPRINTERSUPPORT_H + +#include + +class QCocoaPrinterSupport : public QPlatformPrinterSupport +{ +public: + QCocoaPrinterSupport(); + ~QCocoaPrinterSupport(); + + Q_DECL_OVERRIDE QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); + Q_DECL_OVERRIDE QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode); + Q_DECL_OVERRIDE QList supportedPaperSizes(const QPrinterInfo &) const; + + Q_DECL_OVERRIDE QList availablePrinters(); +}; + +#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 +#include + +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(printEngine); +} + +QList QCocoaPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const +{ + QList 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(const_cast(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 QCocoaPrinterSupport::availablePrinters() +{ + QList returnValue; + QCFType printerList; + if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i = 0; i < count; ++i) { + PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); + QString printerName = QCFString::toQString(PMPrinterGetName(printer)); + returnValue += QPlatformPrinterSupport::printerInfo(printerName, PMPrinterIsDefault(printer)); + } + } + return returnValue; +} -- cgit v1.2.3 From 7dde92d7d1639a1ea8bee39d5250bc58102dc4c8 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 5 Mar 2012 14:40:00 +0100 Subject: Don't keep PMPrint* state separate from NSPrintInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we need to use PMPrintSession, PMPrintSettings, and PMPageLayout, get these directly from the NSPrintInfo when needed. This avoids us needing to keep the settings in sync. The native dialogs can then only rely on getting a pointer to NSPrintInfo (to be done in a future commit). Change-Id: I4720284dcf999e454f86766b4291fbda7bf3c537 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 82 +++++++++++------------- src/plugins/platforms/cocoa/qprintengine_mac_p.h | 10 +-- 2 files changed, 43 insertions(+), 49 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 51b1de6e58..e432b12e67 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -73,8 +73,8 @@ bool QMacPrintEngine::begin(QPaintDevice *dev) 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) { + if (PMSessionValidatePrintSettings(d->session(), d->settings(), kPMDontWantBoolean) != noErr + || PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean) != noErr) { d->state = QPrinter::Error; return false; } @@ -84,14 +84,14 @@ bool QMacPrintEngine::begin(QPaintDevice *dev) QCFString(d->outputFilename), kCFURLPOSIXPathStyle, false); - if (PMSessionSetDestination(d->session, d->settings, kPMDestinationFile, + 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); + OSStatus status = PMSessionBeginCGDocumentNoDialog(d->session(), d->settings(), d->format()); if (status != noErr) { d->state = QPrinter::Error; return false; @@ -145,8 +145,8 @@ void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps) QCFType formats; PMPrinter printer; - if (PMSessionGetCurrentPrinter(session, &printer) == noErr - && PMSessionCreatePageFormatList(session, printer, &formats) == noErr) { + if (PMSessionGetCurrentPrinter(session(), &printer) == noErr + && PMSessionCreatePageFormatList(session(), printer, &formats) == noErr) { CFIndex total = CFArrayGetCount(formats); PMPageFormat tmp; PMRect paper; @@ -157,10 +157,10 @@ void QMacPrintEnginePrivate::setPaperSize(QPrinter::PaperSize ps) 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); + 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) { + if (PMSessionValidatePageFormat(session(), format(), kPMDontWantBoolean) != noErr) { // Don't know, warn for the moment. qWarning("QMacPrintEngine, problem setting format and resolution for this page size"); } @@ -175,19 +175,19 @@ QPrinter::PaperSize QMacPrintEnginePrivate::paperSize() const if (hasCustomPaperSize) return QPrinter::Custom; PMRect paper; - PMGetUnadjustedPaperRect(format, &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 QMacPrintEnginePrivate::supportedResolutions() const { - Q_ASSERT_X(session, "QMacPrinterEngine::supportedResolutions", + Q_ASSERT_X(printInfo, "QMacPrinterEngine::supportedResolutions", "must have a valid printer session"); UInt32 resCount; QList resolutions; PMPrinter printer; - if (PMSessionGetCurrentPrinter(session, &printer) == noErr) { + if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { PMResolution res; OSStatus status = PMPrinterGetPrinterResolutionCount(printer, &resCount); if (status == kPMNotImplemented) { @@ -228,8 +228,7 @@ bool QMacPrintEngine::newPage() { Q_D(QMacPrintEngine); Q_ASSERT(d->state == QPrinter::Active); - OSStatus err = - PMSessionEndPageNoDialog(d->session); + OSStatus err = PMSessionEndPageNoDialog(d->session()); if (err != noErr) { if (err == kPMCancel) { // User canceled, we need to abort! @@ -302,7 +301,7 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const val -= qRound(margins.at(0).toDouble() + margins.at(2).toDouble()); } } else { - val = qt_get_PDMWidth(d->format, property(PPK_FullPage).toBool(), d->resolution); + val = qt_get_PDMWidth(d->format(), property(PPK_FullPage).toBool(), d->resolution); } break; case QPaintDevice::PdmHeight: @@ -315,7 +314,7 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const val -= qRound(margins.at(1).toDouble() + margins.at(3).toDouble()); } } else { - val = qt_get_PDMHeight(d->format, property(PPK_FullPage).toBool(), d->resolution); + val = qt_get_PDMHeight(d->format(), property(PPK_FullPage).toBool(), d->resolution); } break; case QPaintDevice::PdmWidthMM: @@ -329,9 +328,9 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const case QPaintDevice::PdmPhysicalDpiX: case QPaintDevice::PdmPhysicalDpiY: { PMPrinter printer; - if (PMSessionGetCurrentPrinter(d->session, &printer) == noErr) { + if (PMSessionGetCurrentPrinter(d->session(), &printer) == noErr) { PMResolution resolution; - PMPrinterGetOutputResolution(printer, d->settings, &resolution); + PMPrinterGetOutputResolution(printer, d->settings(), &resolution); val = (int)resolution.vRes; break; } @@ -371,10 +370,9 @@ void QMacPrintEnginePrivate::initialize() QCocoaAutoReleasePool pool; printInfo = [[NSPrintInfo alloc] initWithDictionary:[NSDictionary dictionary]]; - session = static_cast([printInfo PMPrintSession]); PMPrinter printer; - if (session && PMSessionGetCurrentPrinter(session, &printer) == noErr) { + if (printInfo && PMSessionGetCurrentPrinter(session(), &printer) == noErr) { QList resolutions = supportedResolutions(); if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { if (resolutions.count() > 1 && mode == QPrinter::HighResolution) { @@ -395,9 +393,6 @@ void QMacPrintEnginePrivate::initialize() } } - settings = static_cast([printInfo PMPrintSettings]); - format = static_cast([printInfo PMPageFormat]); - QHash::const_iterator propC; for (propC = valueCache.constBegin(); propC != valueCache.constEnd(); propC++) { q->setProperty(propC.key(), propC.value()); @@ -406,11 +401,10 @@ void QMacPrintEnginePrivate::initialize() void QMacPrintEnginePrivate::releaseSession() { - PMSessionEndPageNoDialog(session); - PMSessionEndDocumentNoDialog(session); + PMSessionEndPageNoDialog(session()); + PMSessionEndDocumentNoDialog(session()); [printInfo release]; printInfo = 0; - session = 0; } bool QMacPrintEnginePrivate::newPage_helper() @@ -418,7 +412,7 @@ bool QMacPrintEnginePrivate::newPage_helper() Q_Q(QMacPrintEngine); Q_ASSERT(state == QPrinter::Active); - if (PMSessionError(session) != noErr) { + if (PMSessionError(session()) != noErr) { q->abort(); return false; } @@ -430,7 +424,7 @@ bool QMacPrintEnginePrivate::newPage_helper() while (cgEngine->d_func()->stackCount > 0) cgEngine->d_func()->restoreGraphicsState(); - OSStatus status = PMSessionBeginPageNoDialog(session, format, 0); + OSStatus status = PMSessionBeginPageNoDialog(session(), format(), 0); if (status != noErr) { state = QPrinter::Error; return false; @@ -441,7 +435,7 @@ bool QMacPrintEnginePrivate::newPage_helper() CGContextRef cgContext; OSStatus err = noErr; - err = PMSessionGetCGGraphicsContext(session, &cgContext); + err = PMSessionGetCGGraphicsContext(session(), &cgContext); if (err != noErr) { qWarning("QMacPrintEngine::newPage: Cannot retrieve CoreGraphics context: %ld", long(err)); state = QPrinter::Error; @@ -550,7 +544,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va Q_D(QMacPrintEngine); d->valueCache.insert(key, value); - if (!d->session) + if (!d->printInfo) return; switch (key) { @@ -571,7 +565,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_Resolution: { PMPrinter printer; UInt32 count; - if (PMSessionGetCurrentPrinter(d->session, &printer) != noErr) + if (PMSessionGetCurrentPrinter(d->session(), &printer) != noErr) break; if (PMPrinterGetPrinterResolutionCount(printer, &count) != noErr) break; @@ -593,7 +587,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va } } } - PMSessionValidatePageFormat(d->session, d->format, kPMDontWantBoolean); + PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); break; } @@ -602,7 +596,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va break; case PPK_CopyCount: // fallthrough case PPK_NumberOfCopies: - PMSetCopies(d->settings, value.toInt(), false); + PMSetCopies(d->settings(), value.toInt(), false); break; case PPK_Orientation: { if (d->state == QPrinter::Active) { @@ -613,8 +607,8 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va 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); + PMSetOrientation(d->format(), o, false); + PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); } break; } case PPK_OutputFileName: @@ -634,7 +628,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va PMPrinter printer = static_cast(const_cast(CFArrayGetValueAtIndex(printerList, i))); QString name = QCFString::toQString(PMPrinterGetName(printer)); if (name == value.toString()) { - status = PMSessionSetCurrentPMPrinter(d->session, printer); + status = PMSessionSetCurrentPMPrinter(d->session(), printer); printerNameSet = true; break; } @@ -653,7 +647,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_CustomPaperSize: { PMOrientation orientation; - PMGetOrientation(d->format, &orientation); + PMGetOrientation(d->format(), &orientation); d->hasCustomPaperSize = true; d->customSize = value.toSizeF(); if (orientation != kPMPortrait) @@ -682,7 +676,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const Q_D(const QMacPrintEngine); QVariant ret; - if (!d->session && d->valueCache.contains(key)) + if (!d->printInfo && d->valueCache.contains(key)) return *d->valueCache.find(key); switch (key) { @@ -704,7 +698,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_CopyCount: { UInt32 copies = 1; - PMGetCopies(d->settings, &copies); + PMGetCopies(d->settings(), &copies); ret = (uint) copies; break; } @@ -713,7 +707,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const break; case PPK_Orientation: PMOrientation orientation; - PMGetOrientation(d->format, &orientation); + PMGetOrientation(d->format(), &orientation); ret = orientation == kPMPortrait ? QPrinter::Portrait : QPrinter::Landscape; break; case PPK_OutputFileName: @@ -741,8 +735,8 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const -qRound(margins.at(2).toDouble() * hRatio), -qRound(margins.at(3).toDouble()) * vRatio); } - } else if (PMGetAdjustedPageRect(d->format, ¯ect) == noErr - && PMGetAdjustedPaperRect(d->format, &macpaper) == noErr) + } 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), @@ -770,7 +764,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const 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) { + } 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()); @@ -779,7 +773,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const break; } case PPK_PrinterName: { PMPrinter printer; - OSStatus status = PMSessionGetCurrentPrinter(d->session, &printer); + OSStatus status = PMSessionGetCurrentPrinter(d->session(), &printer); if (status != noErr) qWarning("QMacPrintEngine::printerName: Failed getting current PMPrinter: %ld", long(status)); if (printer) @@ -804,7 +798,7 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const } else { PMPaperMargins paperMargins; PMPaper paper; - PMGetPageFormatPaper(d->format, &paper); + PMGetPageFormatPaper(d->format(), &paper); PMPaperGetMargins(paper, &paperMargins); margins << paperMargins.left << paperMargins.top << paperMargins.right << paperMargins.bottom; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index 38bce4ff67..c690a5733c 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -118,9 +118,6 @@ public: QPrinter::PrinterState state; QPrinter::Orientation orient; NSPrintInfo *printInfo; - PMPageFormat format; - PMPrintSettings settings; - PMPrintSession session; PMResolution resolution; QString outputFilename; bool fullPage; @@ -134,8 +131,7 @@ public: qreal bottomMargin; QHash valueCache; QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle), - orient(QPrinter::Portrait), printInfo(0), format(0), settings(0), - session(0), paintEngine(0), + orient(QPrinter::Portrait), printInfo(0), paintEngine(0), hasCustomPaperSize(false), hasCustomPageMargins(false) {} ~QMacPrintEnginePrivate(); void initialize(); @@ -148,6 +144,10 @@ public: { return printInfo != 0; } + + PMPageFormat format() const { return static_cast([printInfo PMPageFormat]); } + PMPrintSession session() const { return static_cast([printInfo PMPrintSession]); } + PMPrintSettings settings() const { return static_cast([printInfo PMPrintSettings]); } }; QT_END_NAMESPACE -- cgit v1.2.3 From 86fc4aa2b661101d392ff8ff832e3cb0e4ce8d91 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 5 Mar 2012 14:42:53 +0100 Subject: Add method to get NSPrintInfo* from QPrintEngine in Cocoa plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an invokable method that takes the QPrintEngine (which will always be a QMacPrintEngine) and return the NSPrintInfo* from the QMacPrintEnginePrivate. This will be used by the native dialogs in QtPrintSupport to get/set printer settings. Change-Id: If1e49027e8f0d505656db51be1f40a23f60e8e57 Reviewed-by: Mark Brand Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoanativeinterface.h | 5 +++++ src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 8 ++++++++ src/plugins/platforms/cocoa/qprintengine_mac_p.h | 3 +++ 3 files changed, 16 insertions(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 2665768edc..8856e90cf3 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -66,6 +66,11 @@ private: 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 7767254e11..29c2e58959 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -52,6 +52,8 @@ #include "qopenglcontext.h" #include +#include "qprintengine_mac_p.h" + void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { if (!window->handle()) { @@ -73,3 +75,9 @@ QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport() { return new QCocoaPrinterSupport(); } + +void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine) +{ + QMacPrintEngine *macPrintEngine = static_cast(printEngine); + return macPrintEngine->d_func()->printInfo; +} diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index c690a5733c..2d37b43dfa 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -108,6 +108,9 @@ public: 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 -- cgit v1.2.3 From 7ae2ea54269654736a6b88ff090a0f5a8cbe5eac Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Wed, 14 Mar 2012 14:11:28 +0100 Subject: Remove unmaintained and broken uikit platform plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was no development done to make this working on Qt 5 Change-Id: Ia08d53c6680a65cb1e60a30e55caa992eaa54bc7 Reviewed-by: Eike Ziller Reviewed-by: Girish Ramakrishnan Reviewed-by: Jørgen Lind --- src/plugins/platforms/uikit/README | 45 -- .../platforms/uikit/examples/qmltest/main.mm | 78 ---- .../platforms/uikit/examples/qmltest/qml/main.qml | 112 ----- .../moc_qmlapplicationviewer.cpp | 110 ----- .../qmlapplicationviewer/qmlapplicationviewer.cpp | 179 -------- .../qmlapplicationviewer/qmlapplicationviewer.h | 80 ---- .../uikit/examples/qmltest/qmltest-Info.plist | 28 -- .../qmltest/qmltest.xcodeproj/project.pbxproj | 491 --------------------- .../uikit/examples/qmltest/qmltest_Prefix.pch | 8 - src/plugins/platforms/uikit/main.mm | 74 ---- src/plugins/platforms/uikit/quikiteventloop.h | 72 --- src/plugins/platforms/uikit/quikiteventloop.mm | 174 -------- src/plugins/platforms/uikit/quikitintegration.h | 72 --- src/plugins/platforms/uikit/quikitintegration.mm | 104 ----- src/plugins/platforms/uikit/quikitscreen.h | 75 ---- src/plugins/platforms/uikit/quikitscreen.mm | 84 ---- .../platforms/uikit/quikitsoftwareinputhandler.h | 61 --- src/plugins/platforms/uikit/quikitwindow.h | 131 ------ src/plugins/platforms/uikit/quikitwindow.mm | 392 ---------------- src/plugins/platforms/uikit/quikitwindowsurface.h | 64 --- src/plugins/platforms/uikit/quikitwindowsurface.mm | 133 ------ src/plugins/platforms/uikit/uikit.pro | 27 -- 22 files changed, 2594 deletions(-) delete mode 100644 src/plugins/platforms/uikit/README delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/main.mm delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/qml/main.qml delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist delete mode 100755 src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj delete mode 100644 src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch delete mode 100644 src/plugins/platforms/uikit/main.mm delete mode 100644 src/plugins/platforms/uikit/quikiteventloop.h delete mode 100644 src/plugins/platforms/uikit/quikiteventloop.mm delete mode 100644 src/plugins/platforms/uikit/quikitintegration.h delete mode 100644 src/plugins/platforms/uikit/quikitintegration.mm delete mode 100644 src/plugins/platforms/uikit/quikitscreen.h delete mode 100644 src/plugins/platforms/uikit/quikitscreen.mm delete mode 100644 src/plugins/platforms/uikit/quikitsoftwareinputhandler.h delete mode 100644 src/plugins/platforms/uikit/quikitwindow.h delete mode 100644 src/plugins/platforms/uikit/quikitwindow.mm delete mode 100644 src/plugins/platforms/uikit/quikitwindowsurface.h delete mode 100644 src/plugins/platforms/uikit/quikitwindowsurface.mm delete mode 100644 src/plugins/platforms/uikit/uikit.pro (limited to 'src/plugins/platforms') 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 - -#include "qmlapplicationviewer/qmlapplicationviewer.h" - -#include -#include -#include - -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 ." -#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(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 -#include -#include -#include -#include -#include - -#if defined(QMLJSDEBUGGER) -#include -#endif - -#if defined(QMLJSDEBUGGER) && !defined(NO_JSDEBUGGER) -#include -#endif -#if defined(QMLJSDEBUGGER) && !defined(NO_QMLOBSERVER) -#include -#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(128); -// break; -// case ScreenOrientationLockLandscape: -// attribute = static_cast(129); -// break; -// default: -// case ScreenOrientationAuto: -// attribute = static_cast(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 - -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 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - - CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:rfc1034identifier} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - - 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 = ""; }; - 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 = ""; }; - 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 = ""; }; - 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 = ""; }; - D3CAA7C713264AAD008BB877 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; - D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_qmlapplicationviewer.cpp; path = qmlapplicationviewer/moc_qmlapplicationviewer.cpp; sourceTree = ""; }; - D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qmlapplicationviewer.cpp; path = qmlapplicationviewer/qmlapplicationviewer.cpp; sourceTree = ""; }; - D3CAA7E513264EA6008BB877 /* qmlapplicationviewer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qmlapplicationviewer.h; path = qmlapplicationviewer/qmlapplicationviewer.h; sourceTree = ""; }; - 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 = ""; - }; - 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { - isa = PBXGroup; - children = ( - 29B97315FDCFA39411CA2CEA /* Other Sources */, - 29B97317FDCFA39411CA2CEA /* Resources */, - D3CAA7E213264E8C008BB877 /* QMLApplicationViewer */, - 29B97323FDCFA39411CA2CEA /* Frameworks */, - 19C28FACFE9D520D11CA2CBB /* Products */, - ); - name = CustomTemplate; - sourceTree = ""; - }; - 29B97315FDCFA39411CA2CEA /* Other Sources */ = { - isa = PBXGroup; - children = ( - 32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */, - D3CAA7C713264AAD008BB877 /* main.mm */, - ); - name = "Other Sources"; - sourceTree = ""; - }; - 29B97317FDCFA39411CA2CEA /* Resources */ = { - isa = PBXGroup; - children = ( - D3CAA88E13265310008BB877 /* qml */, - D3CAA836132652E5008BB877 /* fonts */, - 8D1107310486CEB800E47090 /* qmltest-Info.plist */, - ); - name = Resources; - sourceTree = ""; - }; - 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 = ""; - }; - D3CAA7E213264E8C008BB877 /* QMLApplicationViewer */ = { - isa = PBXGroup; - children = ( - D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */, - D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */, - D3CAA7E513264EA6008BB877 /* qmlapplicationviewer.h */, - ); - name = QMLApplicationViewer; - sourceTree = ""; - }; - 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 = ""; - }; - 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 = ""; - }; -/* 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 - #import -#endif diff --git a/src/plugins/platforms/uikit/main.mm b/src/plugins/platforms/uikit/main.mm deleted file mode 100644 index db413c0775..0000000000 --- a/src/plugins/platforms/uikit/main.mm +++ /dev/null @@ -1,74 +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 - -#include -#include "quikitintegration.h" - -QT_BEGIN_NAMESPACE - -class QUIKitIntegrationPlugin : public QPlatformIntegrationPlugin -{ -public: - QStringList keys() const; - QPlatformIntegration *create(const QString&, const QStringList&); -}; - -QStringList QUIKitIntegrationPlugin::keys() const -{ - QStringList list; - list << "UIKit"; - return list; -} - -QPlatformIntegration * QUIKitIntegrationPlugin::create(const QString& system, const QStringList& paramList) -{ - Q_UNUSED(paramList); - if (system.toLower() == "uikit") - return new QUIKitIntegration; - - return 0; -} - -Q_EXPORT_PLUGIN2(UIKit, QUIKitIntegrationPlugin) - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikiteventloop.h b/src/plugins/platforms/uikit/quikiteventloop.h deleted file mode 100644 index e7f503c42a..0000000000 --- a/src/plugins/platforms/uikit/quikiteventloop.h +++ /dev/null @@ -1,72 +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 QUIKITEVENTLOOP_H -#define QUIKITEVENTLOOP_H - -#include "quikitsoftwareinputhandler.h" - -#include -#include - -@class EventLoopHelper; -@class NSTimer; - -QT_BEGIN_NAMESPACE - -class QUIKitEventLoop : public QPlatformEventLoopIntegration -{ -public: - QUIKitEventLoop(); - ~QUIKitEventLoop(); - - void startEventLoop(); - void quitEventLoop(); - void qtNeedsToProcessEvents(); - - EventLoopHelper *mHelper; - NSTimer *mTimer; - QUIKitSoftwareInputHandler *mInputHandler; -}; - -QT_END_NAMESPACE - -#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 - -#include -#include -#include - -@interface QUIKitAppDelegate : NSObject { -} -@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(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(obj); - if (widget) { - QUIKitWindow *platformWindow = static_cast(widget->platformWindow()); - [platformWindow->nativeView() becomeFirstResponder]; - return true; - } - } else if (event->type() == QEvent::CloseSoftwareInputPanel) { - QWidget *widget = qobject_cast(obj); - if (widget) { - QUIKitWindow *platformWindow = static_cast(widget->platformWindow()); - [platformWindow->nativeView() resignFirstResponder]; - return true; - } - } - return false; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitintegration.h b/src/plugins/platforms/uikit/quikitintegration.h deleted file mode 100644 index 21ef9efb29..0000000000 --- a/src/plugins/platforms/uikit/quikitintegration.h +++ /dev/null @@ -1,72 +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 QPLATFORMINTEGRATION_UIKIT_H -#define QPLATFORMINTEGRATION_UIKIT_H - -#include - -QT_BEGIN_NAMESPACE - -class QUIKitIntegration : public QPlatformIntegration -{ -public: - QUIKitIntegration(); - ~QUIKitIntegration(); - - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; - QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; - QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; - - QList screens() const; - - QPlatformFontDatabase *fontDatabase() const; - - QPlatformEventLoopIntegration *createEventLoopIntegration() const; - -private: - QList mScreens; -}; - -QT_END_NAMESPACE - -#endif - 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 - -#include - -#include - -#include - -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 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.h b/src/plugins/platforms/uikit/quikitscreen.h deleted file mode 100644 index e53589b2c7..0000000000 --- a/src/plugins/platforms/uikit/quikitscreen.h +++ /dev/null @@ -1,75 +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 QUIKITSCREEN_H -#define QUIKITSCREEN_H - -#include - -#include - -QT_BEGIN_NAMESPACE - -class QUIKitScreen : public QPlatformScreen -{ -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; } - - UIScreen *uiScreen() const; - -private: - QRect m_geometry; - int m_depth; - QImage::Format m_format; - QSizeF m_physicalSize; - int m_index; -}; - -QT_END_NAMESPACE - - -#endif 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 - -#include - -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/quikitsoftwareinputhandler.h b/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h deleted file mode 100644 index b4627c15ff..0000000000 --- a/src/plugins/platforms/uikit/quikitsoftwareinputhandler.h +++ /dev/null @@ -1,61 +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 QUIKITSOFTWAREINPUTHANDLER_H -#define QUIKITSOFTWAREINPUTHANDLER_H - -#include - -QT_BEGIN_NAMESPACE - -class QUIKitSoftwareInputHandler : public QObject -{ - Q_OBJECT - -public: - bool eventFilter(QObject *obj, QEvent *event); -}; - -QT_END_NAMESPACE - -#endif 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 - -#import -#import -#import -#import -#import -#import - -@interface EAGLView : UIView -{ - 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 - -#include "quikitwindow.h" - -#include "quikitscreen.h" - -#include -#include -#include -#include -#include - -#include - -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(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.h b/src/plugins/platforms/uikit/quikitwindowsurface.h deleted file mode 100644 index 6ea1b2ad3c..0000000000 --- a/src/plugins/platforms/uikit/quikitwindowsurface.h +++ /dev/null @@ -1,64 +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 QUIKITWINDOWSURFACE_H -#define QUIKITWINDOWSURFACE_H - -#include - -QT_BEGIN_NAMESPACE - -class QUIKitWindowSurface : public QWindowSurface -{ -public: - QUIKitWindowSurface(QWidget *window); - - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - WindowSurfaceFeatures features() const; - -private: - QPaintDevice *mPaintDevice; -}; - -QT_END_NAMESPACE - -#endif // QUIKITWINDOWSURFACE_H 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 -#include - -#include - -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(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 -- cgit v1.2.3 From e8a7e926cf99906d3157a031e1a56fb23fe3e42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 15 Mar 2012 10:18:27 +0100 Subject: Fixed incorrect reporting of child window geometry in xcb plugin. We should only query the position for top levels, otherwise trust the position given in the event. Change-Id: Ic29f25983af3e2c2f27eeb527c08069435ac938c Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 54b3b214b1..4de3734c22 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1307,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); -- cgit v1.2.3 From 99b8b647e3623325a8bfe39bea66c71c5467cdbc Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Mon, 12 Mar 2012 12:07:51 +0100 Subject: Implement cocoa clipboard support. Add QCoccoaClipboard which wraps the existing QMacPasteboard implementation. Remove unused QClipboard integration code from qmacclipboard.mm Change mime type cleanup from using qAddPostRoutine to using an explicit call to destroyMimieTypes in the cocoa platform integration destructor. This is necessary to ensure cleanup happens in the correct order on app shutdown. Change-Id: Ief0e0d996b04c8e84e9fd2cd3a17fb5bd73bb761 Reviewed-by: Bradley T. Hughes --- src/plugins/platforms/cocoa/cocoa.pro | 2 + src/plugins/platforms/cocoa/qcocoaclipboard.h | 70 ++++++++++++++++ src/plugins/platforms/cocoa/qcocoaclipboard.mm | 93 +++++++++++++++++++++ src/plugins/platforms/cocoa/qcocoaintegration.h | 3 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 14 +++- src/plugins/platforms/cocoa/qmacclipboard.mm | 100 ----------------------- src/plugins/platforms/cocoa/qmacmime.h | 3 +- src/plugins/platforms/cocoa/qmacmime.mm | 22 ++--- 8 files changed, 194 insertions(+), 113 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoaclipboard.h create mode 100644 src/plugins/platforms/cocoa/qcocoaclipboard.mm (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index c42932520f..e861f48e7b 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -27,6 +27,7 @@ OBJECTIVE_SOURCES += main.mm \ qcocoafiledialoghelper.mm \ qcocoafontdialoghelper.mm \ qcocoacursor.mm \ + qcocoaclipboard.mm \ qcocoadrag.mm \ qmacclipboard.mm \ qmacmime.mm \ @@ -59,6 +60,7 @@ HEADERS += qcocoaintegration.h \ qcocoafiledialoghelper.h \ qcocoafontdialoghelper.h \ qcocoacursor.h \ + qcocoaclipboard.h \ qcocoadrag.h \ qmacclipboard.h \ qmacmime.h \ diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h new file mode 100644 index 0000000000..27505058bf --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 QCOCOACLIPBOARD_H +#define QCOCOACLIPBOARD_H + +#include +#include "qmacclipboard.h" +#include + +QT_BEGIN_NAMESPACE + +class QCocoaClipboard : public QPlatformClipboard +{ +public: + QCocoaClipboard(); + + 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: + QScopedPointer m_clipboard; + QScopedPointer m_find; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm new file mode 100644 index 0000000000..799fb85183 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 "QCocoaclipboard.h" +#include "qmacmime.h" +#include "qmacclipboard.h" + +QT_BEGIN_NAMESPACE + +QCocoaClipboard::QCocoaClipboard() + :m_clipboard(new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP)) + ,m_find(new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP)) +{ + +} + +QMimeData *QCocoaClipboard::mimeData(QClipboard::Mode mode) +{ + if (QMacPasteboard *pasteBoard = pasteboardForMode(mode)) { + pasteBoard->sync(); + return pasteBoard->mimeData(); + } + return 0; +} + +void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + if (QMacPasteboard *pasteBoard = pasteboardForMode(mode)) { + pasteBoard->sync(); + pasteBoard->setMimeData(data); + emitChanged(mode); + } +} + +bool QCocoaClipboard::supportsMode(QClipboard::Mode mode) const +{ + return (mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer); +} + +bool QCocoaClipboard::ownsMode(QClipboard::Mode mode) const +{ + return false; +} + +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/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 9248df0d37..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 @@ -91,6 +92,7 @@ public: QPlatformNativeInterface *nativeInterface() const; QPlatformInputContext *inputContext() const; QPlatformAccessibility *accessibility() const; + QPlatformClipboard *clipboard() const; QPlatformDrag *drag() const; QStringList themeNames() const; @@ -105,6 +107,7 @@ private: QScopedPointer mAccessibility; QScopedPointer mPlatformTheme; QList mScreens; + QCocoaClipboard *mCocoaClipboard; QScopedPointer mCocoaDrag; }; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 96027e0925..f5febd4a16 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -93,6 +93,7 @@ QCocoaIntegration::QCocoaIntegration() , mEventDispatcher(new QCocoaEventDispatcher()) , mInputContext(new QCocoaInputContext) , mAccessibility(new QPlatformAccessibility) + , mCocoaClipboard(new QCocoaClipboard) , mCocoaDrag(new QCocoaDrag) { QCocoaAutoReleasePool pool; @@ -140,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(); @@ -206,6 +213,11 @@ QPlatformAccessibility *QCocoaIntegration::accessibility() const return mAccessibility.data(); } +QPlatformClipboard *QCocoaIntegration::clipboard() const +{ + return mCocoaClipboard; +} + QPlatformDrag *QCocoaIntegration::drag() const { return mCocoaDrag.data(); 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 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 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 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; @@ -810,6 +800,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 -- cgit v1.2.3 From 006a49b19ac100df587f23eb76dc4ba8855047a0 Mon Sep 17 00:00:00 2001 From: Jerome Leclanche Date: Thu, 15 Mar 2012 00:41:15 +0000 Subject: Fix compiling with --no-accessibility Adds missing QT_NO_ACCESSIBILITY checks where required to build without accessibility support. Change-Id: Id98ecdcb9b351289b21dc2d382100d0b63857db9 Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/xcb/qxcbintegration.cpp | 6 ++++++ src/plugins/platforms/xcb/qxcbintegration.h | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 0db9ef9e64..50d3c4f1b5 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -82,7 +82,9 @@ #include #include +#ifndef QT_NO_ACCESSIBILITY #include +#endif QT_BEGIN_NAMESPACE @@ -113,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); @@ -246,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() diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 4c335f2f06..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; @@ -97,7 +99,9 @@ private: QScopedPointer m_inputContext; QAbstractEventDispatcher *m_eventDispatcher; +#ifndef QT_NO_ACCESSIBILITY QScopedPointer m_accessibility; +#endif #if defined(QT_USE_XCB_SHARED_GRAPHICS_CACHE) QScopedPointer m_sharedGraphicsCache; -- cgit v1.2.3