summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/src/androidjniinput.cpp9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm39
-rw-r--r--src/plugins/platforms/directfb/qdirectfbconvenience.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp20
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.h3
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp2
-rw-r--r--src/plugins/platforms/minimal/qminimalintegration.cpp17
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp8
-rw-r--r--src/plugins/platforms/platforms.pro3
-rw-r--r--src/plugins/platforms/qnx/qnx.pro3
-rw-r--r--src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp30
-rw-r--r--src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h7
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp1601
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_imf.h76
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp9
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp27
-rw-r--r--src/plugins/platforms/qnx/qqnxnativeinterface.cpp14
-rw-r--r--src/plugins/platforms/qnx/qqnxnativeinterface.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp4
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventfilter.h58
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp47
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.h7
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp15
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h1
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h3
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp26
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp2
-rw-r--r--src/plugins/platforms/winrt/blit.hlsl14
-rw-r--r--src/plugins/platforms/winrt/main.cpp74
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.cpp393
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.h77
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.cpp153
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.h77
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.cpp63
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.h63
-rw-r--r--src/plugins/platforms/winrt/qwinrteventdispatcher.cpp79
-rw-r--r--src/plugins/platforms/winrt/qwinrteventdispatcher.h80
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.cpp64
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.h57
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.cpp300
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.h121
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp194
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.h86
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp975
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h168
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.cpp138
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.h80
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp119
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h72
-rw-r--r--src/plugins/platforms/winrt/winrt.json3
-rw-r--r--src/plugins/platforms/winrt/winrt.pro55
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp38
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp35
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbsessionmanager.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp5
68 files changed, 4629 insertions, 1059 deletions
diff --git a/src/plugins/platforms/android/src/androidjniinput.cpp b/src/plugins/platforms/android/src/androidjniinput.cpp
index 8ce95532d3..55d44b7377 100644
--- a/src/plugins/platforms/android/src/androidjniinput.cpp
+++ b/src/plugins/platforms/android/src/androidjniinput.cpp
@@ -471,6 +471,9 @@ namespace QtAndroidInput
case 0x000000ba: // KEYCODE_PROG_BLUE
return Qt::Key_Blue;
+ case 0x000000a5: // KEYCODE_INFO
+ return Qt::Key_Info;
+
case 0x000000a6: // KEYCODE_CHANNEL_UP
return Qt::Key_ChannelUp;
@@ -483,9 +486,15 @@ namespace QtAndroidInput
case 0x000000a9: // KEYCODE_ZOOM_OUT
return Qt::Key_ZoomOut;
+ case 0x000000ac: // KEYCODE_GUIDE
+ return Qt::Key_Guide;
+
case 0x000000af: // KEYCODE_CAPTIONS
return Qt::Key_Subtitle;
+ case 0x000000b0: // KEYCODE_SETTINGS
+ return Qt::Key_Settings;
+
case 0x000000d0: // KEYCODE_CALENDAR
return Qt::Key_Calendar;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 8f74a71b1e..4b637a707d 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -143,7 +143,7 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
[pixelFormat release];
- const GLint interval = 1;
+ const GLint interval = format.swapInterval() >= 0 ? format.swapInterval() : 1;
[m_context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
if (format.alphaBufferSize() > 0) {
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index c7ec315f04..69bea31343 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -214,6 +214,11 @@ public: // for QNSView
static const int NoAlertRequest;
NSInteger m_alertRequest;
id monitor;
+
+ // used by showFullScreen in fake mode
+ QRect m_normalGeometry;
+ Qt::WindowFlags m_oldWindowFlags;
+ NSApplicationPresentationOptions m_presentationOptions;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index ad11a525ad..5702689d84 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -220,6 +220,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_overrideBecomeKey(false)
, m_alertRequest(NoAlertRequest)
, monitor(nil)
+ , m_normalGeometry(QRect(0,0,-1,-1))
{
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
qDebug() << "QCocoaWindow::QCocoaWindow" << this;
@@ -271,8 +272,16 @@ QSurfaceFormat QCocoaWindow::format() const
return window()->requestedFormat();
}
-void QCocoaWindow::setGeometry(const QRect &rect)
+void QCocoaWindow::setGeometry(const QRect &rectIn)
{
+ QRect rect = rectIn;
+ // This means it is a call from QWindow::setFramePosition() and
+ // the coordinates include the frame (size is still the contents rectangle).
+ if (qt_window_private(const_cast<QWindow *>(window()))->positionPolicy
+ == QWindowPrivate::WindowFrameInclusive) {
+ const QMargins margins = frameMargins();
+ rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
+ }
if (geometry() == rect)
return;
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
@@ -1012,13 +1021,35 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
}
if ((m_synchedWindowState & Qt::WindowFullScreen) != (newState & Qt::WindowFullScreen)) {
+ bool fakeFullScreen = true;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
- [m_nsWindow toggleFullScreen : m_nsWindow];
- } else {
- // TODO: "normal" fullscreen
+ if (window()->flags() & Qt::WindowFullscreenButtonHint) {
+ fakeFullScreen = false;
+ [m_nsWindow toggleFullScreen : m_nsWindow];
+ }
}
#endif
+ if (fakeFullScreen) {
+ if (newState & Qt::WindowFullScreen) {
+ QScreen *screen = window()->screen();
+ if (screen) {
+ if (m_normalGeometry.width() < 0) {
+ m_oldWindowFlags = m_windowFlags;
+ window()->setFlags(window()->flags() | Qt::FramelessWindowHint);
+ m_normalGeometry = windowGeometry();
+ setGeometry(screen->geometry());
+ m_presentationOptions = [NSApp presentationOptions];
+ [NSApp setPresentationOptions : m_presentationOptions | NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock];
+ }
+ }
+ } else {
+ window()->setFlags(m_oldWindowFlags);
+ setGeometry(m_normalGeometry);
+ m_normalGeometry.setRect(0, 0, -1, -1);
+ [NSApp setPresentationOptions : m_presentationOptions];
+ }
+ }
}
// New state is now the current synched state
diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
index b56d75a16e..16510095db 100644
--- a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp
@@ -281,12 +281,16 @@ QDirectFbKeyMap::QDirectFbKeyMap()
insert(DIKS_CLEAR , Qt::Key_Clear);
insert(DIKS_MENU , Qt::Key_Menu);
insert(DIKS_HELP , Qt::Key_Help);
+ insert(DIKS_INFO , Qt::Key_Info);
+ insert(DIKS_EXIT , Qt::Key_Exit);
+ insert(DIKS_SETUP , Qt::Key_Settings);
insert(DIKS_CD , Qt::Key_CD);
insert(DIKS_INTERNET , Qt::Key_HomePage);
insert(DIKS_MAIL , Qt::Key_LaunchMail);
insert(DIKS_FAVORITES , Qt::Key_Favorites);
insert(DIKS_PHONE , Qt::Key_Phone);
+ insert(DIKS_PROGRAM , Qt::Key_Guide);
insert(DIKS_TIME , Qt::Key_Time);
insert(DIKS_RED , Qt::Key_Red);
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp
index 2c6846132d..dd3f272d8b 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp
@@ -54,29 +54,13 @@ QT_BEGIN_NAMESPACE
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
EGLDisplay display, EGLenum eglApi)
: QEGLPlatformContext(QEglFSHooks::hooks()->surfaceFormatFor(format), share, display,
- QEglFSIntegration::chooseConfig(display, QEglFSHooks::hooks()->surfaceFormatFor(format)), eglApi),
- m_swapIntervalSet(false)
+ QEglFSIntegration::chooseConfig(display, QEglFSHooks::hooks()->surfaceFormatFor(format)), eglApi)
{
}
bool QEglFSContext::makeCurrent(QPlatformSurface *surface)
{
- bool success = QEGLPlatformContext::makeCurrent(surface);
-
- if (success && !m_swapIntervalSet) {
- m_swapIntervalSet = true;
- int swapInterval = 1;
- QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL");
- if (!swapIntervalString.isEmpty()) {
- bool ok;
- swapInterval = swapIntervalString.toInt(&ok);
- if (!ok)
- swapInterval = 1;
- }
- eglSwapInterval(eglDisplay(), swapInterval);
- }
-
- return success;
+ return QEGLPlatformContext::makeCurrent(surface);
}
EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h
index 8db340252c..6caa49ab4f 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.h
+++ b/src/plugins/platforms/eglfs/qeglfscontext.h
@@ -55,9 +55,6 @@ public:
bool makeCurrent(QPlatformSurface *surface);
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
void swapBuffers(QPlatformSurface *surface);
-
-private:
- bool m_swapIntervalSet;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index bba00da128..cc0e64a83b 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -126,7 +126,7 @@ void QEglFSWindow::create()
EGLDisplay display = static_cast<QEglFSScreen *>(screen)->display();
QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat());
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
- m_format = q_glFormatFromConfig(display, m_config);
+ m_format = q_glFormatFromConfig(display, m_config, platformFormat);
resetSurface();
diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp
index 76b4b5b0eb..7f5c25f239 100644
--- a/src/plugins/platforms/minimal/qminimalintegration.cpp
+++ b/src/plugins/platforms/minimal/qminimalintegration.cpp
@@ -41,17 +41,20 @@
#include "qminimalintegration.h"
#include "qminimalbackingstore.h"
-#ifndef Q_OS_WIN
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
-#else
-#include <QtCore/private/qeventdispatcher_win_p.h>
-#endif
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformfontdatabase.h>
+#if !defined(Q_OS_WIN)
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#elif defined(Q_OS_WINRT)
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+#else
+#include <QtCore/private/qeventdispatcher_win_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
static const char debugBackingStoreEnvironmentVariable[] = "QT_DEBUG_BACKINGSTORE";
@@ -132,7 +135,11 @@ QPlatformBackingStore *QMinimalIntegration::createPlatformBackingStore(QWindow *
QAbstractEventDispatcher *QMinimalIntegration::createEventDispatcher() const
{
#ifdef Q_OS_WIN
+#ifndef Q_OS_WINRT
return new QEventDispatcherWin32;
+#else // !Q_OS_WINRT
+ return new QEventDispatcherWinRT;
+#endif // Q_OS_WINRT
#else
return createUnixEventDispatcher();
#endif
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
index a1da8e3a16..76881db6fc 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -52,7 +52,11 @@
#endif
#elif defined(Q_OS_WIN)
#include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
+#ifndef Q_OS_WINRT
#include <QtCore/private/qeventdispatcher_win_p.h>
+#else
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+#endif
#endif
#include <QtGui/private/qpixmap_raster_p.h>
@@ -143,7 +147,11 @@ QAbstractEventDispatcher *QOffscreenIntegration::createEventDispatcher() const
#if defined(Q_OS_UNIX)
return createUnixEventDispatcher();
#elif defined(Q_OS_WIN)
+#ifndef Q_OS_WINRT
return new QOffscreenEventDispatcher<QEventDispatcherWin32>();
+#else // !Q_OS_WINRT
+ return new QOffscreenEventDispatcher<QEventDispatcherWinRT>();
+#endif // Q_OS_WINRT
#else
return 0;
#endif
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 377ca32e64..4a7c3b279f 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -15,7 +15,8 @@ mac {
else: SUBDIRS += cocoa
}
-win32: SUBDIRS += windows
+win32:!winrt: SUBDIRS += windows
+winrt: SUBDIRS += winrt
qnx {
SUBDIRS += qnx
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index bc7219de5c..100db54a5c 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -62,7 +62,8 @@ HEADERS = main.h \
qqnxabstractcover.h \
qqnxservices.h \
qqnxcursor.h \
- qqnxrasterwindow.h
+ qqnxrasterwindow.h \
+ qqnxscreeneventfilter.h
CONFIG(qqnx_screeneventthread) {
DEFINES += QQNX_SCREENEVENTTHREAD
diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
index a42f73415e..1d8591cfa1 100644
--- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
+++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -62,23 +62,19 @@ void QQnxAbstractVirtualKeyboard::setKeyboardMode(KeyboardMode mode)
applyKeyboardMode(mode);
}
-void QQnxAbstractVirtualKeyboard::setInputHintsFromObject(QObject *focusObject)
+void QQnxAbstractVirtualKeyboard::setInputHints(int inputHints)
{
- if (focusObject) {
- const Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(
- focusObject->property("inputMethodHints").toInt());
- if (hints & Qt::ImhEmailCharactersOnly) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Email);
- } else if (hints & Qt::ImhDialableCharactersOnly) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Phone);
- } else if (hints & Qt::ImhUrlCharactersOnly) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Web);
- } else if (hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhDigitsOnly ||
- hints & Qt::ImhDate || hints & Qt::ImhTime) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::NumPunc);
- } else {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Default);
- }
+ if (inputHints & Qt::ImhEmailCharactersOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Email);
+ } else if (inputHints & Qt::ImhDialableCharactersOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Phone);
+ } else if (inputHints & Qt::ImhUrlCharactersOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Web);
+ } else if (inputHints & Qt::ImhFormattedNumbersOnly || inputHints & Qt::ImhDigitsOnly ||
+ inputHints & Qt::ImhDate || inputHints & Qt::ImhTime) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::NumPunc);
+ } else if (inputHints & Qt::ImhHiddenText) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Password);
} else {
setKeyboardMode(QQnxAbstractVirtualKeyboard::Default);
}
diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
index 9b911e1dec..033d8ebb74 100644
--- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
+++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -59,10 +59,11 @@ public:
// Symbol - All symbols, alternate to NumPunc, currently unused.
// Phone - Phone enhanced keyboard - currently unused as no alternate keyboard available to access a-zA-Z
// Pin - Keyboard for entering Pins (Hex values) currently unused.
+ // Password - Keyboard for entering passwords.
//
// SPECIAL NOTE: Usage of NumPunc may have to be removed, ABC button is non-functional.
//
- enum KeyboardMode { Default, Url, Email, Web, NumPunc, Symbol, Phone, Pin };
+ enum KeyboardMode { Default, Url, Email, Web, NumPunc, Symbol, Phone, Pin, Password };
explicit QQnxAbstractVirtualKeyboard(QObject *parent = 0);
@@ -74,7 +75,7 @@ public:
QLocale locale() const { return m_locale; }
void setKeyboardMode(KeyboardMode mode);
- void setInputHintsFromObject(QObject *focusObject);
+ void setInputHints(int inputHints);
KeyboardMode keyboardMode() const { return m_keyboardMode; }
Q_SIGNALS:
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
index 580553f6e2..619883e843 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -40,10 +40,10 @@
****************************************************************************/
#include "qqnxinputcontext_imf.h"
-#include "qqnxeventthread.h"
#include "qqnxabstractvirtualkeyboard.h"
#include "qqnxintegration.h"
#include "qqnxscreen.h"
+#include "qqnxscreeneventhandler.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QInputMethodEvent>
@@ -54,6 +54,8 @@
#include <QtCore/QVariant>
#include <QtCore/QVariantHash>
#include <QtCore/QWaitCondition>
+#include <QtCore/QQueue>
+#include <QtCore/QGlobalStatic>
#include <dlfcn.h>
#include "imf/imf_client.h"
@@ -62,9 +64,9 @@
#include <sys/keycodes.h>
#if defined(QQNXINPUTCONTEXT_IMF_EVENT_DEBUG)
-#define qInputContextIMFEventDebug qDebug
+#define qInputContextIMFRequestDebug qDebug
#else
-#define qInputContextIMFEventDebug QT_NO_QDEBUG_MACRO
+#define qInputContextIMFRequestDebug QT_NO_QDEBUG_MACRO
#endif
#if defined(QQNXINPUTCONTEXT_DEBUG)
@@ -73,492 +75,426 @@
#define qInputContextDebug QT_NO_QDEBUG_MACRO
#endif
-/** TODO:
- Support inputMethodHints to restrict input (needs additional features in IMF).
-*/
+static QQnxInputContext *sInputContextInstance;
+static QColor sSelectedColor(0,0xb8,0,85);
-#define STRX(x) #x
-#define STR(x) STRX(x)
-
-// Someone tell me why input_control methods are in this namespace, but the rest is not.
-using namespace InputMethodSystem;
-
-#define qs(x) QString::fromLatin1(x)
-#define iarg(name) event->mArgs[qs(#name)] = QVariant::fromValue(name)
-#define parg(name) event->mArgs[qs(#name)] = QVariant::fromValue((void*)name)
-namespace
-{
-
-spannable_string_t *toSpannableString(const QString &text);
+static const input_session_t *sSpellCheckSession = 0;
static const input_session_t *sInputSession = 0;
-bool isSessionOkay(input_session_t *ic)
+static bool isSessionOkay(input_session_t *ic)
{
return ic !=0 && sInputSession != 0 && ic->component_id == sInputSession->component_id;
}
enum ImfEventType
{
- ImfBeginBatchEdit,
- ImfClearMetaKeyStates,
ImfCommitText,
ImfDeleteSurroundingText,
- ImfEndBatchEdit,
ImfFinishComposingText,
- ImfGetCursorCapsMode,
ImfGetCursorPosition,
- ImfGetExtractedText,
- ImfGetSelectedText,
ImfGetTextAfterCursor,
ImfGetTextBeforeCursor,
- ImfPerformEditorAction,
- ImfReportFullscreenMode,
ImfSendEvent,
- ImfSendAsyncEvent,
ImfSetComposingRegion,
ImfSetComposingText,
- ImfSetSelection
+ ImfIsTextSelected,
+ ImfIsAllTextSelected,
};
-// We use this class as a round about way to support a posting synchronous event into
-// Qt's main thread from the IMF thread.
-class ImfEventResult
-{
-public:
- ImfEventResult()
- {
- m_mutex.lock();
- }
-
- ~ImfEventResult()
- {
- m_mutex.unlock();
- }
-
- void wait()
- {
- m_wait.wait(&m_mutex);
- }
-
- void signal()
- {
- m_wait.wakeAll();
- }
-
- void setResult(const QVariant& result)
- {
- m_mutex.lock();
- m_retVal = result;
- signal();
- m_mutex.unlock();
- }
-
- QVariant result()
- {
- return m_retVal;
- }
-
-private:
- QVariant m_retVal;
- QMutex m_mutex;
- QWaitCondition m_wait;
+struct SpellCheckInfo {
+ SpellCheckInfo(void *_context, void (*_spellCheckDone)(void *, const QString &, const QList<int> &))
+ : context(_context), spellCheckDone(_spellCheckDone) {}
+ void *context;
+ void (*spellCheckDone)(void *, const QString &, const QList<int> &);
};
+Q_GLOBAL_STATIC(QQueue<SpellCheckInfo>, sSpellCheckQueue)
-class ImfEvent : public QEvent
+// IMF requests all arrive on IMF's own thread and have to be posted to the main thread to be processed.
+class QQnxImfRequest
{
- public:
- ImfEvent(input_session_t *session, ImfEventType type, ImfEventResult *result) :
- QEvent((QEvent::Type)sUserEventType),
- m_session(session),
- m_imfType(type),
- m_result(result)
- {
- }
- ~ImfEvent() { }
-
- input_session_t *m_session;
- ImfEventType m_imfType;
- QVariantHash m_args;
- ImfEventResult *m_result;
-
- static int sUserEventType;
+public:
+ QQnxImfRequest(input_session_t *_session, ImfEventType _type)
+ : session(_session), type(_type)
+ { }
+ ~QQnxImfRequest() { }
+
+ input_session_t *session;
+ ImfEventType type;
+ union {
+ struct {
+ int32_t n;
+ int32_t flags;
+ bool before;
+ spannable_string_t *result;
+ } gtac; // ic_get_text_before_cursor/ic_get_text_after_cursor
+ struct {
+ int32_t result;
+ } gcp; // ic_get_cursor_position
+ struct {
+ int32_t start;
+ int32_t end;
+ int32_t result;
+ } scr; // ic_set_composing_region
+ struct {
+ spannable_string_t* text;
+ int32_t new_cursor_position;
+ int32_t result;
+ } sct; // ic_set_composing_text
+ struct {
+ spannable_string_t* text;
+ int32_t new_cursor_position;
+ int32_t result;
+ } ct; // ic_commit_text
+ struct {
+ int32_t result;
+ } fct; // ic_finish_composing_text
+ struct {
+ int32_t left_length;
+ int32_t right_length;
+ int32_t result;
+ } dst; // ic_delete_surrounding_text
+ struct {
+ event_t *event;
+ int32_t result;
+ } sae; // ic_send_async_event/ic_send_event
+ struct {
+ int32_t *pIsSelected;
+ int32_t result;
+ } its; // ic_is_text_selected/ic_is_all_text_selected
+ };
};
-int ImfEvent::sUserEventType = QEvent::registerEventType();
-static int32_t imfBeginBatchEdit(input_session_t *ic)
+// Invoke an IMF initiated request synchronously on Qt's main thread. As describe below all
+// IMF requests are made from another thread but need to be executed on the main thread.
+static void executeIMFRequest(QQnxImfRequest *event)
+{
+ QMetaObject::invokeMethod(sInputContextInstance,
+ "processImfEvent",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(QQnxImfRequest*, event));
+}
+
+// The following functions (ic_*) are callback functions called by the input system to query information
+// about the text object that currently has focus or to make changes to it. All calls are made from the
+// input system's own thread. The pattern for each callback function is to copy its parameters into
+// a QQnxImfRequest structure and call executeIMFRequest to have it passed synchronously to Qt's main thread.
+// Any return values should be pre-initialised with suitable default values as in some cases
+// (e.g. a stale session) the call will return without having executed any request specific code.
+//
+// To make the correspondence more obvious, the names of these functions match those defined in the headers.
+// They're in an anonymous namespace to avoid compiler conflicts with external functions defined with the
+// same names.
+namespace
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfBeginBatchEdit, &result);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_begin_batch_edit(input_session_t *ic)
+{
+ Q_UNUSED(ic);
- return ret;
+ // Ignore silently.
+ return 0;
}
-static int32_t imfClearMetaKeyStates(input_session_t *ic, int32_t states)
+// End composition, committing the supplied text.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_commit_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfClearMetaKeyStates, &result);
- iarg(states);
-
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
+ QQnxImfRequest event(ic, ImfCommitText);
+ event.ct.text = text;
+ event.ct.new_cursor_position = new_cursor_position;
+ event.ct.result = -1;
+ executeIMFRequest(&event);
- return ret;
+ return event.ct.result;
}
-static int32_t imfCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+// Delete left_length characters before and right_length characters after the cursor.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_delete_surrounding_text(input_session_t *ic, int32_t left_length, int32_t right_length)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfCommitText, &result);
- parg(text);
- iarg(new_cursor_position);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfDeleteSurroundingText);
+ event.dst.left_length = left_length;
+ event.dst.right_length = right_length;
+ event.dst.result = -1;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ return event.dst.result;
}
-static int32_t imfDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length)
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_end_batch_edit(input_session_t *ic)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfDeleteSurroundingText, &result);
- iarg(left_length);
- iarg(right_length);
+ Q_UNUSED(ic);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ // Ignore silently.
+ return 0;
}
-static int32_t imfEndBatchEdit(input_session_t *ic)
+// End composition, committing what's there.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_finish_composing_text(input_session_t *ic)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfEndBatchEdit, &result);
-
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
+ QQnxImfRequest event(ic, ImfFinishComposingText);
+ event.fct.result = -1;
+ executeIMFRequest(&event);
- return ret;
+ return event.fct.result;
}
-static int32_t imfFinishComposingText(input_session_t *ic)
+// Return the position of the cursor.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_get_cursor_position(input_session_t *ic)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfFinishComposingText, &result);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfGetCursorPosition);
+ event.gcp.result = -1;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ return event.gcp.result;
}
-static int32_t imfGetCursorCapsMode(input_session_t *ic, int32_t req_modes)
+// Return the n characters after the cursor.
+// See comment at beginning of namespace declaration for general information
+static spannable_string_t *ic_get_text_after_cursor(input_session_t *ic, int32_t n, int32_t flags)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetCursorCapsMode, &result);
- iarg(req_modes);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfGetTextAfterCursor);
+ event.gtac.n = n;
+ event.gtac.flags = flags;
+ event.gtac.result = 0;
+ executeIMFRequest(&event);
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ return event.gtac.result;
}
-static int32_t imfGetCursorPosition(input_session_t *ic)
+// Return the n characters before the cursor.
+// See comment at beginning of namespace declaration for general information
+static spannable_string_t *ic_get_text_before_cursor(input_session_t *ic, int32_t n, int32_t flags)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetCursorPosition, &result);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfGetTextBeforeCursor);
+ event.gtac.n = n;
+ event.gtac.flags = flags;
+ event.gtac.result = 0;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ return event.gtac.result;
}
-static extracted_text_t *imfGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
+// Process an event from IMF. Primarily used for reflecting back keyboard events.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_send_event(input_session_t *ic, event_t *event)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic)) {
- extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1);
- et->text = (spannable_string_t *)calloc(sizeof(spannable_string_t),1);
- return et;
- }
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetExtractedText, &result);
- parg(request);
- iarg(flags);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest imfEvent(ic, ImfSendEvent);
+ imfEvent.sae.event = event;
+ imfEvent.sae.result = -1;
+ executeIMFRequest(&imfEvent);
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return imfEvent.sae.result;
}
-static spannable_string_t *imfGetSelectedText(input_session_t *ic, int32_t flags)
+// Same as ic_send_event.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_send_async_event(input_session_t *ic, event_t *event)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetSelectedText, &result);
- iarg(flags);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ // There's no difference from our point of view between ic_send_event & ic_send_async_event
+ QQnxImfRequest imfEvent(ic, ImfSendEvent);
+ imfEvent.sae.event = event;
+ imfEvent.sae.result = -1;
+ executeIMFRequest(&imfEvent);
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return imfEvent.sae.result;
}
-static spannable_string_t *imfGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags)
+// Set the range of text between start and end as the composition range.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_set_composing_region(input_session_t *ic, int32_t start, int32_t end)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetTextAfterCursor, &result);
- iarg(n);
- iarg(flags);
+ QQnxImfRequest event(ic, ImfSetComposingRegion);
+ event.scr.start = start;
+ event.scr.end = end;
+ event.scr.result = -1;
+ executeIMFRequest(&event);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return event.scr.result;
}
-static spannable_string_t *imfGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags)
+// Update the composition range with the supplied text. This can be called when no composition
+// range is in effect in which case one is started at the current cursor position.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_set_composing_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
+ QQnxImfRequest event(ic, ImfSetComposingText);
+ event.sct.text = text;
+ event.sct.new_cursor_position = new_cursor_position;
+ event.sct.result = -1;
+ executeIMFRequest(&event);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetTextBeforeCursor, &result);
- iarg(n);
- iarg(flags);
-
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return event.sct.result;
}
-static int32_t imfPerformEditorAction(input_session_t *ic, int32_t editor_action)
+// Indicate if any text is selected
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_is_text_selected(input_session_t* ic, int32_t* pIsSelected)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfPerformEditorAction, &result);
- iarg(editor_action);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfIsTextSelected);
+ event.its.pIsSelected = pIsSelected;
+ event.its.result = -1;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ return event.its.result;
}
-static int32_t imfReportFullscreenMode(input_session_t *ic, int32_t enabled)
+// Indicate if all text is selected
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_is_all_text_selected(input_session_t* ic, int32_t* pIsSelected)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfReportFullscreenMode, &result);
- iarg(enabled);
+ QQnxImfRequest event(ic, ImfIsAllTextSelected);
+ event.its.pIsSelected = pIsSelected;
+ event.its.result = -1;
+ executeIMFRequest(&event);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ return event.its.result;
}
-static int32_t imfSendEvent(input_session_t *ic, event_t *event)
-{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEvent *imfEvent = new ImfEvent(ic, ImfSendEvent, 0);
- imfEvent->m_args[qs("event")] = QVariant::fromValue(static_cast<void *>(event));
+// LCOV_EXCL_START - exclude from code coverage analysis
+// The following functions are defined in the IMF headers but are not currently called.
- QCoreApplication::postEvent(QCoreApplication::instance(), imfEvent);
+// Not currently used
+static int32_t ic_perform_editor_action(input_session_t *ic, int32_t editor_action)
+{
+ Q_UNUSED(ic);
+ Q_UNUSED(editor_action);
+ qCritical() << "ic_perform_editor_action not implemented";
return 0;
}
-static int32_t imfSendAsyncEvent(input_session_t *ic, event_t *event)
+// Not currently used
+static int32_t ic_report_fullscreen_mode(input_session_t *ic, int32_t enabled)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEvent *imfEvent = new ImfEvent(ic, ImfSendAsyncEvent, 0);
- imfEvent->m_args[qs("event")] = QVariant::fromValue(static_cast<void *>(event));
-
- QCoreApplication::postEvent(QCoreApplication::instance(), imfEvent);
+ Q_UNUSED(ic);
+ Q_UNUSED(enabled);
+ qCritical() << "ic_report_fullscreen_mode not implemented";
return 0;
}
-static int32_t imfSetComposingRegion(input_session_t *ic, int32_t start, int32_t end)
+// Not currently used
+static extracted_text_t *ic_get_extracted_text(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ Q_UNUSED(ic);
+ Q_UNUSED(request);
+ Q_UNUSED(flags);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfSetComposingRegion, &result);
- iarg(start);
- iarg(end);
+ qCritical() << "ic_get_extracted_text not implemented";
+ return 0;
+}
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+// Not currently used
+static spannable_string_t *ic_get_selected_text(input_session_t *ic, int32_t flags)
+{
+ Q_UNUSED(ic);
+ Q_UNUSED(flags);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ qCritical() << "ic_get_selected_text not implemented";
+ return 0;
}
-static int32_t imfSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+// Not currently used
+static int32_t ic_get_cursor_caps_mode(input_session_t *ic, int32_t req_modes)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ Q_UNUSED(ic);
+ Q_UNUSED(req_modes);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfSetComposingText, &result);
- parg(text);
- iarg(new_cursor_position);
+ qCritical() << "ic_get_cursor_caps_mode not implemented";
+ return 0;
+}
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+// Not currently used
+static int32_t ic_clear_meta_key_states(input_session_t *ic, int32_t states)
+{
+ Q_UNUSED(ic);
+ Q_UNUSED(states);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ qCritical() << "ic_clear_meta_key_states not implemented";
+ return 0;
}
-static int32_t imfSetSelection(input_session_t *ic, int32_t start, int32_t end)
+// Not currently used
+static int32_t ic_set_selection(input_session_t *ic, int32_t start, int32_t end)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ Q_UNUSED(ic);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfSetSelection, &result);
- iarg(start);
- iarg(end);
+ qCritical() << "ic_set_selection not implemented";
+ return 0;
+}
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+// End of un-hittable code
+// LCOV_EXCL_STOP
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
-}
static connection_interface_t ic_funcs = {
- imfBeginBatchEdit,
- imfClearMetaKeyStates,
- imfCommitText,
- imfDeleteSurroundingText,
- imfEndBatchEdit,
- imfFinishComposingText,
- imfGetCursorCapsMode,
- imfGetCursorPosition,
- imfGetExtractedText,
- imfGetSelectedText,
- imfGetTextAfterCursor,
- imfGetTextBeforeCursor,
- imfPerformEditorAction,
- imfReportFullscreenMode,
- NULL, //ic_send_key_event
- imfSendEvent,
- imfSendAsyncEvent,
- imfSetComposingRegion,
- imfSetComposingText,
- imfSetSelection,
- NULL, //ic_set_candidates,
+ ic_begin_batch_edit,
+ ic_clear_meta_key_states,
+ ic_commit_text,
+ ic_delete_surrounding_text,
+ ic_end_batch_edit,
+ ic_finish_composing_text,
+ ic_get_cursor_caps_mode,
+ ic_get_cursor_position,
+ ic_get_extracted_text,
+ ic_get_selected_text,
+ ic_get_text_after_cursor,
+ ic_get_text_before_cursor,
+ ic_perform_editor_action,
+ ic_report_fullscreen_mode,
+ 0, //ic_send_key_event
+ ic_send_event,
+ ic_send_async_event,
+ ic_set_composing_region,
+ ic_set_composing_text,
+ ic_set_selection,
+ 0, //ic_set_candidates,
+ 0, //ic_get_cursor_offset,
+ 0, //ic_get_selection,
+ ic_is_text_selected,
+ ic_is_all_text_selected,
+ 0, //ic_get_max_cursor_offset_t
};
+} // namespace
+
static void
-initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId)
+initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId, int eventSize)
{
static int s_transactionId;
// Make sure structure is squeaky clean since it's not clear just what is significant.
- memset(pEvent, 0, sizeof(event_t));
+ memset(pEvent, 0, eventSize);
pEvent->event_type = eventType;
pEvent->event_id = eventId;
pEvent->pid = getpid();
@@ -566,31 +502,20 @@ initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType,
pEvent->transaction_id = ++s_transactionId;
}
-spannable_string_t *toSpannableString(const QString &text)
+static spannable_string_t *toSpannableString(const QString &text)
{
qInputContextDebug() << Q_FUNC_INFO << text;
- spannable_string_t *pString = reinterpret_cast<spannable_string_t *>(malloc(sizeof(spannable_string_t)));
- pString->str = (wchar_t *)malloc(sizeof(wchar_t) * text.length() + 1);
- pString->length = text.length();
+ spannable_string_t *pString = static_cast<spannable_string_t *>(malloc(sizeof(spannable_string_t)));
+ pString->str = static_cast<wchar_t *>(malloc(sizeof(wchar_t) * text.length() + 1));
+ pString->length = text.toWCharArray(pString->str);
pString->spans = 0;
pString->spans_count = 0;
-
- const QChar *pData = text.constData();
- wchar_t *pDst = pString->str;
-
- while (!pData->isNull())
- {
- *pDst = pData->unicode();
- pDst++;
- pData++;
- }
- *pDst = 0;
+ pString->str[pString->length] = 0;
return pString;
}
-} // namespace
static const input_session_t *(*p_ictrl_open_session)(connection_interface_t *) = 0;
static void (*p_ictrl_close_session)(input_session_t *) = 0;
@@ -645,27 +570,30 @@ QT_BEGIN_NAMESPACE
QQnxInputContext::QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard) :
QPlatformInputContext(),
- m_lastCaretPos(0),
+ m_caretPosition(0),
m_isComposing(false),
+ m_isUpdatingText(false),
m_inputPanelVisible(false),
m_inputPanelLocale(QLocale::c()),
+ m_focusObject(0),
m_integration(integration),
- m_virtualKeyboad(keyboard)
+ m_virtualKeyboard(keyboard)
{
qInputContextDebug() << Q_FUNC_INFO;
if (!imfAvailable())
return;
- if ( p_imf_client_init() != 0 ) {
+ // Save a pointer to ourselves so we can execute calls from IMF through executeIMFRequest
+ // In practice there will only ever be a single instance.
+ Q_ASSERT(sInputContextInstance == 0);
+ sInputContextInstance = this;
+
+ if (p_imf_client_init() != 0) {
s_imfInitFailed = true;
qCritical("imf_client_init failed - IMF services will be unavailable");
}
- QCoreApplication::instance()->installEventFilter(this);
-
- // p_vkb_init_selection_service();
-
connect(&keyboard, SIGNAL(visibilityChanged(bool)), this, SLOT(keyboardVisibilityChanged(bool)));
connect(&keyboard, SIGNAL(localeChanged(QLocale)), this, SLOT(keyboardLocaleChanged(QLocale)));
keyboardVisibilityChanged(keyboard.isVisible());
@@ -676,168 +604,75 @@ QQnxInputContext::~QQnxInputContext()
{
qInputContextDebug() << Q_FUNC_INFO;
+ Q_ASSERT(sInputContextInstance == this);
+ sInputContextInstance = 0;
+
if (!imfAvailable())
return;
- QCoreApplication::instance()->removeEventFilter(this);
p_imf_client_disconnect();
}
-#define getarg(type, name) type name = imfEvent->mArgs[qs(#name)].value<type>()
-#define getparg(type, name) type name = (type)(imfEvent->mArgs[qs(#name)].value<void*>())
-
bool QQnxInputContext::isValid() const
{
return imfAvailable();
}
-bool QQnxInputContext::eventFilter(QObject *obj, QEvent *event)
+void QQnxInputContext::processImfEvent(QQnxImfRequest *imfEvent)
{
- if (event->type() == ImfEvent::sUserEventType) {
- // Forward the event to our real handler.
- ImfEvent *imfEvent = static_cast<ImfEvent *>(event);
- switch (imfEvent->m_imfType) {
- case ImfBeginBatchEdit: {
- int32_t ret = onBeginBatchEdit(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfClearMetaKeyStates: {
- getarg(int32_t, states);
- int32_t ret = onClearMetaKeyStates(imfEvent->m_session, states);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfCommitText: {
- getparg(spannable_string_t*, text);
- getarg(int32_t, new_cursor_position);
- int32_t ret = onCommitText(imfEvent->m_session, text, new_cursor_position);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfDeleteSurroundingText: {
- getarg(int32_t, left_length);
- getarg(int32_t, right_length);
- int32_t ret = onDeleteSurroundingText(imfEvent->m_session, left_length, right_length);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfEndBatchEdit: {
- int32_t ret = onEndBatchEdit(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfFinishComposingText: {
- int32_t ret = onFinishComposingText(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfGetCursorCapsMode: {
- getarg(int32_t, req_modes);
- int32_t ret = onGetCursorCapsMode(imfEvent->m_session, req_modes);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfGetCursorPosition: {
- int32_t ret = onGetCursorPosition(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfGetExtractedText: {
- getparg(extracted_text_request_t*, request);
- getarg(int32_t, flags);
- extracted_text_t *ret = onGetExtractedText(imfEvent->m_session, request, flags);
- imfEvent->m_result->setResult(QVariant::fromValue(static_cast<void *>(ret)));
- break;
- }
+ // If input session is no longer current, just bail, imfEvent should already be set with the appropriate
+ // return value. The only exception is spell check events since they're not associated with the
+ // object with focus.
+ if (imfEvent->type != ImfSendEvent || imfEvent->sae.event->event_type != EVENT_SPELL_CHECK) {
+ if (!isSessionOkay(imfEvent->session))
+ return;
+ }
- case ImfGetSelectedText: {
- getarg(int32_t, flags);
- spannable_string_t *ret = onGetSelectedText(imfEvent->m_session, flags);
- imfEvent->m_result->setResult(QVariant::fromValue(static_cast<void *>(ret)));
- break;
- }
+ switch (imfEvent->type) {
+ case ImfCommitText:
+ imfEvent->ct.result = onCommitText(imfEvent->ct.text, imfEvent->ct.new_cursor_position);
+ break;
- case ImfGetTextAfterCursor: {
- getarg(int32_t, n);
- getarg(int32_t, flags);
- spannable_string_t *ret = onGetTextAfterCursor(imfEvent->m_session, n, flags);
- imfEvent->m_result->setResult(QVariant::fromValue(static_cast<void *>(ret)));
- break;
- }
+ case ImfDeleteSurroundingText:
+ imfEvent->dst.result = onDeleteSurroundingText(imfEvent->dst.left_length, imfEvent->dst.right_length);
+ break;
- case ImfGetTextBeforeCursor: {
- getarg(int32_t, n);
- getarg(int32_t, flags);
- spannable_string_t *ret = onGetTextBeforeCursor(imfEvent->m_session, n, flags);
- imfEvent->m_result->setResult(QVariant::fromValue((void*)ret));
- break;
- }
+ case ImfFinishComposingText:
+ imfEvent->fct.result = onFinishComposingText();
+ break;
- case ImfPerformEditorAction: {
- getarg(int32_t, editor_action);
- int32_t ret = onPerformEditorAction(imfEvent->m_session, editor_action);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfGetCursorPosition:
+ imfEvent->gcp.result = onGetCursorPosition();
+ break;
- case ImfReportFullscreenMode: {
- getarg(int32_t, enabled);
- int32_t ret = onReportFullscreenMode(imfEvent->m_session, enabled);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfGetTextAfterCursor:
+ imfEvent->gtac.result = onGetTextAfterCursor(imfEvent->gtac.n, imfEvent->gtac.flags);
+ break;
- case ImfSendEvent: {
- getparg(event_t*, event);
- onSendEvent(imfEvent->m_session, event);
- break;
- }
+ case ImfGetTextBeforeCursor:
+ imfEvent->gtac.result = onGetTextBeforeCursor(imfEvent->gtac.n, imfEvent->gtac.flags);
+ break;
- case ImfSendAsyncEvent: {
- getparg(event_t*, event);
- onSendAsyncEvent(imfEvent->m_session, event);
- break;
- }
+ case ImfSendEvent:
+ imfEvent->sae.result = onSendEvent(imfEvent->sae.event);
+ break;
- case ImfSetComposingRegion: {
- getarg(int32_t, start);
- getarg(int32_t, end);
- int32_t ret = onSetComposingRegion(imfEvent->m_session, start, end);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfSetComposingRegion:
+ imfEvent->scr.result = onSetComposingRegion(imfEvent->scr.start, imfEvent->scr.end);
+ break;
- case ImfSetComposingText: {
- getparg(spannable_string_t*, text);
- getarg(int32_t, new_cursor_position);
- int32_t ret = onSetComposingText(imfEvent->m_session, text, new_cursor_position);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfSetComposingText:
+ imfEvent->sct.result = onSetComposingText(imfEvent->sct.text, imfEvent->sct.new_cursor_position);
+ break;
- case ImfSetSelection: {
- getarg(int32_t, start);
- getarg(int32_t, end);
- int32_t ret = onSetSelection(imfEvent->m_session, start, end);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
- }; //switch
+ case ImfIsTextSelected:
+ imfEvent->its.result = onIsTextSelected(imfEvent->its.pIsSelected);
+ break;
- return true;
- } else {
- // standard event processing
- return QObject::eventFilter(obj, event);
- }
+ case ImfIsAllTextSelected:
+ imfEvent->its.result = onIsAllTextSelected(imfEvent->its.pIsSelected);
+ break;
+ }; //switch
}
bool QQnxInputContext::filterEvent( const QEvent *event )
@@ -845,12 +680,12 @@ bool QQnxInputContext::filterEvent( const QEvent *event )
qInputContextDebug() << Q_FUNC_INFO << event;
switch (event->type()) {
- case QEvent::CloseSoftwareInputPanel: {
+ case QEvent::CloseSoftwareInputPanel:
return dispatchCloseSoftwareInputPanel();
- }
- case QEvent::RequestSoftwareInputPanel: {
+
+ case QEvent::RequestSoftwareInputPanel:
return dispatchRequestSoftwareInputPanel();
- }
+
default:
return false;
}
@@ -869,12 +704,30 @@ void QQnxInputContext::reset()
endComposition();
}
-void QQnxInputContext::update(Qt::InputMethodQueries queries)
+void QQnxInputContext::commit()
{
qInputContextDebug() << Q_FUNC_INFO;
- reset();
+ endComposition();
+}
- QPlatformInputContext::update(queries);
+void QQnxInputContext::update(Qt::InputMethodQueries queries)
+{
+ qInputContextDebug() << Q_FUNC_INFO << queries;
+
+ if (queries & Qt::ImCursorPosition) {
+ int lastCaret = m_caretPosition;
+ updateCursorPosition();
+ // If caret position has changed we need to inform IMF unless this is just due to our own action
+ // such as committing text.
+ if (hasSession() && !m_isUpdatingText && lastCaret != m_caretPosition) {
+ caret_event_t caretEvent;
+ initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED, sizeof(caretEvent));
+ caretEvent.old_pos = lastCaret;
+ caretEvent.new_pos = m_caretPosition;
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event caret changed" << lastCaret << m_caretPosition;
+ p_ictrl_dispatch_event(&caretEvent.event);
+ }
+ }
}
void QQnxInputContext::closeSession()
@@ -887,16 +740,23 @@ void QQnxInputContext::closeSession()
p_ictrl_close_session((input_session_t *)sInputSession);
sInputSession = 0;
}
+ // These are likely already in the right state but this depends on the text control
+ // having called reset or commit. So, just in case, set them to proper values.
+ m_isComposing = false;
+ m_composingText.clear();
}
-void QQnxInputContext::openSession()
+bool QQnxInputContext::openSession()
{
- qInputContextDebug() << Q_FUNC_INFO;
if (!imfAvailable())
- return;
+ return false;
closeSession();
sInputSession = p_ictrl_open_session(&ic_funcs);
+
+ qInputContextDebug() << Q_FUNC_INFO;
+
+ return sInputSession != 0;
}
bool QQnxInputContext::hasSession()
@@ -918,79 +778,89 @@ bool QQnxInputContext::hasSelectedText()
bool QQnxInputContext::dispatchRequestSoftwareInputPanel()
{
+ qInputContextDebug() << Q_FUNC_INFO << "requesting keyboard" << m_inputPanelVisible;
m_virtualKeyboard.showKeyboard();
- qInputContextDebug() << Q_FUNC_INFO << "requesting virtual keyboard";
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input || !inputMethodAccepted())
- return true;
-
- if (!hasSession())
- openSession();
- // This also means that the caret position has moved
- QInputMethodQueryEvent query(Qt::ImCursorPosition);
- QCoreApplication::sendEvent(input, &query);
- int caretPos = query.value(Qt::ImCursorPosition).toInt();
- caret_event_t caretEvent;
- memset(&caretEvent, 0, sizeof(caret_event_t));
- initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED);
- caretEvent.old_pos = m_lastCaretPos;
- m_lastCaretPos = caretEvent.new_pos = caretPos;
- p_ictrl_dispatch_event((event_t *)&caretEvent);
return true;
}
bool QQnxInputContext::dispatchCloseSoftwareInputPanel()
{
+ qInputContextDebug() << Q_FUNC_INFO << "hiding keyboard" << m_inputPanelVisible;
m_virtualKeyboard.hideKeyboard();
- qInputContextDebug() << Q_FUNC_INFO << "hiding virtual keyboard";
- // This also means we are stopping composition, but we should already have done that.
return true;
}
/**
* IMF Event Dispatchers.
*/
-bool QQnxInputContext::dispatchFocusEvent(FocusEventId id, int hints)
+bool QQnxInputContext::dispatchFocusGainEvent(int inputHints)
{
- qInputContextDebug() << Q_FUNC_INFO;
+ if (hasSession())
+ dispatchFocusLossEvent();
- if (!sInputSession) {
- qWarning() << Q_FUNC_INFO << "Attempt to dispatch a focus event with no input session.";
- return false;
- }
+ QObject *input = qGuiApp->focusObject();
- if (!imfAvailable())
+ if (!input || !openSession())
return false;
// Set the last caret position to 0 since we don't really have one and we don't
// want to have the old one.
- m_lastCaretPos = 0;
+ m_caretPosition = 0;
+
+ QInputMethodQueryEvent query(Qt::ImHints);
+ QCoreApplication::sendEvent(input, &query);
focus_event_t focusEvent;
- memset(&focusEvent, 0, sizeof(focusEvent));
- initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, id);
+ initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_GAINED, sizeof(focusEvent));
focusEvent.style = DEFAULT_STYLE;
- if (hints && Qt::ImhNoPredictiveText)
+ if (inputHints & Qt::ImhNoPredictiveText)
focusEvent.style |= NO_PREDICTION | NO_AUTO_CORRECTION;
- if (hints && Qt::ImhNoAutoUppercase)
+ if (inputHints & Qt::ImhNoAutoUppercase)
focusEvent.style |= NO_AUTO_TEXT;
+ // Following styles are mutually exclusive
+ if (inputHints & Qt::ImhHiddenText) {
+ focusEvent.style |= IMF_PASSWORD_TYPE;
+ } else if (inputHints & Qt::ImhDialableCharactersOnly) {
+ focusEvent.style |= IMF_PHONE_TYPE;
+ } else if (inputHints & Qt::ImhUrlCharactersOnly) {
+ focusEvent.style |= IMF_URL_TYPE;
+ } else if (inputHints & Qt::ImhEmailCharactersOnly) {
+ focusEvent.style |= IMF_EMAIL_TYPE;
+ }
+
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event focus gain style:" << focusEvent.style;
+
p_ictrl_dispatch_event((event_t *)&focusEvent);
return true;
}
-bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap)
+void QQnxInputContext::dispatchFocusLossEvent()
{
- if (!imfAvailable())
+ if (hasSession()) {
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event focus lost";
+
+ focus_event_t focusEvent;
+ initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_LOST, sizeof(focusEvent));
+ p_ictrl_dispatch_event((event_t *)&focusEvent);
+ closeSession();
+ }
+}
+
+bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId)
+{
+ Q_UNUSED(scan);
+
+ if (!hasSession())
return false;
int key = (flags & KEY_SYM_VALID) ? sym : cap;
- bool navKey = false;
- switch ( key ) {
+ bool navigationKey = false;
+ switch (key) {
case KEYCODE_RETURN:
/* In a single line edit we should end composition because enter might be used by something.
endComposition();
@@ -1007,27 +877,22 @@ bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan
break;
case KEYCODE_LEFT:
key = NAVIGATE_LEFT;
- navKey = true;
+ navigationKey = true;
break;
case KEYCODE_RIGHT:
key = NAVIGATE_RIGHT;
- navKey = true;
+ navigationKey = true;
break;
case KEYCODE_UP:
key = NAVIGATE_UP;
- navKey = true;
+ navigationKey = true;
break;
case KEYCODE_DOWN:
key = NAVIGATE_DOWN;
- navKey = true;
+ navigationKey = true;
break;
- case KEYCODE_CAPS_LOCK:
- case KEYCODE_LEFT_SHIFT:
- case KEYCODE_RIGHT_SHIFT:
case KEYCODE_LEFT_CTRL:
case KEYCODE_RIGHT_CTRL:
- case KEYCODE_LEFT_ALT:
- case KEYCODE_RIGHT_ALT:
case KEYCODE_MENU:
case KEYCODE_LEFT_HYPER:
case KEYCODE_RIGHT_HYPER:
@@ -1041,85 +906,183 @@ bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan
break;
}
- if ( mod & KEYMOD_CTRL ) {
- // If CTRL is pressed, just let AIR handle it. But terminate any composition first
- //endComposition();
- return false;
- }
-
// Pass the keys we don't know about on through
if ( key == 0 )
return false;
- // IMF doesn't need key releases so just swallow them.
- if (!(flags & KEY_DOWN))
- return true;
-
- if ( navKey ) {
+ if (navigationKey) {
// Even if we're forwarding up events, we can't do this for
// navigation keys.
if ( flags & KEY_DOWN ) {
navigation_event_t navEvent;
- initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key);
+ initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key, sizeof(navEvent));
navEvent.magnitude = 1;
- qInputContextDebug() << Q_FUNC_INFO << "dispatch navigation event " << key;
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even navigation" << key;
p_ictrl_dispatch_event(&navEvent.event);
}
- }
- else {
+ } else {
key_event_t keyEvent;
- initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP);
- keyEvent.key_code = key;
- keyEvent.character = 0;
- keyEvent.meta_key_state = 0;
+ initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP,
+ sizeof(keyEvent));
+ keyEvent.key_code = cap;
+ keyEvent.character = sym;
+ keyEvent.meta_key_state = mod;
+ keyEvent.sequence_id = sequenceId;
p_ictrl_dispatch_event(&keyEvent.event);
- qInputContextDebug() << Q_FUNC_INFO << "dispatch key event " << key;
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even key" << key;
}
- scan = 0;
return true;
}
-void QQnxInputContext::endComposition()
+void QQnxInputContext::updateCursorPosition()
{
- if (!m_isComposing)
+ QObject *input = qGuiApp->focusObject();
+ if (!input)
return;
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ QInputMethodQueryEvent query(Qt::ImCursorPosition);
+ QCoreApplication::sendEvent(input, &query);
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
+
+ qInputContextDebug() << Q_FUNC_INFO << m_caretPosition;
+}
+
+void QQnxInputContext::endComposition()
+{
+ if (!m_isComposing)
return;
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(m_composingText);
- m_composingText = QString();
- m_isComposing = false;
- QCoreApplication::sendEvent(input, &event);
+ finishComposingText();
- action_event_t actionEvent;
- memset(&actionEvent, 0, sizeof(actionEvent));
- initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION);
- p_ictrl_dispatch_event(&actionEvent.event);
+ if (hasSession()) {
+ action_event_t actionEvent;
+ initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION, sizeof(actionEvent));
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even end composition";
+ p_ictrl_dispatch_event(&actionEvent.event);
+ }
}
-void QQnxInputContext::setComposingText(QString const& composingText)
+void QQnxInputContext::updateComposition(spannable_string_t *text, int32_t new_cursor_position)
{
- m_composingText = composingText;
+ QObject *input = qGuiApp->focusObject();
+ if (!input)
+ return;
+
+ if (new_cursor_position > 0)
+ new_cursor_position += text->length - 1;
+
+ m_composingText = QString::fromWCharArray(text->str, text->length);
m_isComposing = true;
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return;
+ qInputContextDebug() << Q_FUNC_INFO << m_composingText << new_cursor_position;
QList<QInputMethodEvent::Attribute> attributes;
- QTextCharFormat format;
- format.setFontUnderline(true);
- attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, composingText.length(), format));
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ new_cursor_position,
+ 1,
+ QVariant()));
+
+ for (unsigned int i = 0; i < text->spans_count; ++i) {
+ QColor highlightColor;
+ bool underline = false;
+
+ if ((text->spans[i].attributes_mask & COMPOSED_TEXT_ATTRIB) != 0)
+ underline = true;
+
+ if ((text->spans[i].attributes_mask & ACTIVE_REGION_ATTRIB) != 0) {
+ underline = true;
+ highlightColor = m_highlightColor[ActiveRegion];
+ } else if ((text->spans[i].attributes_mask & AUTO_CORRECTION_ATTRIB) != 0) {
+ highlightColor = m_highlightColor[AutoCorrected];
+ } else if ((text->spans[i].attributes_mask & REVERT_CORRECTION_ATTRIB) != 0) {
+ highlightColor = m_highlightColor[Reverted];
+ }
- QInputMethodEvent event(composingText, attributes);
+ if (underline || highlightColor.isValid()) {
+ QTextCharFormat format;
+ if (underline)
+ format.setFontUnderline(true);
+ if (highlightColor.isValid())
+ format.setBackground(QBrush(highlightColor));
+ qInputContextDebug() << " attrib: " << underline << highlightColor << text->spans[i].start << text->spans[i].end;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, text->spans[i].start,
+ text->spans[i].end - text->spans[i].start + 1, QVariant(format)));
+ }
+ }
+ QInputMethodEvent event(m_composingText, attributes);
+ m_isUpdatingText = true;
QCoreApplication::sendEvent(input, &event);
+ m_isUpdatingText = false;
+
+ updateCursorPosition();
+}
+
+void QQnxInputContext::finishComposingText()
+{
+ QObject *input = qGuiApp->focusObject();
+
+ if (input) {
+ qInputContextDebug() << Q_FUNC_INFO << m_composingText;
+
+ QInputMethodEvent event;
+ event.setCommitString(m_composingText);
+ m_isUpdatingText = true;
+ QCoreApplication::sendEvent(input, &event);
+ m_isUpdatingText = false;
+ }
+ m_composingText = QString();
+ m_isComposing = false;
+
+ updateCursorPosition();
+}
+
+// Return the index relative to a UTF-16 sequence of characters for a index that is relative to the
+// corresponding UTF-32 character string given a starting index in the UTF-16 string and a count
+// of the number of lead surrogates prior to that index. Updates the highSurrogateCount to reflect the
+// new surrogate characters encountered.
+static int adjustIndex(const QChar *text, int utf32Index, int utf16StartIndex, int *highSurrogateCount)
+{
+ int utf16Index = utf32Index + *highSurrogateCount;
+ while (utf16StartIndex < utf16Index) {
+ if (text[utf16StartIndex].isHighSurrogate()) {
+ ++utf16Index;
+ ++*highSurrogateCount;
+ }
+ ++utf16StartIndex;
+ }
+ return utf16StartIndex;
+}
+
+int QQnxInputContext::handleSpellCheck(spell_check_event_t *event)
+{
+ // These should never happen.
+ if (sSpellCheckQueue->isEmpty() || event->event.event_id != NOTIFY_SP_CHECK_MISSPELLINGS)
+ return -1;
+
+ SpellCheckInfo callerInfo = sSpellCheckQueue->dequeue();
+ spannable_string_t* spellCheckData = *event->data;
+ QString text = QString::fromWCharArray(spellCheckData->str, spellCheckData->length);
+ // Generate the list of indices indicating misspelled words in the text. We use end + 1
+ // since it's more conventional to have the end index point just past the string. We also
+ // can't use the indices directly since they are relative to UTF-32 encoded data and the
+ // conversion to Qt's UTF-16 internal format might cause lengthening.
+ QList<int> indices;
+ int adjustment = 0;
+ int index = 0;
+ for (unsigned int i = 0; i < spellCheckData->spans_count; ++i) {
+ if (spellCheckData->spans[i].attributes_mask & MISSPELLED_WORD_ATTRIB) {
+ index = adjustIndex(text.data(), spellCheckData->spans[i].start, index, &adjustment);
+ indices.push_back(index);
+ index = adjustIndex(text.data(), spellCheckData->spans[i].end + 1, index, &adjustment);
+ indices.push_back(index);
+ }
+ }
+ callerInfo.spellCheckDone(callerInfo.context, text, indices);
+
+ return 0;
}
int32_t QQnxInputContext::processEvent(event_t *event)
@@ -1128,7 +1091,7 @@ int32_t QQnxInputContext::processEvent(event_t *event)
switch (event->event_type) {
case EVENT_SPELL_CHECK: {
qInputContextDebug() << Q_FUNC_INFO << "EVENT_SPELL_CHECK";
- result = 0;
+ result = handleSpellCheck(reinterpret_cast<spell_check_event_t *>(event));
break;
}
@@ -1140,19 +1103,24 @@ int32_t QQnxInputContext::processEvent(event_t *event)
event->event_id == NAVIGATE_LEFT ? KEYCODE_LEFT :
event->event_id == NAVIGATE_RIGHT ? KEYCODE_RIGHT : 0;
- QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0);
- QQnxEventThread::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0);
+ QQnxScreenEventHandler::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0);
+ QQnxScreenEventHandler::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0);
result = 0;
break;
}
case EVENT_KEY: {
- qInputContextDebug() << Q_FUNC_INFO << "EVENT_KEY";
- key_event_t *kevent = static_cast<key_event_t *>(event);
-
- QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_SYM_VALID | KEY_CAP_VALID, kevent->key_code, 0, 0, kevent->key_code);
- QQnxEventThread::injectKeyboardEvent(KEY_SYM_VALID | KEY_CAP_VALID, kevent->key_code, 0, 0, kevent->key_code);
-
+ key_event_t *kevent = reinterpret_cast<key_event_t *>(event);
+ int keySym = kevent->character != 0 ? kevent->character : kevent->key_code;
+ int keyCap = kevent->key_code;
+ int modifiers = 0;
+ if (kevent->meta_key_state & META_SHIFT_ON)
+ modifiers |= KEYMOD_SHIFT;
+ int flags = KEY_SYM_VALID | KEY_CAP_VALID;
+ if (event->event_id == IMF_KEY_DOWN)
+ flags |= KEY_DOWN;
+ qInputContextDebug() << Q_FUNC_INFO << "EVENT_KEY" << flags << keySym;
+ QQnxScreenEventHandler::injectKeyboardEvent(flags, keySym, modifiers, 0, keyCap);
result = 0;
break;
}
@@ -1179,339 +1147,175 @@ int32_t QQnxInputContext::processEvent(event_t *event)
* IMF Event Handlers
*/
-int32_t QQnxInputContext::onBeginBatchEdit(input_session_t *ic)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // We don't care.
- return 0;
-}
-
-int32_t QQnxInputContext::onClearMetaKeyStates(input_session_t *ic, int32_t states)
-{
- Q_UNUSED(states);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onClearMetaKeyStates is unsupported.";
- return 0;
-}
-
-int32_t QQnxInputContext::onCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+int32_t QQnxInputContext::onCommitText(spannable_string_t *text, int32_t new_cursor_position)
{
- Q_UNUSED(new_cursor_position); // TODO: How can we set the cursor position it's not part of the API.
- if (!isSessionOkay(ic))
- return 0;
-
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
-
- QString commitString = QString::fromWCharArray(text->str, text->length);
-
- qInputContextDebug() << Q_FUNC_INFO << "Committing [" << commitString << "]";
-
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(commitString, 0, 0);
+ Q_UNUSED(new_cursor_position);
- QCoreApplication::sendEvent(input, &event);
- m_composingText = QString();
+ updateComposition(text, new_cursor_position);
+ finishComposingText();
return 0;
}
-int32_t QQnxInputContext::onDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length)
+int32_t QQnxInputContext::onDeleteSurroundingText(int32_t left_length, int32_t right_length)
{
qInputContextDebug() << Q_FUNC_INFO << "L:" << left_length << " R:" << right_length;
- if (!isSessionOkay(ic))
- return 0;
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
-
- if (hasSelectedText()) {
- QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, KEYCODE_DELETE, 0, 0, 0);
- QQnxEventThread::injectKeyboardEvent(KEY_CAP_VALID, KEYCODE_DELETE, 0, 0, 0);
- reset();
+ if (!input)
return 0;
- }
int replacementLength = left_length + right_length;
int replacementStart = -left_length;
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(QLatin1String(""), replacementStart, replacementLength);
- QCoreApplication::sendEvent(input, &event);
-
- return 0;
-}
-
-int32_t QQnxInputContext::onEndBatchEdit(input_session_t *ic)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- return 0;
-}
-
-int32_t QQnxInputContext::onFinishComposingText(input_session_t *ic)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
+ finishComposingText();
- // Only update the control, no need to send a message back to imf (don't call
- // end composition)
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(m_composingText);
- m_composingText = QString();
- m_isComposing = false;
+ QInputMethodEvent event;
+ event.setCommitString(QString(), replacementStart, replacementLength);
+ m_isUpdatingText = true;
QCoreApplication::sendEvent(input, &event);
+ m_isUpdatingText = false;
- return 0;
-}
-
-int32_t QQnxInputContext::onGetCursorCapsMode(input_session_t *ic, int32_t req_modes)
-{
- Q_UNUSED(req_modes);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onGetCursorCapsMode is unsupported.";
+ updateCursorPosition();
return 0;
}
-int32_t QQnxInputContext::onGetCursorPosition(input_session_t *ic)
+int32_t QQnxInputContext::onFinishComposingText()
{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ finishComposingText();
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
-
- QInputMethodQueryEvent query(Qt::ImCursorPosition);
- QCoreApplication::sendEvent(input, &query);
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
-
- return m_lastCaretPos;
-}
-
-extracted_text_t *QQnxInputContext::onGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
-{
- Q_UNUSED(flags);
- Q_UNUSED(request);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic)) {
- extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1);
- et->text = reinterpret_cast<spannable_string_t *>(calloc(sizeof(spannable_string_t),1));
- return et;
- }
-
- // Used to update dictionaries, but not supported right now.
- extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1);
- et->text = reinterpret_cast<spannable_string_t *>(calloc(sizeof(spannable_string_t),1));
-
- return et;
+ return 0;
}
-spannable_string_t *QQnxInputContext::onGetSelectedText(input_session_t *ic, int32_t flags)
+int32_t QQnxInputContext::onGetCursorPosition()
{
- Q_UNUSED(flags);
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return 0;
- QInputMethodQueryEvent query(Qt::ImCurrentSelection);
- QCoreApplication::sendEvent(input, &query);
- QString text = query.value(Qt::ImCurrentSelection).toString();
+ updateCursorPosition();
- return toSpannableString(text);
+ return m_caretPosition;
}
-spannable_string_t *QQnxInputContext::onGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags)
+spannable_string_t *QQnxInputContext::onGetTextAfterCursor(int32_t n, int32_t flags)
{
Q_UNUSED(flags);
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return toSpannableString("");
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText);
QCoreApplication::sendEvent(input, &query);
QString text = query.value(Qt::ImSurroundingText).toString();
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
- return toSpannableString(text.mid(m_lastCaretPos+1, n));
+ return toSpannableString(text.mid(m_caretPosition, n));
}
-spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags)
+spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(int32_t n, int32_t flags)
{
Q_UNUSED(flags);
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return toSpannableString("");
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText);
QCoreApplication::sendEvent(input, &query);
QString text = query.value(Qt::ImSurroundingText).toString();
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
- if (n < m_lastCaretPos)
- return toSpannableString(text.mid(m_lastCaretPos - n, n));
+ if (n < m_caretPosition)
+ return toSpannableString(text.mid(m_caretPosition - n, n));
else
- return toSpannableString(text.mid(0, m_lastCaretPos));
-}
-
-int32_t QQnxInputContext::onPerformEditorAction(input_session_t *ic, int32_t editor_action)
-{
- Q_UNUSED(editor_action);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onPerformEditorAction is unsupported.";
-
- return 0;
-}
-
-int32_t QQnxInputContext::onReportFullscreenMode(input_session_t *ic, int32_t enabled)
-{
- Q_UNUSED(enabled);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onReportFullscreenMode is unsupported.";
-
- return 0;
-}
-
-int32_t QQnxInputContext::onSendEvent(input_session_t *ic, event_t *event)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- return processEvent(event);
+ return toSpannableString(text.mid(0, m_caretPosition));
}
-int32_t QQnxInputContext::onSendAsyncEvent(input_session_t *ic, event_t *event)
+int32_t QQnxInputContext::onSendEvent(event_t *event)
{
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return 0;
-
return processEvent(event);
}
-int32_t QQnxInputContext::onSetComposingRegion(input_session_t *ic, int32_t start, int32_t end)
+int32_t QQnxInputContext::onSetComposingRegion(int32_t start, int32_t end)
{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return 0;
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText);
QCoreApplication::sendEvent(input, &query);
QString text = query.value(Qt::ImSurroundingText).toString();
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
- QString empty = QString::fromLatin1("");
- text = text.mid(start, end - start);
+ qInputContextDebug() << Q_FUNC_INFO << text;
+
+ m_isUpdatingText = true;
// Delete the current text.
+ QInputMethodEvent deleteEvent;
+ deleteEvent.setCommitString(QString(), start - m_caretPosition, end - start);
+ QCoreApplication::sendEvent(input, &deleteEvent);
+
+ m_composingText = text.mid(start, end - start);
+ m_isComposing = true;
+
QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(empty, attributes);
- event.setCommitString(empty, start - m_lastCaretPos, end - start);
- QCoreApplication::sendEvent(input, &event);
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, m_composingText.length(), format));
+
+ QInputMethodEvent setTextEvent(m_composingText, attributes);
+ QCoreApplication::sendEvent(input, &setTextEvent);
- // Move the specified text into a preedit string.
- setComposingText(text);
+ m_isUpdatingText = false;
return 0;
}
-int32_t QQnxInputContext::onSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+int32_t QQnxInputContext::onSetComposingText(spannable_string_t *text, int32_t new_cursor_position)
{
- Q_UNUSED(new_cursor_position);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
+ if (text->length > 0) {
+ updateComposition(text, new_cursor_position);
+ } else {
+ // If the composing text is empty we can simply end composition, the visual effect is the same.
+ // However, sometimes one wants to display hint text in an empty text field and for this to work
+ // QQuickTextEdit.inputMethodComposing has to be false if the composition string is empty.
+ m_composingText.clear();
+ finishComposingText();
+ }
+ return 0;
+}
- m_isComposing = true;
+int32_t QQnxInputContext::onIsTextSelected(int32_t* pIsSelected)
+{
+ *pIsSelected = hasSelectedText();
- QString preeditString = QString::fromWCharArray(text->str, text->length);
- setComposingText(preeditString);
+ qInputContextDebug() << Q_FUNC_INFO << *pIsSelected;
return 0;
}
-int32_t QQnxInputContext::onSetSelection(input_session_t *ic, int32_t start, int32_t end)
+int32_t QQnxInputContext::onIsAllTextSelected(int32_t* pIsSelected)
{
- Q_UNUSED(start);
- Q_UNUSED(end);
- qInputContextDebug() << Q_FUNC_INFO;
+ QObject *input = qGuiApp->focusObject();
+ if (!input)
+ return -1;
- if (!isSessionOkay(ic))
- return 0;
+ QInputMethodQueryEvent query(Qt::ImCurrentSelection | Qt::ImSurroundingText);
+ QCoreApplication::sendEvent(input, &query);
+
+ *pIsSelected = query.value(Qt::ImSurroundingText).toString().length() == query.value(Qt::ImCurrentSelection).toString().length();
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onSetSelection is unsupported.";
+ qInputContextDebug() << Q_FUNC_INFO << *pIsSelected;
return 0;
}
@@ -1556,19 +1360,74 @@ void QQnxInputContext::keyboardLocaleChanged(const QLocale &locale)
}
}
+void QQnxInputContext::setHighlightColor(int index, const QColor &color)
+{
+ qInputContextDebug() << Q_FUNC_INFO << "setHighlightColor" << index << color << qGuiApp->focusObject();
+
+ if (!sInputContextInstance)
+ return;
+
+ // If the focus has changed, revert all colors to the default.
+ if (sInputContextInstance->m_focusObject != qGuiApp->focusObject()) {
+ QColor invalidColor;
+ sInputContextInstance->m_highlightColor[ActiveRegion] = sSelectedColor;
+ sInputContextInstance->m_highlightColor[AutoCorrected] = invalidColor;
+ sInputContextInstance->m_highlightColor[Reverted] = invalidColor;
+ sInputContextInstance->m_focusObject = qGuiApp->focusObject();
+ }
+ if (index >= 0 && index <= Reverted)
+ sInputContextInstance->m_highlightColor[index] = color;
+}
+
void QQnxInputContext::setFocusObject(QObject *object)
{
qInputContextDebug() << Q_FUNC_INFO << "input item=" << object;
+ // Ensure the colors are reset if we've a change in focus object
+ setHighlightColor(-1, QColor());
+
if (!inputMethodAccepted()) {
if (m_inputPanelVisible)
hideInputPanel();
+ if (hasSession())
+ dispatchFocusLossEvent();
} else {
- m_virtualKeyboard.setInputHintsFromObject(object);
+ QInputMethodQueryEvent query(Qt::ImHints);
+ QCoreApplication::sendEvent(object, &query);
+ int inputHints = query.value(Qt::ImHints).toInt();
+
+ dispatchFocusGainEvent(inputHints);
+
+ m_virtualKeyboard.setInputHints(inputHints);
if (!m_inputPanelVisible)
showInputPanel();
}
}
+bool QQnxInputContext::checkSpelling(const QString &text, void *context, void (*spellCheckDone)(void *context, const QString &text, const QList<int> &indices))
+{
+ qInputContextDebug() << Q_FUNC_INFO << "text" << text;
+
+ if (!imfAvailable())
+ return false;
+
+ if (!sSpellCheckSession)
+ sSpellCheckSession = p_ictrl_open_session(&ic_funcs);
+
+ action_event_t spellEvent;
+ initEvent(&spellEvent.event, sSpellCheckSession, EVENT_ACTION, ACTION_CHECK_MISSPELLINGS, sizeof(spellEvent));
+ int len = text.length();
+ spellEvent.event_data = alloca(sizeof(wchar_t) * (len + 1));
+ spellEvent.length_data = text.toWCharArray(static_cast<wchar_t*>(spellEvent.event_data)) * sizeof(wchar_t);
+
+ int rc = p_ictrl_dispatch_event(reinterpret_cast<event_t*>(&spellEvent));
+
+ if (rc == 0) {
+ sSpellCheckQueue->enqueue(SpellCheckInfo(context, spellCheckDone));
+ return true;
+ }
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h
index 1980a99ed9..5028215bbe 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -43,9 +43,11 @@
#define QQNXINPUTCONTEXT_H
#include <qpa/qplatforminputcontext.h>
+#include "qqnxscreeneventfilter.h"
#include <QtCore/QLocale>
#include <QtCore/QMetaType>
+#include <QtCore/QList>
#include <qpa/qplatformintegration.h>
#include "imf/imf_client.h"
@@ -55,21 +57,30 @@ QT_BEGIN_NAMESPACE
class QQnxAbstractVirtualKeyboard;
class QQnxIntegration;
+class QQnxImfRequest;
-class QQnxInputContext : public QPlatformInputContext
+class QQnxInputContext : public QPlatformInputContext, public QQnxScreenEventFilter
{
Q_OBJECT
public:
explicit QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard);
~QQnxInputContext();
+ // Indices for selecting and setting highlight colors.
+ enum HighlightIndex {
+ ActiveRegion,
+ AutoCorrected,
+ Reverted,
+ };
+
bool isValid() const;
bool filterEvent(const QEvent *event);
QRectF keyboardRect() const;
void reset();
+ void commit();
void update(Qt::InputMethodQueries);
- bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap);
+ bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId);
void showInputPanel();
@@ -79,61 +90,62 @@ public:
QLocale locale() const;
void setFocusObject(QObject *object);
-protected:
- // Filters only for IMF events.
- bool eventFilter(QObject *obj, QEvent *event);
+ static void setHighlightColor(int index, const QColor &color);
+
+ static bool checkSpelling(const QString &text, void *context, void (*spellCheckDone)(void *context, const QString &text, const QList<int> &indices));
private Q_SLOTS:
void keyboardVisibilityChanged(bool visible);
void keyboardLocaleChanged(const QLocale &locale);
+ void processImfEvent(QQnxImfRequest *event);
private:
// IMF Event dispatchers
- bool dispatchFocusEvent(FocusEventId id, int hints = Qt::ImhNone);
+ bool dispatchFocusGainEvent(int inputHints);
+ void dispatchFocusLossEvent();
bool dispatchRequestSoftwareInputPanel();
bool dispatchCloseSoftwareInputPanel();
+ int handleSpellCheck(spell_check_event_t *event);
int32_t processEvent(event_t *event);
void closeSession();
- void openSession();
+ bool openSession();
bool hasSession();
+ void updateCursorPosition();
void endComposition();
- void setComposingText(QString const &composingText);
+ void finishComposingText();
bool hasSelectedText();
+ void updateComposition(spannable_string_t *text, int32_t new_cursor_position);
// IMF Event handlers - these events will come in from QCoreApplication.
- int32_t onBeginBatchEdit(input_session_t *ic);
- int32_t onClearMetaKeyStates(input_session_t *ic, int32_t states);
- int32_t onCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position);
- int32_t onDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length);
- int32_t onEndBatchEdit(input_session_t *ic);
- int32_t onFinishComposingText(input_session_t *ic);
- int32_t onGetCursorCapsMode(input_session_t *ic, int32_t req_modes);
- int32_t onGetCursorPosition(input_session_t *ic);
- extracted_text_t *onGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags);
- spannable_string_t *onGetSelectedText(input_session_t *ic, int32_t flags);
- spannable_string_t *onGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags);
- spannable_string_t *onGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags);
- int32_t onPerformEditorAction(input_session_t *ic, int32_t editor_action);
- int32_t onReportFullscreenMode(input_session_t *ic, int32_t enabled);
- int32_t onSendEvent(input_session_t *ic, event_t *event);
- int32_t onSendAsyncEvent(input_session_t *ic, event_t *event);
- int32_t onSetComposingRegion(input_session_t *ic, int32_t start, int32_t end);
- int32_t onSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position);
- int32_t onSetSelection(input_session_t *ic, int32_t start, int32_t end);
+ int32_t onCommitText(spannable_string_t *text, int32_t new_cursor_position);
+ int32_t onDeleteSurroundingText(int32_t left_length, int32_t right_length);
+ int32_t onGetCursorCapsMode(int32_t req_modes);
+ int32_t onFinishComposingText();
+ int32_t onGetCursorPosition();
+ spannable_string_t *onGetTextAfterCursor(int32_t n, int32_t flags);
+ spannable_string_t *onGetTextBeforeCursor(int32_t n, int32_t flags);
+ int32_t onSendEvent(event_t *event);
+ int32_t onSetComposingRegion(int32_t start, int32_t end);
+ int32_t onSetComposingText(spannable_string_t *text, int32_t new_cursor_position);
+ int32_t onIsTextSelected(int32_t* pIsSelected);
+ int32_t onIsAllTextSelected(int32_t* pIsSelected);
int32_t onForceUpdate();
- int m_lastCaretPos;
+ int m_caretPosition;
bool m_isComposing;
QString m_composingText;
+ bool m_isUpdatingText;
bool m_inputPanelVisible;
QLocale m_inputPanelLocale;
+ // The object that had focus when the last highlight color was set.
+ QObject *m_focusObject;
+ // Indexed by HighlightIndex
+ QColor m_highlightColor[3];
QQnxIntegration *m_integration;
- QQnxAbstractVirtualKeyboard &m_virtualKeyboad;
+ QQnxAbstractVirtualKeyboard &m_virtualKeyboard;
};
-Q_DECLARE_METATYPE(extracted_text_t*)
-
QT_END_NAMESPACE
#endif // QQNXINPUTCONTEXT_H
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
index f444d34b5e..9270f1ed6b 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,6 +46,7 @@
#include <QtCore/QDebug>
#include <QtGui/QGuiApplication>
+#include <QtGui/QInputMethodEvent>
#if defined(QQNXINPUTCONTEXT_DEBUG)
#define qInputContextDebug qDebug
@@ -179,7 +180,11 @@ void QQnxInputContext::setFocusObject(QObject *object)
if (m_inputPanelVisible)
hideInputPanel();
} else {
- m_virtualKeyboard.setInputHintsFromObject(object);
+ QInputMethodQueryEvent query(Qt::ImHints);
+ QCoreApplication::sendEvent(object, &query);
+ int inputHints = query.value(Qt::ImHints).toInt();
+
+ m_virtualKeyboard.setInputHints(inputHints);
if (!m_inputPanelVisible)
showInputPanel();
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index 52f836abbe..5695ef433a 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -251,6 +251,9 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
#if defined(QQNX_PPS)
// Set up the input context
m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard);
+#if defined(QQNX_IMF)
+ m_screenEventHandler->addScreenEventFilter(m_inputContext);
+#endif
#endif
}
@@ -271,17 +274,6 @@ QQnxIntegration::~QQnxIntegration()
delete m_drag;
#endif
-#if defined(QQNX_PPS)
- // Destroy the hardware button notifier
- delete m_buttonsNotifier;
-
- // Destroy input context
- delete m_inputContext;
-#endif
-
- // Destroy the keyboard class.
- delete m_virtualKeyboard;
-
#if !defined(QT_NO_CLIPBOARD)
// Delete the clipboard
delete m_clipboard;
@@ -321,6 +313,17 @@ QQnxIntegration::~QQnxIntegration()
QQnxGLContext::shutdown();
#endif
+#if defined(QQNX_PPS)
+ // Destroy the hardware button notifier
+ delete m_buttonsNotifier;
+
+ // Destroy input context
+ delete m_inputContext;
+#endif
+
+ // Destroy the keyboard class.
+ delete m_virtualKeyboard;
+
// Destroy services class
delete m_services;
diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
index e468b051cd..d1ceebfebc 100644
--- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
+++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
@@ -44,6 +44,9 @@
#include "qqnxglcontext.h"
#include "qqnxscreen.h"
#include "qqnxwindow.h"
+#if defined(QQNX_IMF)
+#include "qqnxinputcontext_imf.h"
+#endif
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
@@ -91,4 +94,15 @@ void QQnxNativeInterface::setWindowProperty(QPlatformWindow *window, const QStri
}
}
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QQnxNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+#if defined(QQNX_IMF)
+ if (resource == "blackberryIMFSetHighlightColor")
+ return reinterpret_cast<NativeResourceForIntegrationFunction>(QQnxInputContext::setHighlightColor);
+ if (resource == "blackberryIMFCheckSpelling")
+ return reinterpret_cast<NativeResourceForIntegrationFunction>(QQnxInputContext::checkSpelling);
+#endif
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.h b/src/plugins/platforms/qnx/qqnxnativeinterface.h
index dfd386214e..e2fdd32689 100644
--- a/src/plugins/platforms/qnx/qqnxnativeinterface.h
+++ b/src/plugins/platforms/qnx/qqnxnativeinterface.h
@@ -51,8 +51,10 @@ class QQnxNativeInterface : public QPlatformNativeInterface
public:
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
+
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index a09d6ce1f5..e6c37b8445 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -728,8 +728,6 @@ void QQnxScreen::activateWindowGroup(const QByteArray &id)
if (m_coverWindow)
m_coverWindow->setExposed(false);
-
- QWindowSystemInterface::handleWindowActivated(window);
}
void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
@@ -744,8 +742,6 @@ void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->setExposed(false);
-
- QWindowSystemInterface::handleWindowActivated(rootWindow()->window());
}
QQnxWindow *QQnxScreen::rootWindow() const
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventfilter.h b/src/plugins/platforms/qnx/qqnxscreeneventfilter.h
new file mode 100644
index 0000000000..f9ecadd2a9
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxscreeneventfilter.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQNXSCREENEVENTFILTER_H
+#define QQNXSCREENEVENTFILTER_H
+
+QT_BEGIN_NAMESPACE
+
+class QQnxScreenEventFilter
+{
+protected:
+ ~QQnxScreenEventFilter() {}
+
+public:
+ virtual bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index 6f06797393..1e33e2b50f 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,6 +46,7 @@
#include "qqnxintegration.h"
#include "qqnxkeytranslator.h"
#include "qqnxscreen.h"
+#include "qqnxscreeneventfilter.h"
#include <QDebug>
#include <QGuiApplication>
@@ -90,6 +91,16 @@ QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
}
}
+void QQnxScreenEventHandler::addScreenEventFilter(QQnxScreenEventFilter *filter)
+{
+ m_eventFilters.append(filter);
+}
+
+void QQnxScreenEventHandler::removeScreenEventFilter(QQnxScreenEventFilter *filter)
+{
+ m_eventFilters.removeOne(filter);
+}
+
bool QQnxScreenEventHandler::handleEvent(screen_event_t event)
{
// get the event type
@@ -256,7 +267,23 @@ void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event)
if (result)
qFatal("QQNX: failed to query event cap, errno=%d", errno);
- injectKeyboardEvent(flags, sym, modifiers, scan, cap);
+ int sequenceId = 0;
+#if defined(Q_OS_BLACKBERRY)
+ result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SEQUENCE_ID, &sequenceId);
+ if (result)
+ qFatal("QQNX: failed to query event seqId, errno=%d", errno);
+#endif
+
+ bool inject = true;
+ Q_FOREACH (QQnxScreenEventFilter *filter, m_eventFilters) {
+ if (filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) {
+ inject = false;
+ break;
+ }
+ }
+
+ if (inject)
+ injectKeyboardEvent(flags, sym, modifiers, scan, cap);
}
void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
@@ -314,10 +341,6 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
}
}
- // If we don't have a navigator, we don't get activation events.
- if (buttonState && w && w != QGuiApplication::focusWindow() && !m_qnxIntegration->supportsNavigatorEvents())
- QWindowSystemInterface::handleWindowActivated(w);
-
m_lastMouseWindow = qnxWindow;
// Apply scaling to wheel delta and invert value for Qt. We'll probably want to scale
@@ -589,9 +612,15 @@ void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t wi
if (window && screen_get_window_property_iv(window, SCREEN_PROPERTY_KEYBOARD_FOCUS, &focus) != 0)
qFatal("QQnx: failed to query keyboard focus property, errno=%d", errno);
- QWindow *w = focus ? QQnxIntegration::window(window) : 0;
-
- QWindowSystemInterface::handleWindowActivated(w);
+ QWindow *focusWindow = QQnxIntegration::window(window);
+ if (focus) {
+ QWindowSystemInterface::handleWindowActivated(focusWindow);
+ } else if (focusWindow == QGuiApplication::focusWindow()) {
+ // Deactivate only if the window was the focus window.
+ // Screen might send a keyboard focus event for a newly created
+ // window on the secondary screen, with focus 0.
+ QWindowSystemInterface::handleWindowActivated(0);
+ }
}
#include "moc_qqnxscreeneventhandler.cpp"
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
index 1fdb2c83cd..a7bcd449ee 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
class QQnxIntegration;
+class QQnxScreenEventFilter;
#if defined(QQNX_SCREENEVENTTHREAD)
class QQnxScreenEventThread;
#endif
@@ -59,6 +60,9 @@ class QQnxScreenEventHandler : public QObject
public:
explicit QQnxScreenEventHandler(QQnxIntegration *integration);
+ void addScreenEventFilter(QQnxScreenEventFilter *filter);
+ void removeScreenEventFilter(QQnxScreenEventFilter *filter);
+
bool handleEvent(screen_event_t event);
bool handleEvent(screen_event_t event, int qnxType);
@@ -99,6 +103,7 @@ private:
screen_window_t m_lastMouseWindow;
QTouchDevice *m_touchDevice;
QWindowSystemInterface::TouchPoint m_touchPoints[MaximumTouchPoints];
+ QList<QQnxScreenEventFilter*> m_eventFilters;
#if defined(QQNX_SCREENEVENTTHREAD)
QQnxScreenEventThread *m_eventThread;
#endif
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
index 11eb4a5082..f3a6887613 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -135,6 +135,10 @@ void QQnxVirtualKeyboardBps::applyKeyboardMode(KeyboardMode mode)
layout = VIRTUALKEYBOARD_LAYOUT_PIN;
break;
+ case Password:
+ layout = VIRTUALKEYBOARD_LAYOUT_PASSWORD;
+ break;
+
case Default: // fall through
default:
layout = VIRTUALKEYBOARD_LAYOUT_DEFAULT;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 99071cf4f2..9f8c93cce1 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -478,12 +478,7 @@ void QQnxWindow::lower()
void QQnxWindow::requestActivateWindow()
{
- qWindowDebug() << Q_FUNC_INFO << "window =" << window();
-
- // TODO: Tell screen to set keyboard focus to this window.
-
- // Notify that we gained focus.
- gainedFocus();
+ // Overwrite the default implementation where the window is activated
}
@@ -507,14 +502,6 @@ void QQnxWindow::propagateSizeHints()
qWindowDebug() << Q_FUNC_INFO << ": ignored";
}
-void QQnxWindow::gainedFocus()
-{
- qWindowDebug() << Q_FUNC_INFO << "window =" << window();
-
- // Got focus
- QWindowSystemInterface::handleWindowActivated(window());
-}
-
void QQnxWindow::setMMRendererWindowName(const QString &name)
{
m_mmRendererWindowName = name;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index 3c8070b0be..2f44202b4c 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -93,7 +93,6 @@ public:
void propagateSizeHints();
- void gainedFocus();
void setMMRendererWindowName(const QString &name);
void setMMRendererWindow(screen_window_t handle);
void clearMMRendererWindow();
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 7b574b0a56..ee640224cf 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -73,6 +73,7 @@ enum WindowsEventType // Simplify event types
ExposeEvent = WindowEventFlag + 1,
ActivateWindowEvent = WindowEventFlag + 2,
DeactivateWindowEvent = WindowEventFlag + 3,
+ MouseActivateWindowEvent = WindowEventFlag + 4,
LeaveEvent = WindowEventFlag + 5,
CloseEvent = WindowEventFlag + 6,
ShowEvent = WindowEventFlag + 7,
@@ -131,6 +132,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
case WM_ACTIVATEAPP:
return (int)wParamIn ?
QtWindows::ActivateApplicationEvent : QtWindows::DeactivateApplicationEvent;
+ case WM_MOUSEACTIVATE:
+ return QtWindows::MouseActivateWindowEvent;
case WM_ACTIVATE:
return LOWORD(wParamIn) == WA_INACTIVE ?
QtWindows::DeactivateWindowEvent : QtWindows::ActivateWindowEvent;
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 77cac647ba..a87dfe5f16 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -928,6 +928,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
#ifndef Q_OS_WINCE
case QtWindows::ActivateWindowEvent:
+ if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) {
+ *result = LRESULT(MA_NOACTIVATE);
+ return true;
+ }
#ifndef QT_NO_TABLETEVENT
if (!d->m_tabletSupport.isNull())
d->m_tabletSupport->notifyActivate();
@@ -936,6 +940,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (const QWindow *modalWindow = QGuiApplication::modalWindow())
QWindowsWindow::baseWindowOf(modalWindow)->alertWindow();
break;
+ case QtWindows::MouseActivateWindowEvent:
+ if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) {
+ *result = LRESULT(MA_NOACTIVATE);
+ return true;
+ }
+ break;
#endif
#ifndef QT_NO_CONTEXTMENU
case QtWindows::ContextMenu:
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 3a6f9f72e3..2b6a6255b8 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -1620,7 +1620,8 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFon
result << QString::fromLatin1("Arial");
}
- result.append(extraTryFontsForFamily(family));
+ if (script == QChar::Script_Common || script == QChar::Script_Han)
+ result.append(extraTryFontsForFamily(family));
if (QWindowsContext::verboseFonts)
qDebug() << __FUNCTION__ << family << style << styleHint
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 82deb0f473..281f54a9d9 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -882,7 +882,9 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
m_staticContext(staticContext),
m_context(context),
m_renderingContext(0),
- m_pixelFormat(0), m_extensionsUsed(false)
+ m_pixelFormat(0),
+ m_extensionsUsed(false),
+ m_swapInterval(-1)
{
QSurfaceFormat format = context->format();
if (format.renderableType() == QSurfaceFormat::DefaultRenderableType)
@@ -979,11 +981,9 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
- if (requestedAdditional.swapInterval != -1 && m_staticContext->wglSwapInternalExt) {
- m_staticContext->wglSwapInternalExt(requestedAdditional.swapInterval);
- if (m_staticContext->wglGetSwapInternalExt)
- obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt();
- }
+ if (m_staticContext->wglGetSwapInternalExt)
+ obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt();
+
wglMakeCurrent(0, 0);
} while (false);
if (hdc)
@@ -1087,7 +1087,19 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
window->setFlag(QWindowsWindow::OpenGLDoubleBuffered);
}
m_windowContexts.append(newContext);
- return wglMakeCurrent(newContext.hdc, newContext.renderingContext);
+
+ bool success = wglMakeCurrent(newContext.hdc, newContext.renderingContext);
+
+ // Set the swap interval
+ if (m_staticContext->wglSwapInternalExt) {
+ const int interval = surface->format().swapInterval();
+ if (interval >= 0 && m_swapInterval != interval) {
+ m_swapInterval = interval;
+ m_staticContext->wglSwapInternalExt(interval);
+ }
+ }
+
+ return success;
}
void QWindowsGLContext::doneCurrent()
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 730e90bf70..c6b477128a 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -64,11 +64,10 @@ enum QWindowsGLFormatFlags
// Additional format information for Windows.
struct QWindowsOpenGLAdditionalFormat
{
- QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0, unsigned swapIntervalIn = -1) :
- formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn), swapInterval(swapIntervalIn) {}
+ QWindowsOpenGLAdditionalFormat(unsigned formatFlagsIn = 0, unsigned pixmapDepthIn = 0) :
+ formatFlags(formatFlagsIn), pixmapDepth(pixmapDepthIn) { }
unsigned formatFlags; // QWindowsGLFormatFlags.
unsigned pixmapDepth; // for QWindowsGLRenderToPixmap
- int swapInterval;
};
// Per-window data for active OpenGL contexts.
@@ -178,6 +177,7 @@ private:
PIXELFORMATDESCRIPTOR m_obtainedPixelFormatDescriptor;
int m_pixelFormat;
bool m_extensionsUsed;
+ int m_swapInterval;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index b6e75929f8..e72b1d60c8 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -345,8 +345,8 @@ static inline unsigned parseOptions(const QStringList &paramList)
}
} else if (param == QLatin1String("gl=gdi")) {
options |= QWindowsIntegration::DisableArb;
- } else if (param == QLatin1String("mousefromtouch")) {
- options |= QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch;
+ } else if (param == QLatin1String("nomousefromtouch")) {
+ options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch;
}
}
return options;
@@ -563,11 +563,9 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co
case QPlatformIntegration::SynthesizeMouseFromTouchEvents:
#ifdef Q_OS_WINCE
// We do not want Qt to synthesize mouse events as Windows also does that.
- // Alternatively, Windows-generated touch mouse events can be identified and
- // ignored by checking GetMessageExtraInfo() for MI_WP_SIGNATURE (0xFF515700).
return false;
#else // Q_OS_WINCE
- return QVariant(!(d->m_options & PassOsMouseEventsSynthesizedFromTouch));
+ return QVariant(bool(d->m_options & DontPassOsMouseEventsSynthesizedFromTouch));
#endif // !Q_OS_WINCE
default:
break;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 97916a479b..270ff7ef68 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -60,7 +60,7 @@ public:
DisableArb = 0x4,
NoNativeDialogs = 0x8,
XpNativeDialogs = 0x10,
- PassOsMouseEventsSynthesizedFromTouch = 0x20 // Pass OS-generated mouse events from touch.
+ DontPassOsMouseEventsSynthesizedFromTouch = 0x20 // Do not pass OS-generated mouse events from touch.
};
explicit QWindowsIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 3dd8c5a0cd..b43aafeba0 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -167,8 +167,12 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if (et == QtWindows::MouseWheelEvent)
return translateMouseWheelEvent(window, hwnd, msg, result);
+ Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+
#ifndef Q_OS_WINCE
- static const bool passSynthesizedMouseEvents = QWindowsIntegration::instance()->options() & QWindowsIntegration::PassOsMouseEventsSynthesizedFromTouch;
+ // Check for events synthesized from touch. Lower byte is touch index, 0 means pen.
+ static const bool passSynthesizedMouseEvents =
+ !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch);
if (!passSynthesizedMouseEvents) {
// Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch.
// However, when tablet support is active, extraInfo is a packet serial number. This is not a problem
@@ -177,6 +181,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
const bool fromTouch = (extraInfo & signatureMask) == miWpSignature && (extraInfo & 0x80);
if (fromTouch)
return false;
+ source = Qt::MouseEventSynthesizedBySystem;
}
#endif // !Q_OS_WINCE
@@ -187,7 +192,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
globalPosition, buttons,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ QWindowsKeyMapper::queryKeyboardModifiers(),
+ source);
return false; // Allow further event processing (dragging of windows).
}
@@ -335,7 +341,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}
QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ QWindowsKeyMapper::queryKeyboardModifiers(),
+ source);
m_previousCaptureWindow = hasCapture ? window : 0;
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 51902385e1..d1d50eee73 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1193,7 +1193,7 @@ void QWindowsWindow::hide_sys() const
if (flags & Qt::Popup)
ShowWindow(m_data.hwnd, SW_HIDE);
else
- SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
+ SetWindowPos(m_data.hwnd,0, 0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
}
}
diff --git a/src/plugins/platforms/winrt/blit.hlsl b/src/plugins/platforms/winrt/blit.hlsl
new file mode 100644
index 0000000000..170e7f40ca
--- /dev/null
+++ b/src/plugins/platforms/winrt/blit.hlsl
@@ -0,0 +1,14 @@
+uniform SamplerState Sampler : register(s0);
+uniform Texture2D Texture : register(t0);
+
+void blitvs(in float4 pos0 : TEXCOORD0, in float2 tex0 : TEXCOORD1,
+ out float4 gl_Position : SV_POSITION, out float2 coord : TEXCOORD0)
+{
+ coord = tex0;
+ gl_Position = pos0 * float4(1.0, -1.0, 1.0, 1.0);
+}
+
+float4 blitps(in float4 gl_Position : SV_POSITION, in float2 coord : TEXCOORD0) : SV_TARGET0
+{
+ return Texture.Sample(Sampler, coord);
+}
diff --git a/src/plugins/platforms/winrt/main.cpp b/src/plugins/platforms/winrt/main.cpp
new file mode 100644
index 0000000000..89d560dbe3
--- /dev/null
+++ b/src/plugins/platforms/winrt/main.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtintegration.h"
+
+#include <qpa/qplatformintegrationplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "winrt.json")
+
+public:
+ QStringList keys() const;
+ QPlatformIntegration *create(const QString&, const QStringList&);
+};
+
+QStringList QWinRTIntegrationPlugin::keys() const
+{
+ return QStringList(QStringLiteral("WinRT"));
+}
+
+QPlatformIntegration *QWinRTIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+ Q_UNUSED(paramList);
+ if (!system.compare(QLatin1String("winrt"), Qt::CaseInsensitive))
+ return QWinRTIntegration::create();
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
new file mode 100644
index 0000000000..b219548788
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtbackingstore.h"
+
+#include "qwinrtscreen.h"
+#include "qwinrtwindow.h"
+#include "qwinrteglcontext.h"
+#include <QtGui/QOpenGLContext>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <dxgi.h>
+
+// Generated shader headers
+#include "blitps.h"
+#include "blitvs.h"
+
+namespace { // Utility namespace for writing out an ANGLE-compatible binary blob
+
+// Must match packaged ANGLE
+enum : quint32 {
+ AngleMajorVersion = 1,
+ AngleMinorVersion = 2,
+ AngleBuildRevision = 2446,
+ AngleVersion = ((AngleMajorVersion << 24) | (AngleMinorVersion << 16) | AngleBuildRevision),
+ AngleOptimizationLevel = (1 << 14)
+};
+
+struct ShaderString
+{
+ ShaderString(const char *data = 0) : data(data) { }
+ const char *data;
+};
+
+// ANGLE stream compatibility - when size_t is 32-bit, QDataStream::writeBytes() also works
+QDataStream &operator<<(QDataStream &stream, const ShaderString &shaderString)
+{
+ if (!shaderString.data)
+ return stream << size_t(0);
+
+ size_t len = strlen(shaderString.data);
+ stream << len;
+ stream.writeRawData(shaderString.data, int(len));
+ return stream;
+}
+
+struct Attribute
+{
+ Attribute(GLenum type = 0, const char *name = 0, quint32 index = 0)
+ : type(type), name(name), index(index) { }
+ GLenum type;
+ ShaderString name;
+ quint32 index;
+};
+
+struct Sampler
+{
+ enum TextureType { Texture2D, TextureCube };
+ Sampler(bool active = false, GLint unit = 0, TextureType type = Texture2D)
+ : active(active), unit(unit), type(type) { }
+ bool active;
+ GLint unit;
+ TextureType type;
+};
+
+struct Uniform
+{
+ Uniform() { }
+ Uniform(GLenum type, quint32 precision, const char *name, quint32 arraySize,
+ quint32 psRegisterIndex, quint32 vsRegisterIndex, quint32 registerCount)
+ : type(type), precision(precision), name(name), arraySize(arraySize)
+ , psRegisterIndex(psRegisterIndex), vsRegisterIndex(vsRegisterIndex), registerCount(registerCount) { }
+ GLenum type;
+ quint32 precision;
+ ShaderString name;
+ quint32 arraySize;
+ quint32 psRegisterIndex;
+ quint32 vsRegisterIndex;
+ quint32 registerCount;
+};
+
+struct UniformIndex
+{
+ UniformIndex(const char *name = 0, quint32 element = 0, quint32 index = 0)
+ : name(name), element(element), index(index) { }
+ ShaderString name;
+ quint32 element;
+ quint32 index;
+};
+
+static const QByteArray createAngleBinary(
+ const QVector<Attribute> &attributes,
+ const QVector<Sampler> &textureSamplers,
+ const QVector<Sampler> &vertexSamplers,
+ const QVector<Uniform> &uniforms,
+ const QVector<UniformIndex> &uniformIndex,
+ const QByteArray &pixelShader,
+ const QByteArray &vertexShader,
+ const QByteArray &geometryShader = QByteArray(),
+ bool usesPointSize = false)
+{
+ QByteArray binary;
+
+ QDataStream stream(&binary, QIODevice::WriteOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+
+ stream << quint32(GL_PROGRAM_BINARY_ANGLE)
+ << quint32(AngleVersion)
+ << quint32(AngleOptimizationLevel);
+
+ // Vertex attributes
+ for (int i = 0; i < 16; ++i) {
+ if (i < attributes.size())
+ stream << quint32(attributes[i].type) << attributes[i].name << attributes[i].index;
+ else
+ stream << quint32(GL_NONE) << ShaderString() << qint32(-1);
+ }
+
+ // Texture units
+ for (int i = 0; i < 16; ++i) {
+ if (i < textureSamplers.size())
+ stream << textureSamplers[i].active << textureSamplers[i].unit << qint32(textureSamplers[i].type);
+ else
+ stream << false << qint32(0) << qint32(Sampler::Texture2D);
+ }
+
+ // Vertex texture units
+ for (int i = 0; i < 16; ++i) {
+ if (i < vertexSamplers.size())
+ stream << vertexSamplers[i].active << vertexSamplers[i].unit << qint32(vertexSamplers[i].type);
+ else
+ stream << false << qint32(0) << qint32(Sampler::Texture2D);
+ }
+
+ stream << vertexSamplers.size()
+ << textureSamplers.size()
+ << usesPointSize;
+
+ stream << size_t(uniforms.size());
+ foreach (const Uniform &uniform, uniforms) {
+ stream << uniform.type << uniform.precision << uniform.name << uniform.arraySize
+ << uniform.psRegisterIndex << uniform.vsRegisterIndex << uniform.registerCount;
+ }
+
+ stream << size_t(uniformIndex.size());
+ foreach (const UniformIndex &index, uniformIndex)
+ stream << index.name << index.element << index.index;
+
+ stream << quint32(pixelShader.size())
+ << quint32(vertexShader.size())
+ << quint32(geometryShader.size());
+
+ // ANGLE requires that we query the adapter for its LUID. Later on, it may be useful
+ // for checking feature level support, picking the best adapter on the system, etc.
+ IDXGIFactory1 *dxgiFactory;
+ if (FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)))) {
+ qCritical("QWinRTBackingStore: failed to create DXGI factory.");
+ return QByteArray();
+ }
+ IDXGIAdapter *dxgiAdapter;
+ if (FAILED(dxgiFactory->EnumAdapters(0, &dxgiAdapter))) {
+ qCritical("QWinRTBackingStore:: failed to enumerate adapter.");
+ dxgiFactory->Release();
+ return QByteArray();
+ }
+ DXGI_ADAPTER_DESC desc;
+ dxgiAdapter->GetDesc(&desc);
+ dxgiAdapter->Release();
+ QByteArray guid(sizeof(GUID), '\0');
+ memcpy(guid.data(), &desc.AdapterLuid, sizeof(LUID));
+ stream.writeRawData(guid.constData(), guid.size());
+ stream.writeRawData(pixelShader.constData(), pixelShader.size());
+ stream.writeRawData(vertexShader.constData(), vertexShader.size());
+ if (!geometryShader.isEmpty())
+ stream.writeRawData(geometryShader.constData(), geometryShader.size());
+
+ return binary;
+}
+
+} // namespace
+
+QT_BEGIN_NAMESPACE
+
+static const GLfloat normCoords[] = { -1, 1, 1, 1, 1, -1, -1, -1 };
+static const GLfloat quadCoords[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
+
+QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+ , m_context(new QOpenGLContext)
+ , m_shaderProgram(0)
+ , m_fbo(0)
+ , m_texture(0)
+ , m_screen(static_cast<QWinRTScreen*>(window->screen()->handle()))
+{
+ window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap
+
+ m_context->setFormat(window->requestedFormat());
+ m_context->setScreen(window->screen());
+ m_context->create();
+
+ m_context->makeCurrent(window);
+ glGenFramebuffers(1, &m_fbo);
+ glGenRenderbuffers(1, &m_rbo);
+ glGenTextures(1, &m_texture);
+ m_shaderProgram = glCreateProgram();
+
+#if 0 // Standard GLES passthrough shader program
+ static const char *vertexShaderSource =
+ "attribute vec4 pos0;\n"
+ "attribute vec2 tex0;\n"
+ "varying vec2 coord;\n"
+ "void main() {\n"
+ " coord = tex0;\n"
+ " gl_Position = pos0;\n"
+ "}\n";
+ static const char *fragmentShaderSource =
+ "uniform sampler2D texture;\n"
+ "varying highp vec2 coord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(texture, coord);\n"
+ "}\n";
+ GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
+ glCompileShader(vertexShader);
+ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
+ glCompileShader(fragmentShader);
+ glAttachShader(m_shaderProgram, vertexShader);
+ glAttachShader(m_shaderProgram, fragmentShader);
+ glLinkProgram(m_shaderProgram);
+#else // Precompiled passthrough shader
+ QVector<Attribute> attributes = QVector<Attribute>() << Attribute(GL_FLOAT_VEC4, "pos0", 0)
+ << Attribute(GL_FLOAT_VEC2, "tex0", 1);
+ QVector<Sampler> textureSamplers = QVector<Sampler>() << Sampler(true, 0, Sampler::Texture2D);
+ QVector<Sampler> vertexSamplers;
+ QVector<Uniform> uniforms = QVector<Uniform>() << Uniform(GL_SAMPLER_2D, 0, "texture", 0, 0, -1, 1);
+ QVector<UniformIndex> uniformsIndex = QVector<UniformIndex>() << UniformIndex("texture", 0, 0);
+ QByteArray pixelShader(reinterpret_cast<const char *>(q_blitps), sizeof(q_blitps));
+ QByteArray vertexShader(reinterpret_cast<const char *>(q_blitvs), sizeof(q_blitvs));
+ QByteArray binary = createAngleBinary(attributes, textureSamplers, vertexSamplers,
+ uniforms, uniformsIndex, pixelShader, vertexShader);
+ glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size());
+#endif
+ m_context->doneCurrent();
+ resize(window->size(), QRegion());
+}
+
+QWinRTBackingStore::~QWinRTBackingStore()
+{
+ glDeleteBuffers(1, &m_fbo);
+ glDeleteRenderbuffers(1, &m_rbo);
+ glDeleteTextures(1, &m_texture);
+ glDeleteProgram(m_shaderProgram);
+}
+
+QPaintDevice *QWinRTBackingStore::paintDevice()
+{
+ return m_paintDevice.data();
+}
+
+void QWinRTBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(offset)
+
+ const QImage *image = static_cast<QImage *>(m_paintDevice.data());
+
+ m_context->makeCurrent(window);
+
+ // Blitting the entire image width trades zero image copy/relayout for a larger texture upload.
+ // Since we're blitting the whole width anyway, the boundingRect() is used in the assumption that
+ // we don't repeat upload. This is of course dependent on the distance between update regions.
+ // Ideally, we would use the GL_EXT_unpack_subimage extension, which should be possible to implement
+ // since D3D11_MAPPED_SUBRESOURCE supports RowPitch (see below).
+ // Note that single-line blits in a loop are *very* slow, so reducing calls to glTexSubImage2D
+ // is probably a good idea anyway.
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ QRect bounds = region.boundingRect();
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), m_size.width(), bounds.height(),
+ GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y()));
+ // TODO: Implement GL_EXT_unpack_subimage in ANGLE for more minimal uploads
+ //glPixelStorei(GL_UNPACK_ROW_LENGTH, image->bytesPerLine());
+ //glTexSubImage2D(GL_TEXTURE_2D, 0, bounds.x(), bounds.y(), bounds.width(), bounds.height(),
+ // GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y()) + bounds.x() * 4);
+
+ // Bind render buffer
+ glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
+
+ // Bind position
+ glUseProgram(m_shaderProgram);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, normCoords);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, quadCoords);
+
+ // Render
+ glViewport(0, 0, m_size.width(), m_size.height());
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // Unbind
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
+ glUseProgram(0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // fast blit - TODO: perform the blit inside swap buffers instead
+ glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0);
+ glBlitFramebufferANGLE(0, 0, m_size.width(), m_size.height(), // TODO: blit only the changed rectangle
+ 0, 0, m_size.width(), m_size.height(),
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ m_context->swapBuffers(window);
+ m_context->doneCurrent();
+}
+
+void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ Q_UNUSED(staticContents)
+ if (m_size == size)
+ return;
+
+ m_size = size;
+ m_paintDevice.reset(new QImage(m_size, QImage::Format_ARGB32_Premultiplied));
+
+ m_context->makeCurrent(window());
+ // Input texture
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, m_size.width(), m_size.height(),
+ 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ // Render buffer
+ glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, m_size.width(), m_size.height());
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ m_context->doneCurrent();
+}
+
+void QWinRTBackingStore::beginPaint(const QRegion &region)
+{
+ Q_UNUSED(region)
+}
+
+void QWinRTBackingStore::endPaint()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h
new file mode 100644
index 0000000000..8be549b441
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTBACKINGSTORE_H
+#define QWINRTBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTScreen;
+class QOpenGLContext;
+
+class QWinRTBackingStore : public QPlatformBackingStore
+{
+public:
+ explicit QWinRTBackingStore(QWindow *window);
+ ~QWinRTBackingStore();
+ QPaintDevice *paintDevice();
+ void beginPaint(const QRegion &);
+ void endPaint();
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset);
+ void resize(const QSize &size, const QRegion &staticContents);
+
+private:
+ QSize m_size;
+ QScopedPointer<QPaintDevice> m_paintDevice;
+ QScopedPointer<QOpenGLContext> m_context;
+ quint32 m_shaderProgram;
+ quint32 m_fbo;
+ quint32 m_rbo;
+ quint32 m_texture;
+ QWinRTScreen *m_screen;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTBACKINGSTORE_H
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
new file mode 100644
index 0000000000..8241560cef
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcursor.h"
+
+#include <wrl.h>
+#include <windows.ui.core.h>
+#include <windows.foundation.h>
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::Foundation;
+
+QT_BEGIN_NAMESPACE
+
+QWinRTCursor::QWinRTCursor(ICoreWindow *window) : m_window(window), m_cursorFactory(nullptr)
+{
+#ifndef Q_OS_WINPHONE
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), &m_cursorFactory);
+#endif
+}
+
+QWinRTCursor::~QWinRTCursor()
+{
+ if (m_cursorFactory)
+ m_cursorFactory->Release();
+}
+
+#ifndef QT_NO_CURSOR
+void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *)
+{
+#ifndef Q_OS_WINPHONE
+ if (!m_cursorFactory)
+ return;
+
+ CoreCursorType type;
+ switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
+ case Qt::BlankCursor:
+ m_window->put_PointerCursor(nullptr);
+ return;
+ default:
+ case Qt::OpenHandCursor:
+ case Qt::ClosedHandCursor:
+ case Qt::DragCopyCursor:
+ case Qt::DragMoveCursor:
+ case Qt::DragLinkCursor:
+ // (unavailable)
+ case Qt::ArrowCursor:
+ type = CoreCursorType_Arrow;
+ break;
+ case Qt::UpArrowCursor:
+ type = CoreCursorType_UpArrow;
+ break;
+ case Qt::CrossCursor:
+ type = CoreCursorType_Cross;
+ break;
+ case Qt::WaitCursor:
+ case Qt::BusyCursor:
+ type = CoreCursorType_Wait;
+ break;
+ case Qt::IBeamCursor:
+ type = CoreCursorType_IBeam;
+ break;
+ case Qt::SizeVerCursor:
+ case Qt::SplitVCursor:
+ type = CoreCursorType_SizeNorthSouth;
+ break;
+ case Qt::SizeHorCursor:
+ case Qt::SplitHCursor:
+ type = CoreCursorType_SizeWestEast;
+ break;
+ case Qt::SizeBDiagCursor:
+ type = CoreCursorType_SizeNortheastSouthwest;
+ break;
+ case Qt::SizeFDiagCursor:
+ type = CoreCursorType_SizeNorthwestSoutheast;
+ break;
+ case Qt::SizeAllCursor:
+ type = CoreCursorType_SizeAll;
+ break;
+ case Qt::PointingHandCursor:
+ type = CoreCursorType_Hand;
+ break;
+ case Qt::ForbiddenCursor:
+ type = CoreCursorType_UniversalNo;
+ break;
+ case Qt::WhatsThisCursor:
+ type = CoreCursorType_Help;
+ break;
+ case Qt::BitmapCursor:
+ case Qt::CustomCursor:
+ // TODO: figure out if arbitrary bitmaps can be made into resource IDs
+ // For now, we don't get enough info from QCursor to set a custom cursor
+ type = CoreCursorType_Custom;
+ break;
+ }
+
+ ICoreCursor *cursor;
+ if (SUCCEEDED(m_cursorFactory->CreateCursor(type, 0, &cursor)))
+ m_window->put_PointerCursor(cursor);
+#endif // Q_OS_WINPHONE
+}
+#endif // QT_NO_CURSOR
+
+QPoint QWinRTCursor::pos() const
+{
+#ifdef Q_OS_WINPHONE
+ return QPlatformCursor::pos();
+#else
+ Point point;
+ m_window->get_PointerPosition(&point);
+ return QPoint(point.X, point.Y);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h
new file mode 100644
index 0000000000..f7b301a98b
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtcursor.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCURSOR_H
+#define QWINRTCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace UI {
+ namespace Core {
+ struct ICoreWindow;
+ struct ICoreCursorFactory;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCursor : public QPlatformCursor
+{
+public:
+ explicit QWinRTCursor(ABI::Windows::UI::Core::ICoreWindow *window);
+ ~QWinRTCursor();
+#ifndef QT_NO_CURSOR
+ void changeCursor(QCursor * windowCursor, QWindow *);
+#endif
+ QPoint pos() const;
+
+private:
+ ABI::Windows::UI::Core::ICoreWindow *m_window;
+ ABI::Windows::UI::Core::ICoreCursorFactory *m_cursorFactory;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCURSOR_H
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
new file mode 100644
index 0000000000..014378f896
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrteglcontext.h"
+
+QT_BEGIN_NAMESPACE
+
+QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface)
+ : QEGLPlatformContext(format, share, display, EGL_OPENGL_ES_API), m_eglSurface(surface)
+{
+}
+
+EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+{
+ if (surface->surface()->surfaceClass() == QSurface::Window) {
+ // All windows use the same surface
+ return m_eglSurface;
+ } else {
+ // TODO: return EGL surfaces for offscreen surfaces
+ qWarning("This plugin does not support offscreen surfaces.");
+ return EGL_NO_SURFACE;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h
new file mode 100644
index 0000000000..c065847374
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSEGLCONTEXT_H
+#define QWINDOWSEGLCONTEXT_H
+
+#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTEGLContext : public QEGLPlatformContext
+{
+public:
+ explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface);
+
+protected:
+ EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
+
+private:
+ EGLSurface m_eglSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSEGLCONTEXT_H
diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp
new file mode 100644
index 0000000000..3fada75b25
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrteventdispatcher.h"
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformscreenpageflipper.h>
+#include <QtCore/QThread>
+#include <QtGui/QGuiApplication>
+
+#include <Windows.ui.core.h>
+#include <Windows.ApplicationModel.core.h>
+
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::Foundation;
+
+QT_BEGIN_NAMESPACE
+
+QWinRTEventDispatcher::QWinRTEventDispatcher(ICoreDispatcher *dispatcher, QObject *parent)
+ : QEventDispatcherWinRT(parent)
+ , m_dispatcher(dispatcher)
+{
+}
+
+bool QWinRTEventDispatcher::hasPendingEvents()
+{
+ return QEventDispatcherWinRT::hasPendingEvents() || QWindowSystemInterface::windowSystemEventsQueued();
+}
+
+bool QWinRTEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ if (m_dispatcher)
+ m_dispatcher->ProcessEvents(CoreProcessEventsOption_ProcessAllIfPresent);
+
+ const bool didProcess = QWindowSystemInterface::sendWindowSystemEvents(flags);
+
+ return QEventDispatcherWinRT::processEvents(flags & ~QEventLoop::WaitForMoreEvents) || didProcess;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h
new file mode 100644
index 0000000000..275a508b3c
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTEVENTDISPATCHER_H
+#define QWINRTEVENTDISPATCHER_H
+
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/QEvent>
+
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace UI {
+ namespace Core {
+ struct ICoreDispatcher;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTEventDispatcher : public QEventDispatcherWinRT
+{
+ Q_OBJECT
+public:
+ explicit QWinRTEventDispatcher(ABI::Windows::UI::Core::ICoreDispatcher *dispatcher, QObject *parent = 0);
+
+protected:
+ bool hasPendingEvents();
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+
+private:
+ ABI::Windows::UI::Core::ICoreDispatcher *m_dispatcher;
+
+ friend class QWinRTIntegration;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTEVENTDISPATCHER_H
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
new file mode 100644
index 0000000000..c7fa339fad
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtfontdatabase.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+
+QT_BEGIN_NAMESPACE
+
+QString QWinRTFontDatabase::fontDir() const
+{
+ QString fontDirectory = QBasicFontDatabase::fontDir();
+ if (!QFile::exists(fontDirectory)) {
+ // Fall back to app directory + fonts, and just app directory after that
+ const QString applicationDirPath = QCoreApplication::applicationDirPath();
+ fontDirectory = applicationDirPath + QLatin1String("/fonts");
+ if (!QFile::exists(fontDirectory)) {
+ qWarning("No fonts directory found in application package.");
+ fontDirectory = applicationDirPath;
+ }
+ }
+ return fontDirectory;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
new file mode 100644
index 0000000000..49e32470c2
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTFONTDATABASE_H
+#define QWINRTFONTDATABASE_H
+
+#include <QtPlatformSupport/private/qbasicfontdatabase_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTFontDatabase : public QBasicFontDatabase
+{
+public:
+ QString fontDir() const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTFONTDATABASE_H
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
new file mode 100644
index 0000000000..bc15f1e448
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtinputcontext.h"
+#include <QtGui/QWindow>
+
+#include <wrl.h>
+#include <roapi.h>
+#include <windows.ui.viewmanagement.h>
+#include <windows.ui.core.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::UI::ViewManagement;
+using namespace ABI::Windows::UI::Core;
+
+#ifdef Q_OS_WINPHONE
+#include <windows.phone.ui.core.h>
+using namespace ABI::Windows::Phone::UI::Core;
+#endif
+
+typedef ITypedEventHandler<InputPane*, InputPaneVisibilityEventArgs*> InputPaneVisibilityHandler;
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWinRTInputContext
+ \brief Manages Input Method visibility
+ \internal
+ \ingroup qt-qpa-winrt
+
+ Listens to the native virtual keyboard for hide/show events and provides
+ hints to the OS for showing/hiding. On WinRT, showInputPanel()/hideInputPanel()
+ have no effect because WinRT dictates that keyboard presence is user-driven:
+ (http://msdn.microsoft.com/en-us/library/windows/apps/hh465404.aspx)
+ Windows Phone, however, supports direct hiding/showing of the keyboard.
+*/
+
+QWinRTInputContext::QWinRTInputContext(ICoreWindow *window)
+ : m_window(window)
+{
+ IInputPaneStatics *statics;
+ if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(),
+ &statics))) {
+ qWarning(Q_FUNC_INFO ": failed to retrieve input pane statics.");
+ return;
+ }
+
+ IInputPane *inputPane;
+ statics->GetForCurrentView(&inputPane);
+ statics->Release();
+ if (inputPane) {
+ EventRegistrationToken showToken, hideToken;
+ inputPane->add_Showing(Callback<InputPaneVisibilityHandler>(
+ this, &QWinRTInputContext::onShowing).Get(), &showToken);
+ inputPane->add_Hiding(Callback<InputPaneVisibilityHandler>(
+ this, &QWinRTInputContext::onHiding).Get(), &hideToken);
+
+ Rect rect;
+ inputPane->get_OccludedRect(&rect);
+ m_keyboardRect = QRectF(rect.X, rect.Y, rect.Width, rect.Height);
+ m_isInputPanelVisible = !m_keyboardRect.isEmpty();
+ } else {
+ qWarning(Q_FUNC_INFO ": failed to retrieve InputPane.");
+ }
+}
+
+QRectF QWinRTInputContext::keyboardRect() const
+{
+ return m_keyboardRect;
+}
+
+bool QWinRTInputContext::isInputPanelVisible() const
+{
+ return m_isInputPanelVisible;
+}
+
+HRESULT QWinRTInputContext::onShowing(IInputPane *pane, IInputPaneVisibilityEventArgs *)
+{
+ m_isInputPanelVisible = true;
+ emitInputPanelVisibleChanged();
+
+ Rect rect;
+ pane->get_OccludedRect(&rect);
+ setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height));
+
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEventArgs *)
+{
+ m_isInputPanelVisible = false;
+ emitInputPanelVisibleChanged();
+
+ Rect rect;
+ pane->get_OccludedRect(&rect);
+ setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height));
+
+ return S_OK;
+}
+
+void QWinRTInputContext::setKeyboardRect(const QRectF rect)
+{
+ if (m_keyboardRect == rect)
+ return;
+
+ m_keyboardRect = rect;
+ emitKeyboardRectChanged();
+}
+
+#ifdef Q_OS_WINPHONE
+
+void QWinRTInputContext::showInputPanel()
+{
+ ICoreWindowKeyboardInput *input;
+ if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) {
+ input->put_IsKeyboardInputEnabled(true);
+ input->Release();
+ }
+}
+
+void QWinRTInputContext::hideInputPanel()
+{
+ ICoreWindowKeyboardInput *input;
+ if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) {
+ input->put_IsKeyboardInputEnabled(false);
+ input->Release();
+ }
+}
+
+#else // Q_OS_WINPHONE
+
+// IRawElementProviderSimple
+HRESULT QWinRTInputContext::get_ProviderOptions(ProviderOptions *retVal)
+{
+ *retVal = ProviderOptions_ServerSideProvider|ProviderOptions_UseComThreading;
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::GetPatternProvider(PATTERNID id, IUnknown **retVal)
+{
+ switch (id) {
+ case 10002: //UIA_ValuePatternId
+ return QueryInterface(__uuidof(IValueProvider), (void**)retVal);
+ break;
+ case 10014: //UIA_TextPatternId:
+ return QueryInterface(__uuidof(ITextProvider), (void**)retVal);
+ case 10029: //UIA_TextChildPatternId:
+ *retVal = nullptr;
+ break;
+ default:
+ qWarning("Unhandled pattern ID: %d", id);
+ break;
+ }
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::GetPropertyValue(PROPERTYID idProp, VARIANT *retVal)
+{
+ switch (idProp) {
+ case 30003: //UIA_ControlTypePropertyId
+ retVal->vt = VT_I4;
+ retVal->lVal = 50025; //UIA_CustomControlTypeId
+ break;
+ case 30008: //UIA_IsKeyboardFocusablePropertyId
+ case 30009: //UIA_HasKeyboardFocusPropertyId
+ // These are probably never actually called
+ case 30016: //UIA_IsControlElementPropertyId
+ case 30017: //UIA_IsContentElementPropertyId
+ retVal->vt = VT_BOOL;
+ retVal->boolVal = VARIANT_TRUE;
+ break;
+ case 30019: //UIA_IsPasswordPropertyId
+ retVal->vt = VT_BOOL;
+ retVal->boolVal = VARIANT_FALSE;
+ break;
+ case 30020: //UIA_NativeWindowHandlePropertyId
+ retVal->vt = VT_PTR;
+ retVal->punkVal = m_window;
+ break;
+ }
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple **retVal)
+{
+ // Return the window's element provider
+ IInspectable *hostProvider;
+ HRESULT hr = m_window->get_AutomationHostProvider(&hostProvider);
+ if (SUCCEEDED(hr)) {
+ hr = hostProvider->QueryInterface(IID_PPV_ARGS(retVal));
+ hostProvider->Release();
+ }
+ return hr;
+}
+
+// ITextProvider
+HRESULT QWinRTInputContext::GetSelection(SAFEARRAY **)
+{
+ // To be useful, requires listening to the focus object for a selection change and raising an event
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::GetVisibleRanges(SAFEARRAY **)
+{
+ // To be useful, requires listening to the focus object for a selection change and raising an event
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **)
+{
+ // To be useful, requires listening to the focus object for a selection change and raising an event
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::RangeFromPoint(UiaPoint, ITextRangeProvider **)
+{
+ // To be useful, requires listening to the focus object for a selection change and raising an event
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::get_DocumentRange(ITextRangeProvider **)
+{
+ // To be useful, requires listening to the focus object for a selection change and raising an event
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::get_SupportedTextSelection(SupportedTextSelection *)
+{
+ // To be useful, requires listening to the focus object for a selection change and raising an event
+ return S_OK;
+}
+
+// IValueProvider
+HRESULT QWinRTInputContext::SetValue(LPCWSTR)
+{
+ // To be useful, requires listening to the focus object for a value change and raising an event
+ // May be useful for inputPanel autocomplete, etc.
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::get_Value(BSTR *)
+{
+ // To be useful, requires listening to the focus object for a value change and raising an event
+ // May be useful for inputPanel autocomplete, etc.
+ return S_OK;
+}
+
+HRESULT QWinRTInputContext::get_IsReadOnly(BOOL *isReadOnly)
+{
+ // isReadOnly dictates keyboard opening behavior when view is tapped.
+ // We need to decide if the user tapped within a control which is about to receive focus...
+ // Since this isn't possible (this function gets called before we receive the touch event),
+ // the most platform-aligned option is to show the keyboard if an editable item has focus,
+ // and close the keyboard if it is already open.
+ *isReadOnly = m_isInputPanelVisible || !inputMethodAccepted();
+ return S_OK;
+}
+
+#endif // !Q_OS_WINPHONE
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h
new file mode 100644
index 0000000000..0a35f9b6e1
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTINPUTCONTEXT_H
+#define QWINRTINPUTCONTEXT_H
+
+#include <qpa/qplatforminputcontext.h>
+#include <QtCore/QRectF>
+
+#include <wrl.h>
+#ifndef Q_OS_WINPHONE
+# include <UIAutomationCore.h>
+#endif
+
+namespace ABI {
+ namespace Windows {
+ namespace UI {
+ namespace Core {
+ struct ICoreWindow;
+ }
+ namespace ViewManagement {
+ struct IInputPane;
+ struct IInputPaneVisibilityEventArgs;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTInputContext : public QPlatformInputContext
+#ifndef Q_OS_WINPHONE
+ , public Microsoft::WRL::RuntimeClass<
+ Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::WinRtClassicComMix>,
+ IRawElementProviderSimple, ITextProvider, IValueProvider>
+#endif // !Q_OS_WINPHONE
+{
+public:
+ explicit QWinRTInputContext(ABI::Windows::UI::Core::ICoreWindow *window);
+
+ QRectF keyboardRect() const;
+
+ bool isInputPanelVisible() const;
+
+#ifdef Q_OS_WINPHONE
+ void showInputPanel();
+ void hideInputPanel();
+#else // Q_OS_WINPHONE
+ // IRawElementProviderSimple
+ HRESULT __stdcall get_ProviderOptions(ProviderOptions *retVal);
+ HRESULT __stdcall GetPatternProvider(PATTERNID, IUnknown **);
+ HRESULT __stdcall GetPropertyValue(PROPERTYID idProp, VARIANT *retVal);
+ HRESULT __stdcall get_HostRawElementProvider(IRawElementProviderSimple **retVal);
+
+ // ITextProvider
+ HRESULT __stdcall GetSelection(SAFEARRAY **);
+ HRESULT __stdcall GetVisibleRanges(SAFEARRAY **);
+ HRESULT __stdcall RangeFromChild(IRawElementProviderSimple *,ITextRangeProvider **);
+ HRESULT __stdcall RangeFromPoint(UiaPoint, ITextRangeProvider **);
+ HRESULT __stdcall get_DocumentRange(ITextRangeProvider **);
+ HRESULT __stdcall get_SupportedTextSelection(SupportedTextSelection *);
+
+ // IValueProvider
+ HRESULT __stdcall SetValue(LPCWSTR);
+ HRESULT __stdcall get_Value(BSTR *);
+ HRESULT __stdcall get_IsReadOnly(BOOL *);
+#endif // !Q_OS_WINPHONE
+
+private:
+ HRESULT onShowing(ABI::Windows::UI::ViewManagement::IInputPane *,
+ ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *);
+ HRESULT onHiding(ABI::Windows::UI::ViewManagement::IInputPane *,
+ ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *);
+ void setKeyboardRect(const QRectF rect);
+
+ ABI::Windows::UI::Core::ICoreWindow *m_window;
+ QRectF m_keyboardRect;
+ bool m_isInputPanelVisible;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTINPUTCONTEXT_H
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
new file mode 100644
index 0000000000..22c50e67f3
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtintegration.h"
+#include "qwinrtwindow.h"
+#include "qwinrteventdispatcher.h"
+#include "qwinrtbackingstore.h"
+#include "qwinrtscreen.h"
+#include "qwinrtinputcontext.h"
+#include "qwinrtservices.h"
+#include "qwinrteglcontext.h"
+#include "qwinrtfontdatabase.h"
+
+#include <QtGui/QOpenGLContext>
+
+#include <wrl.h>
+#include <windows.ui.core.h>
+#include <windows.ui.viewmanagement.h>
+#include <Windows.ApplicationModel.core.h>
+
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::UI::ViewManagement;
+using namespace ABI::Windows::ApplicationModel::Core;
+
+static IUISettings *getSettings()
+{
+ static IUISettings *settings = 0;
+ if (!settings) {
+ if (FAILED(RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(),
+ reinterpret_cast<IInspectable **>(&settings)))) {
+ qWarning("Could not activate UISettings.");
+ }
+ }
+ return settings;
+}
+
+QT_BEGIN_NAMESPACE
+
+QWinRTIntegration::QWinRTIntegration()
+ : m_success(false)
+ , m_fontDatabase(new QWinRTFontDatabase)
+ , m_services(new QWinRTServices)
+{
+ // Obtain the WinRT Application, view, and window
+ ICoreApplication *application;
+ if (FAILED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ IID_PPV_ARGS(&application))))
+ qCritical("Could not attach to the application factory.");
+
+ ICoreApplicationView *view;
+ if (FAILED(application->GetCurrentView(&view))) {
+ qCritical("Could not obtain the application view - have you started outside of WinRT?");
+ return;
+ }
+
+ // Get core window (will act as our screen)
+ ICoreWindow *window;
+ if (FAILED(view->get_CoreWindow(&window))) {
+ qCritical("Could not obtain the application window - have you started outside of WinRT?");
+ return;
+ }
+ window->Activate();
+ m_screen = new QWinRTScreen(window);
+ screenAdded(m_screen);
+
+ m_success = true;
+}
+
+QWinRTIntegration::~QWinRTIntegration()
+{
+ Windows::Foundation::Uninitialize();
+}
+
+QAbstractEventDispatcher *QWinRTIntegration::createEventDispatcher() const
+{
+ ICoreDispatcher *dispatcher;
+ if (FAILED(m_screen->coreWindow()->get_Dispatcher(&dispatcher)))
+ qCritical("Could not capture UI Dispatcher");
+ return new QWinRTEventDispatcher(dispatcher);
+}
+
+bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps:
+ case OpenGL:
+ case ApplicationState:
+ return true;
+ default:
+ return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QVariant QWinRTIntegration::styleHint(StyleHint hint) const
+{
+ switch (hint) {
+ case CursorFlashTime:
+ if (IUISettings *settings = getSettings()) {
+ quint32 blinkRate;
+ settings->get_CaretBlinkRate(&blinkRate);
+ return blinkRate;
+ }
+ break;
+ case MouseDoubleClickInterval:
+ if (IUISettings *settings = getSettings()) {
+ quint32 doubleClickTime;
+ settings->get_DoubleClickTime(&doubleClickTime);
+ return doubleClickTime;
+ }
+ case ShowIsFullScreen:
+ return true;
+ default:
+ break;
+ }
+ return QPlatformIntegration::styleHint(hint);
+}
+
+QPlatformWindow *QWinRTIntegration::createPlatformWindow(QWindow *window) const
+{
+ return new QWinRTWindow(window);
+}
+
+QPlatformBackingStore *QWinRTIntegration::createPlatformBackingStore(QWindow *window) const
+{
+ return new QWinRTBackingStore(window);
+}
+
+QPlatformOpenGLContext *QWinRTIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ QWinRTScreen *screen = static_cast<QWinRTScreen *>(context->screen()->handle());
+ return new QWinRTEGLContext(context->format(), context->handle(), screen->eglDisplay(), screen->eglSurface());
+}
+
+QPlatformFontDatabase *QWinRTIntegration::fontDatabase() const
+{
+ return m_fontDatabase;
+}
+
+QPlatformInputContext *QWinRTIntegration::inputContext() const
+{
+ return m_screen->inputContext();
+}
+
+QPlatformServices *QWinRTIntegration::services() const
+{
+ return m_services;
+}
+
+Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
+{
+ return m_screen->keyboardModifiers();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h
new file mode 100644
index 0000000000..d9438bcb3a
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtintegration.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTINTEGRATION_H
+#define QWINRTINTEGRATION_H
+
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractEventDispatcher;
+class QWinRTScreen;
+
+class QWinRTIntegration : public QPlatformIntegration
+{
+private:
+ explicit QWinRTIntegration();
+public:
+ ~QWinRTIntegration();
+
+ static QWinRTIntegration *create()
+ {
+ QWinRTIntegration *integration = new QWinRTIntegration;
+ return integration->m_success ? integration : 0;
+ }
+
+ bool hasCapability(QPlatformIntegration::Capability cap) const;
+ QVariant styleHint(StyleHint hint) const;
+
+ QPlatformWindow *createPlatformWindow(QWindow *window) const;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QAbstractEventDispatcher *createEventDispatcher() const;
+ QPlatformFontDatabase *fontDatabase() const;
+ QPlatformInputContext *inputContext() const;
+ QPlatformServices *services() const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const;
+
+private:
+ bool m_success;
+ QWinRTScreen *m_screen;
+ QPlatformFontDatabase *m_fontDatabase;
+ QPlatformServices *m_services;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTINTEGRATION_H
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
new file mode 100644
index 0000000000..911d3619fe
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -0,0 +1,975 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtscreen.h"
+
+#include "qwinrtbackingstore.h"
+#include "qwinrtinputcontext.h"
+#include "qwinrtcursor.h"
+#include "qwinrteglcontext.h"
+
+#include <QtGui/QSurfaceFormat>
+#include <QtGui/QGuiApplication>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/qt_windows.h>
+
+#include <wrl.h>
+#include <windows.system.h>
+#include <windows.devices.input.h>
+#include <windows.ui.h>
+#include <windows.ui.core.h>
+#include <windows.ui.input.h>
+#include <windows.ui.viewmanagement.h>
+#include <windows.graphics.display.h>
+#include <windows.foundation.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::UI::Input;
+using namespace ABI::Windows::UI::ViewManagement;
+using namespace ABI::Windows::Devices::Input;
+using namespace ABI::Windows::Graphics::Display;
+
+typedef ITypedEventHandler<CoreWindow*, WindowActivatedEventArgs*> ActivatedHandler;
+typedef ITypedEventHandler<CoreWindow*, CoreWindowEventArgs*> ClosedHandler;
+typedef ITypedEventHandler<CoreWindow*, CharacterReceivedEventArgs*> CharacterReceivedHandler;
+typedef ITypedEventHandler<CoreWindow*, InputEnabledEventArgs*> InputEnabledHandler;
+typedef ITypedEventHandler<CoreWindow*, KeyEventArgs*> KeyHandler;
+typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
+typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
+typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
+typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
+
+QT_BEGIN_NAMESPACE
+
+static inline Qt::ScreenOrientations qtOrientationsFromNative(DisplayOrientations native)
+{
+ Qt::ScreenOrientations orientations = Qt::PrimaryOrientation;
+ if (native & DisplayOrientations_Portrait)
+ orientations |= Qt::PortraitOrientation;
+ if (native & DisplayOrientations_PortraitFlipped)
+ orientations |= Qt::InvertedPortraitOrientation;
+ if (native & DisplayOrientations_Landscape)
+ orientations |= Qt::LandscapeOrientation;
+ if (native & DisplayOrientations_LandscapeFlipped)
+ orientations |= Qt::InvertedLandscapeOrientation;
+ return orientations;
+}
+
+static inline DisplayOrientations nativeOrientationsFromQt(Qt::ScreenOrientations orientation)
+{
+ DisplayOrientations native = DisplayOrientations_None;
+ if (orientation & Qt::PortraitOrientation)
+ native |= DisplayOrientations_Portrait;
+ if (orientation & Qt::InvertedPortraitOrientation)
+ native |= DisplayOrientations_PortraitFlipped;
+ if (orientation & Qt::LandscapeOrientation)
+ native |= DisplayOrientations_Landscape;
+ if (orientation & Qt::InvertedLandscapeOrientation)
+ native |= DisplayOrientations_LandscapeFlipped;
+ return native;
+}
+
+static inline bool qIsNonPrintable(quint32 keyCode)
+{
+ switch (keyCode) {
+ case '\b':
+ case '\n':
+ case '\t':
+ case '\r':
+ case '\v':
+ case '\f':
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Return Qt meta key from VirtualKey
+static inline Qt::Key qKeyFromVirtual(VirtualKey key)
+{
+ switch (key) {
+
+ default:
+ return Qt::Key_unknown;
+
+ // Non-printable characters
+ case VirtualKey_Enter:
+ return Qt::Key_Enter;
+ case VirtualKey_Tab:
+ return Qt::Key_Tab;
+ case VirtualKey_Back:
+ return Qt::Key_Backspace;
+
+ // Modifiers
+ case VirtualKey_Shift:
+ case VirtualKey_LeftShift:
+ case VirtualKey_RightShift:
+ return Qt::Key_Shift;
+ case VirtualKey_Control:
+ case VirtualKey_LeftControl:
+ case VirtualKey_RightControl:
+ return Qt::Key_Control;
+ case VirtualKey_Menu:
+ case VirtualKey_LeftMenu:
+ case VirtualKey_RightMenu:
+ return Qt::Key_Alt;
+ case VirtualKey_LeftWindows:
+ case VirtualKey_RightWindows:
+ return Qt::Key_Meta;
+
+ // Toggle keys
+ case VirtualKey_CapitalLock:
+ return Qt::Key_CapsLock;
+ case VirtualKey_NumberKeyLock:
+ return Qt::Key_NumLock;
+ case VirtualKey_Scroll:
+ return Qt::Key_ScrollLock;
+
+ // East-Asian language keys
+ case VirtualKey_Kana:
+ //case VirtualKey_Hangul: // Same enum as Kana
+ return Qt::Key_Kana_Shift;
+ case VirtualKey_Junja:
+ return Qt::Key_Hangul_Jeonja;
+ case VirtualKey_Kanji:
+ //case VirtualKey_Hanja: // Same enum as Kanji
+ return Qt::Key_Kanji;
+ case VirtualKey_ModeChange:
+ return Qt::Key_Mode_switch;
+ case VirtualKey_Convert:
+ return Qt::Key_Henkan;
+ case VirtualKey_NonConvert:
+ return Qt::Key_Muhenkan;
+
+ // Misc. keys
+ case VirtualKey_Cancel:
+ return Qt::Key_Cancel;
+ case VirtualKey_Clear:
+ return Qt::Key_Clear;
+ case VirtualKey_Application:
+ return Qt::Key_ApplicationLeft;
+ case VirtualKey_Sleep:
+ return Qt::Key_Sleep;
+ case VirtualKey_Pause:
+ return Qt::Key_Pause;
+ case VirtualKey_PageUp:
+ return Qt::Key_PageUp;
+ case VirtualKey_PageDown:
+ return Qt::Key_PageDown;
+ case VirtualKey_End:
+ return Qt::Key_End;
+ case VirtualKey_Home:
+ return Qt::Key_Home;
+ case VirtualKey_Left:
+ return Qt::Key_Left;
+ case VirtualKey_Up:
+ return Qt::Key_Up;
+ case VirtualKey_Right:
+ return Qt::Key_Right;
+ case VirtualKey_Down:
+ return Qt::Key_Down;
+ case VirtualKey_Select:
+ return Qt::Key_Select;
+ case VirtualKey_Print:
+ return Qt::Key_Print;
+ case VirtualKey_Execute:
+ return Qt::Key_Execute;
+ case VirtualKey_Insert:
+ return Qt::Key_Insert;
+ case VirtualKey_Delete:
+ return Qt::Key_Delete;
+ case VirtualKey_Help:
+ return Qt::Key_Help;
+ case VirtualKey_Snapshot:
+ return Qt::Key_Camera;
+ case VirtualKey_Escape:
+ return Qt::Key_Escape;
+
+ // Function Keys
+ case VirtualKey_F1:
+ return Qt::Key_F1;
+ case VirtualKey_F2:
+ return Qt::Key_F2;
+ case VirtualKey_F3:
+ return Qt::Key_F3;
+ case VirtualKey_F4:
+ return Qt::Key_F4;
+ case VirtualKey_F5:
+ return Qt::Key_F5;
+ case VirtualKey_F6:
+ return Qt::Key_F6;
+ case VirtualKey_F7:
+ return Qt::Key_F7;
+ case VirtualKey_F8:
+ return Qt::Key_F8;
+ case VirtualKey_F9:
+ return Qt::Key_F9;
+ case VirtualKey_F10:
+ return Qt::Key_F10;
+ case VirtualKey_F11:
+ return Qt::Key_F11;
+ case VirtualKey_F12:
+ return Qt::Key_F12;
+ case VirtualKey_F13:
+ return Qt::Key_F13;
+ case VirtualKey_F14:
+ return Qt::Key_F14;
+ case VirtualKey_F15:
+ return Qt::Key_F15;
+ case VirtualKey_F16:
+ return Qt::Key_F16;
+ case VirtualKey_F17:
+ return Qt::Key_F17;
+ case VirtualKey_F18:
+ return Qt::Key_F18;
+ case VirtualKey_F19:
+ return Qt::Key_F19;
+ case VirtualKey_F20:
+ return Qt::Key_F20;
+ case VirtualKey_F21:
+ return Qt::Key_F21;
+ case VirtualKey_F22:
+ return Qt::Key_F22;
+ case VirtualKey_F23:
+ return Qt::Key_F23;
+ case VirtualKey_F24:
+ return Qt::Key_F24;
+
+ // Character keys
+ case VirtualKey_Space:
+ return Qt::Key_Space;
+ case VirtualKey_Number0:
+ case VirtualKey_NumberPad0:
+ return Qt::Key_0;
+ case VirtualKey_Number1:
+ case VirtualKey_NumberPad1:
+ return Qt::Key_1;
+ case VirtualKey_Number2:
+ case VirtualKey_NumberPad2:
+ return Qt::Key_2;
+ case VirtualKey_Number3:
+ case VirtualKey_NumberPad3:
+ return Qt::Key_3;
+ case VirtualKey_Number4:
+ case VirtualKey_NumberPad4:
+ return Qt::Key_4;
+ case VirtualKey_Number5:
+ case VirtualKey_NumberPad5:
+ return Qt::Key_5;
+ case VirtualKey_Number6:
+ case VirtualKey_NumberPad6:
+ return Qt::Key_6;
+ case VirtualKey_Number7:
+ case VirtualKey_NumberPad7:
+ return Qt::Key_7;
+ case VirtualKey_Number8:
+ case VirtualKey_NumberPad8:
+ return Qt::Key_8;
+ case VirtualKey_Number9:
+ case VirtualKey_NumberPad9:
+ return Qt::Key_9;
+ case VirtualKey_A:
+ return Qt::Key_A;
+ case VirtualKey_B:
+ return Qt::Key_B;
+ case VirtualKey_C:
+ return Qt::Key_C;
+ case VirtualKey_D:
+ return Qt::Key_D;
+ case VirtualKey_E:
+ return Qt::Key_E;
+ case VirtualKey_F:
+ return Qt::Key_F;
+ case VirtualKey_G:
+ return Qt::Key_G;
+ case VirtualKey_H:
+ return Qt::Key_H;
+ case VirtualKey_I:
+ return Qt::Key_I;
+ case VirtualKey_J:
+ return Qt::Key_J;
+ case VirtualKey_K:
+ return Qt::Key_K;
+ case VirtualKey_L:
+ return Qt::Key_L;
+ case VirtualKey_M:
+ return Qt::Key_M;
+ case VirtualKey_N:
+ return Qt::Key_N;
+ case VirtualKey_O:
+ return Qt::Key_O;
+ case VirtualKey_P:
+ return Qt::Key_P;
+ case VirtualKey_Q:
+ return Qt::Key_Q;
+ case VirtualKey_R:
+ return Qt::Key_R;
+ case VirtualKey_S:
+ return Qt::Key_S;
+ case VirtualKey_T:
+ return Qt::Key_T;
+ case VirtualKey_U:
+ return Qt::Key_U;
+ case VirtualKey_V:
+ return Qt::Key_V;
+ case VirtualKey_W:
+ return Qt::Key_W;
+ case VirtualKey_X:
+ return Qt::Key_X;
+ case VirtualKey_Y:
+ return Qt::Key_Y;
+ case VirtualKey_Z:
+ return Qt::Key_Z;
+ case VirtualKey_Multiply:
+ return Qt::Key_9;
+ case VirtualKey_Add:
+ return Qt::Key_9;
+ case VirtualKey_Separator:
+ return Qt::Key_9;
+ case VirtualKey_Subtract:
+ return Qt::Key_9;
+ case VirtualKey_Decimal:
+ return Qt::Key_9;
+ case VirtualKey_Divide:
+ return Qt::Key_9;
+
+ /* Keys with no matching Qt enum (?)
+ case VirtualKey_None:
+ case VirtualKey_LeftButton:
+ case VirtualKey_RightButton:
+ case VirtualKey_MiddleButton:
+ case VirtualKey_XButton1:
+ case VirtualKey_XButton2:
+ case VirtualKey_Final:
+ case VirtualKey_Accept:*/
+ }
+}
+
+static inline Qt::Key qKeyFromCode(quint32 code, int mods)
+{
+ if (code >= 'a' && code <= 'z')
+ code = toupper(code);
+ if ((mods & Qt::ControlModifier) != 0) {
+ if (code >= 0 && code <= 31) // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_
+ code += '@'; // to @..A..Z.._
+ }
+ return static_cast<Qt::Key>(code & 0xff);
+}
+
+QWinRTScreen::QWinRTScreen(ICoreWindow *window)
+ : m_coreWindow(window)
+ , m_depth(32)
+ , m_format(QImage::Format_ARGB32_Premultiplied)
+#ifdef Q_OS_WINPHONE
+ , m_inputContext(new QWinRTInputContext(m_coreWindow))
+#else
+ , m_inputContext(Make<QWinRTInputContext>(m_coreWindow).Detach())
+#endif
+ , m_cursor(new QWinRTCursor(window))
+ , m_orientation(Qt::PrimaryOrientation)
+{
+#ifdef Q_OS_WINPHONE // On phone, there can be only one touch device
+ QTouchDevice *touchDevice = new QTouchDevice;
+ touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure);
+ touchDevice->setType(QTouchDevice::TouchScreen);
+ touchDevice->setName(QStringLiteral("WinPhoneTouchScreen"));
+ Pointer pointer = { Pointer::TouchScreen, touchDevice };
+ m_pointers.insert(0, pointer);
+ QWindowSystemInterface::registerTouchDevice(touchDevice);
+#endif
+
+ Rect rect;
+ window->get_Bounds(&rect);
+ m_geometry = QRect(0, 0, rect.Width, rect.Height);
+
+ m_surfaceFormat.setAlphaBufferSize(0);
+ m_surfaceFormat.setRedBufferSize(8);
+ m_surfaceFormat.setGreenBufferSize(8);
+ m_surfaceFormat.setBlueBufferSize(8);
+
+ m_surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+ m_surfaceFormat.setSamples(1);
+ m_surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ m_surfaceFormat.setDepthBufferSize(24);
+ m_surfaceFormat.setStencilBufferSize(8);
+
+ m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (m_eglDisplay == EGL_NO_DISPLAY)
+ qFatal("Qt WinRT platform plugin: failed to initialize EGL display.");
+
+ if (!eglInitialize(m_eglDisplay, NULL, NULL))
+ qFatal("Qt WinRT platform plugin: failed to initialize EGL. This can happen if you haven't included the D3D compiler DLL in your application package.");
+
+ // TODO: move this to Window
+ m_eglSurface = eglCreateWindowSurface(m_eglDisplay, q_configFromGLFormat(m_eglDisplay, m_surfaceFormat), window, NULL);
+ if (m_eglSurface == EGL_NO_SURFACE)
+ qFatal("Could not create EGL surface, error 0x%X", eglGetError());
+
+ // Event handlers mapped to QEvents
+ m_coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &m_tokens[QEvent::KeyPress]);
+ m_coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &m_tokens[QEvent::KeyRelease]);
+ m_coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &m_tokens[QEvent::User]);
+ m_coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &m_tokens[QEvent::Enter]);
+ m_coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &m_tokens[QEvent::Leave]);
+ m_coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseMove]);
+ m_coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonPress]);
+ m_coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::MouseButtonRelease]);
+ m_coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &m_tokens[QEvent::Wheel]);
+ m_coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &m_tokens[QEvent::Resize]);
+
+ // Window event handlers
+ m_coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &m_tokens[QEvent::WindowActivate]);
+ m_coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &m_tokens[QEvent::WindowDeactivate]);
+ m_coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &m_tokens[QEvent::Show]);
+ m_coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &m_tokens[QEvent::InputMethodQuery]);
+
+ // Orientation handling
+ if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(),
+ &m_displayProperties))) {
+ // Set native orientation
+ DisplayOrientations displayOrientation;
+ m_displayProperties->get_NativeOrientation(&displayOrientation);
+ m_nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
+
+ // Set initial orientation
+ onOrientationChanged(0);
+
+ m_displayProperties->add_OrientationChanged(Callback<IDisplayPropertiesEventHandler>(this, &QWinRTScreen::onOrientationChanged).Get(),
+ &m_tokens[QEvent::OrientationChange]);
+ }
+
+#ifndef Q_OS_WINPHONE
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_ApplicationView).Get(),
+ &m_applicationView);
+#endif
+}
+
+QRect QWinRTScreen::geometry() const
+{
+ return m_geometry;
+}
+
+int QWinRTScreen::depth() const
+{
+ return m_depth;
+}
+
+QImage::Format QWinRTScreen::format() const
+{
+ return m_format;
+}
+
+QSurfaceFormat QWinRTScreen::surfaceFormat() const
+{
+ return m_surfaceFormat;
+}
+
+QWinRTInputContext *QWinRTScreen::inputContext() const
+{
+ return m_inputContext;
+}
+
+QPlatformCursor *QWinRTScreen::cursor() const
+{
+ return m_cursor;
+}
+
+Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const
+{
+ Qt::KeyboardModifiers mods;
+ CoreVirtualKeyStates mod;
+ m_coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod);
+ if (mod == CoreVirtualKeyStates_Down)
+ mods |= Qt::ShiftModifier;
+ m_coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod);
+ if (mod == CoreVirtualKeyStates_Down)
+ mods |= Qt::AltModifier;
+ m_coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod);
+ if (mod == CoreVirtualKeyStates_Down)
+ mods |= Qt::ControlModifier;
+ m_coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod);
+ if (mod == CoreVirtualKeyStates_Down) {
+ mods |= Qt::MetaModifier;
+ } else {
+ m_coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod);
+ if (mod == CoreVirtualKeyStates_Down)
+ mods |= Qt::MetaModifier;
+ }
+ return mods;
+}
+
+Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const
+{
+ return m_nativeOrientation;
+}
+
+Qt::ScreenOrientation QWinRTScreen::orientation() const
+{
+ return m_orientation;
+}
+
+void QWinRTScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
+{
+ m_displayProperties->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
+}
+
+ICoreWindow *QWinRTScreen::coreWindow() const
+{
+ return m_coreWindow;
+}
+
+EGLDisplay QWinRTScreen::eglDisplay() const
+{
+ return m_eglDisplay;
+}
+
+EGLSurface QWinRTScreen::eglSurface() const
+{
+ return m_eglSurface;
+}
+
+QWindow *QWinRTScreen::topWindow() const
+{
+ return m_visibleWindows.isEmpty() ? 0 : m_visibleWindows.first();
+}
+
+void QWinRTScreen::addWindow(QWindow *window)
+{
+ if (window == topWindow())
+ return;
+ m_visibleWindows.prepend(window);
+ QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
+ handleExpose();
+}
+
+void QWinRTScreen::removeWindow(QWindow *window)
+{
+ const bool wasTopWindow = window == topWindow();
+ if (!m_visibleWindows.removeAll(window))
+ return;
+ if (wasTopWindow)
+ QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
+ handleExpose();
+}
+
+void QWinRTScreen::raise(QWindow *window)
+{
+ m_visibleWindows.removeAll(window);
+ addWindow(window);
+}
+
+void QWinRTScreen::lower(QWindow *window)
+{
+ const bool wasTopWindow = window == topWindow();
+ if (wasTopWindow && m_visibleWindows.size() == 1)
+ return;
+ m_visibleWindows.removeAll(window);
+ m_visibleWindows.append(window);
+ if (wasTopWindow)
+ QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
+ handleExpose();
+}
+
+void QWinRTScreen::handleExpose()
+{
+ if (m_visibleWindows.isEmpty())
+ return;
+ QList<QWindow *>::const_iterator it = m_visibleWindows.constBegin();
+ QWindowSystemInterface::handleExposeEvent(*it, m_geometry);
+ while (++it != m_visibleWindows.constEnd())
+ QWindowSystemInterface::handleExposeEvent(*it, QRegion());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args)
+{
+ Q_UNUSED(window);
+ VirtualKey virtualKey;
+ args->get_VirtualKey(&virtualKey);
+ Qt::Key key = qKeyFromVirtual(virtualKey);
+ // Defer character key presses to onCharacterReceived
+ if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis))
+ return S_OK;
+ QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, keyboardModifiers());
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args)
+{
+ Q_UNUSED(window);
+ Qt::KeyboardModifiers mods = keyboardModifiers();
+#ifndef Q_OS_WINPHONE
+ CorePhysicalKeyStatus status; // Look for a pressed character key
+ if (SUCCEEDED(args->get_KeyStatus(&status)) && m_activeKeys.contains(status.ScanCode)) {
+ QPair<Qt::Key, QString> keyStatus = m_activeKeys.take(status.ScanCode);
+ QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease,
+ keyStatus.first, mods, keyStatus.second);
+ return S_OK;
+ }
+#endif // !Q_OS_WINPHONE
+ VirtualKey virtualKey;
+ args->get_VirtualKey(&virtualKey);
+ QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease,
+ qKeyFromVirtual(virtualKey), mods);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceivedEventArgs *args)
+{
+ Q_UNUSED(window);
+
+ quint32 keyCode;
+ args->get_KeyCode(&keyCode);
+ // Don't generate character events for non-printables; the meta key stage is enough
+ if (qIsNonPrintable(keyCode))
+ return S_OK;
+
+ Qt::KeyboardModifiers mods = keyboardModifiers();
+ Qt::Key key = qKeyFromCode(keyCode, mods);
+ QString text = QChar(keyCode);
+ QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text);
+#ifndef Q_OS_WINPHONE
+ CorePhysicalKeyStatus status; // Defer release to onKeyUp for physical keys
+ if (SUCCEEDED(args->get_KeyStatus(&status)) && !status.IsKeyReleased) {
+ m_activeKeys.insert(status.ScanCode, qMakePair(key, text));
+ return S_OK;
+ }
+#endif // !Q_OS_WINPHONE
+ QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *args)
+{
+ Q_UNUSED(window);
+ IPointerPoint *pointerPoint;
+ if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) {
+ // Assumes full-screen window
+ Point point;
+ pointerPoint->get_Position(&point);
+ QPoint pos(point.X, point.Y);
+
+ QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos);
+ pointerPoint->Release();
+ }
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onPointerExited(ICoreWindow *window, IPointerEventArgs *args)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(args);
+ QWindowSystemInterface::handleLeaveEvent(0);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *args)
+{
+ Q_UNUSED(window);
+
+ IPointerPoint *pointerPoint;
+ if (FAILED(args->get_CurrentPoint(&pointerPoint)))
+ return E_INVALIDARG;
+
+ // Common traits - point, modifiers, properties
+ Point point;
+ pointerPoint->get_Position(&point);
+ QPointF pos(point.X, point.Y);
+
+ VirtualKeyModifiers modifiers;
+ args->get_KeyModifiers(&modifiers);
+ Qt::KeyboardModifiers mods;
+ if (modifiers & VirtualKeyModifiers_Control)
+ mods |= Qt::ControlModifier;
+ if (modifiers & VirtualKeyModifiers_Menu)
+ mods |= Qt::AltModifier;
+ if (modifiers & VirtualKeyModifiers_Shift)
+ mods |= Qt::ShiftModifier;
+ if (modifiers & VirtualKeyModifiers_Windows)
+ mods |= Qt::MetaModifier;
+
+ IPointerPointProperties *properties;
+ if (FAILED(pointerPoint->get_Properties(&properties)))
+ return E_INVALIDARG;
+
+#ifdef Q_OS_WINPHONE
+ quint32 pointerId = 0;
+ Pointer pointer = m_pointers.value(pointerId);
+#else
+ Pointer pointer = { Pointer::Unknown, 0 };
+ quint32 pointerId;
+ pointerPoint->get_PointerId(&pointerId);
+ if (m_pointers.contains(pointerId)) {
+ pointer = m_pointers.value(pointerId);
+ } else { // We have not yet enumerated this device. Do so now...
+ IPointerDevice *device;
+ if (SUCCEEDED(pointerPoint->get_PointerDevice(&device))) {
+ PointerDeviceType type;
+ device->get_PointerDeviceType(&type);
+ switch (type) {
+ case PointerDeviceType_Touch:
+ pointer.type = Pointer::TouchScreen;
+ pointer.device = new QTouchDevice;
+ pointer.device->setName(QStringLiteral("WinRT TouchScreen ") + QString::number(pointerId));
+ // TODO: We may want to probe the device usage flags for more accurate values for these next two
+ pointer.device->setType(QTouchDevice::TouchScreen);
+ pointer.device->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure);
+ QWindowSystemInterface::registerTouchDevice(pointer.device);
+ break;
+
+ case PointerDeviceType_Pen:
+ pointer.type = Pointer::Tablet;
+ break;
+
+ case PointerDeviceType_Mouse:
+ pointer.type = Pointer::Mouse;
+ break;
+ }
+
+ m_pointers.insert(pointerId, pointer);
+ device->Release();
+ }
+ }
+#endif
+ switch (pointer.type) {
+ case Pointer::Mouse: {
+ qint32 delta;
+ properties->get_MouseWheelDelta(&delta);
+ if (delta) {
+ boolean isHorizontal;
+ properties->get_IsHorizontalMouseWheel(&isHorizontal);
+ QPoint angleDelta(isHorizontal ? delta : 0, isHorizontal ? 0 : delta);
+ QWindowSystemInterface::handleWheelEvent(topWindow(), pos, pos, QPoint(), angleDelta, mods);
+ break;
+ }
+
+ boolean isPressed;
+ Qt::MouseButtons buttons = Qt::NoButton;
+ properties->get_IsLeftButtonPressed(&isPressed);
+ if (isPressed)
+ buttons |= Qt::LeftButton;
+
+ properties->get_IsMiddleButtonPressed(&isPressed);
+ if (isPressed)
+ buttons |= Qt::MiddleButton;
+
+ properties->get_IsRightButtonPressed(&isPressed);
+ if (isPressed)
+ buttons |= Qt::RightButton;
+
+ properties->get_IsXButton1Pressed(&isPressed);
+ if (isPressed)
+ buttons |= Qt::XButton1;
+
+ properties->get_IsXButton2Pressed(&isPressed);
+ if (isPressed)
+ buttons |= Qt::XButton2;
+
+ QWindowSystemInterface::handleMouseEvent(topWindow(), pos, pos, buttons, mods);
+
+ break;
+ }
+ case Pointer::TouchScreen: {
+ quint32 id;
+ pointerPoint->get_PointerId(&id);
+
+ Rect area;
+ properties->get_ContactRect(&area);
+
+ float pressure;
+ properties->get_Pressure(&pressure);
+
+ QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = m_touchPoints.find(id);
+ if (it != m_touchPoints.end()) {
+ boolean isPressed;
+#ifndef Q_OS_WINPHONE
+ pointerPoint->get_IsInContact(&isPressed);
+#else
+ properties->get_IsLeftButtonPressed(&isPressed); // IsInContact not reliable on phone
+#endif
+ it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased;
+ } else {
+ it = m_touchPoints.insert(id, QWindowSystemInterface::TouchPoint());
+ it.value().state = Qt::TouchPointPressed;
+ it.value().id = id;
+ }
+ it.value().area = QRectF(area.X, area.Y, area.Width, area.Height);
+ it.value().normalPosition = QPointF(pos.x()/m_geometry.width(), pos.y()/m_geometry.height());
+ it.value().pressure = pressure;
+
+ QWindowSystemInterface::handleTouchEvent(topWindow(), pointer.device, m_touchPoints.values(), mods);
+
+ // Remove released points, station others
+ for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) {
+ if (i.value().state == Qt::TouchPointReleased)
+ i = m_touchPoints.erase(i);
+ else
+ (i++).value().state = Qt::TouchPointStationary;
+ }
+
+ break;
+ }
+ case Pointer::Tablet: {
+ quint32 id;
+ pointerPoint->get_PointerId(&id);
+
+ boolean isPressed;
+ pointerPoint->get_IsInContact(&isPressed);
+
+ boolean isEraser;
+ properties->get_IsEraser(&isEraser);
+ int pointerType = isEraser ? 3 : 1;
+
+ float pressure;
+ properties->get_Pressure(&pressure);
+
+ float xTilt;
+ properties->get_XTilt(&xTilt);
+
+ float yTilt;
+ properties->get_YTilt(&yTilt);
+
+ float rotation;
+ properties->get_Twist(&rotation);
+
+ QWindowSystemInterface::handleTabletEvent(topWindow(), isPressed, pos, pos, pointerId,
+ pointerType, pressure, xTilt, yTilt,
+ 0, rotation, 0, id, mods);
+
+ break;
+ }
+ }
+
+ properties->Release();
+ pointerPoint->Release();
+
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
+{
+#ifndef Q_OS_WINPHONE
+ args->put_AutomationProvider(m_inputContext);
+#endif
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *window, IWindowSizeChangedEventArgs *args)
+{
+ Q_UNUSED(window);
+
+ Size size;
+ if (FAILED(args->get_Size(&size))) {
+ qWarning(Q_FUNC_INFO ": failed to get size");
+ return S_OK;
+ }
+
+ // Regardless of state, all top-level windows are viewport-sized - this might change if
+ // a more advanced compositor is written.
+ m_geometry.setSize(QSize(size.Width, size.Height));
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry);
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry);
+ QPlatformScreen::resizeMaximizedWindows();
+ handleExpose();
+
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs *args)
+{
+ Q_UNUSED(window);
+
+ CoreWindowActivationState activationState;
+ args->get_WindowActivationState(&activationState);
+ if (activationState == CoreWindowActivationState_Deactivated) {
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
+ return S_OK;
+ }
+
+ // Activate topWindow
+ if (!m_visibleWindows.isEmpty()) {
+ Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated
+ ? Qt::MouseFocusReason : Qt::ActiveWindowFocusReason;
+ QWindowSystemInterface::handleWindowActivated(topWindow(), focusReason);
+ }
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onClosed(ICoreWindow *window, ICoreWindowEventArgs *args)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(args);
+
+ foreach (QWindow *w, QGuiApplication::topLevelWindows())
+ QWindowSystemInterface::handleCloseEvent(w);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChangedEventArgs *args)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(args);
+
+ boolean visible;
+ args->get_Visible(&visible);
+ QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden);
+ return S_OK;
+}
+
+HRESULT QWinRTScreen::onOrientationChanged(IInspectable *)
+{
+ DisplayOrientations displayOrientation;
+ m_displayProperties->get_CurrentOrientation(&displayOrientation);
+ Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
+ if (m_orientation != newOrientation) {
+ m_orientation = newOrientation;
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
+ }
+
+ return S_OK;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
new file mode 100644
index 0000000000..21e50fa10a
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTSCREEN_H
+#define QWINRTSCREEN_H
+
+#include <qpa/qplatformscreen.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <QtCore/QHash>
+#include <QtGui/QSurfaceFormat>
+#include <EGL/egl.h>
+
+#include <EventToken.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace UI {
+ namespace Core {
+ struct IAutomationProviderRequestedEventArgs;
+ struct ICharacterReceivedEventArgs;
+ struct ICoreWindow;
+ struct ICoreWindowEventArgs;
+ struct IKeyEventArgs;
+ struct IPointerEventArgs;
+ struct IVisibilityChangedEventArgs;
+ struct IWindowActivatedEventArgs;
+ struct IWindowSizeChangedEventArgs;
+ }
+ namespace ViewManagement {
+ struct IApplicationViewStatics;
+ }
+ }
+ namespace Graphics {
+ namespace Display {
+ struct IDisplayPropertiesStatics;
+ }
+ }
+ }
+}
+struct IInspectable;
+
+QT_BEGIN_NAMESPACE
+
+class QTouchDevice;
+class QWinRTEGLContext;
+class QWinRTPageFlipper;
+class QWinRTCursor;
+class QWinRTInputContext;
+
+struct Pointer {
+ enum Type { Unknown, Mouse, TouchScreen, Tablet };
+ Type type;
+ QTouchDevice *device;
+};
+
+class QWinRTScreen : public QPlatformScreen
+{
+public:
+ explicit QWinRTScreen(ABI::Windows::UI::Core::ICoreWindow *window);
+ QRect geometry() const;
+ int depth() const;
+ QImage::Format format() const;
+ QSurfaceFormat surfaceFormat() const;
+ QWinRTInputContext *inputContext() const;
+ QPlatformCursor *cursor() const;
+ Qt::KeyboardModifiers keyboardModifiers() const;
+
+ Qt::ScreenOrientation nativeOrientation() const;
+ Qt::ScreenOrientation orientation() const;
+ void setOrientationUpdateMask(Qt::ScreenOrientations mask);
+
+ QWindow *topWindow() const;
+ void addWindow(QWindow *window);
+ void removeWindow(QWindow *window);
+ void raise(QWindow *window);
+ void lower(QWindow *window);
+
+ ABI::Windows::UI::Core::ICoreWindow *coreWindow() const;
+ EGLDisplay eglDisplay() const; // To opengl context
+ EGLSurface eglSurface() const; // To window
+
+private:
+ void handleExpose();
+
+ // Event handlers
+ QHash<QEvent::Type, EventRegistrationToken> m_tokens;
+
+ HRESULT onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args);
+ HRESULT onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args);
+ HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *args);
+ HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args);
+ HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args);
+ HRESULT onPointerUpdated(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IPointerEventArgs *args);
+ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *args);
+
+ HRESULT onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *args);
+ HRESULT onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *args);
+ HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *args);
+ HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *args);
+
+ HRESULT onOrientationChanged(IInspectable *);
+
+ ABI::Windows::UI::Core::ICoreWindow *m_coreWindow;
+ ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView;
+ QRect m_geometry;
+ QImage::Format m_format;
+ QSurfaceFormat m_surfaceFormat;
+ int m_depth;
+ QWinRTInputContext *m_inputContext;
+ QWinRTCursor *m_cursor;
+ QList<QWindow *> m_visibleWindows;
+
+ EGLDisplay m_eglDisplay;
+ EGLSurface m_eglSurface;
+
+ ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayProperties;
+ Qt::ScreenOrientation m_nativeOrientation;
+ Qt::ScreenOrientation m_orientation;
+
+#ifndef Q_OS_WINPHONE
+ QHash<quint32, QPair<Qt::Key, QString> > m_activeKeys;
+#endif
+ QHash<quint32, Pointer> m_pointers;
+ QHash<quint32, QWindowSystemInterface::TouchPoint> m_touchPoints;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTSCREEN_H
diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp
new file mode 100644
index 0000000000..8f0a1d55bb
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtservices.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtservices.h"
+#include <QtCore/QUrl>
+#include <QtCore/QDir>
+#include <QtCore/QCoreApplication>
+
+#include <wrl.h>
+#include <windows.foundation.h>
+#include <windows.storage.h>
+#include <windows.system.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Storage;
+using namespace ABI::Windows::System;
+
+QT_BEGIN_NAMESPACE
+
+QWinRTServices::QWinRTServices()
+{
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), &m_uriFactory);
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFile).Get(), &m_fileFactory);
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(), &m_launcher);
+}
+
+QWinRTServices::~QWinRTServices()
+{
+ if (m_uriFactory)
+ m_uriFactory->Release();
+
+ if (m_fileFactory)
+ m_fileFactory->Release();
+
+ if (m_launcher)
+ m_launcher->Release();
+}
+
+bool QWinRTServices::openUrl(const QUrl &url)
+{
+ if (!(m_uriFactory && m_launcher))
+ return QPlatformServices::openUrl(url);
+
+ IUriRuntimeClass *uri;
+ QString urlString = url.toString(); HSTRING uriString; HSTRING_HEADER header;
+ WindowsCreateStringReference((const wchar_t*)urlString.utf16(), urlString.length(), &header, &uriString);
+ m_uriFactory->CreateUri(uriString, &uri);
+ if (!uri)
+ return false;
+
+ IAsyncOperation<bool> *launchOp;
+ m_launcher->LaunchUriAsync(uri, &launchOp);
+ uri->Release();
+ if (!launchOp)
+ return false;
+
+ boolean result = false;
+ while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL)
+ QCoreApplication::processEvents();
+ launchOp->Release();
+
+ return result;
+}
+
+bool QWinRTServices::openDocument(const QUrl &url)
+{
+ if (!(m_fileFactory && m_launcher))
+ return QPlatformServices::openDocument(url);
+
+ QString pathString = QDir::toNativeSeparators(
+ QDir::cleanPath(qApp->applicationDirPath().append(url.toString(QUrl::RemoveScheme))));
+ HSTRING_HEADER header; HSTRING path;
+ WindowsCreateStringReference((const wchar_t*)pathString.utf16(), pathString.length(), &header, &path);
+ IAsyncOperation<StorageFile*> *fileOp;
+ m_fileFactory->GetFileFromPathAsync(path, &fileOp);
+ if (!fileOp)
+ return false;
+
+ IStorageFile *file = nullptr;
+ while (fileOp->GetResults(&file) == E_ILLEGAL_METHOD_CALL)
+ QCoreApplication::processEvents();
+ fileOp->Release();
+ if (!file)
+ return false;
+
+ IAsyncOperation<bool> *launchOp;
+ m_launcher->LaunchFileAsync(file, &launchOp);
+ if (!launchOp)
+ return false;
+
+ boolean result = false;
+ while (launchOp->GetResults(&result) == E_ILLEGAL_METHOD_CALL)
+ QCoreApplication::processEvents();
+ launchOp->Release();
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h
new file mode 100644
index 0000000000..9cc917030a
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtservices.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTSERVICES_H
+#define QWINRTSERVICES_H
+
+#include <qpa/qplatformservices.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Foundation {
+ struct IUriRuntimeClassFactory;
+ }
+ namespace Storage {
+ struct IStorageFileStatics;
+ }
+ namespace System {
+ struct ILauncherStatics;
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTServices : public QPlatformServices
+{
+public:
+ explicit QWinRTServices();
+ ~QWinRTServices();
+
+ bool openUrl(const QUrl &url);
+ bool openDocument(const QUrl &url);
+
+private:
+ ABI::Windows::Foundation::IUriRuntimeClassFactory *m_uriFactory;
+ ABI::Windows::Storage::IStorageFileStatics *m_fileFactory;
+ ABI::Windows::System::ILauncherStatics *m_launcher;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTSERVICES_H
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
new file mode 100644
index 0000000000..88b753b463
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtwindow.h"
+#include "qwinrtscreen.h"
+
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformscreen.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QWindow>
+#include <QtGui/QOpenGLContext>
+
+QT_BEGIN_NAMESPACE
+
+QWinRTWindow::QWinRTWindow(QWindow *window)
+ : QPlatformWindow(window)
+ , m_screen(static_cast<QWinRTScreen*>(screen()))
+{
+ setWindowFlags(window->flags());
+ setWindowState(window->windowState());
+ handleContentOrientationChange(window->contentOrientation());
+ setGeometry(window->geometry());
+}
+
+QWinRTWindow::~QWinRTWindow()
+{
+ m_screen->removeWindow(window());
+}
+
+QSurfaceFormat QWinRTWindow::format() const
+{
+ return m_screen->surfaceFormat();
+}
+
+bool QWinRTWindow::isActive() const
+{
+ return m_screen->topWindow() == window();
+}
+
+bool QWinRTWindow::isExposed() const
+{
+ const bool exposed = isActive();
+ return exposed;
+}
+
+void QWinRTWindow::setGeometry(const QRect &rect)
+{
+ if (window()->isTopLevel()) {
+ QPlatformWindow::setGeometry(m_screen->geometry());
+ QWindowSystemInterface::handleGeometryChange(window(), geometry());
+ } else {
+ QPlatformWindow::setGeometry(rect);
+ QWindowSystemInterface::handleGeometryChange(window(), rect);
+ }
+}
+
+void QWinRTWindow::setVisible(bool visible)
+{
+ if (!window()->isTopLevel())
+ return;
+ if (visible)
+ m_screen->addWindow(window());
+ else
+ m_screen->removeWindow(window());
+}
+
+void QWinRTWindow::raise()
+{
+ if (!window()->isTopLevel())
+ return;
+ m_screen->raise(window());
+}
+
+void QWinRTWindow::lower()
+{
+ if (!window()->isTopLevel())
+ return;
+ m_screen->lower(window());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
new file mode 100644
index 0000000000..1f19b4f2d5
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTWINDOW_H
+#define QWINRTWINDOW_H
+
+#include <qpa/qplatformwindow.h>
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTScreen;
+
+class QWinRTWindow : public QPlatformWindow
+{
+public:
+ QWinRTWindow(QWindow *window);
+ ~QWinRTWindow();
+
+ QSurfaceFormat format() const;
+ bool isActive() const;
+ bool isExposed() const;
+ void setGeometry(const QRect &rect);
+ void setVisible(bool visible);
+ void raise();
+ void lower();
+
+private:
+ QWinRTScreen *m_screen;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTWINDOW_H
diff --git a/src/plugins/platforms/winrt/winrt.json b/src/plugins/platforms/winrt/winrt.json
new file mode 100644
index 0000000000..962747b697
--- /dev/null
+++ b/src/plugins/platforms/winrt/winrt.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "winrt" ]
+}
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
new file mode 100644
index 0000000000..ea5ff93d00
--- /dev/null
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -0,0 +1,55 @@
+TARGET = qwinrt
+CONFIG -= precompile_header
+
+PLUGIN_TYPE = platforms
+PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private
+
+DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ GL_GLEXT_PROTOTYPES
+
+LIBS += $$QMAKE_LIBS_CORE -ldxgi
+
+SOURCES = \
+ main.cpp \
+ qwinrtbackingstore.cpp \
+ qwinrtcursor.cpp \
+ qwinrteglcontext.cpp \
+ qwinrteventdispatcher.cpp \
+ qwinrtfontdatabase.cpp \
+ qwinrtinputcontext.cpp \
+ qwinrtintegration.cpp \
+ qwinrtscreen.cpp \
+ qwinrtservices.cpp \
+ qwinrtwindow.cpp
+
+HEADERS = \
+ qwinrtbackingstore.h \
+ qwinrtcursor.h \
+ qwinrteglcontext.h \
+ qwinrteventdispatcher.h \
+ qwinrtfontdatabase.h \
+ qwinrtinputcontext.h \
+ qwinrtintegration.h \
+ qwinrtscreen.h \
+ qwinrtservices.h \
+ qwinrtwindow.h
+
+BLIT_INPUT = $$PWD/blit.hlsl
+fxc_blitps.commands = fxc.exe /nologo /T ps_4_0_level_9_1 /E blitps /Vn q_blitps /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+fxc_blitps.output = $$OUT_PWD/blitps.h
+fxc_blitps.input = BLIT_INPUT
+fxc_blitps.dependency_type = TYPE_C
+fxc_blitps.variable_out = HEADERS
+fxc_blitps.CONFIG += target_predeps
+fxc_blitvs.commands = fxc.exe /nologo /T vs_4_0_level_9_1 /E blitvs /Vn q_blitvs /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+fxc_blitvs.output = $$OUT_PWD/blitvs.h
+fxc_blitvs.input = BLIT_INPUT
+fxc_blitvs.dependency_type = TYPE_C
+fxc_blitvs.variable_out = HEADERS
+fxc_blitvs.CONFIG += target_predeps
+QMAKE_EXTRA_COMPILERS += fxc_blitps fxc_blitvs
+
+OTHER_FILES += winrt.json \
+ blit.hlsl
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index e504d93fba..3f1c53b122 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -167,6 +167,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_shareContext(0)
, m_format(format)
, m_isPBufferCurrent(false)
+ , m_swapInterval(-1)
{
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -326,19 +327,50 @@ QGLXContext::~QGLXContext()
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
{
+ bool success = false;
Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+ Display *dpy = DISPLAY_FROM_XCB(m_screen);
+ GLXDrawable glxDrawable = 0;
QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
if (surfaceClass == QSurface::Window) {
m_isPBufferCurrent = false;
QXcbWindow *window = static_cast<QXcbWindow *>(surface);
- return glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), window->xcb_window(), m_context);
+ glxDrawable = window->xcb_window();
+ success = glXMakeCurrent(dpy, glxDrawable, m_context);
} else if (surfaceClass == QSurface::Offscreen) {
m_isPBufferCurrent = true;
QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
- return glXMakeContextCurrent(DISPLAY_FROM_XCB(m_screen), pbuffer->pbuffer(), pbuffer->pbuffer(), m_context);
+ glxDrawable = pbuffer->pbuffer();
+ success = glXMakeContextCurrent(dpy, glxDrawable, glxDrawable, m_context);
+ }
+
+ if (success) {
+ int interval = surface->format().swapInterval();
+ if (interval >= 0 && m_swapInterval != interval) {
+ m_swapInterval = interval;
+ typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int);
+ typedef void (*qt_glXSwapIntervalMESA)(unsigned int);
+ static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0;
+ static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0;
+ static bool resolved = false;
+ if (!resolved) {
+ resolved = true;
+ QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(dpy,
+ m_screen->screenNumber())).split(' ');
+ if (glxExt.contains("GLX_EXT_swap_control"))
+ glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress("glXSwapIntervalEXT");
+ if (glxExt.contains("GLX_MESA_swap_control"))
+ glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress("glXSwapIntervalMESA");
+ }
+ if (glXSwapIntervalEXT)
+ glXSwapIntervalEXT(dpy, glxDrawable, interval);
+ else if (glXSwapIntervalMESA)
+ glXSwapIntervalMESA(interval);
+ }
}
- return false;
+
+ return success;
}
void QGLXContext::doneCurrent()
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index dcc7fe8855..00bba94ab3 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -81,7 +81,7 @@ private:
GLXContext m_shareContext;
QSurfaceFormat m_format;
bool m_isPBufferCurrent;
-
+ int m_swapInterval;
static bool m_queriedDummyContext;
static bool m_supportsThreading;
};
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index e93b36cb99..366e043e98 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -232,9 +232,6 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s
Q_XCB_NOOP(connection());
m_dirty = m_dirty | source;
-
- xcb_flush(xcb_connection());
- Q_XCB_NOOP(connection());
}
void QXcbShmImage::preparePaint(const QRegion &region)
@@ -314,10 +311,11 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
Q_XCB_NOOP(connection());
if (m_syncingResize) {
- xcb_flush(xcb_connection());
connection()->sync();
m_syncingResize = false;
platformWindow->updateSyncRequestCounter();
+ } else {
+ xcb_flush(xcb_connection());
}
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 3c4ab8d3e2..5e632bff7f 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -326,23 +326,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeXRandr();
updateScreens();
- m_connectionEventListener = xcb_generate_id(m_connection);
- xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
- m_connectionEventListener, m_screens.at(0)->root(),
- 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
- m_screens.at(0)->screen()->root_visual, 0, 0);
-#ifndef QT_NO_DEBUG
- QByteArray ba("Qt xcb connection listener window");
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_connectionEventListener,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData()));
-#endif
-
initializeGLX();
initializeXFixes();
initializeXRender();
@@ -379,9 +362,6 @@ QXcbConnection::~QXcbConnection()
#ifndef QT_NO_DRAGANDDROP
delete m_drag;
#endif
- // Delete screens in reverse order to avoid crash in case of multiple screens
- while (!m_screens.isEmpty())
- delete m_screens.takeLast();
#ifdef XCB_USE_XINPUT2_MAEMO
finalizeXInput2Maemo();
@@ -396,6 +376,10 @@ QXcbConnection::~QXcbConnection()
delete m_reader;
+ // Delete screens in reverse order to avoid crash in case of multiple screens
+ while (!m_screens.isEmpty())
+ delete m_screens.takeLast();
+
#ifdef XCB_USE_EGL
if (m_has_egl)
eglTerminate(m_egl_display);
@@ -1081,14 +1065,21 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
xcb_client_message_event_t event;
memset(&event, 0, sizeof(event));
+ const xcb_window_t eventListener = xcb_generate_id(m_connection);
+ Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
+ eventListener, m_screens.at(0)->root(),
+ 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
+ m_screens.at(0)->screen()->root_visual, 0, 0));
+
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
event.sequence = 0;
- event.window = m_connectionEventListener;
+ event.window = eventListener;
event.type = atom(a);
event.data.data32[0] = id;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
+ Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener));
xcb_flush(xcb_connection());
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index ba056a8006..9e64c37b94 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -521,8 +521,6 @@ private:
QByteArray m_displayName;
- xcb_window_t m_connectionEventListener;
-
QXcbKeyboard *m_keyboard;
#ifndef QT_NO_CLIPBOARD
QXcbClipboard *m_clipboard;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index a571f16eb6..9b6d234375 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -181,7 +181,7 @@ void QXcbConnection::xi2Select(xcb_window_t window)
mask.mask_len = sizeof(bitMask);
mask.mask = xiBitMask;
// Enable each touchscreen
- foreach (XInput2DeviceData *dev, m_touchDevices.values()) {
+ foreach (XInput2DeviceData *dev, m_touchDevices) {
mask.deviceid = dev->xiDeviceInfo->deviceid;
Status result = XISelectEvents(xDisplay, window, &mask, 1);
// If we have XInput >= 2.2 and successfully enable a touchscreen, then
diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
index 9d81c8e224..8c10b134bd 100644
--- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
+++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
@@ -50,6 +50,7 @@
#include <X11/SM/SMlib.h>
#include <errno.h> // ERANGE
+#include <cerrno> // ERANGE
class QSmSocketReceiver : public QObject
{
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index e2c6932992..81134ced49 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -293,7 +293,7 @@ void QXcbWindow::create()
#elif defined(XCB_USE_EGL)
EGLDisplay eglDisplay = connection()->egl_display();
EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true);
- m_format = q_glFormatFromConfig(eglDisplay, eglConfig);
+ m_format = q_glFormatFromConfig(eglDisplay, eglConfig, m_format);
VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig);
@@ -668,8 +668,6 @@ void QXcbWindow::show()
m_screen->windowShown(this);
- xcb_flush(xcb_connection());
-
connection()->sync();
}
@@ -1889,7 +1887,6 @@ void QXcbWindow::updateSyncRequestCounter()
{
if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue));
- xcb_flush(xcb_connection());
connection()->sync();
m_syncValue.lo = 0;