summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/android.pro11
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp48
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp124
-rw-r--r--src/plugins/platforms/android/androidjnimain.h3
-rw-r--r--src/plugins/platforms/android/extract.cpp193
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp149
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.h89
-rw-r--r--src/plugins/platforms/android/qandroidplatformbackingstore.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglcontext.cpp4
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.cpp29
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp51
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp18
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h2
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm11
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm58
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm30
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm13
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm23
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm29
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm2
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm7
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h18
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.cpp7
-rw-r--r--src/plugins/platforms/eglfs/qeglfscontext.h4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp16
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h3
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp4
-rw-r--r--src/plugins/platforms/ios/ios.pro12
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.h3
-rw-r--r--src/plugins/platforms/ios/qiosapplicationdelegate.mm45
-rw-r--r--src/plugins/platforms/ios/qioscontext.mm1
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h8
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm32
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.h (renamed from src/plugins/platforms/winrt/qwinrtplatformtheme.h)16
-rw-r--r--src/plugins/platforms/ios/qiosplatformaccessibility.mm85
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h5
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm121
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h8
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm32
-rw-r--r--src/plugins/platforms/ios/qioswindow.h2
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm317
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.h58
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm193
-rw-r--r--src/plugins/platforms/ios/quiview.h28
-rw-r--r--src/plugins/platforms/ios/quiview.mm345
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm117
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm3
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp99
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.h4
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.h2
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp65
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.h2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp11
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h2
-rw-r--r--src/plugins/platforms/windows/cursors.qrc25
-rw-r--r--src/plugins/platforms/windows/images/closedhandcursor_32.pngbin0 -> 278 bytes
-rw-r--r--src/plugins/platforms/windows/images/closedhandcursor_48.pngbin0 -> 350 bytes
-rw-r--r--src/plugins/platforms/windows/images/closedhandcursor_64.pngbin0 -> 418 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragcopycursor_32.pngbin0 -> 300 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragcopycursor_48.pngbin0 -> 376 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragcopycursor_64.pngbin0 -> 444 bytes
-rw-r--r--src/plugins/platforms/windows/images/draglinkcursor_32.pngbin0 -> 345 bytes
-rw-r--r--src/plugins/platforms/windows/images/draglinkcursor_48.pngbin0 -> 394 bytes
-rw-r--r--src/plugins/platforms/windows/images/draglinkcursor_64.pngbin0 -> 470 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragmovecursor_32.pngbin0 -> 322 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragmovecursor_48.pngbin0 -> 390 bytes
-rw-r--r--src/plugins/platforms/windows/images/dragmovecursor_64.pngbin0 -> 463 bytes
-rw-r--r--src/plugins/platforms/windows/images/openhandcursor_32.pngbin0 -> 315 bytes
-rw-r--r--src/plugins/platforms/windows/images/openhandcursor_48.pngbin0 -> 363 bytes
-rw-r--r--src/plugins/platforms/windows/images/openhandcursor_64.pngbin0 -> 452 bytes
-rw-r--r--src/plugins/platforms/windows/images/splithcursor_32.pngbin0 -> 178 bytes
-rw-r--r--src/plugins/platforms/windows/images/splithcursor_48.pngbin0 -> 210 bytes
-rw-r--r--src/plugins/platforms/windows/images/splithcursor_64.pngbin0 -> 243 bytes
-rw-r--r--src/plugins/platforms/windows/images/splitvcursor_32.pngbin0 -> 187 bytes
-rw-r--r--src/plugins/platforms/windows/images/splitvcursor_48.pngbin0 -> 212 bytes
-rw-r--r--src/plugins/platforms/windows/images/splitvcursor_64.pngbin0 -> 211 bytes
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h15
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h15
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp60
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h24
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp509
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp214
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h6
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp829
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h257
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp76
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h23
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.h62
-rw-r--r--src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp387
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h132
-rw-r--r--src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsguieventdispatcher.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp190
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h29
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.h6
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp85
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp32
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp110
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h18
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h89
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp146
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h52
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp52
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h28
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h12
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp124
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h79
-rw-r--r--src/plugins/platforms/windows/windows.pri11
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.cpp60
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.h24
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp58
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp232
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h (renamed from src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.h)29
-rw-r--r--src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp204
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp544
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h84
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.cpp122
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.h27
-rw-r--r--src/plugins/platforms/winrt/qwinrttheme.cpp211
-rw-r--r--src/plugins/platforms/winrt/qwinrttheme.h (renamed from src/plugins/platforms/winrt/qwinrtplatformtheme.cpp)48
-rw-r--r--src/plugins/platforms/winrt/winrt.pro10
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp172
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h11
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h21
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp52
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp15
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp23
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp140
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h23
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp199
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h14
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp45
176 files changed, 6626 insertions, 2346 deletions
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index 243eea071a..0209379afb 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -21,7 +21,9 @@ CONFIG += qpa/genericunixfontdatabase
OTHER_FILES += $$PWD/android.json
-INCLUDEPATH += $$PWD
+INCLUDEPATH += \
+ $$PWD \
+ $$QT_SOURCE_TREE/src/3rdparty/android
SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/androidjnimain.cpp \
@@ -48,7 +50,9 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidplatformrasterwindow.cpp \
$$PWD/qandroidplatformbackingstore.cpp \
$$PWD/qandroidplatformopenglcontext.cpp \
- $$PWD/qandroidplatformforeignwindow.cpp
+ $$PWD/qandroidplatformforeignwindow.cpp \
+ $$PWD/extract.cpp \
+ $$PWD/qandroideventdispatcher.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/androidjnimain.h \
@@ -75,7 +79,8 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/qandroidplatformrasterwindow.h \
$$PWD/qandroidplatformbackingstore.h \
$$PWD/qandroidplatformopenglcontext.h \
- $$PWD/qandroidplatformforeignwindow.h
+ $$PWD/qandroidplatformforeignwindow.h \
+ $$PWD/qandroideventdispatcher.h
#Non-standard install directory, QTBUG-29859
DESTDIR = $$DESTDIR/android
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 3f58597c9b..a7fec8748b 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -43,10 +43,12 @@
#include "androidjnimain.h"
#include "qandroidplatformintegration.h"
#include "qpa/qplatformaccessibility.h"
+#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include "qguiapplication.h"
#include "qwindow.h"
#include "qrect.h"
#include "QtGui/qaccessible.h"
+#include <QtCore/qmath.h>
#include <QtCore/private/qjnihelpers_p.h>
#include "qdebug.h"
@@ -67,6 +69,7 @@ namespace QtAndroidAccessibility
static jmethodID m_setEnabledMethodID = 0;
static jmethodID m_setFocusableMethodID = 0;
static jmethodID m_setFocusedMethodID = 0;
+ static jmethodID m_setScrollableMethodID = 0;
static jmethodID m_setTextSelectionMethodID = 0;
static jmethodID m_setVisibleToUserMethodID = 0;
@@ -169,6 +172,18 @@ namespace QtAndroidAccessibility
return false;
}
+ static jboolean scrollForward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
+ {
+ QAccessibleInterface *iface = interfaceFromId(objectId);
+ return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::increaseAction());
+ }
+
+ static jboolean scrollBackward(JNIEnv */*env*/, jobject /*thiz*/, jint objectId)
+ {
+ QAccessibleInterface *iface = interfaceFromId(objectId);
+ return QAccessibleBridgeUtils::performEffectiveAction(iface, QAccessibleActionInterface::decreaseAction());
+ }
+
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
clazz = env->FindClass(CLASS_NAME); \
@@ -202,6 +217,11 @@ if (!clazz) { \
return false;
}
QAccessible::State state = iface->state();
+ const QStringList actions = QAccessibleBridgeUtils::effectiveActionNames(iface);
+ const bool hasClickableAction = actions.contains(QAccessibleActionInterface::pressAction())
+ || actions.contains(QAccessibleActionInterface::toggleAction());
+ const bool hasIncreaseAction = actions.contains(QAccessibleActionInterface::increaseAction());
+ const bool hasDecreaseAction = actions.contains(QAccessibleActionInterface::decreaseAction());
// try to fill in the text property, this is what the screen reader reads
QString desc = iface->text(QAccessible::Value);
@@ -219,21 +239,26 @@ if (!clazz) { \
}
env->CallVoidMethod(node, m_setEnabledMethodID, !state.disabled);
+ env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable);
env->CallVoidMethod(node, m_setCheckedMethodID, (bool)state.checked);
env->CallVoidMethod(node, m_setFocusableMethodID, (bool)state.focusable);
env->CallVoidMethod(node, m_setFocusedMethodID, (bool)state.focused);
- env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable);
env->CallVoidMethod(node, m_setVisibleToUserMethodID, !state.invisible);
+ env->CallVoidMethod(node, m_setScrollableMethodID, hasIncreaseAction || hasDecreaseAction);
+ env->CallVoidMethod(node, m_setClickableMethodID, hasClickableAction);
+
+ // Add ACTION_CLICK
+ if (hasClickableAction)
+ env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo
+
+ // Add ACTION_SCROLL_FORWARD
+ if (hasIncreaseAction)
+ env->CallVoidMethod(node, m_addActionMethodID, (int)4096); // ACTION_SCROLL_FORWARD defined in AccessibilityNodeInfo
+
+ // Add ACTION_SCROLL_BACKWARD
+ if (hasDecreaseAction)
+ env->CallVoidMethod(node, m_addActionMethodID, (int)8192); // ACTION_SCROLL_BACKWARD defined in AccessibilityNodeInfo
- if (iface->actionInterface()) {
- QStringList actions = iface->actionInterface()->actionNames();
- bool clickable = actions.contains(QAccessibleActionInterface::pressAction());
- bool toggle = actions.contains(QAccessibleActionInterface::toggleAction());
- if (clickable || toggle) {
- env->CallVoidMethod(node, m_setClickableMethodID, (bool)clickable);
- env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo
- }
- }
jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
//CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc)
@@ -251,6 +276,8 @@ if (!clazz) { \
{"hitTest", "(FF)I", (void*)hitTest},
{"populateNode", "(ILandroid/view/accessibility/AccessibilityNodeInfo;)Z", (void*)populateNode},
{"clickAction", "(I)Z", (void*)clickAction},
+ {"scrollForward", "(I)Z", (void*)scrollForward},
+ {"scrollBackward", "(I)Z", (void*)scrollBackward},
};
#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \
@@ -283,6 +310,7 @@ if (!clazz) { \
GET_AND_CHECK_STATIC_METHOD(m_setEnabledMethodID, nodeInfoClass, "setEnabled", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V");
+ GET_AND_CHECK_STATIC_METHOD(m_setScrollableMethodID, nodeInfoClass, "setScrollable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V");
if (QtAndroidPrivate::androidSdkVersion() >= 18) {
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 3e3e169df9..f776e43efa 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -40,21 +40,10 @@
**
****************************************************************************/
-#include <QtGui/private/qguiapplication_p.h>
-
#include <dlfcn.h>
#include <pthread.h>
-#include <qcoreapplication.h>
-#include <qimage.h>
-#include <qpoint.h>
#include <qplugin.h>
-#include <qsemaphore.h>
-#include <qmutex.h>
#include <qdebug.h>
-#include <qglobal.h>
-#include <qobjectdefs.h>
-#include <QtCore/private/qjni_p.h>
-#include <stdlib.h>
#include "androidjnimain.h"
#include "androidjniaccessibility.h"
@@ -63,14 +52,16 @@
#include "androidjnimenu.h"
#include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h"
-
-#include <qabstracteventdispatcher.h>
+#include "qandroidassetsfileenginehandler.h"
#include <android/bitmap.h>
#include <android/asset_manager_jni.h>
-#include "qandroidassetsfileenginehandler.h"
+#include "qandroideventdispatcher.h"
#include <android/api-level.h>
+
#include <QtCore/private/qjnihelpers_p.h>
+#include <QtCore/private/qjni_p.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -78,42 +69,42 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
QT_BEGIN_NAMESPACE
-static JavaVM *m_javaVM = NULL;
-static jclass m_applicationClass = NULL;
-static jobject m_classLoaderObject = NULL;
-static jmethodID m_loadClassMethodID = NULL;
-static AAssetManager *m_assetManager = NULL;
-static jobject m_resourcesObj;
-static jobject m_activityObject = NULL;
-static jmethodID m_createSurfaceMethodID = 0;
-static jmethodID m_insertNativeViewMethodID = 0;
-static jmethodID m_setSurfaceGeometryMethodID = 0;
-static jmethodID m_destroySurfaceMethodID = 0;
+static JavaVM *m_javaVM = Q_NULLPTR;
+static jclass m_applicationClass = Q_NULLPTR;
+static jobject m_classLoaderObject = Q_NULLPTR;
+static jmethodID m_loadClassMethodID = Q_NULLPTR;
+static AAssetManager *m_assetManager = Q_NULLPTR;
+static jobject m_resourcesObj = Q_NULLPTR;
+static jobject m_activityObject = Q_NULLPTR;
+static jmethodID m_createSurfaceMethodID = Q_NULLPTR;
+static jmethodID m_insertNativeViewMethodID = Q_NULLPTR;
+static jmethodID m_setSurfaceGeometryMethodID = Q_NULLPTR;
+static jmethodID m_destroySurfaceMethodID = Q_NULLPTR;
static bool m_activityActive = true; // defaults to true because when the platform plugin is
// initialized, QtActivity::onResume() has already been called
-static jclass m_bitmapClass = 0;
-static jmethodID m_createBitmapMethodID = 0;
-static jobject m_ARGB_8888_BitmapConfigValue = 0;
-static jobject m_RGB_565_BitmapConfigValue = 0;
+static jclass m_bitmapClass = Q_NULLPTR;
+static jmethodID m_createBitmapMethodID = Q_NULLPTR;
+static jobject m_ARGB_8888_BitmapConfigValue = Q_NULLPTR;
+static jobject m_RGB_565_BitmapConfigValue = Q_NULLPTR;
-jmethodID m_setFullScreenMethodID = 0;
+jmethodID m_setFullScreenMethodID = Q_NULLPTR;
static bool m_statusBarShowing = true;
-static jclass m_bitmapDrawableClass = 0;
-static jmethodID m_bitmapDrawableConstructorMethodID = 0;
+static jclass m_bitmapDrawableClass = Q_NULLPTR;
+static jmethodID m_bitmapDrawableConstructorMethodID = Q_NULLPTR;
extern "C" typedef int (*Main)(int, char **); //use the standard main method to start the application
-static Main m_main = NULL;
-static void *m_mainLibraryHnd = NULL;
+static Main m_main = Q_NULLPTR;
+static void *m_mainLibraryHnd = Q_NULLPTR;
static QList<QByteArray> m_applicationParams;
struct SurfaceData
{
~SurfaceData() { delete surface; }
- QJNIObjectPrivate *surface = 0;
- AndroidSurfaceClient *client = 0;
+ QJNIObjectPrivate *surface = Q_NULLPTR;
+ AndroidSurfaceClient *client = Q_NULLPTR;
};
QHash<int, AndroidSurfaceClient *> m_surfaces;
@@ -121,11 +112,8 @@ QHash<int, AndroidSurfaceClient *> m_surfaces;
static QMutex m_surfacesMutex;
static int m_surfaceId = 1;
-static QSemaphore m_quitAppSemaphore;
-static QSemaphore m_pauseApplicationSemaphore;
-static QMutex m_pauseApplicationMutex;
-static QAndroidPlatformIntegration *m_androidPlatformIntegration = 0;
+static QAndroidPlatformIntegration *m_androidPlatformIntegration = Q_NULLPTR;
static int m_desktopWidthPixels = 0;
static int m_desktopHeightPixels = 0;
@@ -133,7 +121,7 @@ static double m_scaledDensity = 0;
static volatile bool m_pauseApplication;
-static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = 0;
+static AndroidAssetsFileEngineHandler *m_androidAssetsFileEngineHandler = Q_NULLPTR;
@@ -212,7 +200,7 @@ namespace QtAndroid
return;
QtAndroid::AttachedJNIEnv env;
- if (env.jniEnv == 0) {
+ if (!env.jniEnv) {
qWarning("Failed to get JNI Environment.");
return;
}
@@ -227,7 +215,7 @@ namespace QtAndroid
return;
QtAndroid::AttachedJNIEnv env;
- if (env.jniEnv == 0) {
+ if (!env.jniEnv) {
qWarning("Failed to get JNI Environment.");
return;
}
@@ -417,6 +405,9 @@ namespace QtAndroid
return;
m_surfaces.remove(surfaceId);
+ if (m_surfaces.isEmpty())
+ m_surfaceId = 1;
+
QJNIEnvironmentPrivate env;
if (!env)
return;
@@ -426,12 +417,18 @@ namespace QtAndroid
surfaceId);
}
+ bool blockEventLoopsWhenSuspended()
+ {
+ static bool block = qgetenv("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED").toInt();
+ return block;
+ }
+
} // namespace QtAndroid
static jboolean startQtAndroidPlugin(JNIEnv* /*env*/, jobject /*object*//*, jobject applicationAssetManager*/)
{
- m_androidPlatformIntegration = 0;
+ m_androidPlatformIntegration = Q_NULLPTR;
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
return true;
}
@@ -450,7 +447,8 @@ static void *startMainMethod(void */*data*/)
if (res < 0)
qWarning() << "dlclose failed:" << dlerror();
}
-
+ m_mainLibraryHnd = Q_NULLPTR;
+ m_main = Q_NULLPTR;
QtAndroid::AttachedJNIEnv env;
if (!env.jniEnv)
return 0;
@@ -465,7 +463,7 @@ static void *startMainMethod(void */*data*/)
static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring paramsString, jstring environmentString)
{
- m_mainLibraryHnd = NULL;
+ m_mainLibraryHnd = Q_NULLPTR;
{ // Set env. vars
const char *nativeString = env->GetStringUTFChars(environmentString, 0);
const QList<QByteArray> envVars = QByteArray(nativeString).split('\t');
@@ -491,7 +489,7 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
// Obtain a handle to the main library (the library that contains the main() function).
// This library should already be loaded, and calling dlopen() will just return a reference to it.
m_mainLibraryHnd = dlopen(m_applicationParams.first().data(), 0);
- if (m_mainLibraryHnd == NULL) {
+ if (m_mainLibraryHnd == Q_NULLPTR) {
qCritical() << "dlopen failed:" << dlerror();
return false;
}
@@ -508,15 +506,16 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
}
pthread_t appThread;
- return pthread_create(&appThread, NULL, startMainMethod, NULL) == 0;
+ return pthread_create(&appThread, Q_NULLPTR, startMainMethod, Q_NULLPTR) == 0;
}
static void quitQtAndroidPlugin(JNIEnv *env, jclass /*clazz*/)
{
Q_UNUSED(env);
- m_androidPlatformIntegration = 0;
+ m_androidPlatformIntegration = Q_NULLPTR;
delete m_androidAssetsFileEngineHandler;
+ m_androidAssetsFileEngineHandler = Q_NULLPTR;
}
static void terminateQt(JNIEnv *env, jclass /*clazz*/)
@@ -535,8 +534,9 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
env->DeleteGlobalRef(m_RGB_565_BitmapConfigValue);
if (m_bitmapDrawableClass)
env->DeleteGlobalRef(m_bitmapDrawableClass);
- m_androidPlatformIntegration = 0;
+ m_androidPlatformIntegration = Q_NULLPTR;
delete m_androidAssetsFileEngineHandler;
+ m_androidAssetsFileEngineHandler = Q_NULLPTR;
}
static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, jint w, jint h)
@@ -579,11 +579,11 @@ static void updateWindow(JNIEnv */*env*/, jobject /*thiz*/)
if (!m_androidPlatformIntegration)
return;
- if (QGuiApplication::instance() != 0) {
+ if (QGuiApplication::instance() != Q_NULLPTR) {
foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
QRect availableGeometry = w->screen()->availableGeometry();
if (w->geometry().width() > 0 && w->geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
- QWindowSystemInterface::handleExposeEvent(w, QRegion(w->geometry()));
+ QWindowSystemInterface::handleExposeEvent(w, QRegion(QRect(QPoint(), w->geometry().size())));
}
}
@@ -596,10 +596,22 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state
{
m_activityActive = (state == Qt::ApplicationActive);
- if (!m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration())
+ if (!m_main || !m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration())
return;
- QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
+ if (state <= Qt::ApplicationInactive) {
+ // Don't send timers and sockets events anymore if we are going to hide all windows
+ QAndroidEventDispatcherStopper::instance()->goingToStop(true);
+ QCoreApplication::processEvents();
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
+ QWindowSystemInterface::flushWindowSystemEvents();
+ if (state == Qt::ApplicationSuspended)
+ QAndroidEventDispatcherStopper::instance()->stopAll();
+ } else {
+ QAndroidEventDispatcherStopper::instance()->startAll();
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state));
+ QAndroidEventDispatcherStopper::instance()->goingToStop(false);
+ }
}
static void handleOrientationChanged(JNIEnv */*env*/, jobject /*thiz*/, jint newRotation, jint nativeOrientation)
@@ -762,8 +774,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
__android_log_print(ANDROID_LOG_INFO, "Qt", "qt start");
UnionJNIEnvToVoid uenv;
- uenv.venv = NULL;
- m_javaVM = 0;
+ uenv.venv = Q_NULLPTR;
+ m_javaVM = Q_NULLPTR;
if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "GetEnv failed");
diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h
index 29896529ca..31b1aa229e 100644
--- a/src/plugins/platforms/android/androidjnimain.h
+++ b/src/plugins/platforms/android/androidjnimain.h
@@ -100,7 +100,7 @@ namespace QtAndroid
if (QtAndroid::javaVM()->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) {
if (QtAndroid::javaVM()->AttachCurrentThread(&jniEnv, NULL) < 0) {
__android_log_print(ANDROID_LOG_ERROR, "Qt", "AttachCurrentThread failed");
- jniEnv = 0;
+ jniEnv = Q_NULLPTR;
return;
}
attached = true;
@@ -120,6 +120,7 @@ namespace QtAndroid
const char *qtTagText();
QString deviceName();
+ bool blockEventLoopsWhenSuspended();
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp
new file mode 100644
index 0000000000..25c3a1c29d
--- /dev/null
+++ b/src/plugins/platforms/android/extract.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** 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 <jni.h>
+#include <android/log.h>
+#include <extract.h>
+#include <alloca.h>
+
+#define LOG_TAG "extractSyleInfo"
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(JNIEnv * env, jobject, Res_png_9patch* chunk)
+{
+ Res_png_9patch::deserialize(chunk);
+ //printChunkInformation(chunk);
+ jintArray result;
+ size_t size = 3+chunk->numXDivs+chunk->numYDivs+chunk->numColors;
+ result = env->NewIntArray(size);
+ if (!result)
+ return 0;
+
+ jint *data = (jint*)malloc(sizeof(jint)*size);
+ size_t pos = 0;
+ data[pos++]=chunk->numXDivs;
+ data[pos++]=chunk->numYDivs;
+ data[pos++]=chunk->numColors;
+ for (int x = 0; x <chunk->numXDivs; x ++)
+ data[pos++]=chunk->xDivs[x];
+ for (int y = 0; y <chunk->numYDivs; y ++)
+ data[pos++]=chunk->yDivs[y];
+ for (int c = 0; c <chunk->numColors; c ++)
+ data[pos++]=chunk->colors[c];
+ env->SetIntArrayRegion(result, 0, size, data);
+ free(data);
+ return result;
+}
+
+extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo(JNIEnv * env, jobject obj, jbyteArray chunkObj)
+{
+ size_t chunkSize = env->GetArrayLength(chunkObj);
+ void* storage = alloca(chunkSize);
+ env->GetByteArrayRegion(chunkObj, 0, chunkSize,
+ reinterpret_cast<jbyte*>(storage));
+
+ if (!env->ExceptionCheck())
+ return Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(env, obj, static_cast<Res_png_9patch*>(storage));
+ else
+ env->ExceptionClear();
+ return 0;
+}
+
+// The following part was shamelessly stolen from ResourceTypes.cpp from Android's sources
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static void deserializeInternal(const void* inData, Res_png_9patch* outData) {
+ char* patch = (char*) inData;
+ if (inData != outData) {
+ memmove(&outData->wasDeserialized, patch, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
+ memmove(&outData->paddingLeft, patch + 12, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors
+ }
+ outData->wasDeserialized = true;
+ char* data = (char*)outData;
+ data += sizeof(Res_png_9patch);
+ outData->xDivs = (int32_t*) data;
+ data += outData->numXDivs * sizeof(int32_t);
+ outData->yDivs = (int32_t*) data;
+ data += outData->numYDivs * sizeof(int32_t);
+ outData->colors = (uint32_t*) data;
+}
+
+Res_png_9patch* Res_png_9patch::deserialize(const void* inData)
+{
+ if (sizeof(void*) != sizeof(int32_t)) {
+ LOGE("Cannot deserialize on non 32-bit system\n");
+ return NULL;
+ }
+ deserializeInternal(inData, (Res_png_9patch*) inData);
+ return (Res_png_9patch*) inData;
+}
+
+extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo20(JNIEnv * env, jobject, long addr)
+{
+ Res_png_9patch20* chunk = reinterpret_cast<Res_png_9patch20*>(addr);
+ Res_png_9patch20::deserialize(chunk);
+ //printChunkInformation(chunk);
+ jintArray result;
+ size_t size = 3+chunk->numXDivs+chunk->numYDivs+chunk->numColors;
+ result = env->NewIntArray(size);
+ if (!result)
+ return 0;
+
+ jint *data = (jint*)malloc(sizeof(jint)*size);
+ size_t pos = 0;
+ data[pos++] = chunk->numXDivs;
+ data[pos++] = chunk->numYDivs;
+ data[pos++] = chunk->numColors;
+
+ int32_t* xDivs = chunk->getXDivs();
+ int32_t* yDivs = chunk->getYDivs();
+ uint32_t* colors = chunk->getColors();
+
+ for (int x = 0; x <chunk->numXDivs; x ++)
+ data[pos++]=xDivs[x];
+ for (int y = 0; y <chunk->numYDivs; y ++)
+ data[pos++] = yDivs[y];
+ for (int c = 0; c <chunk->numColors; c ++)
+ data[pos++] = colors[c];
+ env->SetIntArrayRegion(result, 0, size, data);
+ free(data);
+ return result;
+}
+
+extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo20(JNIEnv * env, jobject obj, jbyteArray chunkObj)
+{
+ size_t chunkSize = env->GetArrayLength(chunkObj);
+ void* storage = alloca(chunkSize);
+ env->GetByteArrayRegion(chunkObj, 0, chunkSize,
+ reinterpret_cast<jbyte*>(storage));
+
+ if (!env->ExceptionCheck())
+ return Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo20(env, obj, long(storage));
+ else
+ env->ExceptionClear();
+ return 0;
+}
+
+static inline void fill9patchOffsets(Res_png_9patch20* patch) {
+ patch->xDivsOffset = sizeof(Res_png_9patch20);
+ patch->yDivsOffset = patch->xDivsOffset + (patch->numXDivs * sizeof(int32_t));
+ patch->colorsOffset = patch->yDivsOffset + (patch->numYDivs * sizeof(int32_t));
+}
+
+Res_png_9patch20* Res_png_9patch20::deserialize(void* inData)
+{
+ Res_png_9patch20* patch = reinterpret_cast<Res_png_9patch20*>(inData);
+ patch->wasDeserialized = true;
+ fill9patchOffsets(patch);
+ return patch;
+}
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
new file mode 100644
index 0000000000..074ba71f80
--- /dev/null
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** 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 "qandroideventdispatcher.h"
+#include "androidjnimain.h"
+
+QAndroidEventDispatcher::QAndroidEventDispatcher(QObject *parent) :
+ QUnixEventDispatcherQPA(parent)
+{
+ if (QtAndroid::blockEventLoopsWhenSuspended())
+ QAndroidEventDispatcherStopper::instance()->addEventDispatcher(this);
+}
+
+QAndroidEventDispatcher::~QAndroidEventDispatcher()
+{
+ if (QtAndroid::blockEventLoopsWhenSuspended())
+ QAndroidEventDispatcherStopper::instance()->removeEventDispatcher(this);
+}
+
+void QAndroidEventDispatcher::start()
+{
+ if (m_stopRequest.testAndSetAcquire(1, 0)) {
+ m_dispatcherSemaphore.release();
+ wakeUp();
+ }
+}
+
+void QAndroidEventDispatcher::stop()
+{
+ if (m_stopRequest.testAndSetAcquire(0, 1)) {
+ wakeUp();
+ m_stopperSemaphore.acquire();
+ }
+}
+
+void QAndroidEventDispatcher::goingToStop(bool stop)
+{
+ m_goingToStop.store(stop ? 1 : 0);
+ if (!stop)
+ wakeUp();
+}
+
+int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout)
+{
+ if (m_stopRequest.load() == 1) {
+ m_stopperSemaphore.release();
+ m_dispatcherSemaphore.acquire();
+ wakeUp();
+ }
+
+ return QUnixEventDispatcherQPA::select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+bool QAndroidEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ if (m_goingToStop.load()) {
+ return QUnixEventDispatcherQPA::processEvents(flags /*| QEventLoop::ExcludeUserInputEvents*/
+ | QEventLoop::ExcludeSocketNotifiers
+ | QEventLoop::X11ExcludeTimers);
+ } else {
+ return QUnixEventDispatcherQPA::processEvents(flags);
+ }
+}
+
+
+QAndroidEventDispatcherStopper *QAndroidEventDispatcherStopper::instance()
+{
+ static QAndroidEventDispatcherStopper androidEventDispatcherStopper;
+ return &androidEventDispatcherStopper;
+}
+
+void QAndroidEventDispatcherStopper::startAll()
+{
+ QMutexLocker lock(&m_mutex);
+ if (started)
+ return;
+
+ started = true;
+ foreach (QAndroidEventDispatcher *d, m_dispatchers)
+ d->start();
+}
+
+void QAndroidEventDispatcherStopper::stopAll()
+{
+ QMutexLocker lock(&m_mutex);
+ if (!started)
+ return;
+
+ started = false;
+ foreach (QAndroidEventDispatcher *d, m_dispatchers)
+ d->stop();
+}
+
+void QAndroidEventDispatcherStopper::addEventDispatcher(QAndroidEventDispatcher *dispatcher)
+{
+ QMutexLocker lock(&m_mutex);
+ m_dispatchers.push_back(dispatcher);
+}
+
+void QAndroidEventDispatcherStopper::removeEventDispatcher(QAndroidEventDispatcher *dispatcher)
+{
+ QMutexLocker lock(&m_mutex);
+ m_dispatchers.erase(std::find(m_dispatchers.begin(), m_dispatchers.end(), dispatcher));
+}
+
+void QAndroidEventDispatcherStopper::goingToStop(bool stop)
+{
+ QMutexLocker lock(&m_mutex);
+ foreach (QAndroidEventDispatcher *d, m_dispatchers)
+ d->goingToStop(stop);
+}
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h
new file mode 100644
index 0000000000..8d1bcf2122
--- /dev/null
+++ b/src/plugins/platforms/android/qandroideventdispatcher.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
+** 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 QANDROIDEVENTDISPATCHER_H
+#define QANDROIDEVENTDISPATCHER_H
+
+#include <QtCore/QMutex>
+#include <QtCore/QSemaphore>
+#include <QtPlatformSupport/private/qunixeventdispatcher_qpa_p.h>
+
+class QAndroidEventDispatcher : public QUnixEventDispatcherQPA
+{
+ Q_OBJECT
+public:
+ explicit QAndroidEventDispatcher(QObject *parent = 0);
+ ~QAndroidEventDispatcher();
+ void start();
+ void stop();
+
+ void goingToStop(bool stop);
+
+protected:
+ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timespec *timeout);
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+
+private:
+ QAtomicInt m_stopRequest;
+ QAtomicInt m_goingToStop;
+ QSemaphore m_dispatcherSemaphore, m_stopperSemaphore;
+};
+
+class QAndroidEventDispatcherStopper
+{
+public:
+ static QAndroidEventDispatcherStopper *instance();
+ void startAll();
+ void stopAll();
+ void addEventDispatcher(QAndroidEventDispatcher *dispatcher);
+ void removeEventDispatcher(QAndroidEventDispatcher *dispatcher);
+ void goingToStop(bool stop);
+
+private:
+ QMutex m_mutex;
+ bool started = true;
+ QVector<QAndroidEventDispatcher *> m_dispatchers;
+};
+
+
+#endif // QANDROIDEVENTDISPATCHER_H
diff --git a/src/plugins/platforms/android/qandroidplatformbackingstore.h b/src/plugins/platforms/android/qandroidplatformbackingstore.h
index 4c24e129c3..c51ebe879d 100644
--- a/src/plugins/platforms/android/qandroidplatformbackingstore.h
+++ b/src/plugins/platforms/android/qandroidplatformbackingstore.h
@@ -55,7 +55,7 @@ public:
virtual QPaintDevice *paintDevice();
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
virtual void resize(const QSize &size, const QRegion &staticContents);
- const QImage image() { return m_image; }
+ QImage toImage() const { return m_image; }
void setBackingStore(QWindow *window);
protected:
QImage m_image;
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index d6d7d3b173..829227f81c 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -47,15 +47,14 @@
#include <QThread>
#include <QOffscreenSurface>
-#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
-
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformoffscreensurface.h>
#include "androidjnimain.h"
#include "qabstracteventdispatcher.h"
+#include "qandroideventdispatcher.h"
#include "qandroidplatformbackingstore.h"
#include "qandroidplatformaccessibility.h"
#include "qandroidplatformclipboard.h"
@@ -236,7 +235,7 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind
QAbstractEventDispatcher *QAndroidPlatformIntegration::createEventDispatcher() const
{
- return createUnixEventDispatcher();
+ return new QAndroidEventDispatcher;
}
QAndroidPlatformIntegration::~QAndroidPlatformIntegration()
diff --git a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp
index f27bea8863..2c6e8370ce 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglcontext.cpp
@@ -58,10 +58,10 @@ QAndroidPlatformOpenGLContext::QAndroidPlatformOpenGLContext(const QSurfaceForma
void QAndroidPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface)
{
- QEGLPlatformContext::swapBuffers(surface);
-
if (surface->surface()->surfaceClass() == QSurface::Window)
static_cast<QAndroidPlatformOpenGLWindow *>(surface)->checkNativeSurface(eglConfig());
+
+ QEGLPlatformContext::swapBuffers(surface);
}
bool QAndroidPlatformOpenGLContext::needsFBOReadBackWorkaroud()
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
index f0c4a1de2a..7c39cb718d 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
@@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE
QAndroidPlatformOpenGLWindow::QAndroidPlatformOpenGLWindow(QWindow *window, EGLDisplay display)
:QAndroidPlatformWindow(window), m_eglDisplay(display)
{
- lockSurface();
- m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), bool(window->flags() & Qt::WindowStaysOnTopHint), 32);
- m_surfaceWaitCondition.wait(&m_surfaceMutex);
- unlockSurface();
}
QAndroidPlatformOpenGLWindow::~QAndroidPlatformOpenGLWindow()
@@ -97,6 +93,13 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
{
QMutexLocker lock(&m_surfaceMutex);
+
+ if (m_nativeSurfaceId == -1) {
+ const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
+ m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
+ m_surfaceWaitCondition.wait(&m_surfaceMutex);
+ }
+
if (m_eglSurface == EGL_NO_SURFACE) {
m_surfaceMutex.unlock();
checkNativeSurface(config);
@@ -117,7 +120,21 @@ void QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
// we've create another surface, the window should be repainted
QRect availableGeometry = screen()->availableGeometry();
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(), geometry().size())));
+}
+
+void QAndroidPlatformOpenGLWindow::applicationStateChanged(Qt::ApplicationState state)
+{
+ QAndroidPlatformWindow::applicationStateChanged(state);
+ if (state <= Qt::ApplicationHidden && QtAndroid::blockEventLoopsWhenSuspended()) {
+ lockSurface();
+ if (m_nativeSurfaceId != -1) {
+ QtAndroid::destroySurface(m_nativeSurfaceId);
+ m_nativeSurfaceId = -1;
+ }
+ clearEgl();
+ unlockSurface();
+ }
}
void QAndroidPlatformOpenGLWindow::createEgl(EGLConfig config)
@@ -170,7 +187,7 @@ void QAndroidPlatformOpenGLWindow::surfaceChanged(JNIEnv *jniEnv, jobject surfac
// repaint the window
QRect availableGeometry = screen()->availableGeometry();
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
- QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry()));
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(), geometry().size())));
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.h b/src/plugins/platforms/android/qandroidplatformopenglwindow.h
index 83df15a524..713f943bc5 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.h
@@ -64,6 +64,8 @@ public:
void checkNativeSurface(EGLConfig config);
+ void applicationStateChanged(Qt::ApplicationState);
+
protected:
virtual void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h);
void createEgl(EGLConfig config);
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 714a670134..529ae0a80d 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -54,6 +54,7 @@
#include <android/bitmap.h>
#include <android/native_window_jni.h>
+#include <qguiapplication.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
@@ -102,6 +103,7 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
m_redrawTimer.setSingleShot(true);
m_redrawTimer.setInterval(0);
connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw()));
+ connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged);
}
QAndroidPlatformScreen::~QAndroidPlatformScreen()
@@ -109,8 +111,7 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen()
if (m_id != -1) {
QtAndroid::destroySurface(m_id);
m_surfaceWaitCondition.wakeOne();
- if (m_nativeSurface)
- ANativeWindow_release(m_nativeSurface);
+ releaseSurface();
}
}
@@ -133,7 +134,7 @@ QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
{
- if (window->parent())
+ if (window->parent() && window->isRaster())
return;
m_windowStack.prepend(window);
@@ -149,10 +150,11 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
{
- if (window->parent())
+ if (window->parent() && window->isRaster())
return;
m_windowStack.removeOne(window);
+
if (window->isRaster()) {
m_rasterSurfaces.deref();
setDirty(window->geometry());
@@ -165,7 +167,7 @@ void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
{
- if (window->parent())
+ if (window->parent() && window->isRaster())
return;
int index = m_windowStack.indexOf(window);
@@ -182,7 +184,7 @@ void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
{
- if (window->parent())
+ if (window->parent() && window->isRaster())
return;
int index = m_windowStack.indexOf(window);
@@ -247,14 +249,25 @@ void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
}
if (m_id != -1) {
- if (m_nativeSurface) {
- ANativeWindow_release(m_nativeSurface);
- m_nativeSurface = 0;
- }
+ releaseSurface();
QtAndroid::setSurfaceGeometry(m_id, rect);
}
}
+void QAndroidPlatformScreen::applicationStateChanged(Qt::ApplicationState state)
+{
+ foreach (QAndroidPlatformWindow *w, m_windowStack)
+ w->applicationStateChanged(state);
+
+ if (state <= Qt::ApplicationHidden && QtAndroid::blockEventLoopsWhenSuspended()) {
+ lockSurface();
+ QtAndroid::destroySurface(m_id);
+ m_id = -1;
+ releaseSurface();
+ unlockSurface();
+ }
+}
+
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
{
QtAndroidMenu::setActiveTopLevelWindow(w);
@@ -332,7 +345,7 @@ void QAndroidPlatformScreen::doRedraw()
QRect windowRect = targetRect.translated(-window->geometry().topLeft());
QAndroidPlatformBackingStore *backingStore = static_cast<QAndroidPlatformRasterWindow *>(window)->backingStore();
if (backingStore)
- compositePainter.drawImage(targetRect.topLeft(), backingStore->image(), windowRect);
+ compositePainter.drawImage(targetRect.topLeft(), backingStore->toImage(), windowRect);
}
}
@@ -365,18 +378,22 @@ void QAndroidPlatformScreen::surfaceChanged(JNIEnv *env, jobject surface, int w,
{
lockSurface();
if (surface && w && h) {
- if (m_nativeSurface)
- ANativeWindow_release(m_nativeSurface);
+ releaseSurface();
m_nativeSurface = ANativeWindow_fromSurface(env, surface);
QMetaObject::invokeMethod(this, "setDirty", Qt::QueuedConnection, Q_ARG(QRect, QRect(0, 0, w, h)));
} else {
- if (m_nativeSurface) {
- ANativeWindow_release(m_nativeSurface);
- m_nativeSurface = 0;
- }
+ releaseSurface();
}
unlockSurface();
m_surfaceWaitCondition.wakeOne();
}
+void QAndroidPlatformScreen::releaseSurface()
+{
+ if (m_nativeSurface) {
+ ANativeWindow_release(m_nativeSurface);
+ m_nativeSurface = 0;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index cd9cf2ca71..311752c7b4 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -107,6 +107,8 @@ private:
Qt::ScreenOrientation orientation() const;
Qt::ScreenOrientation nativeOrientation() const;
void surfaceChanged(JNIEnv *env, jobject surface, int w, int h);
+ void releaseSurface();
+ void applicationStateChanged(Qt::ApplicationState);
private slots:
void doRedraw();
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 558525b78c..d07573fb88 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -45,6 +45,8 @@
#include "qandroidplatformscreen.h"
#include "androidjnimain.h"
+
+#include <qguiapplication.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
@@ -160,5 +162,21 @@ void QAndroidPlatformWindow::updateStatusBarVisibility()
}
}
+bool QAndroidPlatformWindow::isExposed() const
+{
+ return qApp->applicationState() > Qt::ApplicationHidden
+ && window()->isVisible()
+ && !window()->geometry().isEmpty();
+}
+
+void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState)
+{
+ QRegion region;
+ if (isExposed())
+ region = QRect(QPoint(), geometry().size());
+
+ QWindowSystemInterface::handleExposeEvent(window(), region);
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index 764dd3ab86..91e32fa2ac 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -72,7 +72,9 @@ public:
void requestActivateWindow();
void updateStatusBarVisibility();
inline bool isRaster() const { return window()->surfaceType() == QSurface::RasterSurface; }
+ bool isExposed() const;
+ virtual void applicationStateChanged(Qt::ApplicationState);
protected:
void setGeometry(const QRect &rect);
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 1f9c0e051d..ad6cb3a1fc 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -14,7 +14,6 @@ OBJECTIVE_SOURCES += main.mm \
qnsviewaccessibility.mm \
qcocoaautoreleasepool.mm \
qnswindowdelegate.mm \
- qcocoaglcontext.mm \
qcocoanativeinterface.mm \
qcocoaeventdispatcher.mm \
qcocoaapplicationdelegate.mm \
@@ -51,7 +50,6 @@ HEADERS += qcocoaintegration.h \
qnsview.h \
qcocoaautoreleasepool.h \
qnswindowdelegate.h \
- qcocoaglcontext.h \
qcocoanativeinterface.h \
qcocoaeventdispatcher.h \
qcocoaapplicationdelegate.h \
@@ -80,6 +78,12 @@ HEADERS += qcocoaintegration.h \
messages.h \
qcocoamimetypes.h
+contains(QT_CONFIG, opengl.*) {
+ OBJECTIVE_SOURCES += qcocoaglcontext.mm
+
+ HEADERS += qcocoaglcontext.h
+}
+
RESOURCES += qcocoaresources.qrc
LIBS += -framework Cocoa -framework Carbon -framework IOKit -lcups
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 72045a1bbb..8f83b0fe30 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -55,7 +55,7 @@ QCocoaAccessibility::~QCocoaAccessibility()
void QCocoaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
- QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithId: event->uniqueId()];
+ QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: event->uniqueId()];
if (!element) {
qWarning() << "QCocoaAccessibility::notifyAccessibilityUpdate: invalid element";
return;
@@ -140,7 +140,7 @@ static void populateRoleMap()
roleMap[QAccessible::Row] = NSAccessibilityRowRole;
roleMap[QAccessible::RowHeader] = NSAccessibilityRowRole;
roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole;
- roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole;
+ roleMap[QAccessible::Button] = NSAccessibilityButtonRole;
roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole;
roleMap[QAccessible::Link] = NSAccessibilityLinkRole;
roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole;
@@ -149,6 +149,9 @@ static void populateRoleMap()
roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole;
roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole;
roleMap[QAccessible::Client] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Paragraph] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Section] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::WebDocument] = NSAccessibilityGroupRole;
}
/*
@@ -244,7 +247,7 @@ NSArray *unignoredChildren(QAccessibleInterface *interface)
QAccessible::Id childId = QAccessible::uniqueId(child);
//qDebug() << " kid: " << childId << child;
- QCocoaAccessibleElement *element = [QCocoaAccessibleElement elementWithId: childId];
+ QMacAccessibilityElement *element = [QMacAccessibilityElement elementWithId: childId];
if (element)
[kids addObject: element];
else
@@ -343,7 +346,7 @@ id getValueAttribute(QAccessibleInterface *interface)
}
if (QAccessibleValueInterface *valueInterface = interface->valueInterface()) {
- return QCFString::toNSString(QString::number(valueInterface->currentValue().toDouble()));
+ return QCFString::toNSString(valueInterface->currentValue().toString());
}
if (interface->state().checkable) {
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 9760f492ea..4a5baefbc5 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -50,18 +50,18 @@
#import <qaccessible.h>
-@class QT_MANGLE_NAMESPACE(QCocoaAccessibleElement);
+@class QT_MANGLE_NAMESPACE(QMacAccessibilityElement);
-@interface QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) : NSObject {
+@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : NSObject {
NSString *role;
QAccessible::Id axid;
}
- (id)initWithId:(QAccessible::Id)anId;
-+ (QT_MANGLE_NAMESPACE(QCocoaAccessibleElement) *)elementWithId:(QAccessible::Id)anId;
++ (QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *)elementWithId:(QAccessible::Id)anId;
@end
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaAccessibleElement);
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 078dc67cad..9f803e411d 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -43,12 +43,12 @@
#include "qcocoahelpers.h"
#include "qcocoawindow.h"
#include "private/qaccessiblecache_p.h"
-
+#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
#import <AppKit/NSAccessibility.h>
-@implementation QCocoaAccessibleElement
+@implementation QMacAccessibilityElement
- (id)initWithId:(QAccessible::Id)anId
{
@@ -72,7 +72,7 @@
QAccessibleCache *cache = QAccessibleCache::instance();
- QCocoaAccessibleElement *element = cache->elementForId(anId);
+ QMacAccessibilityElement *element = cache->elementForId(anId);
if (!element) {
QAccessibleInterface *iface = QAccessible::accessibleInterface(anId);
Q_ASSERT(iface);
@@ -95,8 +95,8 @@
}
- (BOOL)isEqual:(id)object {
- if ([object isKindOfClass:[QCocoaAccessibleElement class]]) {
- QCocoaAccessibleElement *other = object;
+ if ([object isKindOfClass:[QMacAccessibilityElement class]]) {
+ QMacAccessibilityElement *other = object;
return other->axid == axid;
} else {
return NO;
@@ -196,7 +196,7 @@
}
QAccessible::Id parentId = QAccessible::uniqueId(parent);
- return [QCocoaAccessibleElement elementWithId: parentId];
+ return [QMacAccessibilityElement elementWithId: parentId];
}
@@ -345,7 +345,7 @@
}
if ([attribute isEqualToString: NSAccessibilityLineForIndexParameterizedAttribute]) {
int index = [parameter intValue];
- NSNumber *ln = [QCocoaAccessibleElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
+ NSNumber *ln = [QMacAccessibilityElement lineNumberForIndex: index forText: iface->text(QAccessible::Value)];
return ln;
}
if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
@@ -430,15 +430,11 @@
if (!iface)
return nsActions;
- QAccessibleActionInterface *actionInterface = iface->actionInterface();
- if (actionInterface) {
- QStringList supportedActionNames = actionInterface->actionNames();
-
- foreach (const QString &qtAction, supportedActionNames) {
- NSString *nsAction = QCocoaAccessible::getTranslatedAction(qtAction);
- if (nsAction)
- [nsActions addObject : nsAction];
- }
+ const QStringList &supportedActionNames = QAccessibleBridgeUtils::effectiveActionNames(iface);
+ foreach (const QString &qtAction, supportedActionNames) {
+ NSString *nsAction = QCocoaAccessible::getTranslatedAction(qtAction);
+ if (nsAction)
+ [nsActions addObject : nsAction];
}
return nsActions;
@@ -448,27 +444,25 @@
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (!iface)
return nil; // FIXME is that the right return type??
- QAccessibleActionInterface *actionInterface = iface->actionInterface();
- if (actionInterface) {
- QString qtAction = QCocoaAccessible::translateAction(action);
-
- // Return a description from the action interface if this action is not known to the OS.
- if (qtAction.isEmpty()) {
- QString description = actionInterface->localizedActionDescription(qtAction);
- return QCFString::toNSString(description);
+ QString qtAction = QCocoaAccessible::translateAction(action);
+ QString description;
+ // Return a description from the action interface if this action is not known to the OS.
+ if (qtAction.isEmpty()) {
+ if (QAccessibleActionInterface *actionInterface = iface->actionInterface()) {
+ qtAction = QString::fromNSString((NSString *)action);
+ description = actionInterface->localizedActionDescription(qtAction);
}
+ } else {
+ description = qAccessibleLocalizedActionDescription(qtAction);
}
-
- return NSAccessibilityActionDescription(action);
+ return QCFString::toNSString(description);
}
- (void)accessibilityPerformAction:(NSString *)action {
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (iface) {
- QAccessibleActionInterface *actionInterface = iface->actionInterface();
- if (actionInterface) {
- actionInterface->doAction(QCocoaAccessible::translateAction(action));
- }
+ const QString qtAction = QCocoaAccessible::translateAction(action);
+ QAccessibleBridgeUtils::performEffectiveAction(iface, qtAction);
}
}
@@ -504,7 +498,7 @@
QAccessible::Id childId = QAccessible::uniqueId(childInterface);
// hit a child, forward to child accessible interface.
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithId:childId];
+ QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childId];
if (accessibleElement)
return NSAccessibilityUnignoredAncestor(accessibleElement);
return NSAccessibilityUnignoredAncestor(self);
@@ -521,7 +515,7 @@
QAccessibleInterface *childInterface = iface->focusChild();
if (childInterface) {
QAccessible::Id childAxid = QAccessible::uniqueId(childInterface);
- QCocoaAccessibleElement *accessibleElement = [QCocoaAccessibleElement elementWithId:childAxid];
+ QMacAccessibilityElement *accessibleElement = [QMacAccessibilityElement elementWithId:childAxid];
return NSAccessibilityUnignoredAncestor(accessibleElement);
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 92358ecc74..efe3269d42 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -340,6 +340,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
[reflectionDelegate applicationDidBecomeActive:notification];
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
/*
onApplicationChangedActivation(true);
@@ -363,6 +364,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
[reflectionDelegate applicationDidResignActive:notification];
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
/*
onApplicationChangedActivation(false);
@@ -374,6 +376,26 @@ static void cleanupCocoaApplicationDelegate()
*/
}
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
+{
+ Q_UNUSED(theApplication);
+ Q_UNUSED(flag);
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationShouldHandleReopen:hasVisibleWindows:)])
+ return [reflectionDelegate applicationShouldHandleReopen:theApplication hasVisibleWindows:flag];
+
+ /*
+ true to force delivery of the event even if the application state is already active,
+ because rapp (handle reopen) events are sent each time the dock icon is clicked regardless
+ of the active state of the application or number of visible windows. For example, a browser
+ app that has no windows opened would need the event be to delivered even if it was already
+ active in order to create a new window as per OS X conventions.
+ */
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
+
+ return NO;
+}
+
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
{
[oldDelegate retain];
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index a33373c4c1..8a4e2e68df 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -59,7 +59,9 @@ public:
QPaintDevice *paintDevice();
void flush(QWindow *widget, const QRegion &region, const QPoint &offset);
+#ifndef QT_NO_OPENGL
QImage toImage() const Q_DECL_OVERRIDE;
+#endif
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
CGImageRef getBackingStoreCGImage();
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index d76645c668..e13e295511 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -96,10 +96,12 @@ void QCocoaBackingStore::flush(QWindow *win, const QRegion &region, const QPoint
}
}
+#ifndef QT_NO_OPENGL
QImage QCocoaBackingStore::toImage() const
{
return m_qImage;
}
+#endif
void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
{
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 30f1cdc278..2aa22ea759 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
class QCocoaGLContext : public QPlatformOpenGLContext
{
public:
- QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
~QCocoaGLContext();
QSurfaceFormat format() const;
@@ -77,6 +77,8 @@ public:
void windowWasHidden();
+ QVariant nativeHandle() const;
+
private:
void setActiveWindow(QWindow *window);
void updateSurfaceFormat();
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 3f61bd81ee..7b70fbb4bb 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -46,6 +46,7 @@
#include <qdebug.h>
#include <QtCore/private/qcore_mac_p.h>
#include <QtPlatformSupport/private/cglconvenience_p.h>
+#include <QtPlatformHeaders/qcocoanativecontext.h>
#import <Cocoa/Cocoa.h>
@@ -117,11 +118,33 @@ static void updateFormatFromContext(QSurfaceFormat *format)
format->setProfile(QSurfaceFormat::CompatibilityProfile);
}
-QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle)
: m_context(nil),
m_shareContext(nil),
m_format(format)
{
+ if (!nativeHandle.isNull()) {
+ if (!nativeHandle.canConvert<QCocoaNativeContext>()) {
+ qWarning("QCocoaGLContext: Requires a QCocoaNativeContext");
+ return;
+ }
+ QCocoaNativeContext handle = nativeHandle.value<QCocoaNativeContext>();
+ NSOpenGLContext *context = handle.context();
+ if (!context) {
+ qWarning("QCocoaGLContext: No NSOpenGLContext given");
+ return;
+ }
+ m_context = context;
+ [m_context retain];
+ m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
+ // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
+ const GLint order = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
+ [m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
+ updateSurfaceFormat();
+ return;
+ }
+
// we only support OpenGL contexts under Cocoa
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -168,6 +191,11 @@ QCocoaGLContext::~QCocoaGLContext()
[m_context release];
}
+QVariant QCocoaGLContext::nativeHandle() const
+{
+ return QVariant::fromValue<QCocoaNativeContext>(QCocoaNativeContext(m_context));
+}
+
// Match up with createNSOpenGLPixelFormat!
QSurfaceFormat QCocoaGLContext::format() const
{
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 3b72184d83..d692a179fd 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -80,6 +80,7 @@ NSRect qt_mac_toNSRect(const QRect &rect);
QRect qt_mac_toQRect(const NSRect &rect);
QColor qt_mac_toQColor(const NSColor *color);
+QColor qt_mac_toQColor(CGColorRef color);
// Creates a mutable shape, it's the caller's responsibility to release.
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 9850f83dea..526204a414 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -225,6 +225,24 @@ QColor qt_mac_toQColor(const NSColor *color)
return qtColor;
}
+QColor qt_mac_toQColor(CGColorRef color)
+{
+ QColor qtColor;
+ CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color));
+ const CGFloat *components = CGColorGetComponents(color);
+ if (model == kCGColorSpaceModelRGB) {
+ qtColor.setRgbF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelCMYK) {
+ qtColor.setCmykF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelMonochrome) {
+ qtColor.setRgbF(components[0], components[0], components[0], components[1]);
+ } else {
+ // Colorspace we can't deal with.
+ qWarning("Qt: qt_mac_toQColor: cannot convert from colorspace model: %d", model);
+ Q_ASSERT(false);
+ }
+ return qtColor;
+}
// Use this method to keep all the information in the TextSegment. As long as it is ordered
// we are in OK shape, and we can influence that ourselves.
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 07b73c1a7a..5ca2ccc571 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -113,7 +113,9 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+#endif
QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const;
QAbstractEventDispatcher *createEventDispatcher() const;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index fca7fa042c..4be49ed68f 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -420,30 +420,37 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
{
switch (cap) {
case ThreadedPixmaps:
+#ifndef QT_NO_OPENGL
case OpenGL:
case ThreadedOpenGL:
case BufferQueueingOpenGL:
+#endif
case WindowMasks:
case MultipleWindows:
case ForeignWindows:
case RasterGLSurface:
+ case ApplicationState:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
}
-
-
QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const
{
return new QCocoaWindow(window);
}
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- return new QCocoaGLContext(context->format(), context->shareHandle());
+ QCocoaGLContext *glContext = new QCocoaGLContext(context->format(),
+ context->shareHandle(),
+ context->nativeHandle());
+ context->setNativeHandle(glContext->nativeHandle());
+ return glContext;
}
+#endif
QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *window) const
{
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index 54e45a1d99..da60afd4e7 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -61,15 +61,19 @@ class QCocoaNativeInterface : public QPlatformNativeInterface
public:
QCocoaNativeInterface();
+#ifndef QT_NO_OPENGL
void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
+#endif
void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
Q_INVOKABLE void beep();
+#ifndef QT_NO_OPENGL
static void *cglContextForContext(QOpenGLContext *context);
static void *nsOpenGLContextForContext(QOpenGLContext* context);
+#endif
public Q_SLOTS:
void onAppFocusWindowChanged(QWindow *window);
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index e09c31231d..7b314665de 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qcocoanativeinterface.h"
-#include "qcocoaglcontext.h"
#include "qcocoawindow.h"
#include "qcocoamenu.h"
#include "qcocoamenubar.h"
@@ -53,8 +52,11 @@
#include <qpixmap.h>
#include <qpa/qplatformwindow.h>
#include "qsurfaceformat.h"
+#ifndef QT_NO_OPENGL
#include <qpa/qplatformopenglcontext.h>
#include "qopenglcontext.h"
+#include "qcocoaglcontext.h"
+#endif
#include "qguiapplication.h"
#include <qdebug.h>
@@ -72,6 +74,7 @@ QCocoaNativeInterface::QCocoaNativeInterface()
{
}
+#ifndef QT_NO_OPENGL
void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
{
if (!context)
@@ -83,16 +86,19 @@ void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resource
return 0;
}
+#endif
void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
{
if (!window->handle())
return 0;
- if (resourceString == "nsopenglcontext") {
- return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
- } else if (resourceString == "nsview") {
+ if (resourceString == "nsview") {
return static_cast<QCocoaWindow *>(window->handle())->m_contentView;
+#ifndef QT_NO_OPENGL
+ } else if (resourceString == "nsopenglcontext") {
+ return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
+#endif
} else if (resourceString == "nswindow") {
return static_cast<QCocoaWindow *>(window->handle())->m_nsWindow;
}
@@ -198,6 +204,7 @@ void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window)
QCocoaMenuBar::updateMenuBarImmediately();
}
+#ifndef QT_NO_OPENGL
void *QCocoaNativeInterface::cglContextForContext(QOpenGLContext* context)
{
NSOpenGLContext *nsOpenGLContext = static_cast<NSOpenGLContext*>(nsOpenGLContextForContext(context));
@@ -216,6 +223,7 @@ void *QCocoaNativeInterface::nsOpenGLContextForContext(QOpenGLContext* context)
}
return 0;
}
+#endif
void QCocoaNativeInterface::addToMimeList(void *macPasteboardMime)
{
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index f18be8b69c..26aa871998 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -41,6 +41,8 @@
#include "qcocoasystemsettings.h"
+#include "qcocoahelpers.h"
+
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qfont.h>
@@ -48,30 +50,11 @@
QT_BEGIN_NAMESPACE
-QColor qt_mac_colorFromCGColor(CGColorRef cgcolor)
-{
- QColor pc;
- CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
- const CGFloat *components = CGColorGetComponents(cgcolor);
- if (model == kCGColorSpaceModelRGB) {
- pc.setRgbF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelCMYK) {
- pc.setCmykF(components[0], components[1], components[2], components[3]);
- } else if (model == kCGColorSpaceModelMonochrome) {
- pc.setRgbF(components[0], components[0], components[0], components[1]);
- } else {
- // Colorspace we can't deal with.
- qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
- Q_ASSERT(false);
- }
- return pc;
-}
-
QColor qt_mac_colorForTheme(ThemeBrush brush)
{
QCFType<CGColorRef> cgClr = 0;
HIThemeBrushCreateCGColor(brush, &cgClr);
- return qt_mac_colorFromCGColor(cgClr);
+ return qt_mac_toQColor(cgClr);
}
QColor qt_mac_colorForThemeTextColor(ThemeTextColor themeColor)
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 7a21f7a8d3..8f885ab5f3 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -47,7 +47,9 @@
#include <qpa/qplatformwindow.h>
#include <QRect>
+#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
+#endif
#include "qnsview.h"
#include "qt_mac_p.h"
@@ -201,8 +203,10 @@ public:
void setWindowShadow(Qt::WindowFlags flags);
void setWindowZoomButton(Qt::WindowFlags flags);
+#ifndef QT_NO_OPENGL
void setCurrentContext(QCocoaGLContext *context);
QCocoaGLContext *currentContext() const;
+#endif
bool setWindowModified(bool modified) Q_DECL_OVERRIDE;
@@ -272,7 +276,9 @@ public: // for QNSView
bool m_inConstructor;
bool m_inSetVisible;
+#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
+#endif
QCocoaMenuBar *m_menubar;
NSCursor *m_windowCursor;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 4d0458a4aa..29b983cd89 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -43,7 +43,9 @@
#include "qnswindowdelegate.h"
#include "qcocoaautoreleasepool.h"
#include "qcocoaeventdispatcher.h"
+#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
+#endif
#include "qcocoahelpers.h"
#include "qcocoanativeinterface.h"
#include "qnsview.h"
@@ -373,7 +375,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_windowUnderMouse(false)
, m_inConstructor(true)
, m_inSetVisible(false)
+#ifndef QT_NO_OPENGL
, m_glContext(0)
+#endif
, m_menubar(0)
, m_windowCursor(0)
, m_hasModalSession(false)
@@ -712,8 +716,10 @@ void QCocoaWindow::setVisible(bool visible)
[m_contentView setHidden:NO];
} else {
// qDebug() << "close" << this;
+#ifndef QT_NO_OPENGL
if (m_glContext)
m_glContext->windowWasHidden();
+#endif
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
if (cocoaEventDispatcher)
@@ -1224,6 +1230,7 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
return ((type & Qt::Popup) == Qt::Popup);
}
+#ifndef QT_NO_OPENGL
void QCocoaWindow::setCurrentContext(QCocoaGLContext *context)
{
m_glContext = context;
@@ -1233,6 +1240,7 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
{
return m_glContext;
}
+#endif
void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
{
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 5387f2a825..a75e366a73 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -72,15 +72,19 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QNSViewMouseMoveHelper);
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers currentWheelModifiers;
bool m_subscribesForGlobalFrameNotifications;
+#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
bool m_shouldSetGLContextinDrawRect;
+#endif
NSString *m_inputSource;
QNSViewMouseMoveHelper *m_mouseMoveHelper;
}
- (id)init;
- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow;
+#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
+#endif
- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
- (void)setMaskRegion:(const QRegion *)region;
- (void)invalidateWindowShadowIfNeeded;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a18ee7ff71..011a9ba71a 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -57,13 +57,17 @@
#include <QtCore/QDebug>
#include <private/qguiapplication_p.h>
#include "qcocoabackingstore.h"
+#ifndef QT_NO_OPENGL
#include "qcocoaglcontext.h"
+#endif
#include "qcocoaintegration.h"
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
#include <accessibilityinspector.h>
#endif
+Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.tabletsupport")
+
static QTouchDevice *touchDevice = 0;
// ### HACK Remove once 10.8 is unsupported
@@ -143,8 +147,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_frameStrutButtons = Qt::NoButton;
m_sendKeyEvent = false;
m_subscribesForGlobalFrameNotifications = false;
+#ifndef QT_NO_OPENGL
m_glContext = 0;
m_shouldSetGLContextinDrawRect = false;
+#endif
currentCustomDragTypes = 0;
m_sendUpAsRightButton = false;
m_inputSource = 0;
@@ -210,6 +216,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
return self;
}
+#ifndef QT_NO_OPENGL
- (void) setQCocoaGLContext:(QCocoaGLContext *)context
{
m_glContext = context;
@@ -231,6 +238,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
object:self];
}
}
+#endif
- (void) globalFrameChanged:(NSNotification*)notification
{
@@ -516,10 +524,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (void) drawRect:(NSRect)dirtyRect
{
+#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
[m_glContext->nsOpenGLContext() setView:self];
m_shouldSetGLContextinDrawRect = false;
}
+#endif
if (m_platformWindow->m_drawContentBorderGradient)
NSDrawWindowBackground(dirtyRect);
@@ -986,6 +996,7 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash)
NSPoint tilt = [theEvent tilt];
int xTilt = qRound(tilt.x * 60.0);
int yTilt = qRound(tilt.y * -60.0);
+ Qt::MouseButtons buttons = static_cast<Qt::MouseButtons>(static_cast<uint>([theEvent buttonMask]));
qreal tangentialPressure = 0;
qreal rotation = 0;
int z = 0;
@@ -993,14 +1004,21 @@ Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash)
z = [theEvent absoluteZ];
if (deviceData.capabilityMask & 0x0800)
- tangentialPressure = [theEvent tangentialPressure];
+ tangentialPressure = ([theEvent tangentialPressure] * 2.0) - 1.0;
- rotation = [theEvent rotation];
+ rotation = 360.0 - [theEvent rotation];
+ if (rotation > 180.0)
+ rotation -= 360.0;
Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
- QWindowSystemInterface::handleTabletEvent(m_window, timestamp, down, windowPoint, screenPoint,
- deviceData.device, deviceData.pointerType, pressure, xTilt, yTilt,
+ qCDebug(lcQpaTablet, "event on tablet %d with tool %d type %d unique ID %lld pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
+ deviceId, deviceData.device, deviceData.pointerType, deviceData.uid,
+ windowPoint.x(), windowPoint.y(), screenPoint.x(), screenPoint.y(),
+ static_cast<uint>(buttons), pressure, xTilt, yTilt, rotation);
+
+ QWindowSystemInterface::handleTabletEvent(m_window, timestamp, windowPoint, screenPoint,
+ deviceData.device, deviceData.pointerType, buttons, pressure, xTilt, yTilt,
tangentialPressure, rotation, z, deviceData.uid,
keyboardModifiers);
}
@@ -1092,6 +1110,9 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
tabletDeviceDataHash->remove(deviceId);
}
+ qCDebug(lcQpaTablet, "proximity change on tablet %d: current tool %d type %d unique ID %lld",
+ deviceId, deviceData.device, deviceData.pointerType, deviceData.uid);
+
if (entering) {
QWindowSystemInterface::handleTabletEnterProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid);
} else {
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index d18a01b11c..a02b074771 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -59,7 +59,7 @@
return nil;
QAccessible::Id childId = QAccessible::uniqueId(m_window->accessibleRoot());
- return [QCocoaAccessibleElement elementWithId: childId];
+ return [QMacAccessibilityElement elementWithId: childId];
}
// The QNSView is a container that the user does not interact directly with:
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index f4cd071ab7..d48cbdfac8 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -1084,6 +1084,10 @@ void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem
if (textAA != lineAA)
CGContextSetShouldAntialias(d->hd, textAA);
+ const bool smoothing = textAA && !(fe->fontDef.styleStrategy & QFont::NoSubpixelAntialias);
+ if (d->disabledSmoothFonts == smoothing)
+ CGContextSetShouldSmoothFonts(d->hd, smoothing);
+
if (ti.glyphs.numGlyphs) {
switch (fe->type()) {
case QFontEngine::Mac:
@@ -1100,6 +1104,9 @@ void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem
if (textAA != lineAA)
CGContextSetShouldAntialias(d->hd, !textAA);
+ if (smoothing == d->disabledSmoothFonts)
+ CGContextSetShouldSmoothFonts(d->hd, !d->disabledSmoothFonts);
+
updatePen(oldPen);
updateBrush(oldBrush, oldBrushOrigin);
}
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro
index 03997f2737..8f2ccc3aa6 100644
--- a/src/plugins/platforms/direct2d/direct2d.pro
+++ b/src/plugins/platforms/direct2d/direct2d.pro
@@ -9,7 +9,7 @@ QT *= core-private
QT *= gui-private
QT *= platformsupport-private
-LIBS *= -ld2d1 -ld3d11 -ldwrite -lVersion
+LIBS *= -ld2d1 -ld3d11 -ldwrite -lVersion -lgdi32
include(../windows/windows.pri)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index 1936ef0622..702ef7af92 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -60,22 +60,22 @@ public:
QWindowsDirect2DPlatformPixmap(PixelType pixelType, QWindowsDirect2DBitmap *bitmap);
~QWindowsDirect2DPlatformPixmap();
- virtual void resize(int width, int height);
+ void resize(int width, int height) Q_DECL_OVERRIDE;
virtual void fromImage(const QImage &image,
Qt::ImageConversionFlags flags);
- virtual int metric(QPaintDevice::PaintDeviceMetric metric) const;
- virtual void fill(const QColor &color);
+ int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ void fill(const QColor &color) Q_DECL_OVERRIDE;
- virtual bool hasAlphaChannel() const;
+ bool hasAlphaChannel() const Q_DECL_OVERRIDE;
- virtual QImage toImage() const;
- virtual QImage toImage(const QRect &rect) const;
+ QImage toImage() const Q_DECL_OVERRIDE;
+ QImage toImage(const QRect &rect) const Q_DECL_OVERRIDE;
- virtual QPaintEngine* paintEngine() const;
+ QPaintEngine* paintEngine() const Q_DECL_OVERRIDE;
- virtual qreal devicePixelRatio() const;
- virtual void setDevicePixelRatio(qreal scaleFactor);
+ qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
QWindowsDirect2DBitmap *bitmap() const;
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp
index 4d443b91e3..71c3c1e59b 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp
@@ -42,7 +42,6 @@
#include "qeglfscontext.h"
#include "qeglfswindow.h"
#include "qeglfshooks.h"
-#include "qeglfsintegration.h"
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
@@ -52,9 +51,9 @@
QT_BEGIN_NAMESPACE
-QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display)
- : QEGLPlatformContext(format, share, display,
- QEglFSIntegration::chooseConfig(display, format))
+QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
+ EGLConfig *config, const QVariant &nativeHandle)
+ : QEGLPlatformContext(format, share, display, config, nativeHandle)
{
}
diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h
index 5d406f09f1..d378b7818b 100644
--- a/src/plugins/platforms/eglfs/qeglfscontext.h
+++ b/src/plugins/platforms/eglfs/qeglfscontext.h
@@ -43,13 +43,15 @@
#define QEGLFSCONTEXT_H
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
+#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
class QEglFSContext : public QEGLPlatformContext
{
public:
- QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display);
+ QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
+ EGLConfig *config, const QVariant &nativeHandle);
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE;
void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
};
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 2941806f17..d770ea763a 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -50,6 +50,7 @@
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include <QtPlatformHeaders/QEGLNativeContext>
#include <qpa/qplatformwindow.h>
#include <QtGui/QSurfaceFormat>
@@ -115,9 +116,20 @@ QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const
QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
- EGLDisplay display) const
+ EGLDisplay display,
+ QVariant *nativeHandle) const
{
- return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display);
+ QEglFSContext *ctx;
+ if (!nativeHandle || nativeHandle->isNull()) {
+ EGLConfig config = QEglFSIntegration::chooseConfig(display, format);
+ ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display,
+ &config, QVariant());
+ } else {
+ ctx = new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display,
+ 0, *nativeHandle);
+ }
+ *nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), display));
+ return ctx;
}
QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay display,
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h
index 99dda1ea96..fea05cd400 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.h
@@ -66,7 +66,8 @@ protected:
QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
QEGLPlatformContext *createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
- EGLDisplay display) const Q_DECL_OVERRIDE;
+ EGLDisplay display,
+ QVariant *nativeHandle) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
const QSurfaceFormat &format,
QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index 2d36c0b58e..a0150b7ade 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -82,8 +82,10 @@ void QEglFSWindow::create()
// they will be composited onto the root window's surface.
QEglFSScreen *screen = this->screen();
if (screen->primarySurface() != EGL_NO_SURFACE) {
- if (isRaster() && screen->compositingWindow())
+ if (isRaster() && screen->compositingWindow()) {
+ m_format = screen->compositingWindow()->format();
return;
+ }
#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)
// We can have either a single OpenGL window or multiple raster windows.
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index ffc4ff9b12..ad9912a8d0 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -23,7 +23,10 @@ OBJECTIVE_SOURCES = \
qiostheme.mm \
qiosglobal.mm \
qiosservices.mm \
- qiosclipboard.mm
+ quiview.mm \
+ qiosclipboard.mm \
+ quiaccessibilityelement.mm \
+ qiosplatformaccessibility.mm \
HEADERS = \
qiosintegration.h \
@@ -40,7 +43,10 @@ HEADERS = \
qiosglobal.h \
qiosservices.h \
quiview.h \
- qiosclipboard.h
+ qiosclipboard.h \
+ quiaccessibilityelement.h \
+ qiosplatformaccessibility.h \
OTHER_FILES = \
- quiview_textinput.mm
+ quiview_textinput.mm \
+ quiview_accessibility.mm
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.h b/src/plugins/platforms/ios/qiosapplicationdelegate.h
index 617b740d6e..f3c5c14502 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.h
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.h
@@ -45,7 +45,4 @@
#import "qiosviewcontroller.h"
@interface QIOSApplicationDelegate : UIResponder <UIApplicationDelegate>
-
-@property (strong, nonatomic) UIWindow *window;
-
@end
diff --git a/src/plugins/platforms/ios/qiosapplicationdelegate.mm b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
index 9cf1047a6b..ef9f924384 100644
--- a/src/plugins/platforms/ios/qiosapplicationdelegate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationdelegate.mm
@@ -46,47 +46,12 @@
#include "qiosviewcontroller.h"
#include "qioswindow.h"
-#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <QtCore/QtCore>
@implementation QIOSApplicationDelegate
-@synthesize window;
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
- Q_UNUSED(application);
- Q_UNUSED(launchOptions);
-
- self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
- self.window.rootViewController = [[[QIOSViewController alloc] init] autorelease];
-
-#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0)
- QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
-
- // We prefer to keep the root viewcontroller in fullscreen layout, so that
- // we don't have to compensate for the viewcontroller position. This also
- // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout
- // is the only way.
- if (iosVersion < QSysInfo::MV_IOS_7_0)
- self.window.rootViewController.wantsFullScreenLayout = YES;
-
- // Use translucent statusbar by default on iOS6 iPhones (unless the user changed
- // the default in the Info.plist), so that windows placed under the stausbar are
- // still visible, just like on iOS7.
- if (iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0
- && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone
- && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault)
- [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
-#endif
-
- self.window.hidden = NO;
-
- return YES;
-}
-
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
Q_UNUSED(application);
@@ -96,17 +61,13 @@
if (!QGuiApplication::instance())
return NO;
- QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QIOSIntegration *iosIntegration = QIOSIntegration::instance();
+ Q_ASSERT(iosIntegration);
+
QIOSServices *iosServices = static_cast<QIOSServices *>(iosIntegration->services());
return iosServices->handleUrl(QUrl::fromNSURL(url));
}
-- (void)dealloc
-{
- [window release];
- [super dealloc];
-}
-
@end
diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm
index ddee52196a..4083c2d5a9 100644
--- a/src/plugins/platforms/ios/qioscontext.mm
+++ b/src/plugins/platforms/ios/qioscontext.mm
@@ -47,6 +47,7 @@
#include <QtGui/QOpenGLContext>
#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES2/glext.h>
#import <QuartzCore/CAEAGLLayer.h>
QIOSContext::QIOSContext(QOpenGLContext *context)
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 956c112399..89ca0349d9 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -82,14 +82,20 @@ public:
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
QTouchDevice *touchDevice();
+ QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
+
+ void addScreen(QPlatformScreen *screen) { screenAdded(screen); }
+
+ static QIOSIntegration *instance();
+
private:
QPlatformFontDatabase *m_fontDatabase;
QPlatformClipboard *m_clipboard;
QPlatformInputContext *m_inputContext;
- QPlatformScreen *m_screen;
QTouchDevice *m_touchDevice;
QIOSApplicationState m_applicationState;
QIOSServices *m_platformServices;
+ mutable QPlatformAccessibility *m_accessibility;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 0fe7adff9f..9a722ead37 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -45,12 +45,15 @@
#include "qioswindow.h"
#include "qiosbackingstore.h"
#include "qiosscreen.h"
+#include "qiosplatformaccessibility.h"
#include "qioscontext.h"
#include "qiosclipboard.h"
#include "qiosinputcontext.h"
#include "qiostheme.h"
#include "qiosservices.h"
+#include <QtGui/private/qguiapplication_p.h>
+
#include <qpa/qplatformoffscreensurface.h>
#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h>
@@ -61,12 +64,17 @@
QT_BEGIN_NAMESPACE
+QIOSIntegration *QIOSIntegration::instance()
+{
+ return static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+}
+
QIOSIntegration::QIOSIntegration()
: m_fontDatabase(new QCoreTextFontDatabase)
, m_clipboard(new QIOSClipboard)
- , m_inputContext(new QIOSInputContext)
- , m_screen(new QIOSScreen(QIOSScreen::MainScreen))
+ , m_inputContext(0)
, m_platformServices(new QIOSServices)
+ , m_accessibility(0)
{
if (![UIApplication sharedApplication]) {
qWarning()
@@ -80,7 +88,11 @@ QIOSIntegration::QIOSIntegration()
// Set current directory to app bundle folder
QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String]));
- screenAdded(m_screen);
+ for (UIScreen *screen in [UIScreen screens])
+ addScreen(new QIOSScreen(screen));
+
+ // Depends on a primary screen being present
+ m_inputContext = new QIOSInputContext;
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
@@ -101,11 +113,14 @@ QIOSIntegration::~QIOSIntegration()
delete m_inputContext;
m_inputContext = 0;
- delete m_screen;
- m_screen = 0;
+ foreach (QScreen *screen, QGuiApplication::screens())
+ delete screen->handle();
delete m_platformServices;
m_platformServices = 0;
+
+ delete m_accessibility;
+ m_accessibility = 0;
}
bool QIOSIntegration::hasCapability(Capability cap) const
@@ -229,4 +244,11 @@ QTouchDevice *QIOSIntegration::touchDevice()
return m_touchDevice;
}
+QPlatformAccessibility *QIOSIntegration::accessibility() const
+{
+ if (!m_accessibility)
+ m_accessibility = new QIOSPlatformAccessibility;
+ return m_accessibility;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtplatformtheme.h b/src/plugins/platforms/ios/qiosplatformaccessibility.h
index f4a61982b2..beb0d006e1 100644
--- a/src/plugins/platforms/winrt/qwinrtplatformtheme.h
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.h
@@ -39,22 +39,22 @@
**
****************************************************************************/
-#ifndef QWINRTPLATFORMTHEME_H
-#define QWINRTPLATFORMTHEME_H
+#ifndef QIOSPLATFORMACCESSIBILITY_H
+#define QIOSPLATFORMACCESSIBILITY_H
-#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformaccessibility.h>
QT_BEGIN_NAMESPACE
-class QWinRTPlatformTheme : public QPlatformTheme
+class QIOSPlatformAccessibility: public QPlatformAccessibility
{
public:
- QWinRTPlatformTheme();
+ QIOSPlatformAccessibility();
+ ~QIOSPlatformAccessibility();
- bool usePlatformNativeDialog(DialogType type) const;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
+ virtual void notifyAccessibilityUpdate(QAccessibleEvent *event);
};
QT_END_NAMESPACE
-#endif // QWINRTPLATFORMTHEME_H
+#endif
diff --git a/src/plugins/platforms/ios/qiosplatformaccessibility.mm b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
new file mode 100644
index 0000000000..db579ba559
--- /dev/null
+++ b/src/plugins/platforms/ios/qiosplatformaccessibility.mm
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "qiosplatformaccessibility.h"
+
+#include <QtGui/QtGui>
+#include "qioswindow.h"
+
+QIOSPlatformAccessibility::QIOSPlatformAccessibility()
+{}
+
+QIOSPlatformAccessibility::~QIOSPlatformAccessibility()
+{}
+
+
+void invalidateCache(QAccessibleInterface *iface)
+{
+ if (!iface || !iface->isValid()) {
+ qWarning() << "invalid accessible interface: " << iface;
+ return;
+ }
+
+ QWindow *win = 0;
+ QAccessibleInterface *parent = iface;
+ do {
+ win = parent->window();
+ parent = parent->parent();
+ } while (!win && parent);
+ Q_ASSERT(win && win->handle());
+ QIOSWindow *window = static_cast<QIOSWindow*>(win->handle());
+ window->clearAccessibleCache();
+}
+
+
+void QIOSPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
+{
+ switch (event->type()) {
+ case QAccessible::ObjectCreated:
+ case QAccessible::ObjectShow:
+ case QAccessible::ObjectHide:
+ case QAccessible::ObjectDestroyed:
+ invalidateCache(event->accessibleInterface());
+ break;
+ default:
+ break;
+ }
+}
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
index 173bd11719..9c7d53dcd6 100644
--- a/src/plugins/platforms/ios/qiosscreen.h
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -55,11 +55,9 @@ class QIOSScreen : public QObject, public QPlatformScreen
Q_OBJECT
public:
- QIOSScreen(unsigned int screenIndex);
+ QIOSScreen(UIScreen *screen);
~QIOSScreen();
- enum ScreenIndex { MainScreen = 0 };
-
QRect geometry() const;
QRect availableGeometry() const;
int depth() const;
@@ -82,6 +80,7 @@ public slots:
private:
UIScreen *m_uiScreen;
+ UIWindow *m_uiWindow;
QRect m_geometry;
QRect m_availableGeometry;
int m_depth;
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 5331d05ae9..e876665431 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qiosglobal.h"
+#include "qiosintegration.h"
#include "qiosscreen.h"
#include "qioswindow.h"
#include <qpa/qwindowsysteminterface.h>
@@ -48,6 +49,63 @@
#include <sys/sysctl.h>
+// -------------------------------------------------------------------------
+
+static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
+{
+ foreach (QScreen *screen, QGuiApplication::screens()) {
+ QIOSScreen *platformScreen = static_cast<QIOSScreen *>(screen->handle());
+ if (platformScreen->uiScreen() == uiScreen)
+ return platformScreen;
+ }
+
+ return 0;
+}
+
+@interface QIOSScreenTracker : NSObject
+@end
+
+@implementation QIOSScreenTracker
+
++ (void)load
+{
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center addObserver:self selector:@selector(screenConnected:)
+ name:UIScreenDidConnectNotification object:nil];
+ [center addObserver:self selector:@selector(screenDisconnected:)
+ name:UIScreenDidDisconnectNotification object:nil];
+ [center addObserver:self selector:@selector(screenModeChanged:)
+ name:UIScreenModeDidChangeNotification object:nil];
+}
+
++ (void)screenConnected:(NSNotification*)notification
+{
+ QIOSIntegration *integration = QIOSIntegration::instance();
+ Q_ASSERT_X(integration, Q_FUNC_INFO, "Screen connected before QIOSIntegration creation");
+
+ integration->addScreen(new QIOSScreen([notification object]));
+}
+
++ (void)screenDisconnected:(NSNotification*)notification
+{
+ QIOSScreen *screen = qtPlatformScreenFor([notification object]);
+ Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen disconnected that we didn't know about");
+
+ delete screen;
+}
+
++ (void)screenModeChanged:(NSNotification*)notification
+{
+ QIOSScreen *screen = qtPlatformScreenFor([notification object]);
+ Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen changed that we didn't know about");
+
+ screen->updateProperties();
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
@interface QIOSOrientationListener : NSObject {
@public
QIOSScreen *m_screen;
@@ -99,6 +157,8 @@
@end
+// -------------------------------------------------------------------------
+
/*!
Returns the model identifier of the device.
@@ -118,27 +178,51 @@ static QString deviceModelIdentifier()
return QString::fromLatin1(value);
}
-QIOSScreen::QIOSScreen(unsigned int screenIndex)
+QIOSScreen::QIOSScreen(UIScreen *screen)
: QPlatformScreen()
- , m_uiScreen([[UIScreen screens] count] > screenIndex
- ? [[UIScreen screens] objectAtIndex:screenIndex]
- : [UIScreen mainScreen])
+ , m_uiScreen(screen)
+ , m_uiWindow(0)
, m_orientationListener(0)
{
- QString deviceIdentifier = deviceModelIdentifier();
+ for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) {
+ if (existingWindow.screen == m_uiScreen) {
+ m_uiWindow = [m_uiWindow retain];
+ break;
+ }
+ }
- if (deviceIdentifier == QStringLiteral("iPhone2,1") /* iPhone 3GS */
- || deviceIdentifier == QStringLiteral("iPod3,1") /* iPod touch 3G */) {
- m_depth = 18;
- } else {
- m_depth = 24;
+ if (!m_uiWindow) {
+ // Create a window and associated view-controller that we can use
+ m_uiWindow = [[UIWindow alloc] initWithFrame:[m_uiScreen bounds]];
+ m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease];
+
+ // FIXME: Only do once windows are added to the screen, and for any screen
+ if (screen == [UIScreen mainScreen]) {
+ m_uiWindow.screen = m_uiScreen;
+ m_uiWindow.hidden = NO;
+ }
}
- if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
- && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
- m_unscaledDpi = 132;
+ if (screen == [UIScreen mainScreen]) {
+ QString deviceIdentifier = deviceModelIdentifier();
+
+ if (deviceIdentifier == QStringLiteral("iPhone2,1") /* iPhone 3GS */
+ || deviceIdentifier == QStringLiteral("iPod3,1") /* iPod touch 3G */) {
+ m_depth = 18;
+ } else {
+ m_depth = 24;
+ }
+
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
+ && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) {
+ m_unscaledDpi = 132;
+ } else {
+ m_unscaledDpi = 163; // Regular iPhone DPI
+ }
} else {
- m_unscaledDpi = 163; // Regular iPhone DPI
+ // External display, hard to say
+ m_depth = 24;
+ m_unscaledDpi = 96;
}
connect(qGuiApp, &QGuiApplication::focusWindowChanged, this, &QIOSScreen::updateStatusBarVisibility);
@@ -149,17 +233,12 @@ QIOSScreen::QIOSScreen(unsigned int screenIndex)
QIOSScreen::~QIOSScreen()
{
[m_orientationListener release];
+ [m_uiWindow release];
}
void QIOSScreen::updateProperties()
{
- UIWindow *uiWindow = 0;
- for (uiWindow in [[UIApplication sharedApplication] windows]) {
- if (uiWindow.screen == m_uiScreen)
- break;
- }
-
- bool inPortrait = UIInterfaceOrientationIsPortrait(uiWindow.rootViewController.interfaceOrientation);
+ bool inPortrait = UIInterfaceOrientationIsPortrait(m_uiWindow.rootViewController.interfaceOrientation);
QRect geometry = inPortrait ? fromCGRect(m_uiScreen.bounds).toRect()
: QRect(m_uiScreen.bounds.origin.x, m_uiScreen.bounds.origin.y,
m_uiScreen.bounds.size.height, m_uiScreen.bounds.size.width);
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index a0017808d3..5e95cdd3ee 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -41,7 +41,13 @@
#import <UIKit/UIKit.h>
-@interface QIOSViewController : UIViewController
+class QIOSScreen;
+
+@interface QIOSViewController : UIViewController {
+ QIOSScreen *m_screen;
+}
+
+- (id)initWithQIOSScreen:(QIOSScreen *)screen;
- (BOOL)prefersStatusBarHidden;
@end
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 2fe679fc20..73f1b51b83 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -53,6 +53,35 @@
@implementation QIOSViewController
+- (id)initWithQIOSScreen:(QIOSScreen *)screen
+{
+ if (self = [self init]) {
+ m_screen = screen;
+
+#if QT_IOS_DEPLOYMENT_TARGET_BELOW(__IPHONE_7_0)
+ QSysInfo::MacVersion iosVersion = QSysInfo::MacintoshVersion;
+
+ // We prefer to keep the root viewcontroller in fullscreen layout, so that
+ // we don't have to compensate for the viewcontroller position. This also
+ // gives us the same behavior on iOS 5/6 as on iOS 7, where full screen layout
+ // is the only way.
+ if (iosVersion < QSysInfo::MV_IOS_7_0)
+ self.wantsFullScreenLayout = YES;
+
+ // Use translucent statusbar by default on iOS6 iPhones (unless the user changed
+ // the default in the Info.plist), so that windows placed under the stausbar are
+ // still visible, just like on iOS7.
+ if (screen->uiScreen() == [UIScreen mainScreen]
+ && iosVersion >= QSysInfo::MV_IOS_6_0 && iosVersion < QSysInfo::MV_IOS_7_0
+ && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone
+ && [UIApplication sharedApplication].statusBarStyle == UIStatusBarStyleDefault)
+ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
+#endif
+ }
+
+ return self;
+}
+
-(BOOL)shouldAutorotate
{
// Until a proper orientation and rotation API is in place, we always auto rotate.
@@ -85,8 +114,7 @@
if (!QCoreApplication::instance())
return; // FIXME: Store orientation for later (?)
- QIOSScreen *qiosScreen = static_cast<QIOSScreen *>(QGuiApplication::primaryScreen()->handle());
- qiosScreen->updateProperties();
+ m_screen->updateProperties();
}
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 6b6892e6e4..bcff3e202c 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -87,6 +87,8 @@ public:
WId winId() const { return WId(m_view); };
+ void clearAccessibleCache();
+
private:
void applicationStateChanged(Qt::ApplicationState state);
void applyGeometry(const QRect &rect);
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 6f5c96cfc1..76bd9bb2b5 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -39,323 +39,23 @@
**
****************************************************************************/
-#include "qiosglobal.h"
#include "qioswindow.h"
-#include "quiview.h"
+
+#include "qiosapplicationdelegate.h"
#include "qioscontext.h"
-#include "qiosinputcontext.h"
+#include "qiosglobal.h"
+#include "qiosintegration.h"
#include "qiosscreen.h"
-#include "qiosapplicationdelegate.h"
#include "qiosviewcontroller.h"
-#include "qiosintegration.h"
-#include <QtGui/private/qguiapplication_p.h>
+#include "quiview.h"
+
#include <QtGui/private/qwindow_p.h>
#include <qpa/qplatformintegration.h>
#import <QuartzCore/CAEAGLLayer.h>
-#include <QtGui/QKeyEvent>
-#include <qpa/qwindowsysteminterface.h>
-
#include <QtDebug>
-// Include category as an alternative to using -ObjC (Apple QA1490)
-#include "quiview_textinput.mm"
-
-@implementation QUIView
-
-@synthesize autocapitalizationType;
-@synthesize autocorrectionType;
-@synthesize enablesReturnKeyAutomatically;
-@synthesize keyboardAppearance;
-@synthesize keyboardType;
-@synthesize returnKeyType;
-@synthesize secureTextEntry;
-
-+ (Class)layerClass
-{
- return [CAEAGLLayer class];
-}
-
--(id)initWithQIOSWindow:(QIOSWindow *)window
-{
- if (self = [self initWithFrame:toCGRect(window->geometry())])
- m_qioswindow = window;
-
- return self;
-}
-
-- (id)initWithFrame:(CGRect)frame
-{
- if ((self = [super initWithFrame:frame])) {
- // Set up EAGL layer
- CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
- eaglLayer.opaque = TRUE;
- eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
- kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
-
- if (isQtApplication())
- self.hidden = YES;
-
- self.multipleTouchEnabled = YES;
- m_inSendEventToFocusObject = NO;
- }
-
- return self;
-}
-
-- (void)willMoveToWindow:(UIWindow *)newWindow
-{
- // UIKIt will normally set the scale factor of a view to match the corresponding
- // screen scale factor, but views backed by CAEAGLLayers need to do this manually.
- self.contentScaleFactor = newWindow && newWindow.screen ?
- newWindow.screen.scale : [[UIScreen mainScreen] scale];
-
- // FIXME: Allow the scale factor to be customized through QSurfaceFormat.
-}
-
-- (void)didAddSubview:(UIView *)subview
-{
- if ([subview isKindOfClass:[QUIView class]])
- self.clipsToBounds = YES;
-}
-
-- (void)willRemoveSubview:(UIView *)subview
-{
- for (UIView *view in self.subviews) {
- if (view != subview && [view isKindOfClass:[QUIView class]])
- return;
- }
-
- self.clipsToBounds = NO;
-}
-
-- (void)setNeedsDisplay
-{
- [super setNeedsDisplay];
-
- // We didn't implement drawRect: so we have to manually
- // mark the layer as needing display.
- [self.layer setNeedsDisplay];
-}
-
-- (void)layoutSubviews
-{
- // This method is the de facto way to know that view has been resized,
- // or otherwise needs invalidation of its buffers. Note though that we
- // do not get this callback when the view just changes its position, so
- // the position of our QWindow (and platform window) will only get updated
- // when the size is also changed.
-
- if (!CGAffineTransformIsIdentity(self.transform))
- qWarning() << m_qioswindow->window()
- << "is backed by a UIView that has a transform set. This is not supported.";
-
- // The original geometry requested by setGeometry() might be different
- // from what we end up with after applying window constraints.
- QRect requestedGeometry = m_qioswindow->geometry();
-
- QRect actualGeometry;
- if (m_qioswindow->window()->isTopLevel()) {
- UIWindow *uiWindow = self.window;
- UIView *rootView = uiWindow.rootViewController.view;
- CGRect rootViewPositionInRelationToRootViewController =
- [rootView convertRect:uiWindow.bounds fromView:uiWindow];
-
- actualGeometry = fromCGRect(CGRectOffset([self.superview convertRect:self.frame toView:rootView],
- -rootViewPositionInRelationToRootViewController.origin.x,
- -rootViewPositionInRelationToRootViewController.origin.y
- + rootView.bounds.origin.y)).toRect();
- } else {
- actualGeometry = fromCGRect(self.frame).toRect();
- }
-
- // Persist the actual/new geometry so that QWindow::geometry() can
- // be queried on the resize event.
- m_qioswindow->QPlatformWindow::setGeometry(actualGeometry);
-
- QRect previousGeometry = requestedGeometry != actualGeometry ?
- requestedGeometry : qt_window_private(m_qioswindow->window())->geometry;
-
- QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), actualGeometry, previousGeometry);
- QWindowSystemInterface::flushWindowSystemEvents();
-
- if (actualGeometry.size() != previousGeometry.size()) {
- // Trigger expose event on resize
- [self setNeedsDisplay];
-
- // A new size means we also need to resize the FBO's corresponding buffers,
- // but we defer that to when the application calls makeCurrent.
- }
-}
-
-- (void)displayLayer:(CALayer *)layer
-{
- Q_UNUSED(layer);
- Q_ASSERT(layer == self.layer);
-
- [self sendUpdatedExposeEvent];
-}
-
-- (void)sendUpdatedExposeEvent
-{
- QRegion region;
-
- if (m_qioswindow->isExposed()) {
- QSize bounds = fromCGRect(self.layer.bounds).toRect().size();
-
- Q_ASSERT(m_qioswindow->geometry().size() == bounds);
- Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
-
- region = QRect(QPoint(), bounds);
- }
-
- QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
- QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
-{
- // We deliver touch events in global coordinates. But global in this respect
- // means the same coordinate system that we use for describing the geometry
- // of the top level QWindow we're inside. And that would be the coordinate
- // system of the superview of the UIView that backs that window:
- QPlatformWindow *topLevel = m_qioswindow;
- while (QPlatformWindow *topLevelParent = topLevel->parent())
- topLevel = topLevelParent;
- UIView *rootView = reinterpret_cast<UIView *>(topLevel->winId()).superview;
- CGSize rootViewSize = rootView.frame.size;
-
- foreach (UITouch *uiTouch, m_activeTouches.keys()) {
- QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
- if (![touches containsObject:uiTouch]) {
- touchPoint.state = Qt::TouchPointStationary;
- } else {
- touchPoint.state = state;
- touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
- QPoint touchPos = fromCGPoint([uiTouch locationInView:rootView]).toPoint();
- touchPoint.area = QRectF(touchPos, QSize(0, 0));
- touchPoint.normalPosition = QPointF(touchPos.x() / rootViewSize.width, touchPos.y() / rootViewSize.height);
- }
- }
-}
-
-- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
-{
- // Send touch event synchronously
- QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
- QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
-{
- // UIKit generates [Began -> Moved -> Ended] event sequences for
- // each touch point. Internally we keep a hashmap of active UITouch
- // points to QWindowSystemInterface::TouchPoints, and assigns each TouchPoint
- // an id for use by Qt.
- for (UITouch *touch in touches) {
- Q_ASSERT(!m_activeTouches.contains(touch));
- m_activeTouches[touch].id = m_nextTouchId++;
- }
-
- if (m_activeTouches.size() == 1) {
- QPlatformWindow *topLevel = m_qioswindow;
- while (QPlatformWindow *p = topLevel->parent())
- topLevel = p;
- if (topLevel->window() != QGuiApplication::focusWindow())
- topLevel->requestActivateWindow();
- }
-
- [self updateTouchList:touches withState:Qt::TouchPointPressed];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
-}
-
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
-{
- [self updateTouchList:touches withState:Qt::TouchPointMoved];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
-}
-
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
-{
- [self updateTouchList:touches withState:Qt::TouchPointReleased];
- [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
-
- // Remove ended touch points from the active set:
- for (UITouch *touch in touches)
- m_activeTouches.remove(touch);
- if (m_activeTouches.isEmpty())
- m_nextTouchId = 0;
-}
-
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
-{
- if (m_activeTouches.isEmpty())
- return;
-
- // When four-finger swiping, we get a touchesCancelled callback
- // which includes all four touch points. The swipe gesture is
- // then active until all four touches have been released, and
- // we start getting touchesBegan events again.
-
- // When five-finger pinching, we also get a touchesCancelled
- // callback with all five touch points, but the pinch gesture
- // ends when the second to last finger is released from the
- // screen. The last finger will not emit any more touch
- // events, _but_, will contribute to starting another pinch
- // gesture. That second pinch gesture will _not_ trigger a
- // touchesCancelled event when starting, but as each finger
- // is released, and we may get touchesMoved events for the
- // remaining fingers. [event allTouches] also contains one
- // less touch point than it should, so this behavior is
- // likely a bug in the iOS system gesture recognizer, but we
- // have to take it into account when maintaining the Qt state.
- // We do this by assuming that there are no cases where a
- // sub-set of the active touch events are intentionally cancelled.
-
- if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
- qWarning("Subset of active touches cancelled by UIKit");
-
- m_activeTouches.clear();
- m_nextTouchId = 0;
-
- NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
-
- // Send cancel touch event synchronously
- QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
- QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-@end
-
-@implementation UIView (QIOS)
-
-- (QWindow *)qwindow
-{
- if ([self isKindOfClass:[QUIView class]]) {
- if (QIOSWindow *w = static_cast<QUIView *>(self)->m_qioswindow)
- return w->window();
- }
- return nil;
-}
-
-- (UIViewController *)viewController
-{
- id responder = self;
- while ((responder = [responder nextResponder])) {
- if ([responder isKindOfClass:UIViewController.class])
- return responder;
- }
- return nil;
-}
-
-@end
-
-QT_BEGIN_NAMESPACE
-
QIOSWindow::QIOSWindow(QWindow *window)
: QPlatformWindow(window)
, m_view([[QUIView alloc] initWithQIOSWindow:this])
@@ -634,6 +334,11 @@ qreal QIOSWindow::devicePixelRatio() const
return m_view.contentScaleFactor;
}
+void QIOSWindow::clearAccessibleCache()
+{
+ [m_view clearAccessibleCache];
+}
+
#include "moc_qioswindow.cpp"
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
new file mode 100644
index 0000000000..7c5a930e86
--- /dev/null
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QUIACCESSIBILITYELEMENT_H
+#define QUIACCESSIBILITYELEMENT_H
+
+#import <UIKit/UIKit.h>
+#import <QtGui/QtGui>
+
+@interface QMacAccessibilityElement : UIAccessibilityElement
+{}
+
+@property (readonly) QAccessible::Id axid;
+
+- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
++ (QMacAccessibilityElement *) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view;
+
+@end
+
+#endif
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
new file mode 100644
index 0000000000..331c38460c
--- /dev/null
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "quiaccessibilityelement.h"
+
+#include "private/qaccessiblecache_p.h"
+
+@implementation QMacAccessibilityElement
+
+- (id) initWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
+{
+ Q_ASSERT((int)anId < 0);
+ self = [super initWithAccessibilityContainer: view];
+ if (self)
+ _axid = anId;
+
+ return self;
+}
+
++ (id) elementWithId: (QAccessible::Id) anId withAccessibilityContainer: (id) view
+{
+ Q_ASSERT(anId);
+ if (!anId)
+ return nil;
+
+ QAccessibleCache *cache = QAccessibleCache::instance();
+
+ QMacAccessibilityElement *element = cache->elementForId(anId);
+ if (!element) {
+ Q_ASSERT(QAccessible::accessibleInterface(anId));
+ element = [[self alloc] initWithId:anId withAccessibilityContainer: view];
+ cache->insertElement(anId, element);
+ }
+ return element;
+}
+
+- (void) invalidate
+{
+ [self release];
+}
+
+- (BOOL) isAccessibilityElement
+{
+ return YES;
+}
+
+- (NSString*) accessibilityLabel
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return @"";
+ }
+
+ return iface->text(QAccessible::Name).toNSString();
+}
+
+- (NSString*) accessibilityHint
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return @"";
+ }
+ return iface->text(QAccessible::Description).toNSString();
+}
+
+- (NSString*) accessibilityValue
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return @"";
+ }
+
+ QAccessible::State state = iface->state();
+
+ if (state.checkable)
+ return state.checked ? @"checked" : @"unchecked"; // FIXME: translation
+
+ QAccessibleValueInterface *val = iface->valueInterface();
+ if (val) {
+ return val->currentValue().toString().toNSString();
+ } else if (QAccessibleTextInterface *text = iface->textInterface()) {
+ // FIXME doesn't work?
+ return text->text(0, text->characterCount() - 1).toNSString();
+ }
+
+ return [super accessibilityHint];
+}
+
+- (CGRect) accessibilityFrame
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return CGRect();
+ }
+
+ QRect rect = iface->rect();
+ return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+- (UIAccessibilityTraits) accessibilityTraits
+{
+ UIAccessibilityTraits traits = UIAccessibilityTraitNone;
+
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (!iface) {
+ qWarning() << "invalid accessible interface for: " << self.axid;
+ return traits;
+ }
+ QAccessible::State state = iface->state();
+ if (state.disabled)
+ traits |= UIAccessibilityTraitNotEnabled;
+
+ if (iface->role() == QAccessible::Button)
+ traits |= UIAccessibilityTraitButton;
+
+ if (iface->valueInterface())
+ traits |= UIAccessibilityTraitAdjustable;
+
+ return traits;
+}
+
+- (BOOL) accessibilityActivate
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (QAccessibleActionInterface *action = iface->actionInterface()) {
+ if (action->actionNames().contains(QAccessibleActionInterface::pressAction())) {
+ action->doAction(QAccessibleActionInterface::pressAction());
+ return YES;
+ } else if (action->actionNames().contains(QAccessibleActionInterface::showMenuAction())) {
+ action->doAction(QAccessibleActionInterface::showMenuAction());
+ return YES;
+ }
+ }
+ return NO; // fall back to sending mouse clicks
+}
+
+- (void) accessibilityIncrement
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (QAccessibleActionInterface *action = iface->actionInterface())
+ action->doAction(QAccessibleActionInterface::increaseAction());
+}
+
+- (void) accessibilityDecrement
+{
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid);
+ if (QAccessibleActionInterface *action = iface->actionInterface())
+ action->doAction(QAccessibleActionInterface::decreaseAction());
+}
+
+@end
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 122e7c604b..99c710ffee 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -40,11 +40,23 @@
****************************************************************************/
#import <UIKit/UIKit.h>
-#include "qioswindow.h"
+
+#include <qhash.h>
+#include <qstring.h>
+
+#include <qpa/qwindowsysteminterface.h>
+
+class QIOSWindow;
@interface QUIView : UIView
{
-@public
+ @public
+ QIOSWindow *m_qioswindow;
+ @private
+ QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
+ int m_nextTouchId;
+
+ @public
UITextAutocapitalizationType autocapitalizationType;
UITextAutocorrectionType autocorrectionType;
BOOL enablesReturnKeyAutomatically;
@@ -52,11 +64,11 @@
UIKeyboardType keyboardType;
UIReturnKeyType returnKeyType;
BOOL secureTextEntry;
- QIOSWindow *m_qioswindow;
- QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
- int m_nextTouchId;
QString m_markedText;
BOOL m_inSendEventToFocusObject;
+
+ @private
+ NSMutableArray *m_accessibleElements;
}
@property(nonatomic, assign) id<UITextInputDelegate> inputDelegate;
@@ -69,6 +81,8 @@
@property(nonatomic) UIReturnKeyType returnKeyType;
@property(nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry;
+- (id)initWithQIOSWindow:(QIOSWindow *)window;
+- (void)sendUpdatedExposeEvent;
@end
@interface QUIView (TextInput) <UITextInput>
@@ -77,3 +91,7 @@
- (void)commit;
+ (bool)inUpdateKeyboardLayout;
@end
+
+@interface QUIView (Accessibility)
+- (void)clearAccessibleCache;
+@end
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
new file mode 100644
index 0000000000..2726c6e3e0
--- /dev/null
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "quiview.h"
+
+#include "qiosglobal.h"
+#include "qiosintegration.h"
+#include "qioswindow.h"
+
+#include <QtGui/private/qwindow_p.h>
+
+// Include category as an alternative to using -ObjC (Apple QA1490)
+#include "quiview_textinput.mm"
+#include "quiview_accessibility.mm"
+
+@implementation QUIView
+
+@synthesize autocapitalizationType;
+@synthesize autocorrectionType;
+@synthesize enablesReturnKeyAutomatically;
+@synthesize keyboardAppearance;
+@synthesize keyboardType;
+@synthesize returnKeyType;
+@synthesize secureTextEntry;
+
++ (Class)layerClass
+{
+ return [CAEAGLLayer class];
+}
+
+-(id)initWithQIOSWindow:(QIOSWindow *)window
+{
+ if (self = [self initWithFrame:toCGRect(window->geometry())])
+ m_qioswindow = window;
+
+ m_accessibleElements = [[NSMutableArray alloc] init];
+ return self;
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame])) {
+ // Set up EAGL layer
+ CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
+ eaglLayer.opaque = TRUE;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+
+ if (isQtApplication())
+ self.hidden = YES;
+
+ self.multipleTouchEnabled = YES;
+ m_inSendEventToFocusObject = NO;
+ }
+
+ return self;
+}
+
+- (void)willMoveToWindow:(UIWindow *)newWindow
+{
+ // UIKIt will normally set the scale factor of a view to match the corresponding
+ // screen scale factor, but views backed by CAEAGLLayers need to do this manually.
+ self.contentScaleFactor = newWindow && newWindow.screen ?
+ newWindow.screen.scale : [[UIScreen mainScreen] scale];
+
+ // FIXME: Allow the scale factor to be customized through QSurfaceFormat.
+}
+
+- (void)didAddSubview:(UIView *)subview
+{
+ if ([subview isKindOfClass:[QUIView class]])
+ self.clipsToBounds = YES;
+}
+
+- (void)willRemoveSubview:(UIView *)subview
+{
+ for (UIView *view in self.subviews) {
+ if (view != subview && [view isKindOfClass:[QUIView class]])
+ return;
+ }
+
+ self.clipsToBounds = NO;
+}
+
+- (void)setNeedsDisplay
+{
+ [super setNeedsDisplay];
+
+ // We didn't implement drawRect: so we have to manually
+ // mark the layer as needing display.
+ [self.layer setNeedsDisplay];
+}
+
+- (void)layoutSubviews
+{
+ // This method is the de facto way to know that view has been resized,
+ // or otherwise needs invalidation of its buffers. Note though that we
+ // do not get this callback when the view just changes its position, so
+ // the position of our QWindow (and platform window) will only get updated
+ // when the size is also changed.
+
+ if (!CGAffineTransformIsIdentity(self.transform))
+ qWarning() << m_qioswindow->window()
+ << "is backed by a UIView that has a transform set. This is not supported.";
+
+ // The original geometry requested by setGeometry() might be different
+ // from what we end up with after applying window constraints.
+ QRect requestedGeometry = m_qioswindow->geometry();
+
+ QRect actualGeometry;
+ if (m_qioswindow->window()->isTopLevel()) {
+ UIWindow *uiWindow = self.window;
+ UIView *rootView = uiWindow.rootViewController.view;
+ CGRect rootViewPositionInRelationToRootViewController =
+ [rootView convertRect:uiWindow.bounds fromView:uiWindow];
+
+ actualGeometry = fromCGRect(CGRectOffset([self.superview convertRect:self.frame toView:rootView],
+ -rootViewPositionInRelationToRootViewController.origin.x,
+ -rootViewPositionInRelationToRootViewController.origin.y
+ + rootView.bounds.origin.y)).toRect();
+ } else {
+ actualGeometry = fromCGRect(self.frame).toRect();
+ }
+
+ // Persist the actual/new geometry so that QWindow::geometry() can
+ // be queried on the resize event.
+ m_qioswindow->QPlatformWindow::setGeometry(actualGeometry);
+
+ QRect previousGeometry = requestedGeometry != actualGeometry ?
+ requestedGeometry : qt_window_private(m_qioswindow->window())->geometry;
+
+ QWindowSystemInterface::handleGeometryChange(m_qioswindow->window(), actualGeometry, previousGeometry);
+ QWindowSystemInterface::flushWindowSystemEvents();
+
+ if (actualGeometry.size() != previousGeometry.size()) {
+ // Trigger expose event on resize
+ [self setNeedsDisplay];
+
+ // A new size means we also need to resize the FBO's corresponding buffers,
+ // but we defer that to when the application calls makeCurrent.
+ }
+}
+
+- (void)displayLayer:(CALayer *)layer
+{
+ Q_UNUSED(layer);
+ Q_ASSERT(layer == self.layer);
+
+ [self sendUpdatedExposeEvent];
+}
+
+- (void)sendUpdatedExposeEvent
+{
+ QRegion region;
+
+ if (m_qioswindow->isExposed()) {
+ QSize bounds = fromCGRect(self.layer.bounds).toRect().size();
+
+ Q_ASSERT(m_qioswindow->geometry().size() == bounds);
+ Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
+
+ region = QRect(QPoint(), bounds);
+ }
+
+ QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+- (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state
+{
+ // We deliver touch events in global coordinates. But global in this respect
+ // means the same coordinate system that we use for describing the geometry
+ // of the top level QWindow we're inside. And that would be the coordinate
+ // system of the superview of the UIView that backs that window:
+ QPlatformWindow *topLevel = m_qioswindow;
+ while (QPlatformWindow *topLevelParent = topLevel->parent())
+ topLevel = topLevelParent;
+ UIView *rootView = reinterpret_cast<UIView *>(topLevel->winId()).superview;
+ CGSize rootViewSize = rootView.frame.size;
+
+ foreach (UITouch *uiTouch, m_activeTouches.keys()) {
+ QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch];
+ if (![touches containsObject:uiTouch]) {
+ touchPoint.state = Qt::TouchPointStationary;
+ } else {
+ touchPoint.state = state;
+ touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0;
+ QPoint touchPos = fromCGPoint([uiTouch locationInView:rootView]).toPoint();
+ touchPoint.area = QRectF(touchPos, QSize(0, 0));
+ touchPoint.normalPosition = QPointF(touchPos.x() / rootViewSize.width, touchPos.y() / rootViewSize.height);
+ }
+ }
+}
+
+- (void) sendTouchEventWithTimestamp:(ulong)timeStamp
+{
+ // Send touch event synchronously
+ QIOSIntegration *iosIntegration = QIOSIntegration::instance();
+ QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ // UIKit generates [Began -> Moved -> Ended] event sequences for
+ // each touch point. Internally we keep a hashmap of active UITouch
+ // points to QWindowSystemInterface::TouchPoints, and assigns each TouchPoint
+ // an id for use by Qt.
+ for (UITouch *touch in touches) {
+ Q_ASSERT(!m_activeTouches.contains(touch));
+ m_activeTouches[touch].id = m_nextTouchId++;
+ }
+
+ if (m_activeTouches.size() == 1) {
+ QPlatformWindow *topLevel = m_qioswindow;
+ while (QPlatformWindow *p = topLevel->parent())
+ topLevel = p;
+ if (topLevel->window() != QGuiApplication::focusWindow())
+ topLevel->requestActivateWindow();
+ }
+
+ [self updateTouchList:touches withState:Qt::TouchPointPressed];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self updateTouchList:touches withState:Qt::TouchPointMoved];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ [self updateTouchList:touches withState:Qt::TouchPointReleased];
+ [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)];
+
+ // Remove ended touch points from the active set:
+ for (UITouch *touch in touches)
+ m_activeTouches.remove(touch);
+ if (m_activeTouches.isEmpty())
+ m_nextTouchId = 0;
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
+{
+ if (m_activeTouches.isEmpty())
+ return;
+
+ // When four-finger swiping, we get a touchesCancelled callback
+ // which includes all four touch points. The swipe gesture is
+ // then active until all four touches have been released, and
+ // we start getting touchesBegan events again.
+
+ // When five-finger pinching, we also get a touchesCancelled
+ // callback with all five touch points, but the pinch gesture
+ // ends when the second to last finger is released from the
+ // screen. The last finger will not emit any more touch
+ // events, _but_, will contribute to starting another pinch
+ // gesture. That second pinch gesture will _not_ trigger a
+ // touchesCancelled event when starting, but as each finger
+ // is released, and we may get touchesMoved events for the
+ // remaining fingers. [event allTouches] also contains one
+ // less touch point than it should, so this behavior is
+ // likely a bug in the iOS system gesture recognizer, but we
+ // have to take it into account when maintaining the Qt state.
+ // We do this by assuming that there are no cases where a
+ // sub-set of the active touch events are intentionally cancelled.
+
+ if (touches && (static_cast<NSInteger>([touches count]) != m_activeTouches.count()))
+ qWarning("Subset of active touches cancelled by UIKit");
+
+ m_activeTouches.clear();
+ m_nextTouchId = 0;
+
+ NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
+
+ // Send cancel touch event synchronously
+ QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+@end
+
+@implementation UIView (QtHelpers)
+
+- (QWindow *)qwindow
+{
+ if ([self isKindOfClass:[QUIView class]]) {
+ if (QIOSWindow *w = static_cast<QUIView *>(self)->m_qioswindow)
+ return w->window();
+ }
+ return nil;
+}
+
+- (UIViewController *)viewController
+{
+ id responder = self;
+ while ((responder = [responder nextResponder])) {
+ if ([responder isKindOfClass:UIViewController.class])
+ return responder;
+ }
+ return nil;
+}
+
+@end
diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm
new file mode 100644
index 0000000000..6565e08302
--- /dev/null
+++ b/src/plugins/platforms/ios/quiview_accessibility.mm
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "qiosplatformaccessibility.h"
+#include "quiaccessibilityelement.h"
+
+#include <QtGui/private/qguiapplication_p.h>
+
+@implementation QUIView (Accessibility)
+
+- (void)createAccessibleElement:(QAccessibleInterface *)iface
+{
+ if (!iface || iface->state().invisible)
+ return;
+ QAccessible::Id accessibleId = QAccessible::uniqueId(iface);
+ UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self];
+ [m_accessibleElements addObject: elem];
+}
+
+- (void)createAccessibleContainer:(QAccessibleInterface *)iface
+{
+ if (!iface)
+ return;
+
+ if (iface->childCount() == 0) {
+ [self createAccessibleElement: iface];
+ } else {
+ for (int i = 0; i < iface->childCount(); ++i)
+ [self createAccessibleContainer: iface->child(i)];
+ }
+}
+
+- (void)initAccessibility
+{
+ static bool init = false;
+ if (!init)
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+ init = true;
+
+ if ([m_accessibleElements count])
+ return;
+
+ QWindow *win = m_qioswindow->window();
+ QAccessibleInterface *iface = win->accessibleRoot();
+ if (iface)
+ [self createAccessibleContainer: iface];
+}
+
+- (void)clearAccessibleCache
+{
+ [m_accessibleElements removeAllObjects];
+ UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"");
+}
+
+// this is a container, returning yes here means the functions below will never be called
+- (BOOL)isAccessibilityElement
+{
+ return NO;
+}
+
+- (NSInteger)accessibilityElementCount
+{
+ [self initAccessibility];
+ return [m_accessibleElements count];
+}
+
+- (id)accessibilityElementAtIndex:(NSInteger)index
+{
+ [self initAccessibility];
+ return m_accessibleElements[index];
+}
+
+- (NSInteger)indexOfAccessibilityElement:(id)element
+{
+ [self initAccessibility];
+ return [m_accessibleElements indexOfObject:element];
+}
+
+@end
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index e65ac1cc46..861c8151c6 100644
--- a/src/plugins/platforms/ios/quiview_textinput.mm
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -39,7 +39,10 @@
**
****************************************************************************/
+#include "qiosinputcontext.h"
+
#include <QtGui/qtextformat.h>
+#include <QtGui/private/qguiapplication_p.h>
class StaticVariables
{
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
index 6c6c516a4e..3f959b859c 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
@@ -179,7 +179,7 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL
// Get the basic surface format details
if (d->context)
- qglx_surfaceFormatFromGLXFBConfig(&d->format, x11->display(), config, d->context);
+ qglx_surfaceFormatFromGLXFBConfig(&d->format, x11->display(), config);
// Create a temporary window so that we can make the new context current
d->window = createDummyWindow(x11, config);
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index add45ecbe5..59dc84ebc8 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -209,6 +209,103 @@ QQnxScreen::~QQnxScreen()
delete m_cursor;
}
+QPixmap QQnxScreen::grabWindow(WId window, int x, int y, int width, int height) const
+{
+ QQnxWindow *qnxWin = findWindow(reinterpret_cast<screen_window_t>(window));
+ if (!qnxWin) {
+ qWarning("grabWindow: unknown window");
+ return QPixmap();
+ }
+
+ QRect bound = qnxWin->geometry();
+
+ if (width < 0)
+ width = bound.width();
+ if (height < 0)
+ height = bound.height();
+
+ bound &= QRect(x + bound.x(), y + bound.y(), width, height);
+
+ if (bound.width() <= 0 || bound.height() <= 0) {
+ qWarning("grabWindow: size is null");
+ return QPixmap();
+ }
+
+ // Create new context, only SCREEN_DISPLAY_MANAGER_CONTEXT can read from screen
+ screen_context_t context;
+ if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
+ if (errno == EPERM)
+ qWarning("grabWindow: root privileges required");
+ else
+ qWarning("grabWindow: cannot create context");
+ return QPixmap();
+ }
+
+ // Find corresponding display in SCREEN_DISPLAY_MANAGER_CONTEXT
+ int count = 0;
+ screen_display_t display = 0;
+ screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
+ if (count > 0) {
+ const size_t idLen = 30;
+ char matchId[idLen];
+ char id[idLen];
+ bool found = false;
+
+ screen_display_t *displays = static_cast<screen_display_t*>
+ (calloc(count, sizeof(screen_display_t)));
+ screen_get_context_property_pv(context, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
+ screen_get_display_property_cv(m_display, SCREEN_PROPERTY_ID_STRING, idLen, matchId);
+
+ while (count && !found) {
+ --count;
+ screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
+ found = !strncmp(id, matchId, idLen);
+ }
+
+ if (found)
+ display = displays[count];
+
+ free(displays);
+ }
+
+ // Create screen and Qt pixmap
+ screen_pixmap_t pixmap;
+ QPixmap result;
+ if (display && !screen_create_pixmap(&pixmap, context)) {
+ screen_buffer_t buffer;
+ void *pointer;
+ int stride;
+ const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };
+
+ int val = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
+ screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_USAGE, &val);
+ val = SCREEN_FORMAT_RGBA8888;
+ screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_FORMAT, &val);
+
+ int err = screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
+ err = err || screen_create_pixmap_buffer(pixmap);
+ err = err || screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_BUFFERS,
+ reinterpret_cast<void**>(&buffer));
+ err = err || screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, &pointer);
+ err = err || screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
+ err = err || screen_read_display(display, buffer, 1, rect, 0);
+
+ if (!err) {
+ const QImage img(static_cast<unsigned char*>(pointer),
+ bound.width(), bound.height(), stride, QImage::Format_ARGB32);
+ result = QPixmap::fromImage(img);
+ } else {
+ qWarning("grabWindow: capture error");
+ }
+ screen_destroy_pixmap(pixmap);
+ } else {
+ qWarning("grabWindow: display/pixmap error ");
+ }
+ screen_destroy_context(context);
+
+ return result;
+}
+
static int defaultDepth()
{
qScreenDebug() << Q_FUNC_INFO;
@@ -463,7 +560,7 @@ void QQnxScreen::resizeWindows(const QRect &previousScreenGeometry)
}
}
-QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle)
+QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle) const
{
Q_FOREACH (QQnxWindow *window, m_childWindows) {
QQnxWindow * const result = window->findWindow(windowHandle);
diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h
index 6b2281f7b9..a8a18c6240 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.h
+++ b/src/plugins/platforms/qnx/qqnxscreen.h
@@ -62,6 +62,8 @@ public:
QQnxScreen(screen_context_t context, screen_display_t display, bool primaryScreen);
~QQnxScreen();
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+
QRect geometry() const { return m_currentGeometry; }
QRect availableGeometry() const;
int depth() const;
@@ -86,7 +88,7 @@ public:
screen_context_t nativeContext() const { return m_screenContext; }
const char *windowGroupName() const { return m_rootWindow ? m_rootWindow->groupName().constData() : 0; }
- QQnxWindow *findWindow(screen_window_t windowHandle);
+ QQnxWindow *findWindow(screen_window_t windowHandle) const;
/* Window hierarchy management */
void addWindow(QQnxWindow *child);
diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp
index 6c67345e05..366adb9059 100644
--- a/src/plugins/platforms/windows/accessible/comutils.cpp
+++ b/src/plugins/platforms/windows/accessible/comutils.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h
index ebf16dfdf8..2ef11ec0dd 100644
--- a/src/plugins/platforms/windows/accessible/comutils.h
+++ b/src/plugins/platforms/windows/accessible/comutils.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index 032f33163a..20658f9cad 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -43,7 +43,7 @@
#include "iaccessible2.h"
#include "qwindowsaccessibility.h"
-
+#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qclipboard.h>
#include <QtWidgets/qapplication.h>
@@ -358,6 +358,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role)
case QAccessible::LayeredPane: r = IA2_ROLE_LAYERED_PANE; break;
case QAccessible::Terminal: r = IA2_ROLE_TERMINAL; break;
case QAccessible::Desktop: r = IA2_ROLE_DESKTOP_PANE; break;
+ case QAccessible::Paragraph: r = IA2_ROLE_PARAGRAPH; break;
+ case QAccessible::Section: r = IA2_ROLE_SECTION; break;
default: break;
}
@@ -545,10 +547,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions)
accessibleDebugClientCalls(accessible);
if (!accessible)
return E_FAIL;
- *nActions = 0;
-
- if (QAccessibleActionInterface *actionIface = actionInterface())
- *nActions = actionIface->actionNames().count();
+ *nActions = QAccessibleBridgeUtils::effectiveActionNames(accessible).count();
return S_OK;
}
@@ -558,15 +557,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex)
accessibleDebugClientCalls(accessible);
if (!accessible)
return E_FAIL;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- actionIface->doAction(actionName);
- return S_OK;
- }
- return S_FALSE;
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ return QAccessibleBridgeUtils::performEffectiveAction(accessible, actionName) ? S_OK : S_FALSE;
}
HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description)
@@ -576,13 +571,15 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionInde
if (!accessible)
return E_FAIL;
*description = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ if (QAccessibleActionInterface *actionIface = actionInterface())
*description = QStringToBSTR(actionIface->localizedActionDescription(actionName));
- }
+ else
+ *description = QStringToBSTR(qAccessibleLocalizedActionDescription(actionName));
+
return *description ? S_OK : S_FALSE;
}
@@ -622,13 +619,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR
if (!accessible)
return E_FAIL;
*name = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
- *name = QStringToBSTR(actionName);
- }
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ *name = QStringToBSTR(actionName);
return *name ? S_OK : S_FALSE;
}
@@ -639,14 +634,16 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIn
if (!accessible)
return E_FAIL;
*localizedName = 0;
- if (QAccessibleActionInterface *actionIface = actionInterface()) {
- const QStringList actionNames = actionIface->actionNames();
- if (actionIndex < 0 || actionIndex >= actionNames.count())
- return E_INVALIDARG;
+ const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(accessible);
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
- const QString actionName = actionNames.at(actionIndex);
+ const QString actionName = actionNames.at(actionIndex);
+ if (QAccessibleActionInterface *actionIface = actionInterface())
*localizedName = QStringToBSTR(actionIface->localizedActionName(actionName));
- }
+ else
+ *localizedName = QStringToBSTR(QAccessibleActionInterface::tr(qPrintable(actionName)));
+
return *localizedName ? S_OK : S_FALSE;
}
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h
index 9c42fdc631..fd92fb25bf 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.h
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
index 307f2fc3bb..f5b0f2f166 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
index f25e2281a0..9e14868415 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index bda806d102..d606ecb6a5 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -890,6 +890,11 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BST
}
}
}
+
+ QString shortcut = accessible->text(QAccessible::Accelerator);
+ if (!shortcut.isEmpty())
+ name.append(QLatin1Char(' ') + shortcut);
+
if (name.size()) {
*pszName = QStringToBSTR(name);
return S_OK;
@@ -930,6 +935,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VAR
// does not support IAccessible2, since it should prefer IA2::role() then.
if (role == QAccessible::LayeredPane)
role = QAccessible::Pane;
+ else if (role == QAccessible::WebDocument)
+ role = QAccessible::Document;
else
role = QAccessible::Client;
}
@@ -1034,7 +1041,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BS
QString value;
if (accessible->valueInterface()) {
- value = QString::number(accessible->valueInterface()->currentValue().toDouble());
+ value = accessible->valueInterface()->currentValue().toString();
} else {
value = accessible->text(QAccessible::Value);
}
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
index 43482da4be..b9cc2ccb44 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
diff --git a/src/plugins/platforms/windows/cursors.qrc b/src/plugins/platforms/windows/cursors.qrc
new file mode 100644
index 0000000000..fded527aac
--- /dev/null
+++ b/src/plugins/platforms/windows/cursors.qrc
@@ -0,0 +1,25 @@
+<RCC>
+ <qresource prefix="/qt-project.org/windows/cursors">
+ <file>images/closedhandcursor_32.png</file>
+ <file>images/closedhandcursor_48.png</file>
+ <file>images/closedhandcursor_64.png</file>
+ <file>images/dragcopycursor_32.png</file>
+ <file>images/dragcopycursor_48.png</file>
+ <file>images/dragcopycursor_64.png</file>
+ <file>images/draglinkcursor_32.png</file>
+ <file>images/draglinkcursor_48.png</file>
+ <file>images/draglinkcursor_64.png</file>
+ <file>images/dragmovecursor_32.png</file>
+ <file>images/dragmovecursor_48.png</file>
+ <file>images/dragmovecursor_64.png</file>
+ <file>images/openhandcursor_32.png</file>
+ <file>images/openhandcursor_48.png</file>
+ <file>images/openhandcursor_64.png</file>
+ <file>images/splithcursor_32.png</file>
+ <file>images/splithcursor_48.png</file>
+ <file>images/splithcursor_64.png</file>
+ <file>images/splitvcursor_32.png</file>
+ <file>images/splitvcursor_48.png</file>
+ <file>images/splitvcursor_64.png</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/platforms/windows/images/closedhandcursor_32.png b/src/plugins/platforms/windows/images/closedhandcursor_32.png
new file mode 100644
index 0000000000..7b3cba1965
--- /dev/null
+++ b/src/plugins/platforms/windows/images/closedhandcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/closedhandcursor_48.png b/src/plugins/platforms/windows/images/closedhandcursor_48.png
new file mode 100644
index 0000000000..e63031605e
--- /dev/null
+++ b/src/plugins/platforms/windows/images/closedhandcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/closedhandcursor_64.png b/src/plugins/platforms/windows/images/closedhandcursor_64.png
new file mode 100644
index 0000000000..438680ed4e
--- /dev/null
+++ b/src/plugins/platforms/windows/images/closedhandcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragcopycursor_32.png b/src/plugins/platforms/windows/images/dragcopycursor_32.png
new file mode 100644
index 0000000000..f40ac6a600
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragcopycursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragcopycursor_48.png b/src/plugins/platforms/windows/images/dragcopycursor_48.png
new file mode 100644
index 0000000000..21ee467f46
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragcopycursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragcopycursor_64.png b/src/plugins/platforms/windows/images/dragcopycursor_64.png
new file mode 100644
index 0000000000..c49bcf33aa
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragcopycursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/draglinkcursor_32.png b/src/plugins/platforms/windows/images/draglinkcursor_32.png
new file mode 100644
index 0000000000..5efbce90d3
--- /dev/null
+++ b/src/plugins/platforms/windows/images/draglinkcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/draglinkcursor_48.png b/src/plugins/platforms/windows/images/draglinkcursor_48.png
new file mode 100644
index 0000000000..51205101b1
--- /dev/null
+++ b/src/plugins/platforms/windows/images/draglinkcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/draglinkcursor_64.png b/src/plugins/platforms/windows/images/draglinkcursor_64.png
new file mode 100644
index 0000000000..55eb0e313a
--- /dev/null
+++ b/src/plugins/platforms/windows/images/draglinkcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragmovecursor_32.png b/src/plugins/platforms/windows/images/dragmovecursor_32.png
new file mode 100644
index 0000000000..32781a15ff
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragmovecursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragmovecursor_48.png b/src/plugins/platforms/windows/images/dragmovecursor_48.png
new file mode 100644
index 0000000000..6b15af6e84
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragmovecursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/dragmovecursor_64.png b/src/plugins/platforms/windows/images/dragmovecursor_64.png
new file mode 100644
index 0000000000..e9e4ece29f
--- /dev/null
+++ b/src/plugins/platforms/windows/images/dragmovecursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/openhandcursor_32.png b/src/plugins/platforms/windows/images/openhandcursor_32.png
new file mode 100644
index 0000000000..a6948d48f7
--- /dev/null
+++ b/src/plugins/platforms/windows/images/openhandcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/openhandcursor_48.png b/src/plugins/platforms/windows/images/openhandcursor_48.png
new file mode 100644
index 0000000000..e8beb8d29d
--- /dev/null
+++ b/src/plugins/platforms/windows/images/openhandcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/openhandcursor_64.png b/src/plugins/platforms/windows/images/openhandcursor_64.png
new file mode 100644
index 0000000000..d12e3a7283
--- /dev/null
+++ b/src/plugins/platforms/windows/images/openhandcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splithcursor_32.png b/src/plugins/platforms/windows/images/splithcursor_32.png
new file mode 100644
index 0000000000..1ad479eddf
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splithcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splithcursor_48.png b/src/plugins/platforms/windows/images/splithcursor_48.png
new file mode 100644
index 0000000000..bf59b9cdca
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splithcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splithcursor_64.png b/src/plugins/platforms/windows/images/splithcursor_64.png
new file mode 100644
index 0000000000..b857458671
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splithcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splitvcursor_32.png b/src/plugins/platforms/windows/images/splitvcursor_32.png
new file mode 100644
index 0000000000..ebb55ae2e1
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splitvcursor_32.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splitvcursor_48.png b/src/plugins/platforms/windows/images/splitvcursor_48.png
new file mode 100644
index 0000000000..5408920652
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splitvcursor_48.png
Binary files differ
diff --git a/src/plugins/platforms/windows/images/splitvcursor_64.png b/src/plugins/platforms/windows/images/splitvcursor_64.png
new file mode 100644
index 0000000000..7f09a40c01
--- /dev/null
+++ b/src/plugins/platforms/windows/images/splitvcursor_64.png
Binary files differ
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index ee640224cf..1b2502af10 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -103,6 +103,7 @@ enum WindowsEventType // Simplify event types
AccessibleObjectFromWindowRequest = ApplicationEventFlag + 3,
QueryEndSessionApplicationEvent = ApplicationEventFlag + 4,
EndSessionApplicationEvent = ApplicationEventFlag + 5,
+ AppCommandEvent = ApplicationEventFlag + 6,
InputMethodStartCompositionEvent = InputMethodEventFlag + 1,
InputMethodCompositionEvent = InputMethodEventFlag + 2,
InputMethodEndCompositionEvent = InputMethodEventFlag + 3,
@@ -117,6 +118,14 @@ enum WindowsEventType // Simplify event types
UnknownEvent = 542
};
+// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
+enum ProcessDpiAwareness
+{
+ ProcessDpiUnaware,
+ ProcessSystemDpiAware,
+ ProcessPerMonitorDpiAware
+};
+
} // namespace QtWindows
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn)
@@ -234,6 +243,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
case WM_ENDSESSION:
return QtWindows::EndSessionApplicationEvent;
#endif
+#if defined(WM_APPCOMMAND)
+ case WM_APPCOMMAND:
+ return QtWindows::AppCommandEvent;
+#endif
default:
break;
}
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 758f6c941f..e19b8a4db1 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -59,11 +59,11 @@ public:
QWindowsBackingStore(QWindow *window);
~QWindowsBackingStore();
- virtual QPaintDevice *paintDevice();
- virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
- virtual void resize(const QSize &size, const QRegion &r);
- virtual bool scroll(const QRegion &area, int dx, int dy);
- virtual void beginPaint(const QRegion &);
+ QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
+ void resize(const QSize &size, const QRegion &r) Q_DECL_OVERRIDE;
+ bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
+ void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
HDC getDC() const;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index dcfeba12fa..e43b524aa8 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -145,7 +145,7 @@ static void cleanClipboardPostRoutine()
QWindowsClipboard *QWindowsClipboard::m_instance = 0;
QWindowsClipboard::QWindowsClipboard() :
- m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0)
+ m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0), m_formatListenerRegistered(false)
{
QWindowsClipboard::m_instance = this;
qAddPostRoutine(cleanClipboardPostRoutine);
@@ -178,20 +178,40 @@ void QWindowsClipboard::registerViewer()
m_clipboardViewer = QWindowsContext::instance()->
createDummyWindow(QStringLiteral("Qt5ClipboardView"), L"Qt5ClipboardView",
qClipboardViewerWndProc, WS_OVERLAPPED);
- m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
- qCDebug(lcQpaMime) << __FUNCTION__ << "m_clipboardViewer: " << m_clipboardViewer << "next: " << m_nextClipboardViewer;
+ // Try format listener API (Vista onwards) first.
+ if (QWindowsContext::user32dll.addClipboardFormatListener && QWindowsContext::user32dll.removeClipboardFormatListener) {
+ m_formatListenerRegistered = QWindowsContext::user32dll.addClipboardFormatListener(m_clipboardViewer);
+ if (!m_formatListenerRegistered)
+ qErrnoWarning("AddClipboardFormatListener() failed.");
+ }
+
+ if (!m_formatListenerRegistered)
+ m_nextClipboardViewer = SetClipboardViewer(m_clipboardViewer);
+
+ qCDebug(lcQpaMime) << __FUNCTION__ << "m_clipboardViewer:" << m_clipboardViewer
+ << "format listener:" << m_formatListenerRegistered
+ << "next:" << m_nextClipboardViewer;
}
void QWindowsClipboard::unregisterViewer()
{
if (m_clipboardViewer) {
- ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
+ if (m_formatListenerRegistered) {
+ QWindowsContext::user32dll.removeClipboardFormatListener(m_clipboardViewer);
+ m_formatListenerRegistered = false;
+ } else {
+ ChangeClipboardChain(m_clipboardViewer, m_nextClipboardViewer);
+ m_nextClipboardViewer = 0;
+ }
DestroyWindow(m_clipboardViewer);
- m_clipboardViewer = m_nextClipboardViewer = 0;
+ m_clipboardViewer = 0;
}
}
+// ### FIXME: Qt 6: Remove the clipboard chain handling code and make the
+// format listener the default.
+
static bool isProcessBeingDebugged(HWND hwnd)
{
DWORD pid = 0;
@@ -232,6 +252,8 @@ void QWindowsClipboard::propagateClipboardMessage(UINT message, WPARAM wParam, L
bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
+ enum { wMClipboardUpdate = 0x031D };
+
*result = 0;
if (QWindowsContext::verbose)
qCDebug(lcQpaMime) << __FUNCTION__ << hwnd << message << QWindowsGuiEventDispatcher::windowsMessageName(message);
@@ -246,14 +268,16 @@ bool QWindowsClipboard::clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM w
}
}
return true;
- case WM_DRAWCLIPBOARD: {
+ case wMClipboardUpdate: // Clipboard Format listener (Vista onwards)
+ case WM_DRAWCLIPBOARD: { // Clipboard Viewer Chain handling (up to XP)
const bool owned = ownsClipboard();
qCDebug(lcQpaMime) << "Clipboard changed owned " << owned;
emitChanged(QClipboard::Clipboard);
// clean up the clipboard object if we no longer own the clipboard
if (!owned && m_data)
releaseIData();
- propagateClipboardMessage(message, wParam, lParam);
+ if (!m_formatListenerRegistered)
+ propagateClipboardMessage(message, wParam, lParam);
}
return true;
case WM_DESTROY:
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 30bc0143f4..a3e9da7f3f 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -54,8 +54,8 @@ class QWindowsClipboardRetrievalMimeData : public QWindowsInternalMimeData {
public:
protected:
- virtual IDataObject *retrieveDataObject() const;
- virtual void releaseDataObject(IDataObject *) const;
+ IDataObject *retrieveDataObject() const Q_DECL_OVERRIDE;
+ void releaseDataObject(IDataObject *) const Q_DECL_OVERRIDE;
};
class QWindowsClipboard : public QPlatformClipboard
@@ -66,10 +66,10 @@ public:
void registerViewer(); // Call in initialization, when context is up.
void cleanup();
- virtual QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);
- virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
- virtual bool supportsMode(QClipboard::Mode mode) const;
- virtual bool ownsMode(QClipboard::Mode mode) const;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
+ bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
inline bool clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
@@ -88,6 +88,7 @@ private:
QWindowsOleDataObject *m_data;
HWND m_clipboardViewer;
HWND m_nextClipboardViewer;
+ bool m_formatListenerRegistered;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index f2f285f0f6..9706615047 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -191,7 +191,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() :
updateLayeredWindowIndirect(0),
isHungAppWindow(0),
registerTouchWindow(0), unregisterTouchWindow(0),
- getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0)
+ getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0),
+ addClipboardFormatListener(0), removeClipboardFormatListener(0)
{
}
@@ -207,6 +208,11 @@ void QWindowsUser32DLL::init()
updateLayeredWindowIndirect = (UpdateLayeredWindowIndirect)(library.resolve("UpdateLayeredWindowIndirect"));
isHungAppWindow = (IsHungAppWindow)library.resolve("IsHungAppWindow");
setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
+
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) {
+ addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
+ removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
+ }
}
bool QWindowsUser32DLL::initTouch()
@@ -247,8 +253,26 @@ void QWindowsShell32DLL::init()
sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList");
}
+QWindowsShcoreDLL::QWindowsShcoreDLL()
+ : getProcessDpiAwareness(0)
+ , setProcessDpiAwareness(0)
+ , getDpiForMonitor(0)
+{
+}
+
+void QWindowsShcoreDLL::init()
+{
+ if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1)
+ return;
+ QSystemLibrary library(QStringLiteral("SHCore"));
+ getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
+ setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
+ getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
+}
+
QWindowsUser32DLL QWindowsContext::user32dll;
QWindowsShell32DLL QWindowsContext::shell32dll;
+QWindowsShcoreDLL QWindowsContext::shcoredll;
#endif // !Q_OS_WINCE
@@ -299,9 +323,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
#ifndef Q_OS_WINCE
QWindowsContext::user32dll.init();
QWindowsContext::shell32dll.init();
- // Ensure metrics functions report correct data, QTBUG-30063.
- if (QWindowsContext::user32dll.setProcessDPIAware)
- QWindowsContext::user32dll.setProcessDPIAware();
+ QWindowsContext::shcoredll.init();
if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
@@ -358,6 +380,25 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
#endif
}
+void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
+{
+#ifndef Q_OS_WINCE
+ qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
+ if (QWindowsContext::shcoredll.isValid()) {
+ const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness);
+ if (FAILED(hr))
+ qWarning() << "SetProcessDpiAwareness failed:" << QWindowsContext::comErrorString(hr);
+ } else {
+ if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
+ if (!QWindowsContext::user32dll.setProcessDPIAware())
+ qErrnoWarning("SetProcessDPIAware() failed");
+ }
+ }
+#else // !Q_OS_WINCE
+ Q_UNUSED(dpiAwareness)
+#endif
+}
+
QWindowsContext *QWindowsContext::instance()
{
return m_instance;
@@ -419,9 +460,17 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
&& (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
style |= CS_DROPSHADOW;
}
- if (type == Qt::Tool || type == Qt::ToolTip || type == Qt::Popup) {
+ switch (type) {
+ case Qt::Tool:
+ case Qt::ToolTip:
+ case Qt::Popup:
style |= CS_SAVEBITS; // Save/restore background
icon = false;
+ break;
+ case Qt::Dialog:
+ if (!(flags & Qt::WindowSystemMenuHint))
+ icon = false; // QTBUG-2027, dialogs without system menu.
+ break;
}
// Create a unique name for the flag combination
QString cname = QStringLiteral("Qt5QWindow");
@@ -913,6 +962,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::InputMethodKeyEvent:
case QtWindows::InputMethodKeyDownEvent:
case QtWindows::KeyboardLayoutChangeEvent:
+ case QtWindows::AppCommandEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
#else
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index f5dbd072c7..086b968255 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -94,6 +94,8 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *UpdateLayeredWindowIndirect)(HWND, const UPDATELAYEREDWINDOWINFO *);
typedef BOOL (WINAPI *IsHungAppWindow)(HWND);
typedef BOOL (WINAPI *SetProcessDPIAware)();
+ typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
+ typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
// Functions missing in Q_CC_GNU stub libraries.
SetLayeredWindowAttributes setLayeredWindowAttributes;
@@ -111,6 +113,10 @@ struct QWindowsUser32DLL
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware;
+
+ // Clipboard listeners, Windows Vista onwards
+ AddClipboardFormatListener addClipboardFormatListener;
+ RemoveClipboardFormatListener removeClipboardFormatListener;
};
struct QWindowsShell32DLL
@@ -126,6 +132,22 @@ struct QWindowsShell32DLL
SHGetStockIconInfo sHGetStockIconInfo;
SHGetImageList sHGetImageList;
};
+
+// Shell scaling library (Windows 8.1 onwards)
+struct QWindowsShcoreDLL {
+ QWindowsShcoreDLL();
+ void init();
+ inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
+
+ typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int);
+ typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
+ typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
+
+ GetProcessDpiAwareness getProcessDpiAwareness;
+ SetProcessDpiAwareness setProcessDpiAwareness;
+ GetDpiForMonitor getDpiForMonitor;
+};
+
#endif // Q_OS_WINCE
class QWindowsContext
@@ -184,6 +206,7 @@ public:
void setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
void setTabletAbsoluteRange(int a);
+ void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
// Returns a combination of SystemInfoFlags
unsigned systemInfo() const;
@@ -197,6 +220,7 @@ public:
#ifndef Q_OS_WINCE
static QWindowsUser32DLL user32dll;
static QWindowsShell32DLL shell32dll;
+ static QWindowsShcoreDLL shcoredll;
#endif
static QByteArray comErrorString(HRESULT hr);
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index d8fb104b3c..8352dac0b6 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -98,7 +98,7 @@ QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c)
\sa QWindowsWindowCursor
*/
-HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY)
+HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot)
{
HCURSOR cur = 0;
QBitmap mask = pixmap.mask();
@@ -112,8 +112,8 @@ HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int
ICONINFO ii;
ii.fIcon = 0;
- ii.xHotspot = hotX;
- ii.yHotspot = hotY;
+ ii.xHotspot = hotSpot.x();
+ ii.yHotspot = hotSpot.y();
ii.hbmMask = im;
ii.hbmColor = ic;
@@ -124,20 +124,120 @@ HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int
return cur;
}
-HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
+// Create a cursor from image and mask of the format QImage::Format_Mono.
+static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
+ QPoint hotSpot = QPoint(),
+ bool invb = false, bool invm = false)
{
- int hx = c.hotSpot().x();
- int hy = c.hotSpot().y();
- const Qt::CursorShape cshape = c.shape();
- if (cshape == Qt::BitmapCursor) {
- const QPixmap pixmap = c.pixmap();
- if (!pixmap.isNull())
- if (const HCURSOR hc = createPixmapCursor(pixmap, hx, hy))
- return hc;
+ const int width = bbits.width();
+ const int height = bbits.height();
+ if (hotSpot.isNull())
+ hotSpot = QPoint(width / 2, height / 2);
+ const int n = qMax(1, width / 8);
+#if !defined(Q_OS_WINCE)
+ QScopedArrayPointer<uchar> xBits(new uchar[height * n]);
+ QScopedArrayPointer<uchar> xMask(new uchar[height * n]);
+ int x = 0;
+ for (int i = 0; i < height; ++i) {
+ const uchar *bits = bbits.scanLine(i);
+ const uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < n; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xff;
+ if (invm)
+ m ^= 0xff;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ }
+ return CreateCursor(GetModuleHandle(0), hotSpot.x(), hotSpot.y(), width, height,
+ xBits.data(), xMask.data());
+#elif defined(GWES_ICONCURS) // Q_OS_WINCE
+ // Windows CE only supports fixed cursor size.
+ int sysW = GetSystemMetrics(SM_CXCURSOR);
+ int sysH = GetSystemMetrics(SM_CYCURSOR);
+ int sysN = qMax(1, sysW / 8);
+ uchar* xBits = new uchar[sysH * sysN];
+ uchar* xMask = new uchar[sysH * sysN];
+ int x = 0;
+ for (int i = 0; i < sysH; ++i) {
+ if (i >= height) {
+ memset(&xBits[x] , 255, sysN);
+ memset(&xMask[x] , 0, sysN);
+ x += sysN;
+ } else {
+ int fillWidth = n > sysN ? sysN : n;
+ const uchar *bits = bbits.scanLine(i);
+ const uchar *mask = mbits.scanLine(i);
+ for (int j = 0; j < fillWidth; ++j) {
+ uchar b = bits[j];
+ uchar m = mask[j];
+ if (invb)
+ b ^= 0xFF;
+ if (invm)
+ m ^= 0xFF;
+ xBits[x] = ~m;
+ xMask[x] = b ^ m;
+ ++x;
+ }
+ for (int j = fillWidth; j < sysN; ++j ) {
+ xBits[x] = 255;
+ xMask[x] = 0;
+ ++x;
+ }
+ }
}
- // Non-standard Windows cursors are created from bitmaps
+ HCURSOR hcurs = CreateCursor(qWinAppInst(), hotSpot.x(), hotSpot.y(), sysW, sysH,
+ xBits, xMask);
+ delete [] xBits;
+ delete [] xMask;
+ return hcurs;
+#else
+ Q_UNUSED(n);
+ Q_UNUSED(invm);
+ Q_UNUSED(invb);
+ Q_UNUSED(mbits);
+ return 0;
+#endif
+}
+static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); }
+static inline QSize standardCursorSize() { return QSize(32, 32); }
+
+#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG)
+// Create pixmap cursors from data and scale the image if the cursor size is
+// higher than the standard 32. Note that bitmap cursors as produced by
+// createBitmapCursor() only work for standard sizes (32,48,64...), which does
+// not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting
+// in a non-standard 24x24 size).
+static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
+ // The cursor size the bitmap is targeted for
+ const QSize &bitmapTargetCursorSize,
+ // The actual size of the bitmap data
+ int bitmapSize, const uchar *bits,
+ const uchar *maskBits)
+{
+ QPixmap rawImage = QPixmap::fromImage(QBitmap::fromData(QSize(bitmapSize, bitmapSize), bits).toImage());
+ rawImage.setMask(QBitmap::fromData(QSize(bitmapSize, bitmapSize), maskBits));
+
+ const qreal factor = qreal(systemCursorSize.width()) / qreal(bitmapTargetCursorSize.width());
+ // Scale images if the cursor size is significantly different, starting with 150% where the system cursor
+ // size is 48.
+ if (qAbs(factor - 1.0) > 0.4) {
+ const QTransform transform = QTransform::fromScale(factor, factor);
+ rawImage = rawImage.transformed(transform, Qt::SmoothTransformation);
+ }
+ const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2);
+ return QCursor(rawImage, hotSpot.x(), hotSpot.y());
+}
+
+QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+{
+ // Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -203,171 +303,250 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f,
0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00};
- wchar_t *sh = 0;
- switch (c.shape()) { // map to windows cursor
- case Qt::ArrowCursor:
- sh = IDC_ARROW;
- break;
- case Qt::UpArrowCursor:
- sh = IDC_UPARROW;
- break;
- case Qt::CrossCursor:
- sh = IDC_CROSS;
- break;
- case Qt::WaitCursor:
- sh = IDC_WAIT;
- break;
- case Qt::IBeamCursor:
- sh = IDC_IBEAM;
- break;
- case Qt::SizeVerCursor:
- sh = IDC_SIZENS;
- break;
- case Qt::SizeHorCursor:
- sh = IDC_SIZEWE;
- break;
- case Qt::SizeBDiagCursor:
- sh = IDC_SIZENESW;
- break;
- case Qt::SizeFDiagCursor:
- sh = IDC_SIZENWSE;
- break;
- case Qt::SizeAllCursor:
- sh = IDC_SIZEALL;
- break;
- case Qt::ForbiddenCursor:
- sh = IDC_NO;
- break;
- case Qt::WhatsThisCursor:
- sh = IDC_HELP;
- break;
- case Qt::BusyCursor:
- sh = IDC_APPSTARTING;
- break;
- case Qt::PointingHandCursor:
- sh = IDC_HAND;
- break;
- case Qt::BlankCursor:
+ static const char * const moveDragCursorXpmC[] = {
+ "11 20 3 1",
+ ". c None",
+ "a c #FFFFFF",
+ "X c #000000", // X11 cursor is traditionally black
+ "aa.........",
+ "aXa........",
+ "aXXa.......",
+ "aXXXa......",
+ "aXXXXa.....",
+ "aXXXXXa....",
+ "aXXXXXXa...",
+ "aXXXXXXXa..",
+ "aXXXXXXXXa.",
+ "aXXXXXXXXXa",
+ "aXXXXXXaaaa",
+ "aXXXaXXa...",
+ "aXXaaXXa...",
+ "aXa..aXXa..",
+ "aa...aXXa..",
+ "a.....aXXa.",
+ "......aXXa.",
+ ".......aXXa",
+ ".......aXXa",
+ "........aa."};
+
+ static const char * const copyDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "XX......................",
+ "XaX.....................",
+ "XaaX....................",
+ "XaaaX...................",
+ "XaaaaX..................",
+ "XaaaaaX.................",
+ "XaaaaaaX................",
+ "XaaaaaaaX...............",
+ "XaaaaaaaaX..............",
+ "XaaaaaaaaaX.............",
+ "XaaaaaaXXXX.............",
+ "XaaaXaaX................",
+ "XaaXXaaX................",
+ "XaX..XaaX...............",
+ "XX...XaaX...............",
+ "X.....XaaX..............",
+ "......XaaX..............",
+ ".......XaaX.............",
+ ".......XaaX.............",
+ "........XX...aaaaaaaaaaa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXaaaaaXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXXXaXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aaaaaaaaaaa"};
+
+ static const char * const linkDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "XX......................",
+ "XaX.....................",
+ "XaaX....................",
+ "XaaaX...................",
+ "XaaaaX..................",
+ "XaaaaaX.................",
+ "XaaaaaaX................",
+ "XaaaaaaaX...............",
+ "XaaaaaaaaX..............",
+ "XaaaaaaaaaX.............",
+ "XaaaaaaXXXX.............",
+ "XaaaXaaX................",
+ "XaaXXaaX................",
+ "XaX..XaaX...............",
+ "XX...XaaX...............",
+ "X.....XaaX..............",
+ "......XaaX..............",
+ ".......XaaX.............",
+ ".......XaaX.............",
+ "........XX...aaaaaaaaaaa",
+ ".............aXXXXXXXXXa",
+ ".............aXXXaaaaXXa",
+ ".............aXXXXaaaXXa",
+ ".............aXXXaaaaXXa",
+ ".............aXXaaaXaXXa",
+ ".............aXXaaXXXXXa",
+ ".............aXXaXXXXXXa",
+ ".............aXXXaXXXXXa",
+ ".............aXXXXXXXXXa",
+ ".............aaaaaaaaaaa"};
+
+ switch (cursorShape) {
case Qt::SplitVCursor:
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
case Qt::SplitHCursor:
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
case Qt::OpenHandCursor:
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits);
case Qt::ClosedHandCursor:
- case Qt::BitmapCursor: {
- QImage bbits, mbits;
- bool invb, invm;
- if (cshape == Qt::BlankCursor) {
- bbits = QImage(32, 32, QImage::Format_Mono);
- bbits.fill(0); // ignore color table
- mbits = bbits.copy();
- hx = hy = 16;
- invb = invm = false;
- } else if (cshape == Qt::OpenHandCursor || cshape == Qt::ClosedHandCursor) {
- bool open = cshape == Qt::OpenHandCursor;
- QBitmap cb = QBitmap::fromData(QSize(16, 16), open ? openhand_bits : closedhand_bits);
- QBitmap cm = QBitmap::fromData(QSize(16, 16), open ? openhandm_bits : closedhandm_bits);
- bbits = cb.toImage().convertToFormat(QImage::Format_Mono);
- mbits = cm.toImage().convertToFormat(QImage::Format_Mono);
- hx = hy = 8;
- invb = invm = false;
- } else if (cshape == Qt::BitmapCursor) {
- bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
- mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
- invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
- invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
- } else { // Qt::SplitVCursor, Qt::SplitHCursor
- const QBitmap cb = QBitmap::fromData(QSize(32, 32), cshape == Qt::SplitVCursor ? vsplit_bits : hsplit_bits);
- const QBitmap cm = QBitmap::fromData(QSize(32, 32), cshape == Qt::SplitVCursor ? vsplitm_bits : hsplitm_bits);
- bbits = cb.toImage().convertToFormat(QImage::Format_Mono);
- mbits = cm.toImage().convertToFormat(QImage::Format_Mono);
- hx = hy = 16;
- invb = invm = false;
- }
- const int n = qMax(1, bbits.width() / 8);
- const int h = bbits.height();
-#if !defined(Q_OS_WINCE)
- QScopedArrayPointer<uchar> xBits(new uchar[h * n]);
- QScopedArrayPointer<uchar> xMask(new uchar[h * n]);
- int x = 0;
- for (int i = 0; i < h; ++i) {
- uchar *bits = bbits.scanLine(i);
- uchar *mask = mbits.scanLine(i);
- for (int j = 0; j < n; ++j) {
- uchar b = bits[j];
- uchar m = mask[j];
- if (invb)
- b ^= 0xff;
- if (invm)
- m ^= 0xff;
- xBits[x] = ~m;
- xMask[x] = b ^ m;
- ++x;
- }
- }
- return CreateCursor(GetModuleHandle(0), hx, hy, bbits.width(), bbits.height(),
- xBits.data(), xMask.data());
-#elif defined(GWES_ICONCURS) // Q_WS_WINCE
- // Windows CE only supports fixed cursor size.
- int sysW = GetSystemMetrics(SM_CXCURSOR);
- int sysH = GetSystemMetrics(SM_CYCURSOR);
- int sysN = qMax(1, sysW / 8);
- uchar* xBits = new uchar[sysH * sysN];
- uchar* xMask = new uchar[sysH * sysN];
- int x = 0;
- for (int i = 0; i < sysH; ++i) {
- if (i >= h) {
- memset(&xBits[x] , 255, sysN);
- memset(&xMask[x] , 0, sysN);
- x += sysN;
- } else {
- int fillWidth = n > sysN ? sysN : n;
- uchar *bits = bbits.scanLine(i);
- uchar *mask = mbits.scanLine(i);
- for (int j = 0; j < fillWidth; ++j) {
- uchar b = bits[j];
- uchar m = mask[j];
- if (invb)
- b ^= 0xFF;
- if (invm)
- m ^= 0xFF;
- xBits[x] = ~m;
- xMask[x] = b ^ m;
- ++x;
- }
- for (int j = fillWidth; j < sysN; ++j ) {
- xBits[x] = 255;
- xMask[x] = 0;
- ++x;
- }
- }
+ return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
+ case Qt::DragCopyCursor:
+ return QCursor(QPixmap(copyDragCursorXpmC), 0, 0);
+ case Qt::DragMoveCursor:
+ return QCursor(QPixmap(moveDragCursorXpmC), 0, 0);
+ case Qt::DragLinkCursor:
+ return QCursor(QPixmap(linkDragCursorXpmC), 0, 0);
+ }
+
+ return QCursor();
+}
+#else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
+struct QWindowsCustomPngCursor {
+ Qt::CursorShape shape;
+ int size;
+ const char *fileName;
+ int hotSpotX;
+ int hotSpotY;
+};
+
+QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+{
+ static const QWindowsCustomPngCursor pngCursors[] = {
+ { Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
+ { Qt::SplitVCursor, 48, "splitvcursor_48.png", 16, 17 },
+ { Qt::SplitVCursor, 64, "splitvcursor_64.png", 22, 22 },
+ { Qt::SplitHCursor, 32, "splithcursor_32.png", 11, 11 },
+ { Qt::SplitHCursor, 48, "splithcursor_48.png", 16, 17 },
+ { Qt::SplitHCursor, 64, "splithcursor_64.png", 22, 22 },
+ { Qt::OpenHandCursor, 32, "openhandcursor_32.png", 10, 12 },
+ { Qt::OpenHandCursor, 48, "openhandcursor_48.png", 15, 16 },
+ { Qt::OpenHandCursor, 64, "openhandcursor_64.png", 20, 24 },
+ { Qt::ClosedHandCursor, 32, "closedhandcursor_32.png", 10, 12 },
+ { Qt::ClosedHandCursor, 48, "closedhandcursor_48.png", 15, 16 },
+ { Qt::ClosedHandCursor, 64, "closedhandcursor_64.png", 20, 24 },
+ { Qt::DragCopyCursor, 32, "dragcopycursor_32.png", 0, 0 },
+ { Qt::DragCopyCursor, 48, "dragcopycursor_48.png", 0, 0 },
+ { Qt::DragCopyCursor, 64, "dragcopycursor_64.png", 0, 0 },
+ { Qt::DragMoveCursor, 32, "dragmovecursor_32.png", 0, 0 },
+ { Qt::DragMoveCursor, 48, "dragmovecursor_48.png", 0, 0 },
+ { Qt::DragMoveCursor, 64, "dragmovecursor_64.png", 0, 0 },
+ { Qt::DragLinkCursor, 32, "draglinkcursor_32.png", 0, 0 },
+ { Qt::DragLinkCursor, 48, "draglinkcursor_48.png", 0, 0 },
+ { Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 }
+ };
+
+ const int cursorSize = GetSystemMetrics(SM_CXCURSOR);
+ const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]);
+ const QWindowsCustomPngCursor *bestFit = 0;
+ int sizeDelta = INT_MAX;
+ for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) {
+ if (s->shape != cursorShape)
+ continue;
+ const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize);
+ if (currentSizeDelta < sizeDelta) {
+ bestFit = s;
+ if (currentSizeDelta == 0)
+ break; // Perfect match found
+ sizeDelta = currentSizeDelta;
}
+ }
- HCURSOR hcurs = CreateCursor(qWinAppInst(), hx, hy, sysW, sysH,
- xBits, xMask);
- delete [] xBits;
- delete [] xMask;
- return hcurs;
-#else
- Q_UNUSED(n);
- Q_UNUSED(h);
- return 0;
-#endif
+ if (!bestFit)
+ return QCursor();
+ const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") +
+ QString::fromLatin1(bestFit->fileName));
+ return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY);
+}
+#endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
+
+struct QWindowsStandardCursorMapping {
+ Qt::CursorShape shape;
+ LPCWSTR resource;
+};
+
+HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
+{
+ static const QWindowsStandardCursorMapping standardCursors[] = {
+ { Qt::ArrowCursor, IDC_ARROW},
+ { Qt::UpArrowCursor, IDC_UPARROW },
+ { Qt::CrossCursor, IDC_CROSS },
+ { Qt::WaitCursor, IDC_WAIT },
+ { Qt::IBeamCursor, IDC_IBEAM },
+ { Qt::SizeVerCursor, IDC_SIZENS },
+ { Qt::SizeHorCursor, IDC_SIZEWE },
+ { Qt::SizeBDiagCursor, IDC_SIZENESW },
+ { Qt::SizeFDiagCursor, IDC_SIZENWSE },
+ { Qt::SizeAllCursor, IDC_SIZEALL },
+ { Qt::ForbiddenCursor, IDC_NO },
+ { Qt::WhatsThisCursor, IDC_HELP },
+ { Qt::BusyCursor, IDC_APPSTARTING },
+ { Qt::PointingHandCursor, IDC_HAND }
+ };
+
+ const Qt::CursorShape cursorShape = c.shape();
+ switch (cursorShape) {
+ case Qt::BitmapCursor: {
+ const QPixmap pixmap = c.pixmap();
+ if (!pixmap.isNull())
+ return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
+ const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
+ const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
+ const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
+ const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
+ return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm);
}
+ case Qt::BlankCursor: {
+ QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
+ blank.fill(0); // ignore color table
+ return createBitmapCursor(blank, blank);
+ }
+ case Qt::SplitVCursor:
+ case Qt::SplitHCursor:
+ case Qt::OpenHandCursor:
+ case Qt::ClosedHandCursor:
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
- case Qt::DragLinkCursor: {
- const QPixmap pixmap = QGuiApplicationPrivate::instance()->getPixmapCursor(cshape);
- return createPixmapCursor(pixmap, hx, hy);
- }
+ case Qt::DragLinkCursor:
+ return createSystemCursor(customCursor(cursorShape));
default:
- qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cshape);
- return 0;
+ break;
}
-#ifdef Q_OS_WINCE
- return LoadCursor(0, sh);
+
+ // Load available standard cursors from resources
+ const QWindowsStandardCursorMapping *sEnd = standardCursors + sizeof(standardCursors) / sizeof(standardCursors[0]);
+ for (const QWindowsStandardCursorMapping *s = standardCursors; s < sEnd; ++s) {
+ if (s->shape == cursorShape) {
+#ifndef Q_OS_WINCE
+ return (HCURSOR)LoadImage(0, s->resource, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
#else
- return (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ return LoadCursor(0, s->resource);
#endif
+ }
+ }
+
+ qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cursorShape);
+ return 0;
}
/*!
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 31da4e367d..34cb668856 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -101,12 +101,13 @@ public:
QWindowsCursor() {}
- virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
- virtual QPoint pos() const { return mousePosition(); }
- virtual void setPos(const QPoint &pos);
+ void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
+ QPoint pos() const Q_DECL_OVERRIDE { return mousePosition(); }
+ void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
- static HCURSOR createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY);
+ static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot);
static HCURSOR createSystemCursor(const QCursor &c);
+ static QCursor customCursor(Qt::CursorShape cursorShape);
static QPoint mousePosition();
static CursorState cursorState();
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index bcf9f544b5..864c9e40f5 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -71,11 +71,11 @@ public:
typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
~QWindowsDialogHelperBase() { cleanupThread(); }
- virtual void exec();
+ void exec() Q_DECL_OVERRIDE;
virtual bool show(Qt::WindowFlags windowFlags,
Qt::WindowModality windowModality,
QWindow *parent);
- virtual void hide();
+ void hide() Q_DECL_OVERRIDE;
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 60c3daff23..861ddbe5b6 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -69,146 +69,6 @@
QT_BEGIN_NAMESPACE
-// These pixmaps approximate the images in the Windows User Interface Guidelines.
-// XPM
-
-static const char * const moveDragCursorXpmC[] = {
-"11 20 3 1",
-". c None",
-"a c #FFFFFF",
-"X c #000000", // X11 cursor is traditionally black
-"aa.........",
-"aXa........",
-"aXXa.......",
-"aXXXa......",
-"aXXXXa.....",
-"aXXXXXa....",
-"aXXXXXXa...",
-"aXXXXXXXa..",
-"aXXXXXXXXa.",
-"aXXXXXXXXXa",
-"aXXXXXXaaaa",
-"aXXXaXXa...",
-"aXXaaXXa...",
-"aXa..aXXa..",
-"aa...aXXa..",
-"a.....aXXa.",
-"......aXXa.",
-".......aXXa",
-".......aXXa",
-"........aa."};
-
-
-/* XPM */
-static const char * const copyDragCursorXpmC[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXaaaaaXXa",
-".............aXXXXaXXXXa",
-".............aXXXXaXXXXa",
-".............aXXXXXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-/* XPM */
-static const char * const linkDragCursorXpmC[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"XX......................",
-"XaX.....................",
-"XaaX....................",
-"XaaaX...................",
-"XaaaaX..................",
-"XaaaaaX.................",
-"XaaaaaaX................",
-"XaaaaaaaX...............",
-"XaaaaaaaaX..............",
-"XaaaaaaaaaX.............",
-"XaaaaaaXXXX.............",
-"XaaaXaaX................",
-"XaaXXaaX................",
-"XaX..XaaX...............",
-"XX...XaaX...............",
-"X.....XaaX..............",
-"......XaaX..............",
-".......XaaX.............",
-".......XaaX.............",
-"........XX...aaaaaaaaaaa",
-".............aXXXXXXXXXa",
-".............aXXXaaaaXXa",
-".............aXXXXaaaXXa",
-".............aXXXaaaaXXa",
-".............aXXaaaXaXXa",
-".............aXXaaXXXXXa",
-".............aXXaXXXXXXa",
-".............aXXXaXXXXXa",
-".............aXXXXXXXXXa",
-".............aaaaaaaaaaa"};
-
-static const char * const ignoreDragCursorXpmC[] = {
-"24 30 3 1",
-". c None",
-"a c #000000",
-"X c #FFFFFF",
-"aa......................",
-"aXa.....................",
-"aXXa....................",
-"aXXXa...................",
-"aXXXXa..................",
-"aXXXXXa.................",
-"aXXXXXXa................",
-"aXXXXXXXa...............",
-"aXXXXXXXXa..............",
-"aXXXXXXXXXa.............",
-"aXXXXXXaaaa.............",
-"aXXXaXXa................",
-"aXXaaXXa................",
-"aXa..aXXa...............",
-"aa...aXXa...............",
-"a.....aXXa..............",
-"......aXXa.....XXXX.....",
-".......aXXa..XXaaaaXX...",
-".......aXXa.XaaaaaaaaX..",
-"........aa.XaaaXXXXaaaX.",
-"...........XaaaaX..XaaX.",
-"..........XaaXaaaX..XaaX",
-"..........XaaXXaaaX.XaaX",
-"..........XaaX.XaaaXXaaX",
-"..........XaaX..XaaaXaaX",
-"...........XaaX..XaaaaX.",
-"...........XaaaXXXXaaaX.",
-"............XaaaaaaaaX..",
-".............XXaaaaXX...",
-"...............XXXX....."};
-
/*!
\class QWindowsDragCursorWindow
\brief A toplevel window showing the drag icon in case of touch drag.
@@ -490,7 +350,7 @@ void QWindowsOleDropSource::createCursors()
newHotSpot = QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y()));
}
- if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot.x(), newHotSpot.y())) {
+ if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) {
const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot);
if (it == m_cursors.end())
m_cursors.insert(action, entry);
@@ -864,22 +724,86 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
switch (action) {
case Qt::CopyAction:
if (m_copyDragCursor.isNull())
- m_copyDragCursor = QPixmap(copyDragCursorXpmC);
+ m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap();
return m_copyDragCursor;
case Qt::TargetMoveAction:
case Qt::MoveAction:
if (m_moveDragCursor.isNull())
- m_moveDragCursor = QPixmap(moveDragCursorXpmC);
+ m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap();
return m_moveDragCursor;
case Qt::LinkAction:
if (m_linkDragCursor.isNull())
- m_linkDragCursor = QPixmap(linkDragCursorXpmC);
+ m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap();
return m_linkDragCursor;
default:
break;
}
- if (m_ignoreDragCursor.isNull())
+
+ static const char * const ignoreDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "aa......................",
+ "aXa.....................",
+ "aXXa....................",
+ "aXXXa...................",
+ "aXXXXa..................",
+ "aXXXXXa.................",
+ "aXXXXXXa................",
+ "aXXXXXXXa...............",
+ "aXXXXXXXXa..............",
+ "aXXXXXXXXXa.............",
+ "aXXXXXXaaaa.............",
+ "aXXXaXXa................",
+ "aXXaaXXa................",
+ "aXa..aXXa...............",
+ "aa...aXXa...............",
+ "a.....aXXa..............",
+ "......aXXa.....XXXX.....",
+ ".......aXXa..XXaaaaXX...",
+ ".......aXXa.XaaaaaaaaX..",
+ "........aa.XaaaXXXXaaaX.",
+ "...........XaaaaX..XaaX.",
+ "..........XaaXaaaX..XaaX",
+ "..........XaaXXaaaX.XaaX",
+ "..........XaaX.XaaaXXaaX",
+ "..........XaaX..XaaaXaaX",
+ "...........XaaX..XaaaaX.",
+ "...........XaaaXXXXaaaX.",
+ "............XaaaaaaaaX..",
+ ".............XXaaaaXX...",
+ "...............XXXX....."};
+
+ if (m_ignoreDragCursor.isNull()) {
+#if !defined (Q_OS_WINCE)
+ HCURSOR cursor = LoadCursor(NULL, IDC_NO);
+ ICONINFO iconInfo = {0, 0, 0, 0, 0};
+ GetIconInfo(cursor, &iconInfo);
+ BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
+
+ if (iconInfo.hbmColor
+ && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
+ && bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
+ const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
+ uchar *colorBits = new uchar[colorBitsLength];
+ GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
+ const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
+ bmColor.bmWidthBytes, QImage::Format_ARGB32);
+
+ m_ignoreDragCursor = QPixmap::fromImage(colorImage);
+ delete [] colorBits;
+ } else {
+ m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+ }
+
+ DeleteObject(iconInfo.hbmMask);
+ DeleteObject(iconInfo.hbmColor);
+ DestroyCursor(cursor);
+#else // !Q_OS_WINCE
m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+#endif // !Q_OS_WINCE
+ }
return m_ignoreDragCursor;
}
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 4f758fbf3f..b4d303a10f 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
QWindowsDropMimeData() {}
- virtual IDataObject *retrieveDataObject() const;
+ IDataObject *retrieveDataObject() const Q_DECL_OVERRIDE;
};
class QWindowsOleDropTarget : public IDropTarget
@@ -90,9 +90,9 @@ public:
QWindowsDrag();
virtual ~QWindowsDrag();
- virtual QMimeData *platformDropData() { return &m_dropData; }
+ QMimeData *platformDropData() Q_DECL_OVERRIDE { return &m_dropData; }
- virtual Qt::DropAction drag(QDrag *drag);
+ Qt::DropAction drag(QDrag *drag) Q_DECL_OVERRIDE;
static QWindowsDrag *instance();
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index d5ca06bb3f..c62875d0ef 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -46,23 +46,297 @@
#include <QtCore/QDebug>
#include <QtGui/QOpenGLContext>
-#include <QtPlatformSupport/private/qeglconvenience_p.h>
-
QT_BEGIN_NAMESPACE
/*!
\class QWindowsEGLStaticContext
\brief Static data for QWindowsEGLContext.
- Keeps the display. The class is shared via
- QSharedPointer in the windows, the contexts
- and in QWindowsIntegration. The display will
- be closed if the last instance is deleted.
+ Keeps the display. The class is shared via QSharedPointer in the windows, the
+ contexts and in QWindowsIntegration. The display will be closed if the last instance
+ is deleted.
+
+ No EGL or OpenGL functions are called directly. Instead, they are resolved
+ dynamically. This works even if the plugin links directly to libegl/libglesv2 so
+ there is no need to differentiate between dynamic or Angle-only builds in here.
\internal
\ingroup qt-lighthouse-win
*/
+QWindowsLibEGL QWindowsEGLStaticContext::libEGL;
+QWindowsLibGLESv2 QWindowsEGLStaticContext::libGLESv2;
+
+#ifndef QT_STATIC
+
+#ifdef Q_CC_MINGW
+static void *resolveFunc(HMODULE lib, const char *name)
+{
+ QString baseNameStr = QString::fromLatin1(name);
+ QString nameStr;
+ void *proc = 0;
+
+ // Play nice with 32-bit mingw: Try func first, then func@0, func@4,
+ // func@8, func@12, ..., func@64. The def file does not provide any aliases
+ // in libEGL and libGLESv2 in these builds which results in exporting
+ // function names like eglInitialize@12. This cannot be fixed without
+ // breaking binary compatibility. So be flexible here instead.
+
+ int argSize = -1;
+ while (!proc && argSize <= 64) {
+ nameStr = baseNameStr;
+ if (argSize >= 0)
+ nameStr += QLatin1Char('@') + QString::number(argSize);
+ argSize = argSize < 0 ? 0 : argSize + 4;
+ proc = (void *) ::GetProcAddress(lib, nameStr.toLatin1().constData());
+ }
+ return proc;
+}
+#else
+static void *resolveFunc(HMODULE lib, const char *name)
+{
+# ifndef Q_OS_WINCE
+ return (void *) ::GetProcAddress(lib, name);
+# else
+ return (void *) ::GetProcAddress(lib, (const wchar_t *) QString::fromLatin1(name).utf16());
+# endif // Q_OS_WINCE
+}
+#endif // Q_CC_MINGW
+
+void *QWindowsLibEGL::resolve(const char *name)
+{
+ void *proc = m_lib ? resolveFunc(m_lib, name) : 0;
+ if (!proc)
+ qErrnoWarning(::GetLastError(), "Failed to resolve EGL function %s", name);
+
+ return proc;
+}
+
+#endif // !QT_STATIC
+
+#ifndef QT_STATIC
+# define RESOLVE(signature, name) signature(resolve( #name ));
+#else
+# define RESOLVE(signature, name) signature(&::name);
+#endif
+
+bool QWindowsLibEGL::init()
+{
+#ifdef QT_DEBUG
+ const char dllName[] = "libEGLd.dll";
+#else
+ const char dllName[] = "libEGL.dll";
+#endif
+
+ qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName;
+
+#ifndef QT_STATIC
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+#endif
+
+ eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError);
+ eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay);
+ eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize);
+ eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate);
+ eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig);
+ eglGetConfigAttrib = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLint, EGLint *)), eglGetConfigAttrib);
+ eglCreateWindowSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay, EGLConfig, EGLNativeWindowType, const EGLint *)), eglCreateWindowSurface);
+ eglCreatePbufferSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLDisplay , EGLConfig, const EGLint *)), eglCreatePbufferSurface);
+ eglDestroySurface = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface )), eglDestroySurface);
+ eglBindAPI = RESOLVE((EGLBoolean (EGLAPIENTRY * )(EGLenum )), eglBindAPI);
+ eglSwapInterval = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLint )), eglSwapInterval);
+ eglCreateContext = RESOLVE((EGLContext (EGLAPIENTRY *)(EGLDisplay , EGLConfig , EGLContext , const EGLint *)), eglCreateContext);
+ eglDestroyContext = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLContext)), eglDestroyContext);
+ eglMakeCurrent = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface , EGLSurface , EGLContext )), eglMakeCurrent);
+ eglGetCurrentContext = RESOLVE((EGLContext (EGLAPIENTRY *)(void)), eglGetCurrentContext);
+ eglGetCurrentSurface = RESOLVE((EGLSurface (EGLAPIENTRY *)(EGLint )), eglGetCurrentSurface);
+ eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
+ eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
+ eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
+
+ return eglGetError && eglGetDisplay && eglInitialize;
+}
+
+#ifndef QT_STATIC
+void *QWindowsLibGLESv2::resolve(const char *name)
+{
+ void *proc = m_lib ? resolveFunc(m_lib, name) : 0;
+ if (!proc)
+ qWarning() << "Failed to resolve OpenGL ES function" << name;
+
+ return proc;
+}
+#endif // !QT_STATIC
+
+bool QWindowsLibGLESv2::init()
+{
+#ifdef QT_DEBUG
+ const char dllName[] = "libGLESv2d.dll";
+#else
+ const char dllName[] = "libGLESv2.dll";
+#endif
+
+ qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName;
+#ifndef QT_STATIC
+ m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", dllName);
+ return false;
+ }
+#endif // !QT_STATIC
+
+ glBindTexture = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindTexture);
+ glBlendFunc = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glBlendFunc);
+ glClear = RESOLVE((void (APIENTRY *)(GLbitfield )), glClear);
+ glClearColor = RESOLVE((void (APIENTRY *)(GLfloat , GLfloat , GLfloat , GLfloat )), glClearColor);
+ glClearStencil = RESOLVE((void (APIENTRY *)(GLint )), glClearStencil);
+ glColorMask = RESOLVE((void (APIENTRY *)(GLboolean , GLboolean , GLboolean , GLboolean )), glColorMask);
+ glCopyTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLenum , GLint , GLint , GLsizei , GLsizei , GLint )), glCopyTexImage2D);
+ glCopyTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLint , GLint , GLsizei , GLsizei )), glCopyTexSubImage2D);
+ glCullFace = RESOLVE((void (APIENTRY *)(GLenum )), glCullFace);
+ glDeleteTextures = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint *)), glDeleteTextures);
+ glDepthFunc = RESOLVE((void (APIENTRY *)(GLenum )), glDepthFunc);
+ glDepthMask = RESOLVE((void (APIENTRY *)(GLboolean )), glDepthMask);
+ glDisable = RESOLVE((void (APIENTRY *)(GLenum )), glDisable);
+ glDrawArrays = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLsizei )), glDrawArrays);
+ glDrawElements = RESOLVE((void (APIENTRY *)(GLenum , GLsizei , GLenum , const GLvoid *)), glDrawElements);
+ glEnable = RESOLVE((void (APIENTRY *)(GLenum )), glEnable);
+ glFinish = RESOLVE((void (APIENTRY *)()), glFinish);
+ glFlush = RESOLVE((void (APIENTRY *)()), glFlush);
+ glFrontFace = RESOLVE((void (APIENTRY *)(GLenum )), glFrontFace);
+ glGenTextures = RESOLVE((void (APIENTRY *)(GLsizei , GLuint *)), glGenTextures);
+ glGetBooleanv = RESOLVE((void (APIENTRY *)(GLenum , GLboolean *)), glGetBooleanv);
+ glGetError = RESOLVE((GLenum (APIENTRY *)()), glGetError);
+ glGetFloatv = RESOLVE((void (APIENTRY *)(GLenum , GLfloat *)), glGetFloatv);
+ glGetIntegerv = RESOLVE((void (APIENTRY *)(GLenum , GLint *)), glGetIntegerv);
+ glGetString = RESOLVE((const GLubyte * (APIENTRY *)(GLenum )), glGetString);
+ glGetTexParameterfv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLfloat *)), glGetTexParameterfv);
+ glGetTexParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint *)), glGetTexParameteriv);
+ glHint = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glHint);
+ glIsEnabled = RESOLVE((GLboolean (APIENTRY *)(GLenum )), glIsEnabled);
+ glIsTexture = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsTexture);
+ glLineWidth = RESOLVE((void (APIENTRY *)(GLfloat )), glLineWidth);
+ glPixelStorei = RESOLVE((void (APIENTRY *)(GLenum , GLint )), glPixelStorei);
+ glPolygonOffset = RESOLVE((void (APIENTRY *)(GLfloat , GLfloat )), glPolygonOffset);
+ glReadPixels = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , GLvoid *)), glReadPixels);
+ glScissor = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )), glScissor);
+ glStencilFunc = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLuint )), glStencilFunc);
+ glStencilMask = RESOLVE((void (APIENTRY *)(GLuint )), glStencilMask);
+ glStencilOp = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum )), glStencilOp);
+ glTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)), glTexImage2D);
+ glTexParameterf = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLfloat )), glTexParameterf);
+ glTexParameterfv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , const GLfloat *)), glTexParameterfv);
+ glTexParameteri = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint )), glTexParameteri);
+ glTexParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , const GLint *)), glTexParameteriv);
+ glTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)), glTexSubImage2D);
+ glViewport = RESOLVE((void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )), glViewport);
+
+ glActiveTexture = RESOLVE((void (APIENTRY *)(GLenum)), glActiveTexture);
+ glAttachShader = RESOLVE((void (APIENTRY *)(GLuint , GLuint )), glAttachShader);
+ glBindAttribLocation = RESOLVE((void (APIENTRY *)(GLuint , GLuint , const GLchar* )), glBindAttribLocation);
+ glBindBuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindBuffer);
+ glBindFramebuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindFramebuffer);
+ glBindRenderbuffer = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glBindRenderbuffer);
+ glBlendColor = RESOLVE((void (APIENTRY *)(GLclampf , GLclampf , GLclampf , GLclampf )), glBlendColor);
+ glBlendEquation = RESOLVE((void (APIENTRY *)(GLenum )), glBlendEquation);
+ glBlendEquationSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum )), glBlendEquationSeparate);
+ glBlendFuncSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )), glBlendFuncSeparate);
+ glBufferData = RESOLVE((void (APIENTRY *)(GLenum , qopengl_GLsizeiptr , const GLvoid* , GLenum )), glBufferData);
+ glBufferSubData = RESOLVE((void (APIENTRY *)(GLenum , qopengl_GLintptr , qopengl_GLsizeiptr , const GLvoid* )), glBufferSubData);
+ glCheckFramebufferStatus = RESOLVE((GLenum (APIENTRY *)(GLenum )), glCheckFramebufferStatus);
+ glCompileShader = RESOLVE((void (APIENTRY *)(GLuint )), glCompileShader);
+ glCompressedTexImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLenum , GLsizei , GLsizei, GLint, GLsizei, const GLvoid* )), glCompressedTexImage2D);
+ glCompressedTexSubImage2D = RESOLVE((void (APIENTRY *)(GLenum , GLint , GLint , GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid* )), glCompressedTexSubImage2D);
+ glCreateProgram = RESOLVE((GLuint (APIENTRY *)(void)), glCreateProgram);
+ glCreateShader = RESOLVE((GLuint (APIENTRY *)(GLenum )), glCreateShader);
+ glDeleteBuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint*)), glDeleteBuffers);
+ glDeleteFramebuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint* )), glDeleteFramebuffers);
+ glDeleteProgram = RESOLVE((void (APIENTRY *)(GLuint )), glDeleteProgram);
+ glDeleteRenderbuffers = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint* )), glDeleteRenderbuffers);
+ glDeleteShader = RESOLVE((void (APIENTRY *)(GLuint )), glDeleteShader);
+ glDetachShader = RESOLVE((void (APIENTRY *)(GLuint , GLuint )), glDetachShader);
+ glDisableVertexAttribArray = RESOLVE((void (APIENTRY *)(GLuint )), glDisableVertexAttribArray);
+ glEnableVertexAttribArray = RESOLVE((void (APIENTRY *)(GLuint )), glEnableVertexAttribArray);
+ glFramebufferRenderbuffer = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint )), glFramebufferRenderbuffer);
+ glFramebufferTexture2D = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLuint , GLint )), glFramebufferTexture2D);
+ glGenBuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenBuffers);
+ glGenerateMipmap = RESOLVE((void (APIENTRY *)(GLenum )), glGenerateMipmap);
+ glGenFramebuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenFramebuffers);
+ glGenRenderbuffers = RESOLVE((void (APIENTRY *)(GLsizei , GLuint* )), glGenRenderbuffers);
+ glGetActiveAttrib = RESOLVE((void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )), glGetActiveAttrib);
+ glGetActiveUniform = RESOLVE((void (APIENTRY *)(GLuint , GLuint , GLsizei , GLsizei* , GLint* , GLenum* , GLchar* )), glGetActiveUniform);
+ glGetAttachedShaders = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLuint* )), glGetAttachedShaders);
+ glGetAttribLocation = RESOLVE((int (APIENTRY *)(GLuint , const GLchar* )), glGetAttribLocation);
+ glGetBufferParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* )), glGetBufferParameteriv);
+ glGetFramebufferAttachmentParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum, GLenum , GLint* )), glGetFramebufferAttachmentParameteriv);
+ glGetProgramiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetProgramiv);
+ glGetProgramInfoLog = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )), glGetProgramInfoLog);
+ glGetRenderbufferParameteriv = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* )), glGetRenderbufferParameteriv);
+ glGetShaderiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetShaderiv);
+ glGetShaderInfoLog = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei*, GLchar*)), glGetShaderInfoLog);
+ glGetShaderPrecisionFormat = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint* , GLint* )), glGetShaderPrecisionFormat);
+ glGetShaderSource = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , GLsizei* , GLchar* )), glGetShaderSource);
+ glGetUniformfv = RESOLVE((void (APIENTRY *)(GLuint , GLint , GLfloat*)), glGetUniformfv);
+ glGetUniformiv = RESOLVE((void (APIENTRY *)(GLuint , GLint , GLint*)), glGetUniformiv);
+ glGetUniformLocation = RESOLVE((int (APIENTRY *)(GLuint , const GLchar* )), glGetUniformLocation);
+ glGetVertexAttribfv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLfloat* )), glGetVertexAttribfv);
+ glGetVertexAttribiv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLint* )), glGetVertexAttribiv);
+ glGetVertexAttribPointerv = RESOLVE((void (APIENTRY *)(GLuint , GLenum , GLvoid** pointer)), glGetVertexAttribPointerv);
+ glIsBuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsBuffer);
+ glIsFramebuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsFramebuffer);
+ glIsProgram = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsProgram);
+ glIsRenderbuffer = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsRenderbuffer);
+ glIsShader = RESOLVE((GLboolean (APIENTRY *)(GLuint )), glIsShader);
+ glLinkProgram = RESOLVE((void (APIENTRY *)(GLuint )), glLinkProgram);
+ glReleaseShaderCompiler = RESOLVE((void (APIENTRY *)(void)), glReleaseShaderCompiler);
+ glRenderbufferStorage = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLsizei , GLsizei )), glRenderbufferStorage);
+ glSampleCoverage = RESOLVE((void (APIENTRY *)(GLclampf , GLboolean )), glSampleCoverage);
+ glShaderBinary = RESOLVE((void (APIENTRY *)(GLsizei , const GLuint*, GLenum , const GLvoid* , GLsizei )), glShaderBinary);
+ glShaderSource = RESOLVE((void (APIENTRY *)(GLuint , GLsizei , const GLchar* *, const GLint* )), glShaderSource);
+ glStencilFuncSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLint , GLuint )), glStencilFuncSeparate);
+ glStencilMaskSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLuint )), glStencilMaskSeparate);
+ glStencilOpSeparate = RESOLVE((void (APIENTRY *)(GLenum , GLenum , GLenum , GLenum )), glStencilOpSeparate);
+ glUniform1f = RESOLVE((void (APIENTRY *)(GLint , GLfloat )), glUniform1f);
+ glUniform1fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform1fv);
+ glUniform1i = RESOLVE((void (APIENTRY *)(GLint , GLint )), glUniform1i);
+ glUniform1iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform1iv);
+ glUniform2f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat )), glUniform2f);
+ glUniform2fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform2fv);
+ glUniform2i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint )), glUniform2i);
+ glUniform2iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform2iv);
+ glUniform3f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat )), glUniform3f);
+ glUniform3fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform3fv);
+ glUniform3i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint , GLint )), glUniform3i);
+ glUniform3iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform3iv);
+ glUniform4f = RESOLVE((void (APIENTRY *)(GLint , GLfloat , GLfloat , GLfloat , GLfloat )), glUniform4f);
+ glUniform4fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLfloat* )), glUniform4fv);
+ glUniform4i = RESOLVE((void (APIENTRY *)(GLint , GLint , GLint , GLint , GLint )), glUniform4i);
+ glUniform4iv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , const GLint* )), glUniform4iv);
+ glUniformMatrix2fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix2fv);
+ glUniformMatrix3fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix3fv);
+ glUniformMatrix4fv = RESOLVE((void (APIENTRY *)(GLint , GLsizei , GLboolean , const GLfloat* )), glUniformMatrix4fv);
+ glUseProgram = RESOLVE((void (APIENTRY *)(GLuint )), glUseProgram);
+ glValidateProgram = RESOLVE((void (APIENTRY *)(GLuint )), glValidateProgram);
+ glVertexAttrib1f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat )), glVertexAttrib1f);
+ glVertexAttrib1fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib1fv);
+ glVertexAttrib2f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat )), glVertexAttrib2f);
+ glVertexAttrib2fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib2fv);
+ glVertexAttrib3f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat )), glVertexAttrib3f);
+ glVertexAttrib3fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib3fv);
+ glVertexAttrib4f = RESOLVE((void (APIENTRY *)(GLuint , GLfloat , GLfloat , GLfloat , GLfloat )), glVertexAttrib4f);
+ glVertexAttrib4fv = RESOLVE((void (APIENTRY *)(GLuint , const GLfloat* )), glVertexAttrib4fv);
+ glVertexAttribPointer = RESOLVE((void (APIENTRY *)(GLuint , GLint, GLenum, GLboolean, GLsizei, const GLvoid* )), glVertexAttribPointer);
+
+ glClearDepthf = RESOLVE((void (APIENTRY *)(GLclampf )), glClearDepthf);
+ glDepthRangef = RESOLVE((void (APIENTRY *)(GLclampf , GLclampf )), glDepthRangef);
+
+ return glBindTexture && glCreateShader && glClearDepthf;
+}
+
QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int version)
: m_display(display), m_version(version)
{
@@ -76,7 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
return 0;
}
- EGLDisplay display = eglGetDisplay((EGLNativeDisplayType)dc);
+ if (!libEGL.init()) {
+ qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
+ return 0;
+ }
+ if (!libGLESv2.init()) {
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
+ return 0;
+ }
+
+ EGLDisplay display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
if (!display) {
qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
return 0;
@@ -84,9 +367,11 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
EGLint major;
EGLint minor;
- if (!eglInitialize(display, &major, &minor)) {
- qWarning("%s: Could not initialize egl display: error %d\n",
- Q_FUNC_INFO, eglGetError());
+ if (!libEGL.eglInitialize(display, &major, &minor)) {
+ int err = libEGL.eglGetError();
+ qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
+ if (err == 0x3001)
+ qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
return 0;
}
@@ -97,7 +382,70 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create()
QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
{
qCDebug(lcQpaGl) << __FUNCTION__ << "Releasing EGL display " << m_display;
- eglTerminate(m_display);
+ libEGL.eglTerminate(m_display);
+}
+
+QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *context)
+{
+ return new QWindowsEGLContext(this, context->format(), context->shareHandle());
+}
+
+void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig)
+{
+ EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig,
+ (EGLNativeWindowType) nativeWindow, 0);
+ if (surface == EGL_NO_SURFACE)
+ qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, libEGL.eglGetError());
+
+ return surface;
+}
+
+void QWindowsEGLStaticContext::destroyWindowSurface(void *nativeSurface)
+{
+ libEGL.eglDestroySurface(m_display, (EGLSurface) nativeSurface);
+}
+
+QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EGLConfig config,
+ const QSurfaceFormat &referenceFormat)
+{
+ QSurfaceFormat format;
+ EGLint redSize = 0;
+ EGLint greenSize = 0;
+ EGLint blueSize = 0;
+ EGLint alphaSize = 0;
+ EGLint depthSize = 0;
+ EGLint stencilSize = 0;
+ EGLint sampleCount = 0;
+
+ libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
+ libEGL.eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
+
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ format.setVersion(referenceFormat.majorVersion(), referenceFormat.minorVersion());
+ format.setProfile(referenceFormat.profile());
+ format.setOptions(referenceFormat.options());
+
+ format.setRedBufferSize(redSize);
+ format.setGreenBufferSize(greenSize);
+ format.setBlueBufferSize(blueSize);
+ format.setAlphaBufferSize(alphaSize);
+ format.setDepthBufferSize(depthSize);
+ format.setStencilBufferSize(stencilSize);
+ format.setSamples(sampleCount);
+ format.setStereo(false);
+ format.setSwapInterval(referenceFormat.swapInterval());
+
+ // Clear the EGL error state because some of the above may
+ // have errored out because the attribute is not applicable
+ // to the surface type. Such errors don't matter.
+ libEGL.eglGetError();
+
+ return format;
}
/*!
@@ -121,40 +469,465 @@ QWindowsEGLStaticContext::~QWindowsEGLStaticContext()
\ingroup qt-lighthouse-win
*/
-QWindowsEGLContext::QWindowsEGLContext(const QWindowsEGLStaticContextPtr &staticContext,
+QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share)
- : QEGLPlatformContext(format, share, staticContext->display())
- , m_staticContext(staticContext)
+ : m_staticContext(staticContext)
+ , m_eglDisplay(staticContext->display())
+ , m_api(EGL_OPENGL_ES_API)
+ , m_swapInterval(-1)
{
+ if (!m_staticContext)
+ return;
+
+ m_eglConfig = chooseConfig(format);
+ m_format = m_staticContext->formatFromConfig(m_eglDisplay, m_eglConfig, format);
+ m_shareContext = share ? static_cast<QWindowsEGLContext *>(share)->m_eglContext : 0;
+
+ QVector<EGLint> contextAttrs;
+ contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
+ contextAttrs.append(m_format.majorVersion());
+ contextAttrs.append(EGL_NONE);
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
+ if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
+ m_shareContext = 0;
+ m_eglContext = QWindowsEGLStaticContext::libEGL.eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData());
+ }
+
+ if (m_eglContext == EGL_NO_CONTEXT) {
+ qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ return;
+ }
+
+ // Make the context current to ensure the GL version query works. This needs a surface too.
+ const EGLint pbufferAttributes[] = {
+ EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ EGL_LARGEST_PBUFFER, EGL_FALSE,
+ EGL_NONE
+ };
+ EGLSurface pbuffer = QWindowsEGLStaticContext::libEGL.eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufferAttributes);
+ if (pbuffer == EGL_NO_SURFACE)
+ return;
+
+ if (QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, pbuffer, pbuffer, m_eglContext)) {
+ const GLubyte *s = QWindowsEGLStaticContext::libGLESv2.glGetString(GL_VERSION);
+ if (s) {
+ QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
+ int major, minor;
+ if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
+ m_format.setMajorVersion(major);
+ m_format.setMinorVersion(minor);
+ }
+ }
+ m_format.setProfile(QSurfaceFormat::NoProfile);
+ m_format.setOptions(QSurfaceFormat::FormatOptions());
+ QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+ QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer);
}
QWindowsEGLContext::~QWindowsEGLContext()
{
+ if (m_eglContext != EGL_NO_CONTEXT) {
+ QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
+ m_eglContext = EGL_NO_CONTEXT;
+ }
}
-bool QWindowsEGLContext::hasThreadedOpenGLCapability()
+bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
{
- return false;
+ Q_ASSERT(surface->surface()->supportsOpenGL());
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+
+ QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
+ Q_ASSERT(eglSurface);
+
+ // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation
+ if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext &&
+ QWindowsEGLStaticContext::libEGL.eglGetCurrentDisplay() == m_eglDisplay &&
+ QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_READ) == eglSurface &&
+ QWindowsEGLStaticContext::libEGL.eglGetCurrentSurface(EGL_DRAW) == eglSurface) {
+ return true;
+ }
+
+ const bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_eglContext);
+ if (ok) {
+ const int requestedSwapInterval = surface->format().swapInterval();
+ if (requestedSwapInterval >= 0 && m_swapInterval != requestedSwapInterval) {
+ m_swapInterval = requestedSwapInterval;
+ QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval);
+ }
+ } else {
+ qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+ }
+
+ return ok;
}
-EGLSurface QWindowsEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
+void QWindowsEGLContext::doneCurrent()
{
- const QWindowsWindow *window = static_cast<const QWindowsWindow *>(surface);
- return window->eglSurfaceHandle();
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (!ok)
+ qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
}
-bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
+void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
{
- bool ok = false;
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
- if (EGLSurface eglSurface = window->ensureEglSurfaceHandle(m_staticContext, eglConfig())) {
- ok = eglMakeCurrent(eglDisplay(), eglSurface, eglSurface, eglContext());
- if (!ok)
- qWarning("%s: eglMakeCurrent() failed, eglError: 0x%x, this: %p \n",
- Q_FUNC_INFO, eglGetError(), this);
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
+ Q_ASSERT(eglSurface);
+
+ bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
+ if (!ok)
+ qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
+}
+
+QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
+{
+ // We support AllGLFunctionsQueryable, which means this function must be able to
+ // return a function pointer for standard GLES2 functions too. These are not
+ // guaranteed to be queryable via eglGetProcAddress().
+ static struct StdFunc {
+ const char *name;
+ void *func;
+ } standardFuncs[] = {
+ { "glBindTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glBindTexture },
+ { "glBlendFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendFunc },
+ { "glClear", (void *) QWindowsEGLStaticContext::libGLESv2.glClear },
+ { "glClearColor", (void *) QWindowsEGLStaticContext::libGLESv2.glClearColor },
+ { "glClearStencil", (void *) QWindowsEGLStaticContext::libGLESv2.glClearStencil },
+ { "glColorMask", (void *) QWindowsEGLStaticContext::libGLESv2.glColorMask },
+ { "glCopyTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCopyTexSubImage2D },
+ { "glCullFace", (void *) QWindowsEGLStaticContext::libGLESv2.glCullFace },
+ { "glDeleteTextures", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteTextures },
+ { "glDepthFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthFunc },
+ { "glDepthMask", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthMask },
+ { "glDisable", (void *) QWindowsEGLStaticContext::libGLESv2.glDisable },
+ { "glDrawArrays", (void *) QWindowsEGLStaticContext::libGLESv2.glDrawArrays },
+ { "glDrawElements", (void *) QWindowsEGLStaticContext::libGLESv2.glDrawElements },
+ { "glEnable", (void *) QWindowsEGLStaticContext::libGLESv2.glEnable },
+ { "glFinish", (void *) QWindowsEGLStaticContext::libGLESv2.glFinish },
+ { "glFlush", (void *) QWindowsEGLStaticContext::libGLESv2.glFlush },
+ { "glFrontFace", (void *) QWindowsEGLStaticContext::libGLESv2.glFrontFace },
+ { "glGenTextures", (void *) QWindowsEGLStaticContext::libGLESv2.glGenTextures },
+ { "glGetBooleanv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetBooleanv },
+ { "glGetError", (void *) QWindowsEGLStaticContext::libGLESv2.glGetError },
+ { "glGetFloatv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetFloatv },
+ { "glGetIntegerv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetIntegerv },
+ { "glGetString", (void *) QWindowsEGLStaticContext::libGLESv2.glGetString },
+ { "glGetTexParameterfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetTexParameterfv },
+ { "glGetTexParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetTexParameteriv },
+ { "glHint", (void *) QWindowsEGLStaticContext::libGLESv2.glHint },
+ { "glIsEnabled", (void *) QWindowsEGLStaticContext::libGLESv2.glIsEnabled },
+ { "glIsTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glIsTexture },
+ { "glLineWidth", (void *) QWindowsEGLStaticContext::libGLESv2.glLineWidth },
+ { "glPixelStorei", (void *) QWindowsEGLStaticContext::libGLESv2.glPixelStorei },
+ { "glPolygonOffset", (void *) QWindowsEGLStaticContext::libGLESv2.glPolygonOffset },
+ { "glReadPixels", (void *) QWindowsEGLStaticContext::libGLESv2.glReadPixels },
+ { "glScissor", (void *) QWindowsEGLStaticContext::libGLESv2.glScissor },
+ { "glStencilFunc", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilFunc },
+ { "glStencilMask", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilMask },
+ { "glStencilOp", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilOp },
+ { "glTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glTexImage2D },
+ { "glTexParameterf", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameterf },
+ { "glTexParameterfv", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameterfv },
+ { "glTexParameteri", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameteri },
+ { "glTexParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glTexParameteriv },
+ { "glTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glTexSubImage2D },
+ { "glViewport", (void *) QWindowsEGLStaticContext::libGLESv2.glViewport },
+
+ { "glActiveTexture", (void *) QWindowsEGLStaticContext::libGLESv2.glActiveTexture },
+ { "glAttachShader", (void *) QWindowsEGLStaticContext::libGLESv2.glAttachShader },
+ { "glBindAttribLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glBindAttribLocation },
+ { "glBindBuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindBuffer },
+ { "glBindFramebuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindFramebuffer },
+ { "glBindRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glBindRenderbuffer },
+ { "glBlendColor", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendColor },
+ { "glBlendEquation", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendEquation },
+ { "glBlendEquationSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendEquationSeparate },
+ { "glBlendFuncSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glBlendFuncSeparate },
+ { "glBufferData", (void *) QWindowsEGLStaticContext::libGLESv2.glBufferData },
+ { "glBufferSubData", (void *) QWindowsEGLStaticContext::libGLESv2.glBufferSubData },
+ { "glCheckFramebufferStatus", (void *) QWindowsEGLStaticContext::libGLESv2.glCheckFramebufferStatus },
+ { "glCompileShader", (void *) QWindowsEGLStaticContext::libGLESv2.glCompileShader },
+ { "glCompressedTexImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCompressedTexImage2D },
+ { "glCompressedTexSubImage2D", (void *) QWindowsEGLStaticContext::libGLESv2.glCompressedTexSubImage2D },
+ { "glCreateProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glCreateProgram },
+ { "glCreateShader", (void *) QWindowsEGLStaticContext::libGLESv2.glCreateShader },
+ { "glDeleteBuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteBuffers },
+ { "glDeleteFramebuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteFramebuffers },
+ { "glDeleteProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteProgram },
+ { "glDeleteRenderbuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteRenderbuffers },
+ { "glDeleteShader", (void *) QWindowsEGLStaticContext::libGLESv2.glDeleteShader },
+ { "glDetachShader", (void *) QWindowsEGLStaticContext::libGLESv2.glDetachShader },
+ { "glDisableVertexAttribArray", (void *) QWindowsEGLStaticContext::libGLESv2.glDisableVertexAttribArray },
+ { "glEnableVertexAttribArray", (void *) QWindowsEGLStaticContext::libGLESv2.glEnableVertexAttribArray },
+ { "glFramebufferRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glFramebufferRenderbuffer },
+ { "glFramebufferTexture2D", (void *) QWindowsEGLStaticContext::libGLESv2.glFramebufferTexture2D },
+ { "glGenBuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenBuffers },
+ { "glGenerateMipmap", (void *) QWindowsEGLStaticContext::libGLESv2.glGenerateMipmap },
+ { "glGenFramebuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenFramebuffers },
+ { "glGenRenderbuffers", (void *) QWindowsEGLStaticContext::libGLESv2.glGenRenderbuffers },
+ { "glGetActiveAttrib", (void *) QWindowsEGLStaticContext::libGLESv2.glGetActiveAttrib },
+ { "glGetActiveUniform", (void *) QWindowsEGLStaticContext::libGLESv2.glGetActiveUniform },
+ { "glGetAttachedShaders", (void *) QWindowsEGLStaticContext::libGLESv2.glGetAttachedShaders },
+ { "glGetAttribLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glGetAttribLocation },
+ { "glGetBufferParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetBufferParameteriv },
+ { "glGetFramebufferAttachmentParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetFramebufferAttachmentParameteriv },
+ { "glGetProgramiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetProgramiv },
+ { "glGetProgramInfoLog", (void *) QWindowsEGLStaticContext::libGLESv2.glGetProgramInfoLog },
+ { "glGetRenderbufferParameteriv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetRenderbufferParameteriv },
+ { "glGetShaderiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderiv },
+ { "glGetShaderInfoLog", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderInfoLog },
+ { "glGetShaderPrecisionFormat", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderPrecisionFormat },
+ { "glGetShaderSource", (void *) QWindowsEGLStaticContext::libGLESv2.glGetShaderSource },
+ { "glGetUniformfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformfv },
+ { "glGetUniformiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformiv },
+ { "glGetUniformLocation", (void *) QWindowsEGLStaticContext::libGLESv2.glGetUniformLocation },
+ { "glGetVertexAttribfv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribfv },
+ { "glGetVertexAttribiv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribiv },
+ { "glGetVertexAttribPointerv", (void *) QWindowsEGLStaticContext::libGLESv2.glGetVertexAttribPointerv },
+ { "glIsBuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsBuffer },
+ { "glIsFramebuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsFramebuffer },
+ { "glIsProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glIsProgram },
+ { "glIsRenderbuffer", (void *) QWindowsEGLStaticContext::libGLESv2.glIsRenderbuffer },
+ { "glIsShader", (void *) QWindowsEGLStaticContext::libGLESv2.glIsShader },
+ { "glLinkProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glLinkProgram },
+ { "glReleaseShaderCompiler", (void *) QWindowsEGLStaticContext::libGLESv2.glReleaseShaderCompiler },
+ { "glRenderbufferStorage", (void *) QWindowsEGLStaticContext::libGLESv2.glRenderbufferStorage },
+ { "glSampleCoverage", (void *) QWindowsEGLStaticContext::libGLESv2.glSampleCoverage },
+ { "glShaderBinary", (void *) QWindowsEGLStaticContext::libGLESv2.glShaderBinary },
+ { "glShaderSource", (void *) QWindowsEGLStaticContext::libGLESv2.glShaderSource },
+ { "glStencilFuncSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilFuncSeparate },
+ { "glStencilMaskSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilMaskSeparate },
+ { "glStencilOpSeparate", (void *) QWindowsEGLStaticContext::libGLESv2.glStencilOpSeparate },
+ { "glUniform1f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1f },
+ { "glUniform1fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1fv },
+ { "glUniform1i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1i },
+ { "glUniform1iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform1iv },
+ { "glUniform2f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2f },
+ { "glUniform2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2fv },
+ { "glUniform2i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2i },
+ { "glUniform2iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform2iv },
+ { "glUniform3f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3f },
+ { "glUniform3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3fv },
+ { "glUniform3i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3i },
+ { "glUniform3iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform3iv },
+ { "glUniform4f", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4f },
+ { "glUniform4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4fv },
+ { "glUniform4i", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4i },
+ { "glUniform4iv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniform4iv },
+ { "glUniformMatrix2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix2fv },
+ { "glUniformMatrix3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix3fv },
+ { "glUniformMatrix4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glUniformMatrix4fv },
+ { "glUseProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glUseProgram },
+ { "glValidateProgram", (void *) QWindowsEGLStaticContext::libGLESv2.glValidateProgram },
+ { "glVertexAttrib1f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib1f },
+ { "glVertexAttrib1fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib1fv },
+ { "glVertexAttrib2f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib2f },
+ { "glVertexAttrib2fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib2fv },
+ { "glVertexAttrib3f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib3f },
+ { "glVertexAttrib3fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib3fv },
+ { "glVertexAttrib4f", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib4f },
+ { "glVertexAttrib4fv", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttrib4fv },
+ { "glVertexAttribPointer", (void *) QWindowsEGLStaticContext::libGLESv2.glVertexAttribPointer },
+
+ { "glClearDepthf", (void *) QWindowsEGLStaticContext::libGLESv2.glClearDepthf },
+ { "glDepthRangef", (void *) QWindowsEGLStaticContext::libGLESv2.glDepthRangef }
+ };
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
+ if (procName == standardFuncs[i].name)
+ return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
+
+ QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
+ QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QWindowsEGLStaticContext::libEGL.eglGetProcAddress(procName.constData()));
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaGl) << __FUNCTION__ << procName << QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() << "returns" << procAddress;
+ if (!procAddress && QWindowsContext::verbose)
+ qWarning("%s: Unable to resolve '%s'", __FUNCTION__, procName.constData());
+ return procAddress;
+}
+
+static QVector<EGLint> createConfigAttributesFromFormat(const QSurfaceFormat &format)
+{
+ int redSize = format.redBufferSize();
+ int greenSize = format.greenBufferSize();
+ int blueSize = format.blueBufferSize();
+ int alphaSize = format.alphaBufferSize();
+ int depthSize = format.depthBufferSize();
+ int stencilSize = format.stencilBufferSize();
+ int sampleCount = format.samples();
+
+ QVector<EGLint> configAttributes;
+ configAttributes.reserve(16);
+
+ configAttributes.append(EGL_RED_SIZE);
+ configAttributes.append(redSize > 0 ? redSize : 0);
+
+ configAttributes.append(EGL_GREEN_SIZE);
+ configAttributes.append(greenSize > 0 ? greenSize : 0);
+
+ configAttributes.append(EGL_BLUE_SIZE);
+ configAttributes.append(blueSize > 0 ? blueSize : 0);
+
+ configAttributes.append(EGL_ALPHA_SIZE);
+ configAttributes.append(alphaSize > 0 ? alphaSize : 0);
+
+ configAttributes.append(EGL_DEPTH_SIZE);
+ configAttributes.append(depthSize > 0 ? depthSize : 0);
+
+ configAttributes.append(EGL_STENCIL_SIZE);
+ configAttributes.append(stencilSize > 0 ? stencilSize : 0);
+
+ configAttributes.append(EGL_SAMPLES);
+ configAttributes.append(sampleCount > 0 ? sampleCount : 0);
+
+ configAttributes.append(EGL_SAMPLE_BUFFERS);
+ configAttributes.append(sampleCount > 0);
+
+ return configAttributes;
+}
+
+static bool reduceConfigAttributes(QVector<EGLint> *configAttributes)
+{
+ int i = -1;
+
+ i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
}
- return ok;
+
+ i = configAttributes->indexOf(EGL_BUFFER_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i+1) == 16) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+ }
+
+ i = configAttributes->indexOf(EGL_SAMPLES);
+ if (i >= 0) {
+ EGLint value = configAttributes->value(i+1, 0);
+ if (value > 1)
+ configAttributes->replace(i+1, qMin(EGLint(16), value / 2));
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_ALPHA_SIZE);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
+ i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA);
+ if (i >= 0) {
+ configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB);
+ configAttributes->replace(i+1,true);
+
+ }
+#endif
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_STENCIL_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i + 1) > 1)
+ configAttributes->replace(i + 1, 1);
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+
+ i = configAttributes->indexOf(EGL_DEPTH_SIZE);
+ if (i >= 0) {
+ if (configAttributes->at(i + 1) > 1)
+ configAttributes->replace(i + 1, 1);
+ else
+ configAttributes->remove(i, 2);
+ return true;
+ }
+#ifdef EGL_BIND_TO_TEXTURE_RGB
+ i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB);
+ if (i >= 0) {
+ configAttributes->remove(i,2);
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format)
+{
+ QVector<EGLint> configureAttributes = createConfigAttributesFromFormat(format);
+ configureAttributes.append(EGL_SURFACE_TYPE);
+ configureAttributes.append(EGL_WINDOW_BIT);
+ configureAttributes.append(EGL_RENDERABLE_TYPE);
+ configureAttributes.append(EGL_OPENGL_ES2_BIT);
+ configureAttributes.append(EGL_NONE);
+
+ EGLDisplay display = m_staticContext->display();
+ EGLConfig cfg = 0;
+ do {
+ // Get the number of matching configurations for this set of properties.
+ EGLint matching = 0;
+ if (!QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching)
+ continue;
+
+ // Fetch all of the matching configurations and find the
+ // first that matches the pixel format we wanted.
+ int i = configureAttributes.indexOf(EGL_RED_SIZE);
+ int confAttrRed = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_GREEN_SIZE);
+ int confAttrGreen = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_BLUE_SIZE);
+ int confAttrBlue = configureAttributes.at(i+1);
+ i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
+ int confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
+
+ QVector<EGLConfig> configs(matching);
+ QWindowsEGLStaticContext::libEGL.eglChooseConfig(display, configureAttributes.constData(), configs.data(), configs.size(), &matching);
+ if (!cfg && matching > 0)
+ cfg = configs.first();
+
+ EGLint red = 0;
+ EGLint green = 0;
+ EGLint blue = 0;
+ EGLint alpha = 0;
+ for (int i = 0; i < configs.size(); ++i) {
+ if (confAttrRed)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red);
+ if (confAttrGreen)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green);
+ if (confAttrBlue)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue);
+ if (confAttrAlpha)
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha);
+
+ if (red == confAttrRed && green == confAttrGreen
+ && blue == confAttrBlue && alpha == confAttrAlpha)
+ return configs[i];
+ }
+ } while (reduceConfigAttributes(&configureAttributes));
+
+ if (!cfg)
+ qWarning("Cannot find EGLConfig, returning null config");
+
+ return cfg;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 33653b2f2e..6c4ac08da1 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -42,20 +42,237 @@
#ifndef QWINDOWSEGLCONTEXT_H
#define QWINDOWSEGLCONTEXT_H
-#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
-#include <QSharedPointer>
+#include "qwindowsopenglcontext.h"
+#include <EGL/egl.h>
QT_BEGIN_NAMESPACE
-class QWindowsEGLStaticContext
+struct QWindowsLibEGL
+{
+ bool init();
+
+ EGLint (EGLAPIENTRY * eglGetError)(void);
+ EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id);
+ EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
+ EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy);
+ EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
+ EGLConfig *configs, EGLint config_size,
+ EGLint *num_config);
+ EGLBoolean (EGLAPIENTRY * eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
+ EGLint attribute, EGLint *value);
+ EGLSurface (EGLAPIENTRY * eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list);
+ EGLSurface (EGLAPIENTRY * eglCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list);
+ EGLBoolean (EGLAPIENTRY * eglDestroySurface)(EGLDisplay dpy, EGLSurface surface);
+ EGLBoolean (EGLAPIENTRY * eglBindAPI)(EGLenum api);
+ EGLBoolean (EGLAPIENTRY * eglSwapInterval)(EGLDisplay dpy, EGLint interval);
+ EGLContext (EGLAPIENTRY * eglCreateContext)(EGLDisplay dpy, EGLConfig config,
+ EGLContext share_context,
+ const EGLint *attrib_list);
+ EGLBoolean (EGLAPIENTRY * eglDestroyContext)(EGLDisplay dpy, EGLContext ctx);
+ EGLBoolean (EGLAPIENTRY * eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
+ EGLSurface read, EGLContext ctx);
+ EGLContext (EGLAPIENTRY * eglGetCurrentContext)(void);
+ EGLSurface (EGLAPIENTRY * eglGetCurrentSurface)(EGLint readdraw);
+ EGLDisplay (EGLAPIENTRY * eglGetCurrentDisplay)(void);
+ EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
+ __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname);
+
+private:
+#ifndef QT_STATIC
+ void *resolve(const char *name);
+ HMODULE m_lib;
+#endif
+};
+
+struct QWindowsLibGLESv2
+{
+ bool init();
+#ifndef QT_STATIC
+ void *moduleHandle() const { return m_lib; }
+#else
+ void *moduleHandle() const { return Q_NULLPTR; }
+#endif
+
+ // GL1+GLES2 common
+ void (APIENTRY * glBindTexture)(GLenum target, GLuint texture);
+ void (APIENTRY * glBlendFunc)(GLenum sfactor, GLenum dfactor);
+ void (APIENTRY * glClear)(GLbitfield mask);
+ void (APIENTRY * glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (APIENTRY * glClearStencil)(GLint s);
+ void (APIENTRY * glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void (APIENTRY * glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+ void (APIENTRY * glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glCullFace)(GLenum mode);
+ void (APIENTRY * glDeleteTextures)(GLsizei n, const GLuint* textures);
+ void (APIENTRY * glDepthFunc)(GLenum func);
+ void (APIENTRY * glDepthMask)(GLboolean flag);
+ void (APIENTRY * glDisable)(GLenum cap);
+ void (APIENTRY * glDrawArrays)(GLenum mode, GLint first, GLsizei count);
+ void (APIENTRY * glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+ void (APIENTRY * glEnable)(GLenum cap);
+ void (APIENTRY * glFinish)();
+ void (APIENTRY * glFlush)();
+ void (APIENTRY * glFrontFace)(GLenum mode);
+ void (APIENTRY * glGenTextures)(GLsizei n, GLuint* textures);
+ void (APIENTRY * glGetBooleanv)(GLenum pname, GLboolean* params);
+ GLenum (APIENTRY * glGetError)();
+ void (APIENTRY * glGetFloatv)(GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetIntegerv)(GLenum pname, GLint* params);
+ const GLubyte * (APIENTRY * glGetString)(GLenum name);
+ void (APIENTRY * glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glHint)(GLenum target, GLenum mode);
+ GLboolean (APIENTRY * glIsEnabled)(GLenum cap);
+ GLboolean (APIENTRY * glIsTexture)(GLuint texture);
+ void (APIENTRY * glLineWidth)(GLfloat width);
+ void (APIENTRY * glPixelStorei)(GLenum pname, GLint param);
+ void (APIENTRY * glPolygonOffset)(GLfloat factor, GLfloat units);
+ void (APIENTRY * glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+ void (APIENTRY * glScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glStencilFunc)(GLenum func, GLint ref, GLuint mask);
+ void (APIENTRY * glStencilMask)(GLuint mask);
+ void (APIENTRY * glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
+ void (APIENTRY * glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+ void (APIENTRY * glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params);
+ void (APIENTRY * glTexParameteri)(GLenum target, GLenum pname, GLint param);
+ void (APIENTRY * glTexParameteriv)(GLenum target, GLenum pname, const GLint* params);
+ void (APIENTRY * glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ // GLES2
+ void (APIENTRY * glActiveTexture)(GLenum texture);
+ void (APIENTRY * glAttachShader)(GLuint program, GLuint shader);
+ void (APIENTRY * glBindAttribLocation)(GLuint program, GLuint index, const char* name);
+ void (APIENTRY * glBindBuffer)(GLenum target, GLuint buffer);
+ void (APIENTRY * glBindFramebuffer)(GLenum target, GLuint framebuffer);
+ void (APIENTRY * glBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+ void (APIENTRY * glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (APIENTRY * glBlendEquation)(GLenum mode);
+ void (APIENTRY * glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha);
+ void (APIENTRY * glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ void (APIENTRY * glBufferData)(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage);
+ void (APIENTRY * glBufferSubData)(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data);
+ GLenum (APIENTRY * glCheckFramebufferStatus)(GLenum target);
+ void (APIENTRY * glCompileShader)(GLuint shader);
+ void (APIENTRY * glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+ void (APIENTRY * glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+ GLuint (APIENTRY * glCreateProgram)();
+ GLuint (APIENTRY * glCreateShader)(GLenum type);
+ void (APIENTRY * glDeleteBuffers)(GLsizei n, const GLuint* buffers);
+ void (APIENTRY * glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers);
+ void (APIENTRY * glDeleteProgram)(GLuint program);
+ void (APIENTRY * glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers);
+ void (APIENTRY * glDeleteShader)(GLuint shader);
+ void (APIENTRY * glDetachShader)(GLuint program, GLuint shader);
+ void (APIENTRY * glDisableVertexAttribArray)(GLuint index);
+ void (APIENTRY * glEnableVertexAttribArray)(GLuint index);
+ void (APIENTRY * glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+ void (APIENTRY * glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+ void (APIENTRY * glGenBuffers)(GLsizei n, GLuint* buffers);
+ void (APIENTRY * glGenerateMipmap)(GLenum target);
+ void (APIENTRY * glGenFramebuffers)(GLsizei n, GLuint* framebuffers);
+ void (APIENTRY * glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers);
+ void (APIENTRY * glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+ void (APIENTRY * glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+ void (APIENTRY * glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+ GLint (APIENTRY * glGetAttribLocation)(GLuint program, const char* name);
+ void (APIENTRY * glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+ void (APIENTRY * glGetProgramiv)(GLuint program, GLenum pname, GLint* params);
+ void (APIENTRY * glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+ void (APIENTRY * glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glGetShaderiv)(GLuint shader, GLenum pname, GLint* params);
+ void (APIENTRY * glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+ void (APIENTRY * glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+ void (APIENTRY * glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+ void (APIENTRY * glGetUniformfv)(GLuint program, GLint location, GLfloat* params);
+ void (APIENTRY * glGetUniformiv)(GLuint program, GLint location, GLint* params);
+ GLint (APIENTRY * glGetUniformLocation)(GLuint program, const char* name);
+ void (APIENTRY * glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params);
+ void (APIENTRY * glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer);
+ GLboolean (APIENTRY * glIsBuffer)(GLuint buffer);
+ GLboolean (APIENTRY * glIsFramebuffer)(GLuint framebuffer);
+ GLboolean (APIENTRY * glIsProgram)(GLuint program);
+ GLboolean (APIENTRY * glIsRenderbuffer)(GLuint renderbuffer);
+ GLboolean (APIENTRY * glIsShader)(GLuint shader);
+ void (APIENTRY * glLinkProgram)(GLuint program);
+ void (APIENTRY * glReleaseShaderCompiler)();
+ void (APIENTRY * glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+ void (APIENTRY * glSampleCoverage)(GLclampf value, GLboolean invert);
+ void (APIENTRY * glShaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
+ void (APIENTRY * glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length);
+ void (APIENTRY * glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask);
+ void (APIENTRY * glStencilMaskSeparate)(GLenum face, GLuint mask);
+ void (APIENTRY * glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+ void (APIENTRY * glUniform1f)(GLint location, GLfloat x);
+ void (APIENTRY * glUniform1fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform1i)(GLint location, GLint x);
+ void (APIENTRY * glUniform1iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniform2f)(GLint location, GLfloat x, GLfloat y);
+ void (APIENTRY * glUniform2fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform2i)(GLint location, GLint x, GLint y);
+ void (APIENTRY * glUniform2iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z);
+ void (APIENTRY * glUniform3fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform3i)(GLint location, GLint x, GLint y, GLint z);
+ void (APIENTRY * glUniform3iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void (APIENTRY * glUniform4fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (APIENTRY * glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w);
+ void (APIENTRY * glUniform4iv)(GLint location, GLsizei count, const GLint* v);
+ void (APIENTRY * glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (APIENTRY * glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (APIENTRY * glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (APIENTRY * glUseProgram)(GLuint program);
+ void (APIENTRY * glValidateProgram)(GLuint program);
+ void (APIENTRY * glVertexAttrib1f)(GLuint indx, GLfloat x);
+ void (APIENTRY * glVertexAttrib1fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y);
+ void (APIENTRY * glVertexAttrib2fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+ void (APIENTRY * glVertexAttrib3fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void (APIENTRY * glVertexAttrib4fv)(GLuint indx, const GLfloat* values);
+ void (APIENTRY * glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+
+ // ES only
+ void (APIENTRY * glClearDepthf)(GLclampf depth);
+ void (APIENTRY * glDepthRangef)(GLclampf nearVal, GLclampf farVal);
+
+private:
+#ifndef QT_STATIC
+ void *resolve(const char *name);
+ HMODULE m_lib;
+#endif
+};
+
+class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
{
Q_DISABLE_COPY(QWindowsEGLStaticContext)
+
public:
static QWindowsEGLStaticContext *create();
~QWindowsEGLStaticContext();
EGLDisplay display() const { return m_display; }
+ QWindowsOpenGLContext *createContext(QOpenGLContext *context);
+ void *moduleHandle() const { return libGLESv2.moduleHandle(); }
+ QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGLES; }
+
+ void *createWindowSurface(void *nativeWindow, void *nativeConfig) Q_DECL_OVERRIDE;
+ void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE;
+
+ QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat);
+
+ static QWindowsLibEGL libEGL;
+ static QWindowsLibGLESv2 libGLESv2;
+
private:
QWindowsEGLStaticContext(EGLDisplay display, int version);
@@ -63,26 +280,38 @@ private:
const int m_version; //! majorVersion<<8 + minorVersion
};
-class QWindowsEGLContext : public QEGLPlatformContext
+class QWindowsEGLContext : public QWindowsOpenGLContext
{
public:
- typedef QSharedPointer<QWindowsEGLStaticContext> QWindowsEGLStaticContextPtr;
-
- QWindowsEGLContext(const QWindowsEGLStaticContextPtr& staticContext,
+ QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share);
-
~QWindowsEGLContext();
- static bool hasThreadedOpenGLCapability();
+ bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void doneCurrent() Q_DECL_OVERRIDE;
+ void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
- bool makeCurrent(QPlatformSurface *surface);
+ QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
+ bool isSharing() const Q_DECL_OVERRIDE { return m_shareContext != EGL_NO_CONTEXT; }
+ bool isValid() const Q_DECL_OVERRIDE { return m_eglContext != EGL_NO_CONTEXT; }
-protected:
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface);
+ void *nativeContext() const Q_DECL_OVERRIDE { return m_eglContext; }
+ void *nativeDisplay() const Q_DECL_OVERRIDE { return m_eglDisplay; }
+ void *nativeConfig() const Q_DECL_OVERRIDE { return m_eglConfig; }
private:
- const QWindowsEGLStaticContextPtr m_staticContext;
+ EGLConfig chooseConfig(const QSurfaceFormat &format);
+
+ QWindowsEGLStaticContext *m_staticContext;
+ EGLContext m_eglContext;
+ EGLContext m_shareContext;
+ EGLDisplay m_eglDisplay;
+ EGLConfig m_eglConfig;
+ QSurfaceFormat m_format;
+ EGLenum m_api;
+ int m_swapInterval;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 696dc06cee..b22c35137d 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -164,25 +164,24 @@ namespace {
{
Q_ASSERT(tagName.size() == 4);
quint32 tagId = *(reinterpret_cast<const quint32 *>(tagName.constData()));
- if (Q_UNLIKELY(m_fontData.size() < sizeof(OffsetSubTable)))
+ const size_t fontDataSize = m_fontData.size();
+ if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable)))
return 0;
OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data());
TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1);
- quint16 tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables);
- if (Q_UNLIKELY(quint32(m_fontData.size()) < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount))
+ const size_t tableCount = qFromBigEndian<quint16>(offsetSubTable->numTables);
+ if (Q_UNLIKELY(fontDataSize < sizeof(OffsetSubTable) + sizeof(TableDirectory) * tableCount))
return 0;
- TableDirectory *nameTableDirectoryEntry = 0;
- for (int i = 0; i < tableCount; ++i, ++tableDirectory) {
- if (tableDirectory->identifier == tagId) {
- nameTableDirectoryEntry = tableDirectory;
- break;
- }
+ TableDirectory *tableDirectoryEnd = tableDirectory + tableCount;
+ for (TableDirectory *entry = tableDirectory; entry < tableDirectoryEnd; ++entry) {
+ if (entry->identifier == tagId)
+ return entry;
}
- return nameTableDirectoryEntry;
+ return 0;
}
QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry)
@@ -1064,7 +1063,7 @@ QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine,
if (script == QChar::Script_Common)
return new QWindowsMultiFontEngine(fontEngine, script);
// ### as long as fallbacksForFamily() does not take script parameter into account,
- // prefer QFontEngineMultiQPA's loadEngine() implementation for complex scripts
+ // prefer QFontEngineMultiBasicImpl's loadEngine() implementation for complex scripts
return QPlatformFontDatabase::fontEngineMulti(fontEngine, script);
}
@@ -1521,13 +1520,15 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request)
#endif
if (request.styleStrategy & QFont::PreferAntialias) {
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) {
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && !(request.styleStrategy & QFont::NoSubpixelAntialias)) {
qual = CLEARTYPE_QUALITY;
} else {
qual = ANTIALIASED_QUALITY;
}
} else if (request.styleStrategy & QFont::NoAntialias) {
qual = NONANTIALIASED_QUALITY;
+ } else if ((request.styleStrategy & QFont::NoSubpixelAntialias) && sharedFontData()->clearTypeEnabled) {
+ qual = ANTIALIASED_QUALITY;
}
lf.lfQuality = qual;
@@ -1613,37 +1614,36 @@ QStringList QWindowsFontDatabase::extraTryFontsForFamily(const QString &family)
return result;
}
+QString QWindowsFontDatabase::familyForStyleHint(QFont::StyleHint styleHint)
+{
+ switch (styleHint) {
+ case QFont::Times:
+ return QStringLiteral("Times New Roman");
+ case QFont::Courier:
+ return QStringLiteral("Courier New");
+ case QFont::Monospace:
+ return QStringLiteral("Courier New");
+ case QFont::Cursive:
+ return QStringLiteral("Comic Sans MS");
+ case QFont::Fantasy:
+ return QStringLiteral("Impact");
+ case QFont::Decorative:
+ return QStringLiteral("Old English");
+ case QFont::Helvetica:
+ return QStringLiteral("Arial");
+ case QFont::System:
+ default:
+ break;
+ }
+ return QStringLiteral("MS Shell Dlg 2");
+}
+
QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script);
if (!result.isEmpty())
return result;
-
- switch (styleHint) {
- case QFont::Times:
- result << QString::fromLatin1("Times New Roman");
- break;
- case QFont::Courier:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Monospace:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Cursive:
- result << QString::fromLatin1("Comic Sans MS");
- break;
- case QFont::Fantasy:
- result << QString::fromLatin1("Impact");
- break;
- case QFont::Decorative:
- result << QString::fromLatin1("Old English");
- break;
- case QFont::Helvetica:
- case QFont::System:
- default:
- result << QString::fromLatin1("Arial");
- }
-
+ result.append(QWindowsFontDatabase::familyForStyleHint(styleHint));
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index a2324544d2..1ef346a430 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -77,17 +77,17 @@ public:
QWindowsFontDatabase();
~QWindowsFontDatabase();
- virtual void populateFontDatabase();
- virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
- virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
- virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
- virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
- virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
- virtual void releaseHandle(void *handle);
- virtual QString fontDir() const;
-
- virtual QFont defaultFont() const { return systemDefaultFont(); }
- virtual bool fontsAlwaysScalable() const;
+ void populateFontDatabase() Q_DECL_OVERRIDE;
+ QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) Q_DECL_OVERRIDE;
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE;
+ QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE;
+ QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) Q_DECL_OVERRIDE;
+ void releaseHandle(void *handle) Q_DECL_OVERRIDE;
+ QString fontDir() const Q_DECL_OVERRIDE;
+
+ QFont defaultFont() const Q_DECL_OVERRIDE { return systemDefaultFont(); }
+ bool fontsAlwaysScalable() const Q_DECL_OVERRIDE;
void derefUniqueFont(const QString &uniqueFont);
void refUniqueFont(const QString &uniqueFont);
@@ -104,6 +104,7 @@ public:
static LOGFONT fontDefToLOGFONT(const QFontDef &fontDef);
static QStringList extraTryFontsForFamily(const QString &family);
+ static QString familyForStyleHint(QFont::StyleHint styleHint);
private:
void populate(const QString &family = QString());
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 734f645e65..2f038106de 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -442,30 +442,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
if (!result.isEmpty())
return result;
- switch (styleHint) {
- case QFont::Times:
- result << QString::fromLatin1("Times New Roman");
- break;
- case QFont::Courier:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Monospace:
- result << QString::fromLatin1("Courier New");
- break;
- case QFont::Cursive:
- result << QString::fromLatin1("Comic Sans MS");
- break;
- case QFont::Fantasy:
- result << QString::fromLatin1("Impact");
- break;
- case QFont::Decorative:
- result << QString::fromLatin1("Old English");
- break;
- case QFont::Helvetica:
- case QFont::System:
- default:
- result << QString::fromLatin1("Arial");
- }
+ result.append(QWindowsFontDatabase::familyForStyleHint(styleHint));
#ifdef Q_OS_WINCE
QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\FontLink\\SystemLink"), QSettings::NativeFormat);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index bad6c54bf4..cf6108d87a 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -57,8 +57,8 @@ public:
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
- virtual QString fontDir() const;
- virtual QFont defaultFont() const;
+ QString fontDir() const Q_DECL_OVERRIDE;
+ QFont defaultFont() const Q_DECL_OVERRIDE;
private:
void populate(const QString &family = QString());
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 6f97c8584b..d3cbea0b92 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -111,11 +111,6 @@ static void resolveGetCharWidthI()
ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QStringLiteral("gdi32"), "GetCharWidthI");
}
-// defined in qtextengine_win.cpp
-typedef void *SCRIPT_CACHE;
-typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *);
-extern fScriptFreeCache ScriptFreeCache;
-
static inline quint32 getUInt(unsigned char *p)
{
quint32 val;
@@ -1300,7 +1295,7 @@ void QWindowsFontEngine::initFontInfo(const QFontDef &request,
Will probably be superseded by a common Free Type font engine in Qt 5.X.
*/
QWindowsMultiFontEngine::QWindowsMultiFontEngine(QFontEngine *fe, int script)
- : QFontEngineMultiQPA(fe, script)
+ : QFontEngineMultiBasicImpl(fe, script)
{
}
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h
index 0ddf778fa0..8fe063121a 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.h
+++ b/src/plugins/platforms/windows/qwindowsfontengine.h
@@ -53,7 +53,7 @@
// We mean it.
//
-#include <QtGui/private/qfontengine_qpa_p.h>
+#include <QtGui/private/qfontengine_p.h>
#include <QtGui/QImage>
#include <QtCore/QSharedPointer>
@@ -78,48 +78,48 @@ public:
void initFontInfo(const QFontDef &request,
HDC fontHdc, int dpi);
- virtual QFixed lineThickness() const;
- virtual Properties properties() const;
- virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
- virtual FaceId faceId() const;
- virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
- virtual int synthesized() const;
- virtual QFixed emSquareSize() const;
+ QFixed lineThickness() const Q_DECL_OVERRIDE;
+ Properties properties() const Q_DECL_OVERRIDE;
+ void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) Q_DECL_OVERRIDE;
+ FaceId faceId() const Q_DECL_OVERRIDE;
+ bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE;
+ int synthesized() const Q_DECL_OVERRIDE;
+ QFixed emSquareSize() const Q_DECL_OVERRIDE;
- virtual glyph_t glyphIndex(uint ucs4) const;
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
- virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;
+ glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
+ void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const Q_DECL_OVERRIDE;
- virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags);
+ void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
HGDIOBJ selectDesignFont() const;
- virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
- virtual glyph_metrics_t boundingBox(glyph_t g) { return boundingBox(g, QTransform()); }
- virtual glyph_metrics_t boundingBox(glyph_t g, const QTransform &t);
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
+ glyph_metrics_t boundingBox(glyph_t g) Q_DECL_OVERRIDE { return boundingBox(g, QTransform()); }
+ glyph_metrics_t boundingBox(glyph_t g, const QTransform &t) Q_DECL_OVERRIDE;
- virtual QFixed ascent() const;
- virtual QFixed descent() const;
- virtual QFixed leading() const;
- virtual QFixed xHeight() const;
- virtual QFixed averageCharWidth() const;
- virtual qreal maxCharWidth() const;
- virtual qreal minLeftBearing() const;
- virtual qreal minRightBearing() const;
+ QFixed ascent() const Q_DECL_OVERRIDE;
+ QFixed descent() const Q_DECL_OVERRIDE;
+ QFixed leading() const Q_DECL_OVERRIDE;
+ QFixed xHeight() const Q_DECL_OVERRIDE;
+ QFixed averageCharWidth() const Q_DECL_OVERRIDE;
+ qreal maxCharWidth() const Q_DECL_OVERRIDE;
+ qreal minLeftBearing() const Q_DECL_OVERRIDE;
+ qreal minRightBearing() const Q_DECL_OVERRIDE;
- virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); }
- virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
- virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform);
- virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat);
+ QImage alphaMapForGlyph(glyph_t t) Q_DECL_OVERRIDE { return alphaMapForGlyph(t, QTransform()); }
+ QImage alphaMapForGlyph(glyph_t, const QTransform &xform) Q_DECL_OVERRIDE;
+ QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE;
- virtual QFontEngine *cloneWithSize(qreal pixelSize) const;
- virtual bool supportsTransformation(const QTransform &transform) const;
+ QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
+ bool supportsTransformation(const QTransform &transform) const Q_DECL_OVERRIDE;
#ifndef Q_CC_MINGW
- virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+ void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0) Q_DECL_OVERRIDE;
#endif
bool hasUnreliableGlyphOutline() const Q_DECL_OVERRIDE;
@@ -172,7 +172,7 @@ private:
};
-class QWindowsMultiFontEngine : public QFontEngineMultiQPA
+class QWindowsMultiFontEngine : public QFontEngineMultiBasicImpl
{
public:
explicit QWindowsMultiFontEngine(QFontEngine *fe, int script);
diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
index 2da014ddc3..9ee074b33e 100644
--- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
+++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h
@@ -74,7 +74,7 @@ public:
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
QFixed emSquareSize() const;
- virtual glyph_t glyphIndex(uint ucs4) const;
+ glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const;
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index eaa4eca84e..e09018ef69 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -48,6 +48,7 @@
#include <QtCore/QSysInfo>
#include <QtGui/QGuiApplication>
#include <qpa/qplatformnativeinterface.h>
+#include <QtPlatformHeaders/QWGLNativeContext>
#include <algorithm>
@@ -144,6 +145,131 @@
QT_BEGIN_NAMESPACE
+QWindowsOpengl32DLL QOpenGLStaticContext::opengl32;
+
+void *QWindowsOpengl32DLL::resolve(const char *name)
+{
+#ifndef Q_OS_WINCE
+ void *proc = m_lib ? (void *) ::GetProcAddress(m_lib, name) : 0;
+#else
+ void *proc = m_lib ? (void *) ::GetProcAddress(m_lib, (const wchar_t *) QString::fromLatin1(name).utf16()) : 0;
+#endif
+ if (!proc)
+ qErrnoWarning(::GetLastError(), "Failed to resolve OpenGL function %s", name);
+
+ return proc;
+}
+
+bool QWindowsOpengl32DLL::init(bool softwareRendering)
+{
+ const QByteArray opengl32 = QByteArrayLiteral("opengl32.dll");
+ const QByteArray swopengl = QByteArrayLiteral("QtSoftwareOpenGL.dll");
+
+ QByteArray openglDll = qgetenv("QT_OPENGL_DLL");
+ if (openglDll.isEmpty())
+ openglDll = softwareRendering ? swopengl : opengl32;
+
+ openglDll = openglDll.toLower();
+ m_nonOpengl32 = openglDll != opengl32;
+
+ qCDebug(lcQpaGl) << "Qt: Using WGL and OpenGL from" << openglDll;
+
+ m_lib = ::LoadLibraryA(openglDll.constData());
+ if (!m_lib) {
+ qErrnoWarning(::GetLastError(), "Failed to load %s", openglDll.constData());
+ return false;
+ }
+
+ if (moduleIsNotOpengl32()) {
+ // Load opengl32.dll always. GDI functions like ChoosePixelFormat do
+ // GetModuleHandle for opengl32.dll and behave differently (and call back into
+ // opengl32) when the module is present. This is fine for dummy contexts and windows.
+ ::LoadLibraryA("opengl32.dll");
+ }
+
+ wglCreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(resolve("wglCreateContext"));
+ wglDeleteContext = reinterpret_cast<BOOL (WINAPI *)(HGLRC)>(resolve("wglDeleteContext"));
+ wglGetCurrentContext = reinterpret_cast<HGLRC (WINAPI *)()>(resolve("wglGetCurrentContext"));
+ wglGetCurrentDC = reinterpret_cast<HDC (WINAPI *)()>(resolve("wglGetCurrentDC"));
+ wglGetProcAddress = reinterpret_cast<PROC (WINAPI *)(LPCSTR)>(resolve("wglGetProcAddress"));
+ wglMakeCurrent = reinterpret_cast<BOOL (WINAPI *)(HDC, HGLRC)>(resolve("wglMakeCurrent"));
+ wglShareLists = reinterpret_cast<BOOL (WINAPI *)(HGLRC, HGLRC)>(resolve("wglShareLists"));
+ wglSwapBuffers = reinterpret_cast<BOOL (WINAPI *)(HDC)>(resolve("wglSwapBuffers"));
+ wglSetPixelFormat = reinterpret_cast<BOOL (WINAPI *)(HDC, int, const PIXELFORMATDESCRIPTOR *)>(resolve("wglSetPixelFormat"));
+
+ glBindTexture = reinterpret_cast<void (APIENTRY *)(GLenum , GLuint )>(resolve("glBindTexture"));
+ glBlendFunc = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glBlendFunc"));
+ glClear = reinterpret_cast<void (APIENTRY *)(GLbitfield )>(resolve("glClear"));
+ glClearColor = reinterpret_cast<void (APIENTRY *)(GLfloat , GLfloat , GLfloat , GLfloat )>(resolve("glClearColor"));
+ glClearStencil = reinterpret_cast<void (APIENTRY *)(GLint )>(resolve("glClearStencil"));
+ glColorMask = reinterpret_cast<void (APIENTRY *)(GLboolean , GLboolean , GLboolean , GLboolean )>(resolve("glColorMask"));
+ glCopyTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLenum , GLint , GLint , GLsizei , GLsizei , GLint )>(resolve("glCopyTexImage2D"));
+ glCopyTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLint , GLint , GLsizei , GLsizei )>(resolve("glCopyTexSubImage2D"));
+ glCullFace = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glCullFace"));
+ glDeleteTextures = reinterpret_cast<void (APIENTRY *)(GLsizei , const GLuint *)>(resolve("glDeleteTextures"));
+ glDepthFunc = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glDepthFunc"));
+ glDepthMask = reinterpret_cast<void (APIENTRY *)(GLboolean )>(resolve("glDepthMask"));
+ glDisable = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glDisable"));
+ glDrawArrays = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLsizei )>(resolve("glDrawArrays"));
+ glDrawElements = reinterpret_cast<void (APIENTRY *)(GLenum , GLsizei , GLenum , const GLvoid *)>(resolve("glDrawElements"));
+ glEnable = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glEnable"));
+ glFinish = reinterpret_cast<void (APIENTRY *)()>(resolve("glFinish"));
+ glFlush = reinterpret_cast<void (APIENTRY *)()>(resolve("glFlush"));
+ glFrontFace = reinterpret_cast<void (APIENTRY *)(GLenum )>(resolve("glFrontFace"));
+ glGenTextures = reinterpret_cast<void (APIENTRY *)(GLsizei , GLuint *)>(resolve("glGenTextures"));
+ glGetBooleanv = reinterpret_cast<void (APIENTRY *)(GLenum , GLboolean *)>(resolve("glGetBooleanv"));
+ glGetError = reinterpret_cast<GLenum (APIENTRY *)()>(resolve("glGetError"));
+ glGetFloatv = reinterpret_cast<void (APIENTRY *)(GLenum , GLfloat *)>(resolve("glGetFloatv"));
+ glGetIntegerv = reinterpret_cast<void (APIENTRY *)(GLenum , GLint *)>(resolve("glGetIntegerv"));
+ glGetString = reinterpret_cast<const GLubyte * (APIENTRY *)(GLenum )>(resolve("glGetString"));
+ glGetTexParameterfv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLfloat *)>(resolve("glGetTexParameterfv"));
+ glGetTexParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint *)>(resolve("glGetTexParameteriv"));
+ glHint = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum )>(resolve("glHint"));
+ glIsEnabled = reinterpret_cast<GLboolean (APIENTRY *)(GLenum )>(resolve("glIsEnabled"));
+ glIsTexture = reinterpret_cast<GLboolean (APIENTRY *)(GLuint )>(resolve("glIsTexture"));
+ glLineWidth = reinterpret_cast<void (APIENTRY *)(GLfloat )>(resolve("glLineWidth"));
+ glPixelStorei = reinterpret_cast<void (APIENTRY *)(GLenum , GLint )>(resolve("glPixelStorei"));
+ glPolygonOffset = reinterpret_cast<void (APIENTRY *)(GLfloat , GLfloat )>(resolve("glPolygonOffset"));
+ glReadPixels = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , GLvoid *)>(resolve("glReadPixels"));
+ glScissor = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )>(resolve("glScissor"));
+ glStencilFunc = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLuint )>(resolve("glStencilFunc"));
+ glStencilMask = reinterpret_cast<void (APIENTRY *)(GLuint )>(resolve("glStencilMask"));
+ glStencilOp = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLenum )>(resolve("glStencilOp"));
+ glTexImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(resolve("glTexImage2D"));
+ glTexParameterf = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLfloat )>(resolve("glTexParameterf"));
+ glTexParameterfv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , const GLfloat *)>(resolve("glTexParameterfv"));
+ glTexParameteri = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , GLint )>(resolve("glTexParameteri"));
+ glTexParameteriv = reinterpret_cast<void (APIENTRY *)(GLenum , GLenum , const GLint *)>(resolve("glTexParameteriv"));
+ glTexSubImage2D = reinterpret_cast<void (APIENTRY *)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(resolve("glTexSubImage2D"));
+ glViewport = reinterpret_cast<void (APIENTRY *)(GLint , GLint , GLsizei , GLsizei )>(resolve("glViewport"));
+
+ glClearDepth = reinterpret_cast<void (APIENTRY *)(GLdouble )>(resolve("glClearDepth"));
+ glDepthRange = reinterpret_cast<void (APIENTRY *)(GLdouble , GLdouble )>(resolve("glDepthRange"));
+
+ return wglCreateContext && glBindTexture && glClearDepth;
+}
+
+BOOL QWindowsOpengl32DLL::swapBuffers(HDC dc)
+{
+ if (moduleIsNotOpengl32())
+ return wglSwapBuffers(dc);
+ else
+ return SwapBuffers(dc);
+}
+
+BOOL QWindowsOpengl32DLL::setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd)
+{
+ if (moduleIsNotOpengl32())
+ return wglSetPixelFormat(dc, pf, pfd);
+ else
+ return SetPixelFormat(dc, pf, pfd);
+}
+
+QWindowsOpenGLContext *QOpenGLStaticContext::createContext(QOpenGLContext *context)
+{
+ return new QWindowsGLContext(this, context);
+}
+
template <class MaskType, class FlagType> inline bool testFlag(MaskType mask, FlagType flag)
{
return (mask & MaskType(flag)) != 0;
@@ -210,10 +336,11 @@ static inline bool
bool ignoreGLSupport = false) // ARB format may not contain it.
{
const bool pixmapRequested = testFlag(additional.formatFlags, QWindowsGLRenderToPixmap);
- return (ignoreGLSupport || testFlag(pfd.dwFlags, PFD_SUPPORT_OPENGL))
- && testFlag(pfd.dwFlags, PFD_DRAW_TO_BITMAP) == pixmapRequested
- && hasGLOverlay(pfd) == testFlag(additional.formatFlags, QWindowsGLOverlay)
- && (!pixmapRequested || pfd.cColorBits == additional.pixmapDepth);
+ const bool pixmapOk = !pixmapRequested || testFlag(pfd.dwFlags, PFD_DRAW_TO_BITMAP);
+ const bool colorOk = !pixmapRequested || pfd.cColorBits == additional.pixmapDepth;
+ const bool glOk = ignoreGLSupport || testFlag(pfd.dwFlags, PFD_SUPPORT_OPENGL);
+ const bool overlayOk = hasGLOverlay(pfd) == testFlag(additional.formatFlags, QWindowsGLOverlay);
+ return pixmapOk && glOk && overlayOk && colorOk;
}
static void describeFormats(HDC hdc)
@@ -299,10 +426,23 @@ static PIXELFORMATDESCRIPTOR
// over the available formats to find the best one.
// Note: As of Windows 7, it seems direct-rendering is handled, so,
// the code might be obsolete?
+//
+// NB! When using an implementation with a name different than opengl32.dll
+// this code path should not be used since it will result in a mess due to GDI
+// relying on and possibly calling back into functions in opengl32.dll (and not
+// the one we are using). This is not a problem usually since for Mesa, which
+// we are most likely to ship with a name other than opengl32.dll, the ARB code
+// path should work. Hence the early bail out below.
+//
static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format,
const QWindowsOpenGLAdditionalFormat &additional,
PIXELFORMATDESCRIPTOR *obtainedPfd)
{
+ if (QOpenGLStaticContext::opengl32.moduleIsNotOpengl32()) {
+ qWarning("%s: Attempted to use GDI functions with a non-opengl32.dll library", Q_FUNC_INFO);
+ return 0;
+ }
+
// 1) Try ChoosePixelFormat().
PIXELFORMATDESCRIPTOR requestedPfd = qPixelFormatFromSurfaceFormat(format, QWindowsGLDirectRendering);
initPixelFormatDescriptor(obtainedPfd);
@@ -352,12 +492,12 @@ static int choosePixelFormat(HDC hdc, const QSurfaceFormat &format,
static inline HGLRC createContext(HDC hdc, HGLRC shared)
{
- HGLRC result = wglCreateContext(hdc);
+ HGLRC result = QOpenGLStaticContext::opengl32.wglCreateContext(hdc);
if (!result) {
qErrnoWarning("%s: wglCreateContext failed.", __FUNCTION__);
return 0;
}
- if (shared && !wglShareLists(shared, result))
+ if (shared && !QOpenGLStaticContext::opengl32.wglShareLists(shared, result))
qErrnoWarning("%s: wglShareLists() failed.", __FUNCTION__);
return result;
}
@@ -623,7 +763,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext,
if (!result) {
QString message;
QDebug(&message).nospace() << __FUNCTION__ << ": wglCreateContextAttribsARB() failed (GL error code: 0x"
- << hex << glGetError() << dec << ") for format: " << format << ", shared context: " << shared;
+ << hex << staticContext.opengl32.glGetError() << dec << ") for format: " << format << ", shared context: " << shared;
qErrnoWarning("%s", qPrintable(message));
}
return result;
@@ -648,16 +788,17 @@ static inline HGLRC createDummyGLContext(HDC dc)
initPixelFormatDescriptor(&pixelFormDescriptor);
pixelFormDescriptor.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_GENERIC_FORMAT;
pixelFormDescriptor.iPixelType = PFD_TYPE_RGBA;
+ // Use the GDI variant, for the dummy this is fine, even when using something other than opengl32.dll.
const int pixelFormat = ChoosePixelFormat(dc, &pixelFormDescriptor);
if (!pixelFormat) {
qErrnoWarning("%s: ChoosePixelFormat failed.", __FUNCTION__);
return 0;
}
- if (!SetPixelFormat(dc, pixelFormat, &pixelFormDescriptor)) {
+ if (!QOpenGLStaticContext::opengl32.setPixelFormat(dc, pixelFormat, &pixelFormDescriptor)) {
qErrnoWarning("%s: SetPixelFormat failed.", __FUNCTION__);
return 0;
}
- HGLRC rc = wglCreateContext(dc);
+ HGLRC rc = QOpenGLStaticContext::opengl32.wglCreateContext(dc);
if (!rc) {
qErrnoWarning("%s: wglCreateContext failed.", __FUNCTION__);
return 0;
@@ -668,8 +809,8 @@ static inline HGLRC createDummyGLContext(HDC dc)
static inline QOpenGLContextData currentOpenGLContextData()
{
QOpenGLContextData result;
- result.hdc = wglGetCurrentDC();
- result.renderingContext = wglGetCurrentContext();
+ result.hdc = QOpenGLStaticContext::opengl32.wglGetCurrentDC();
+ result.renderingContext = QOpenGLStaticContext::opengl32.wglGetCurrentContext();
return result;
}
@@ -721,7 +862,7 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
}
// v3 onwards
GLint value = 0;
- glGetIntegerv(GL_CONTEXT_FLAGS, &value);
+ QOpenGLStaticContext::opengl32.glGetIntegerv(GL_CONTEXT_FLAGS, &value);
if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
result.options |= QSurfaceFormat::DeprecatedFunctions;
if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
@@ -730,7 +871,7 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
return result;
// v3.2 onwards: Profiles
value = 0;
- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
+ QOpenGLStaticContext::opengl32.glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
if (value & GL_CONTEXT_CORE_PROFILE_BIT)
result.profile = QSurfaceFormat::CoreProfile;
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
@@ -784,15 +925,15 @@ QOpenGLTemporaryContext::QOpenGLTemporaryContext() :
m_previous(currentOpenGLContextData()),
m_current(createDummyWindowOpenGLContextData())
{
- wglMakeCurrent(m_current.hdc, m_current.renderingContext);
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(m_current.hdc, m_current.renderingContext);
}
QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
{
- wglMakeCurrent(m_previous.hdc, m_previous.renderingContext);
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(m_previous.hdc, m_previous.renderingContext);
ReleaseDC(m_current.hwnd, m_current.hdc);
DestroyWindow(m_current.hwnd);
- wglDeleteContext(m_current.renderingContext);
+ QOpenGLStaticContext::opengl32.wglDeleteContext(m_current.renderingContext);
}
/*!
@@ -807,6 +948,11 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
Functions pending integration in the next version of OpenGL are post-fixed ARB.
+ No WGL or OpenGL functions are called directly from the windows plugin. Instead, the
+ static context loads opengl32.dll and resolves the necessary functions. This allows
+ building the plugin without linking to opengl32 and enables QT_OPENGL_DYNAMIC builds
+ where both the EGL and WGL (this) based implementation of the context are built.
+
\note Initialization requires an active context (see create()).
\sa QWindowsGLContext
@@ -822,11 +968,11 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
extensionNames(QOpenGLStaticContext::getGlString(GL_EXTENSIONS)),
extensions(0),
defaultFormat(QWindowsOpenGLContextFormat::current()),
- wglGetPixelFormatAttribIVARB((WglGetPixelFormatAttribIVARB)wglGetProcAddress("wglGetPixelFormatAttribivARB")),
- wglChoosePixelFormatARB((WglChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB")),
- wglCreateContextAttribsARB((WglCreateContextAttribsARB)wglGetProcAddress("wglCreateContextAttribsARB")),
- wglSwapInternalExt((WglSwapInternalExt)wglGetProcAddress("wglSwapIntervalEXT")),
- wglGetSwapInternalExt((WglGetSwapInternalExt)wglGetProcAddress("wglGetSwapIntervalEXT"))
+ wglGetPixelFormatAttribIVARB((WglGetPixelFormatAttribIVARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetPixelFormatAttribivARB")),
+ wglChoosePixelFormatARB((WglChoosePixelFormatARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")),
+ wglCreateContextAttribsARB((WglCreateContextAttribsARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")),
+ wglSwapInternalExt((WglSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")),
+ wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT"))
{
if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
|| extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
@@ -835,16 +981,21 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
QByteArray QOpenGLStaticContext::getGlString(unsigned int which)
{
- if (const GLubyte *s = glGetString(which))
+ if (const GLubyte *s = opengl32.glGetString(which))
return QByteArray((const char*)s);
return QByteArray();
}
-QOpenGLStaticContext *QOpenGLStaticContext::create()
+QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering)
{
+ if (!opengl32.init(softwareRendering)) {
+ qWarning("%s: Failed to load and resolve WGL/OpenGL functions", Q_FUNC_INFO);
+ return 0;
+ }
+
// We need a current context for wglGetProcAdress()/getGLString() to work.
QScopedPointer<QOpenGLTemporaryContext> temporaryContext;
- if (!wglGetCurrentContext())
+ if (!QOpenGLStaticContext::opengl32.wglGetCurrentContext())
temporaryContext.reset(new QOpenGLTemporaryContext);
QOpenGLStaticContext *result = new QOpenGLStaticContext;
qCDebug(lcQpaGl) << __FUNCTION__ << *result;
@@ -881,15 +1032,61 @@ QDebug operator<<(QDebug d, const QOpenGLStaticContext &s)
\ingroup qt-lighthouse-win
*/
-QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContext,
+QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
QOpenGLContext *context) :
m_staticContext(staticContext),
m_context(context),
m_renderingContext(0),
m_pixelFormat(0),
m_extensionsUsed(false),
- m_swapInterval(-1)
+ m_swapInterval(-1),
+ m_ownsContext(true)
{
+ if (!m_staticContext) // Something went very wrong. Stop here, isValid() will return false.
+ return;
+
+ QVariant nativeHandle = context->nativeHandle();
+ if (!nativeHandle.isNull()) {
+ // Adopt and existing context.
+ if (!nativeHandle.canConvert<QWGLNativeContext>()) {
+ qWarning("QWindowsGLContext: Requires a QWGLNativeContext");
+ return;
+ }
+ QWGLNativeContext handle = nativeHandle.value<QWGLNativeContext>();
+ HGLRC wglcontext = handle.context();
+ HWND wnd = handle.window();
+ if (!wglcontext || !wnd) {
+ qWarning("QWindowsGLContext: No context and window given");
+ return;
+ }
+
+ HDC dc = GetDC(wnd);
+ // A window with an associated pixel format is mandatory.
+ // When no SetPixelFormat() call has been made, the following will fail.
+ m_pixelFormat = GetPixelFormat(dc);
+ bool ok = m_pixelFormat != 0;
+ if (!ok)
+ qWarning("QWindowsGLContext: Failed to get pixel format");
+ ok = DescribePixelFormat(dc, m_pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &m_obtainedPixelFormatDescriptor);
+ if (!ok) {
+ qWarning("QWindowsGLContext: Failed to describe pixel format");
+ } else {
+ QWindowsOpenGLAdditionalFormat obtainedAdditional;
+ m_obtainedFormat = GDI::qSurfaceFormatFromPixelFormat(m_obtainedPixelFormatDescriptor, &obtainedAdditional);
+ m_renderingContext = wglcontext;
+ ok = updateObtainedParams(dc);
+ }
+
+ ReleaseDC(wnd, dc);
+
+ if (ok)
+ m_ownsContext = false;
+ else
+ m_renderingContext = 0;
+
+ return;
+ }
+
QSurfaceFormat format = context->format();
if (format.renderableType() == QSurfaceFormat::DefaultRenderableType)
format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -901,7 +1098,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
static bool opengl32dll = false;
if (!opengl32dll) {
GLint params;
- glGetIntegerv(GL_DEPTH_BITS, &params);
+ staticContext->opengl32.glGetIntegerv(GL_DEPTH_BITS, &params);
opengl32dll = true;
}
@@ -912,7 +1109,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
HWND dummyWindow = 0;
HDC hdc = 0;
bool tryExtensions = false;
- int obtainedSwapInternal = -1;
+ int obtainedSwapInterval = -1;
do {
dummyWindow = createDummyGLWindow();
if (!dummyWindow)
@@ -954,7 +1151,7 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
qWarning("%s: Unable find a suitable pixel format.", __FUNCTION__);
break;
}
- if (!SetPixelFormat(hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
+ if (!QOpenGLStaticContext::opengl32.setPixelFormat(hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
qErrnoWarning("SetPixelFormat failed.");
break;
}
@@ -978,18 +1175,16 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
}
// Query obtained parameters and apply swap interval.
- if (!wglMakeCurrent(hdc, m_renderingContext)) {
- qWarning("Failed to make context current.");
+ if (!updateObtainedParams(hdc, &obtainedSwapInterval))
break;
- }
- QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
+ } while (false);
- if (m_staticContext->wglGetSwapInternalExt)
- obtainedSwapInternal = m_staticContext->wglGetSwapInternalExt();
+ // Make the HGLRC retrievable via QOpenGLContext::nativeHandle().
+ // Do not provide the window since it is the dummy one and it is about to disappear.
+ if (m_renderingContext)
+ context->setNativeHandle(QVariant::fromValue<QWGLNativeContext>(QWGLNativeContext(m_renderingContext, 0)));
- wglMakeCurrent(0, 0);
- } while (false);
if (hdc)
ReleaseDC(dummyWindow, hdc);
if (dummyWindow)
@@ -998,18 +1193,34 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
qCDebug(lcQpaGl) << __FUNCTION__ << this << (tryExtensions ? "ARB" : "GDI")
<< " requested: " << context->format()
<< "\n obtained #" << m_pixelFormat << (m_extensionsUsed ? "ARB" : "GDI") << m_obtainedFormat
- << "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInternal
+ << "\n " << m_obtainedPixelFormatDescriptor << " swap interval: " << obtainedSwapInterval
<< "\n default: " << m_staticContext->defaultFormat
<< "\n HGLRC=" << m_renderingContext;
}
QWindowsGLContext::~QWindowsGLContext()
{
- if (m_renderingContext)
- wglDeleteContext(m_renderingContext);
+ if (m_renderingContext && m_ownsContext)
+ QOpenGLStaticContext::opengl32.wglDeleteContext(m_renderingContext);
releaseDCs();
}
+bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval)
+{
+ if (!QOpenGLStaticContext::opengl32.wglMakeCurrent(hdc, m_renderingContext)) {
+ qWarning("Failed to make context current.");
+ return false;
+ }
+
+ QWindowsOpenGLContextFormat::current().apply(&m_obtainedFormat);
+
+ if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval)
+ *obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt();
+
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0);
+ return true;
+}
+
void QWindowsGLContext::releaseDCs()
{
const QOpenGLContextData *end = m_windowContexts.end();
@@ -1043,11 +1254,11 @@ void QWindowsGLContext::swapBuffers(QPlatformSurface *surface)
{
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaGl) << __FUNCTION__ << surface;
- if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, handleOf(surface))) {
- SwapBuffers(contextData->hdc);
- } else {
+
+ if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, handleOf(surface)))
+ QOpenGLStaticContext::opengl32.swapBuffers(contextData->hdc);
+ else
qWarning("%s: Cannot find window %p", __FUNCTION__, handleOf(surface));
- }
}
bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
@@ -1066,11 +1277,11 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Repeated calls to wglMakeCurrent when vsync is enabled in the driver will
// often result in 100% cpuload. This check is cheap and avoids the problem.
// This is reproducable on NVidia cards and Intel onboard chips.
- if (wglGetCurrentContext() == contextData->renderingContext
- && wglGetCurrentDC() == contextData->hdc) {
+ if (QOpenGLStaticContext::opengl32.wglGetCurrentContext() == contextData->renderingContext
+ && QOpenGLStaticContext::opengl32.wglGetCurrentDC() == contextData->hdc) {
return true;
}
- return wglMakeCurrent(contextData->hdc, contextData->renderingContext);
+ return QOpenGLStaticContext::opengl32.wglMakeCurrent(contextData->hdc, contextData->renderingContext);
}
// Create a new entry.
const QOpenGLContextData newContext(m_renderingContext, hwnd, GetDC(hwnd));
@@ -1079,7 +1290,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
// Initialize pixel format first time. This will apply to
// the HWND as well and must be done only once.
if (!window->testFlag(QWindowsWindow::OpenGlPixelFormatInitialized)) {
- if (!SetPixelFormat(newContext.hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
+ if (!QOpenGLStaticContext::opengl32.setPixelFormat(newContext.hdc, m_pixelFormat, &m_obtainedPixelFormatDescriptor)) {
qErrnoWarning("%s: SetPixelFormat() failed", __FUNCTION__);
ReleaseDC(newContext.hwnd, newContext.hdc);
return false;
@@ -1090,7 +1301,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
}
m_windowContexts.append(newContext);
- bool success = wglMakeCurrent(newContext.hdc, newContext.renderingContext);
+ bool success = QOpenGLStaticContext::opengl32.wglMakeCurrent(newContext.hdc, newContext.renderingContext);
// Set the swap interval
if (m_staticContext->wglSwapInternalExt) {
@@ -1110,17 +1321,83 @@ void QWindowsGLContext::doneCurrent()
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaGl) << __FUNCTION__ << this << m_windowContexts.size() << "contexts";
#endif // DEBUG_GL
- wglMakeCurrent(0, 0);
+ QOpenGLStaticContext::opengl32.wglMakeCurrent(0, 0);
releaseDCs();
}
-QWindowsGLContext::GL_Proc QWindowsGLContext::getProcAddress(const QByteArray &procName)
+QFunctionPointer QWindowsGLContext::getProcAddress(const QByteArray &procName)
{
- // TODO: Will that work with the calling conventions?
- GL_Proc procAddress = reinterpret_cast<GL_Proc>(wglGetProcAddress(procName.constData()));
+ // We support AllGLFunctionsQueryable, which means this function must be able to
+ // return a function pointer even for functions that are in GL.h and exported
+ // normally from opengl32.dll. wglGetProcAddress() is not guaranteed to work for such
+ // functions, however in QT_OPENGL_DYNAMIC builds QOpenGLFunctions will just blindly
+ // call into here for _any_ OpenGL function. Hence the need to handle these specially
+ // here. The list has to match QOpenGLFunctions. See
+ // QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *).
+ static struct StdFunc {
+ const char *name;
+ void *func;
+ } standardFuncs[] = {
+ { "glBindTexture", (void *) QOpenGLStaticContext::opengl32.glBindTexture },
+ { "glBlendFunc", (void *) QOpenGLStaticContext::opengl32.glBlendFunc },
+ { "glClear", (void *) QOpenGLStaticContext::opengl32.glClear },
+ { "glClearColor", (void *) QOpenGLStaticContext::opengl32.glClearColor },
+ { "glClearStencil", (void *) QOpenGLStaticContext::opengl32.glClearStencil },
+ { "glColorMask", (void *) QOpenGLStaticContext::opengl32.glColorMask },
+ { "glCopyTexImage2D", (void *) QOpenGLStaticContext::opengl32.glCopyTexImage2D },
+ { "glCopyTexSubImage2D", (void *) QOpenGLStaticContext::opengl32.glCopyTexSubImage2D },
+ { "glCullFace", (void *) QOpenGLStaticContext::opengl32.glCullFace },
+ { "glDeleteTextures", (void *) QOpenGLStaticContext::opengl32.glDeleteTextures },
+ { "glDepthFunc", (void *) QOpenGLStaticContext::opengl32.glDepthFunc },
+ { "glDepthMask", (void *) QOpenGLStaticContext::opengl32.glDepthMask },
+ { "glDisable", (void *) QOpenGLStaticContext::opengl32.glDisable },
+ { "glDrawArrays", (void *) QOpenGLStaticContext::opengl32.glDrawArrays },
+ { "glDrawElements", (void *) QOpenGLStaticContext::opengl32.glDrawElements },
+ { "glEnable", (void *) QOpenGLStaticContext::opengl32.glEnable },
+ { "glFinish", (void *) QOpenGLStaticContext::opengl32.glFinish },
+ { "glFlush", (void *) QOpenGLStaticContext::opengl32.glFlush },
+ { "glFrontFace", (void *) QOpenGLStaticContext::opengl32.glFrontFace },
+ { "glGenTextures", (void *) QOpenGLStaticContext::opengl32.glGenTextures },
+ { "glGetBooleanv", (void *) QOpenGLStaticContext::opengl32.glGetBooleanv },
+ { "glGetError", (void *) QOpenGLStaticContext::opengl32.glGetError },
+ { "glGetFloatv", (void *) QOpenGLStaticContext::opengl32.glGetFloatv },
+ { "glGetIntegerv", (void *) QOpenGLStaticContext::opengl32.glGetIntegerv },
+ { "glGetString", (void *) QOpenGLStaticContext::opengl32.glGetString },
+ { "glGetTexParameterfv", (void *) QOpenGLStaticContext::opengl32.glGetTexParameterfv },
+ { "glGetTexParameteriv", (void *) QOpenGLStaticContext::opengl32.glGetTexParameteriv },
+ { "glHint", (void *) QOpenGLStaticContext::opengl32.glHint },
+ { "glIsEnabled", (void *) QOpenGLStaticContext::opengl32.glIsEnabled },
+ { "glIsTexture", (void *) QOpenGLStaticContext::opengl32.glIsTexture },
+ { "glLineWidth", (void *) QOpenGLStaticContext::opengl32.glLineWidth },
+ { "glPixelStorei", (void *) QOpenGLStaticContext::opengl32.glPixelStorei },
+ { "glPolygonOffset", (void *) QOpenGLStaticContext::opengl32.glPolygonOffset },
+ { "glReadPixels", (void *) QOpenGLStaticContext::opengl32.glReadPixels },
+ { "glScissor", (void *) QOpenGLStaticContext::opengl32.glScissor },
+ { "glStencilFunc", (void *) QOpenGLStaticContext::opengl32.glStencilFunc },
+ { "glStencilMask", (void *) QOpenGLStaticContext::opengl32.glStencilMask },
+ { "glStencilOp", (void *) QOpenGLStaticContext::opengl32.glStencilOp },
+ { "glTexImage2D", (void *) QOpenGLStaticContext::opengl32.glTexImage2D },
+ { "glTexParameterf", (void *) QOpenGLStaticContext::opengl32.glTexParameterf },
+ { "glTexParameterfv", (void *) QOpenGLStaticContext::opengl32.glTexParameterfv },
+ { "glTexParameteri", (void *) QOpenGLStaticContext::opengl32.glTexParameteri },
+ { "glTexParameteriv", (void *) QOpenGLStaticContext::opengl32.glTexParameteriv },
+ { "glTexSubImage2D", (void *) QOpenGLStaticContext::opengl32.glTexSubImage2D },
+ { "glViewport", (void *) QOpenGLStaticContext::opengl32.glViewport },
+
+ { "glClearDepth", (void *) QOpenGLStaticContext::opengl32.glClearDepth },
+ { "glDepthRange", (void *) QOpenGLStaticContext::opengl32.glDepthRange },
+ };
+ for (size_t i = 0; i < sizeof(standardFuncs) / sizeof(StdFunc); ++i)
+ if (procName == standardFuncs[i].name)
+ return reinterpret_cast<QFunctionPointer>(standardFuncs[i].func);
+
+ // Even though we use QFunctionPointer, it does not mean the function can be called.
+ // It will need to be cast to the proper function type with the correct calling
+ // convention. QFunctionPointer is nothing more than a glorified void* here.
+ QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName.constData()));
if (QWindowsContext::verbose > 1)
- qCDebug(lcQpaGl) << __FUNCTION__ << procName << wglGetCurrentContext() << "returns" << procAddress;
- if (!procAddress)
+ qCDebug(lcQpaGl) << __FUNCTION__ << procName << QOpenGLStaticContext::opengl32.wglGetCurrentContext() << "returns" << procAddress;
+ if (!procAddress && QWindowsContext::verbose)
qWarning("%s: Unable to resolve '%s'", __FUNCTION__, procName.constData());
return procAddress;
}
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index c6b477128a..0afeb67a65 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -44,10 +44,9 @@
#include "array.h"
#include "qtwindows_additional.h"
+#include "qwindowsopenglcontext.h"
-#include <qpa/qplatformopenglcontext.h>
#include <QtGui/QOpenGLContext>
-#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
@@ -81,6 +80,8 @@ struct QOpenGLContextData
HDC hdc;
};
+class QOpenGLStaticContext;
+
struct QWindowsOpenGLContextFormat
{
QWindowsOpenGLContextFormat();
@@ -94,7 +95,87 @@ struct QWindowsOpenGLContextFormat
QDebug operator<<(QDebug d, const QWindowsOpenGLContextFormat &);
-class QOpenGLStaticContext
+struct QWindowsOpengl32DLL
+{
+ bool init(bool softwareRendering);
+ void *moduleHandle() const { return m_lib; }
+ bool moduleIsNotOpengl32() const { return m_nonOpengl32; }
+
+ // Wrappers. Always use these instead of SwapBuffers/wglSwapBuffers/etc.
+ BOOL swapBuffers(HDC dc);
+ BOOL setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd);
+
+ // WGL
+ HGLRC (WINAPI * wglCreateContext)(HDC dc);
+ BOOL (WINAPI * wglDeleteContext)(HGLRC context);
+ HGLRC (WINAPI * wglGetCurrentContext)();
+ HDC (WINAPI * wglGetCurrentDC)();
+ PROC (WINAPI * wglGetProcAddress)(LPCSTR name);
+ BOOL (WINAPI * wglMakeCurrent)(HDC dc, HGLRC context);
+ BOOL (WINAPI * wglShareLists)(HGLRC context1, HGLRC context2);
+
+ // GL1+GLES2 common
+ void (APIENTRY * glBindTexture)(GLenum target, GLuint texture);
+ void (APIENTRY * glBlendFunc)(GLenum sfactor, GLenum dfactor);
+ void (APIENTRY * glClear)(GLbitfield mask);
+ void (APIENTRY * glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (APIENTRY * glClearStencil)(GLint s);
+ void (APIENTRY * glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void (APIENTRY * glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+ void (APIENTRY * glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glCullFace)(GLenum mode);
+ void (APIENTRY * glDeleteTextures)(GLsizei n, const GLuint* textures);
+ void (APIENTRY * glDepthFunc)(GLenum func);
+ void (APIENTRY * glDepthMask)(GLboolean flag);
+ void (APIENTRY * glDisable)(GLenum cap);
+ void (APIENTRY * glDrawArrays)(GLenum mode, GLint first, GLsizei count);
+ void (APIENTRY * glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+ void (APIENTRY * glEnable)(GLenum cap);
+ void (APIENTRY * glFinish)();
+ void (APIENTRY * glFlush)();
+ void (APIENTRY * glFrontFace)(GLenum mode);
+ void (APIENTRY * glGenTextures)(GLsizei n, GLuint* textures);
+ void (APIENTRY * glGetBooleanv)(GLenum pname, GLboolean* params);
+ GLenum (APIENTRY * glGetError)();
+ void (APIENTRY * glGetFloatv)(GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetIntegerv)(GLenum pname, GLint* params);
+ const GLubyte * (APIENTRY * glGetString)(GLenum name);
+ void (APIENTRY * glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params);
+ void (APIENTRY * glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (APIENTRY * glHint)(GLenum target, GLenum mode);
+ GLboolean (APIENTRY * glIsEnabled)(GLenum cap);
+ GLboolean (APIENTRY * glIsTexture)(GLuint texture);
+ void (APIENTRY * glLineWidth)(GLfloat width);
+ void (APIENTRY * glPixelStorei)(GLenum pname, GLint param);
+ void (APIENTRY * glPolygonOffset)(GLfloat factor, GLfloat units);
+ void (APIENTRY * glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+ void (APIENTRY * glScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
+ void (APIENTRY * glStencilFunc)(GLenum func, GLint ref, GLuint mask);
+ void (APIENTRY * glStencilMask)(GLuint mask);
+ void (APIENTRY * glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
+ void (APIENTRY * glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+ void (APIENTRY * glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params);
+ void (APIENTRY * glTexParameteri)(GLenum target, GLenum pname, GLint param);
+ void (APIENTRY * glTexParameteriv)(GLenum target, GLenum pname, const GLint* params);
+ void (APIENTRY * glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+ void (APIENTRY * glViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ // GL only
+ void (APIENTRY * glClearDepth)(GLdouble depth);
+ void (APIENTRY * glDepthRange)(GLdouble zNear, GLdouble zFar);
+
+private:
+ void *resolve(const char *name);
+ HMODULE m_lib;
+ bool m_nonOpengl32;
+
+ // For Mesa llvmpipe shipped with a name other than opengl32.dll
+ BOOL (WINAPI * wglSwapBuffers)(HDC dc);
+ BOOL (WINAPI * wglSetPixelFormat)(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd);
+};
+
+class QOpenGLStaticContext : public QWindowsStaticOpenGLContext
{
Q_DISABLE_COPY(QOpenGLStaticContext)
QOpenGLStaticContext();
@@ -125,9 +206,17 @@ public:
bool hasExtensions() const
{ return wglGetPixelFormatAttribIVARB && wglChoosePixelFormatARB && wglCreateContextAttribsARB; }
- static QOpenGLStaticContext *create();
+ static QOpenGLStaticContext *create(bool softwareRendering = false);
static QByteArray getGlString(unsigned int which);
+ QWindowsOpenGLContext *createContext(QOpenGLContext *context);
+ void *moduleHandle() const { return opengl32.moduleHandle(); }
+ QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGL; }
+
+ // For a regular opengl32.dll report the ThreadedOpenGL capability.
+ // For others, which are likely to be software-only, don't.
+ bool supportsThreadedOpenGL() const { return !opengl32.moduleIsNotOpengl32(); }
+
const QByteArray vendor;
const QByteArray renderer;
const QByteArray extensionNames;
@@ -139,37 +228,39 @@ public:
WglCreateContextAttribsARB wglCreateContextAttribsARB;
WglSwapInternalExt wglSwapInternalExt;
WglGetSwapInternalExt wglGetSwapInternalExt;
+
+ static QWindowsOpengl32DLL opengl32;
};
QDebug operator<<(QDebug d, const QOpenGLStaticContext &);
-class QWindowsGLContext : public QPlatformOpenGLContext
+class QWindowsGLContext : public QWindowsOpenGLContext
{
public:
- typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
-
- explicit QWindowsGLContext(const QOpenGLStaticContextPtr &staticContext,
- QOpenGLContext *context);
- virtual ~QWindowsGLContext();
- bool isSharing() const { return m_context->shareHandle(); }
- bool isValid() const { return m_renderingContext; }
- virtual QSurfaceFormat format() const { return m_obtainedFormat; }
+ explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context);
+ ~QWindowsGLContext();
+ bool isSharing() const Q_DECL_OVERRIDE { return m_context->shareHandle(); }
+ bool isValid() const Q_DECL_OVERRIDE { return m_renderingContext; }
+ QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_obtainedFormat; }
- virtual void swapBuffers(QPlatformSurface *surface);
+ void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- virtual bool makeCurrent(QPlatformSurface *surface);
- virtual void doneCurrent();
+ bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void doneCurrent() Q_DECL_OVERRIDE;
typedef void (*GL_Proc) ();
- virtual GL_Proc getProcAddress(const QByteArray &procName);
+ QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE;
+
+ HGLRC renderingContext() const { return m_renderingContext; }
- HGLRC renderingContext() const { return m_renderingContext; }
+ void *nativeContext() const Q_DECL_OVERRIDE { return m_renderingContext; }
private:
inline void releaseDCs();
+ bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = 0);
- const QOpenGLStaticContextPtr m_staticContext;
+ QOpenGLStaticContext *m_staticContext;
QOpenGLContext *m_context;
QSurfaceFormat m_obtainedFormat;
HGLRC m_renderingContext;
@@ -178,6 +269,7 @@ private:
int m_pixelFormat;
bool m_extensionsUsed;
int m_swapInterval;
+ bool m_ownsContext;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
index 878db7185d..8a8306f01a 100644
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
+++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
@@ -115,6 +115,9 @@ messageDebugEntries[] = {
{WM_SYSCOMMAND, "WM_SYSCOMMAND", true},
{WM_KEYUP, "WM_KEYUP", true},
{WM_SYSKEYUP, "WM_SYSKEYUP", true},
+#if defined(WM_APPCOMMAND)
+ {WM_APPCOMMAND, "WM_APPCOMMAND", true},
+#endif
{WM_IME_CHAR, "WM_IMECHAR", true},
{WM_IME_KEYDOWN, "WM_IMECHAR", true},
{WM_CANCELMODE, "WM_CANCELMODE", true},
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
index 65ef912b43..6f67c47279 100644
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
+++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h
@@ -59,8 +59,8 @@ public:
static const char *windowsMessageName(UINT msg);
- virtual bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);
- virtual void sendPostedEvents();
+ bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags) Q_DECL_OVERRIDE;
+ void sendPostedEvents() Q_DECL_OVERRIDE;
private:
QEventLoop::ProcessEventsFlags m_flags;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 2429e8a4fa..bc7ffc9afd 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -88,18 +88,6 @@ static inline void imeNotifyCancelComposition(HWND hwnd)
ImmReleaseContext(hwnd, himc);
}
-// Query a QObject for an InputMethod-related value
-// by sending a QInputMethodQueryEvent.
-template <class T>
- bool inputMethodQuery(QObject *fo, Qt::InputMethodQuery query, T *result)
-{
- QInputMethodQueryEvent queryEvent(query);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return false;
- *result = qvariant_cast<T>(queryEvent.value(query));
- return true;
-}
-
/*!
\class QWindowsInputContext
\brief Windows Input context implementation
@@ -170,7 +158,7 @@ QWindowsInputContext::QWindowsInputContext() :
m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")),
m_endCompositionRecursionGuard(false)
{
- connect(qApp->inputMethod(), SIGNAL(cursorRectangleChanged()),
+ connect(QGuiApplication::inputMethod(), SIGNAL(cursorRectangleChanged()),
this, SLOT(cursorRectChanged()));
}
@@ -215,7 +203,7 @@ void QWindowsInputContext::cursorRectChanged()
{
if (!m_compositionContext.hwnd)
return;
- const QInputMethod *inputMethod = qApp->inputMethod();
+ const QInputMethod *inputMethod = QGuiApplication::inputMethod();
QRect cursorRectangle = inputMethod->cursorRectangle().toRect();
if (!cursorRectangle.isValid())
return;
@@ -536,9 +524,10 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
if (!fo)
return false;
- QString surroundingText;
- if (!inputMethodQuery(fo, Qt::ImSurroundingText, &surroundingText))
+ const QVariant surroundingTextV = QInputMethod::queryFocusObject(Qt::ImSurroundingText, QVariant());
+ if (!surroundingTextV.isValid())
return -1;
+ const QString surroundingText = surroundingTextV.toString();
const DWORD memSize = sizeof(RECONVERTSTRING)
+ (surroundingText.length() + 1) * sizeof(ushort);
qCDebug(lcQpaInputMethods) << __FUNCTION__ << " reconv=" << reconv
@@ -547,8 +536,8 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
if (!reconv)
return surroundingText.isEmpty() ? -1 : int(memSize);
- int pos = 0;
- inputMethodQuery(fo, Qt::ImCursorPosition, &pos);
+ const QVariant posV = QInputMethod::queryFocusObject(Qt::ImCursorPosition, QVariant());
+ const int pos = posV.isValid() ? posV.toInt() : 0;
// Find the word in the surrounding text.
QTextBoundaryFinder bounds(QTextBoundaryFinder::Word, surroundingText);
bounds.setPosition(pos);
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index 31a076cbf8..51ea8adf1e 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -68,9 +68,9 @@ public:
explicit QWindowsInputContext();
~QWindowsInputContext();
- virtual void reset();
- virtual void update(Qt::InputMethodQueries);
- virtual void invokeAction(QInputMethod::Action, int cursorPosition);
+ void reset() Q_DECL_OVERRIDE;
+ void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
+ void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
static QWindowsInputContext *instance();
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 78bf833526..529dd75ed5 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** 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.
@@ -43,19 +43,7 @@
#include "qwindowsintegration.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
-
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLContext>
-#endif
-
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
-# include "qwindowsglcontext.h"
-#endif
-
-#if !defined(QT_NO_OPENGL)
-# include <QtGui/QOpenGLFunctions>
-#endif
+#include "qwindowsopenglcontext.h"
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
@@ -89,6 +77,19 @@
#include <QtCore/QDebug>
#include <QtCore/QVariant>
+#include <limits.h>
+
+#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
+# include "qwindowseglcontext.h"
+#endif
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
+# include "qwindowsglcontext.h"
+#endif
+
+#ifndef Q_OS_WINCE
+# include "qwindowsopengltester.h"
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -134,15 +135,9 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate
{
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- typedef QSharedPointer<QWindowsEGLStaticContext> QEGLStaticContextPtr;
-#endif
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
- typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
-#endif
-
explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
+ bool ensureStaticOpenGLContext();
unsigned m_options;
QWindowsContext m_context;
@@ -153,12 +148,9 @@ struct QWindowsIntegrationPrivate
QWindowsDrag m_drag;
# endif
#endif
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- QEGLStaticContextPtr m_staticEGLContext;
-#endif
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
- QOpenGLStaticContextPtr m_staticOpenGLContext;
-#endif
+#ifndef QT_NO_OPENGL
+ QSharedPointer<QWindowsStaticOpenGLContext> m_staticOpenGLContext;
+#endif // QT_NO_OPENGL
QScopedPointer<QPlatformInputContext> m_inputContext;
#ifndef QT_NO_ACCESSIBILITY
QWindowsAccessibility m_accessibility;
@@ -166,8 +158,32 @@ struct QWindowsIntegrationPrivate
QWindowsServices m_services;
};
+template <typename IntType>
+bool parseIntOption(const QString &parameter,const QLatin1String &option,
+ IntType minimumValue, IntType maximumValue, IntType *target)
+{
+ const int valueLength = parameter.size() - option.size() - 1;
+ if (valueLength < 1 || !parameter.startsWith(option) || parameter.at(option.size()) != QLatin1Char('='))
+ return false;
+ bool ok;
+ const QStringRef valueRef = parameter.rightRef(valueLength);
+ const int value = valueRef.toInt(&ok);
+ if (ok) {
+ if (value >= minimumValue && value <= maximumValue)
+ *target = static_cast<IntType>(value);
+ else {
+ qWarning() << "Value" << value << "for option" << option << "out of range"
+ << minimumValue << ".." << maximumValue;
+ }
+ } else {
+ qWarning() << "Invalid value" << valueRef << "for option" << option;
+ }
+ return true;
+}
+
static inline unsigned parseOptions(const QStringList &paramList,
- int *tabletAbsoluteRange)
+ int *tabletAbsoluteRange,
+ QtWindows::ProcessDpiAwareness *dpiAwareness)
{
unsigned options = 0;
foreach (const QString &param, paramList) {
@@ -187,10 +203,11 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::DisableArb;
} else if (param == QLatin1String("nomousefromtouch")) {
options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch;
- } else if (param.startsWith(QLatin1String("verbose="))) {
- QWindowsContext::verbose = param.right(param.size() - 8).toInt();
- } else if (param.startsWith(QLatin1String("tabletabsoluterange="))) {
- *tabletAbsoluteRange = param.rightRef(param.size() - 20).toInt();
+ } else if (parseIntOption(param, QLatin1String("verbose"), 0, INT_MAX, &QWindowsContext::verbose)
+ || parseIntOption(param, QLatin1String("tabletabsoluterange"), 0, INT_MAX, tabletAbsoluteRange)
+ || parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorDpiAware, dpiAwareness)) {
+ } else {
+ qWarning() << "Unknown option" << param;
}
}
return options;
@@ -201,9 +218,13 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
, m_fontDatabase(0)
{
int tabletAbsoluteRange = -1;
- m_options = parseOptions(paramList, &tabletAbsoluteRange);
+ // Default to per-monitor awareness to avoid being scaled when monitors with different DPI
+ // are connected to Windows 8.1
+ QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
+ m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
if (tabletAbsoluteRange >= 0)
m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
+ m_context.setProcessDpiAwareness(dpiAwareness);
}
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
@@ -242,12 +263,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
case OpenGL:
return true;
case ThreadedOpenGL:
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- return QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL
- ? QWindowsEGLContext::hasThreadedOpenGLCapability() : true;
-# else
- return true;
-# endif // QT_OPENGL_ES_2
+ return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->supportsThreadedOpenGL() : false;
#endif // !QT_NO_OPENGL
case WindowMasks:
return true;
@@ -257,6 +273,8 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
case RasterGLSurface:
return true;
+ case AllGLFunctionsQueryable:
+ return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -273,8 +291,7 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
if (customMarginsV.isValid())
requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
- const QWindowsWindowData obtained
- = QWindowsWindowData::create(window, requested, window->title());
+ QWindowsWindowData obtained = QWindowsWindowData::create(window, requested, window->title());
qCDebug(lcQpaWindows).nospace()
<< __FUNCTION__ << '<' << window
<< "\n Requested: " << requested.geometry << "frame incl.: "
@@ -292,6 +309,11 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
}
+#ifndef QT_NO_OPENGL
+ d->ensureStaticOpenGLContext();
+ obtained.staticOpenGLContext = d->m_staticOpenGLContext;
+#endif // QT_NO_OPENGL
+
return obtained;
}
@@ -303,32 +325,80 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
}
#ifndef QT_NO_OPENGL
-QPlatformOpenGLContext
- *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+static QWindowsStaticOpenGLContext *q_staticOpenGLContext = 0;
+
+QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create()
{
- qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) {
- if (d->m_staticEGLContext.isNull()) {
- QWindowsEGLStaticContext *staticContext = QWindowsEGLStaticContext::create();
- if (!staticContext)
- return 0;
- d->m_staticEGLContext = QSharedPointer<QWindowsEGLStaticContext>(staticContext);
+ QWindowsStaticOpenGLContext *ctx = 0;
+
+#if defined(QT_OPENGL_DYNAMIC)
+ const QByteArray requested = qgetenv("QT_OPENGL"); // angle, desktop, software
+ const bool angleRequested = QCoreApplication::testAttribute(Qt::AA_UseOpenGLES) || requested == QByteArrayLiteral("angle");
+ const bool desktopRequested = QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL) || requested == QByteArrayLiteral("desktop");
+ const bool softwareRequested = QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL) || requested == QByteArrayLiteral("software");
+
+ // If ANGLE is requested, use it, don't try anything else.
+ if (angleRequested) {
+ ctx = QWindowsEGLStaticContext::create();
+ } else {
+ // If opengl32.dll seems to be OpenGL 2.x capable, or desktop OpenGL is requested, use it.
+ if (!softwareRequested && (desktopRequested || QWindowsOpenGLTester::testDesktopGL()))
+ ctx = QOpenGLStaticContext::create();
+ // If failed and desktop OpenGL is not explicitly requested, try ANGLE.
+ if (!ctx && !desktopRequested && !softwareRequested)
+ ctx = QWindowsEGLStaticContext::create();
+ // Try software.
+ if (!ctx) {
+ ctx = QOpenGLStaticContext::create(true);
+ // If software was explicitly requested but failed, try the regular one.
+ if (!ctx && softwareRequested && QWindowsOpenGLTester::testDesktopGL())
+ ctx = QOpenGLStaticContext::create();
}
- return new QWindowsEGLContext(d->m_staticEGLContext, context->format(), context->shareHandle());
}
+#elif defined(QT_OPENGL_ES_2)
+ ctx = QWindowsEGLStaticContext::create();
+#elif !defined(QT_NO_OPENGL)
+ ctx = QOpenGLStaticContext::create();
#endif
-#if !defined(QT_OPENGL_ES_2)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- if (d->m_staticOpenGLContext.isNull())
- d->m_staticOpenGLContext =
- QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
- QScopedPointer<QWindowsGLContext> result(new QWindowsGLContext(d->m_staticOpenGLContext, context));
- return result->isValid() ? result.take() : 0;
+
+ q_staticOpenGLContext = ctx;
+
+ return ctx;
+}
+
+bool QWindowsIntegrationPrivate::ensureStaticOpenGLContext()
+{
+ if (m_staticOpenGLContext.isNull())
+ m_staticOpenGLContext = QSharedPointer<QWindowsStaticOpenGLContext>(QWindowsStaticOpenGLContext::create());
+ return !m_staticOpenGLContext.isNull();
+}
+
+QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
+ if (d->ensureStaticOpenGLContext()) {
+ QScopedPointer<QWindowsOpenGLContext> result(d->m_staticOpenGLContext->createContext(context));
+ if (result->isValid())
+ return result.take();
}
-#endif // !QT_OPENGL_ES_2
return 0;
}
+
+QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType()
+{
+#if defined(QT_OPENGL_ES_2)
+ return QOpenGLContext::LibGLES;
+#elif !defined(QT_OPENGL_DYNAMIC)
+ return QOpenGLContext::LibGL;
+#else
+ return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->moduleType() : QOpenGLContext::LibGL;
+#endif
+}
+
+QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext()
+{
+ return q_staticOpenGLContext;
+}
#endif // !QT_NO_OPENGL
/* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 0f417c8239..cae415ccd9 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate;
struct QWindowsWindowData;
class QWindowsWindow;
+class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
{
@@ -73,28 +74,30 @@ public:
QWindowsWindowData createWindowData(QWindow *window) const;
QPlatformWindow *createPlatformWindow(QWindow *window) const;
#ifndef QT_NO_OPENGL
- virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
+ QOpenGLContext::OpenGLModuleType openGLModuleType();
+ static QWindowsStaticOpenGLContext *staticOpenGLContext();
#endif
- virtual QAbstractEventDispatcher *createEventDispatcher() const;
+ QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
void initialize() Q_DECL_OVERRIDE;
#ifndef QT_NO_CLIPBOARD
- virtual QPlatformClipboard *clipboard() const;
+ QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
# ifndef QT_NO_DRAGANDDROP
- virtual QPlatformDrag *drag() const;
+ QPlatformDrag *drag() const Q_DECL_OVERRIDE;
# endif
#endif // !QT_NO_CLIPBOARD
- virtual QPlatformInputContext *inputContext() const;
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
#ifndef QT_NO_ACCESSIBILITY
- virtual QPlatformAccessibility *accessibility() const;
+ QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
#endif
- virtual QPlatformFontDatabase *fontDatabase() const;
- virtual QStringList themeNames() const;
- virtual QPlatformTheme *createPlatformTheme(const QString &name) const;
+ QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
+ QStringList themeNames() const Q_DECL_OVERRIDE;
+ QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
QPlatformServices *services() const;
- virtual QVariant styleHint(StyleHint hint) const;
+ QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
- virtual Qt::KeyboardModifiers queryKeyboardModifiers() const;
- virtual QList<int> possibleKeys(const QKeyEvent *e) const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
+ QList<int> possibleKeys(const QKeyEvent *e) const Q_DECL_OVERRIDE;
static QWindowsIntegration *instance();
@@ -103,7 +106,7 @@ public:
unsigned options() const;
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
- virtual QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const;
+ QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE;
#endif
private:
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.h b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
index 0c12c662c4..08f2d09534 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.h
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
@@ -54,9 +54,9 @@ class QDebug;
// Implementation in qwindowsclipboard.cpp.
class QWindowsInternalMimeData : public QInternalMimeData {
public:
- virtual bool hasFormat_sys(const QString &mimetype) const;
- virtual QStringList formats_sys() const;
- virtual QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const;
+ bool hasFormat_sys(const QString &mimetype) const Q_DECL_OVERRIDE;
+ QStringList formats_sys() const Q_DECL_OVERRIDE;
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
protected:
virtual IDataObject *retrieveDataObject() const = 0;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 6bcfe01a18..dc1de047fe 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -428,6 +428,63 @@ static const uint KeyTbl[] = { // Keyboard mapping table
0
};
+static const uint CmdTbl[] = { // Multimedia keys mapping table
+ // Dec | Hex | AppCommand
+ Qt::Key_unknown, // 0 0x00
+ Qt::Key_Back, // 1 0x01 APPCOMMAND_BROWSER_BACKWARD
+ Qt::Key_Forward, // 2 0x02 APPCOMMAND_BROWSER_FORWARD
+ Qt::Key_Refresh, // 3 0x03 APPCOMMAND_BROWSER_REFRESH
+ Qt::Key_Stop, // 4 0x04 APPCOMMAND_BROWSER_STOP
+ Qt::Key_Search, // 5 0x05 APPCOMMAND_BROWSER_SEARCH
+ Qt::Key_Favorites, // 6 0x06 APPCOMMAND_BROWSER_FAVORITES
+ Qt::Key_Home, // 7 0x07 APPCOMMAND_BROWSER_HOME
+ Qt::Key_VolumeMute, // 8 0x08 APPCOMMAND_VOLUME_MUTE
+ Qt::Key_VolumeDown, // 9 0x09 APPCOMMAND_VOLUME_DOWN
+ Qt::Key_VolumeUp, // 10 0x0a APPCOMMAND_VOLUME_UP
+ Qt::Key_MediaNext, // 11 0x0b APPCOMMAND_MEDIA_NEXTTRACK
+ Qt::Key_MediaPrevious, // 12 0x0c APPCOMMAND_MEDIA_PREVIOUSTRACK
+ Qt::Key_MediaStop, // 13 0x0d APPCOMMAND_MEDIA_STOP
+ Qt::Key_MediaTogglePlayPause, // 14 0x0e APPCOMMAND_MEDIA_PLAYPAUSE
+ Qt::Key_LaunchMail, // 15 0x0f APPCOMMAND_LAUNCH_MAIL
+ Qt::Key_LaunchMedia, // 16 0x10 APPCOMMAND_LAUNCH_MEDIA_SELECT
+ Qt::Key_Launch0, // 17 0x11 APPCOMMAND_LAUNCH_APP1
+ Qt::Key_Launch1, // 18 0x12 APPCOMMAND_LAUNCH_APP2
+ Qt::Key_BassDown, // 19 0x13 APPCOMMAND_BASS_DOWN
+ Qt::Key_BassBoost, // 20 0x14 APPCOMMAND_BASS_BOOST
+ Qt::Key_BassUp, // 21 0x15 APPCOMMAND_BASS_UP
+ Qt::Key_TrebleDown, // 22 0x16 APPCOMMAND_TREBLE_DOWN
+ Qt::Key_TrebleUp, // 23 0x17 APPCOMMAND_TREBLE_UP
+ Qt::Key_MicMute, // 24 0x18 APPCOMMAND_MICROPHONE_VOLUME_MUTE
+ Qt::Key_MicVolumeDown, // 25 0x19 APPCOMMAND_MICROPHONE_VOLUME_DOWN
+ Qt::Key_MicVolumeUp, // 26 0x1a APPCOMMAND_MICROPHONE_VOLUME_UP
+ Qt::Key_Help, // 27 0x1b APPCOMMAND_HELP
+ Qt::Key_Find, // 28 0x1c APPCOMMAND_FIND
+ Qt::Key_New, // 29 0x1d APPCOMMAND_NEW
+ Qt::Key_Open, // 30 0x1e APPCOMMAND_OPEN
+ Qt::Key_Close, // 31 0x1f APPCOMMAND_CLOSE
+ Qt::Key_Save, // 32 0x20 APPCOMMAND_SAVE
+ Qt::Key_Print, // 33 0x21 APPCOMMAND_PRINT
+ Qt::Key_Undo, // 34 0x22 APPCOMMAND_UNDO
+ Qt::Key_Redo, // 35 0x23 APPCOMMAND_REDO
+ Qt::Key_Copy, // 36 0x24 APPCOMMAND_COPY
+ Qt::Key_Cut, // 37 0x25 APPCOMMAND_CUT
+ Qt::Key_Paste, // 38 0x26 APPCOMMAND_PASTE
+ Qt::Key_Reply, // 39 0x27 APPCOMMAND_REPLY_TO_MAIL
+ Qt::Key_MailForward, // 40 0x28 APPCOMMAND_FORWARD_MAIL
+ Qt::Key_Send, // 41 0x29 APPCOMMAND_SEND_MAIL
+ Qt::Key_Spell, // 42 0x2a APPCOMMAND_SPELL_CHECK
+ Qt::Key_unknown, // 43 0x2b APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE
+ Qt::Key_unknown, // 44 0x2c APPCOMMAND_MIC_ON_OFF_TOGGLE
+ Qt::Key_unknown, // 45 0x2d APPCOMMAND_CORRECTION_LIST
+ Qt::Key_MediaPlay, // 46 0x2e APPCOMMAND_MEDIA_PLAY
+ Qt::Key_MediaPause, // 47 0x2f APPCOMMAND_MEDIA_PAUSE
+ Qt::Key_MediaRecord, // 48 0x30 APPCOMMAND_MEDIA_RECORD
+ Qt::Key_AudioForward, // 49 0x31 APPCOMMAND_MEDIA_FAST_FORWARD
+ Qt::Key_AudioRewind, // 50 0x32 APPCOMMAND_MEDIA_REWIND
+ Qt::Key_ChannelDown, // 51 0x33 APPCOMMAND_MEDIA_CHANNEL_DOWN
+ Qt::Key_ChannelUp // 52 0x34 APPCOMMAND_MEDIA_CHANNEL_UP
+};
+
// Possible modifier states.
// NOTE: The order of these states match the order in QWindowsKeyMapper::updatePossibleKeyCodes()!
static const Qt::KeyboardModifiers ModsTbl[] = {
@@ -747,6 +804,11 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
return true;
}
+#if defined(WM_APPCOMMAND)
+ if (msg.message == WM_APPCOMMAND)
+ return translateMultimediaKeyEventInternal(widget, msg);
+#endif
+
// WM_(IME_)CHAR messages already contain the character in question so there is
// no need to fiddle with our key map. In any other case add this key to the
// keymap if it is not present yet.
@@ -761,6 +823,29 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
return translateKeyEventInternal(widget, msg, false);
}
+bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg)
+{
+#if defined(WM_APPCOMMAND)
+ const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
+ const int dwKeys = GET_KEYSTATE_LPARAM(msg.lParam);
+ int state = 0;
+ state |= (dwKeys & MK_SHIFT ? int(Qt::ShiftModifier) : 0);
+ state |= (dwKeys & MK_CONTROL ? int(Qt::ControlModifier) : 0);
+
+ QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
+
+ if (cmd < 0 || cmd > 52)
+ return false;
+
+ const int qtKey = CmdTbl[cmd];
+ sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
+ return true;
+#else
+ Q_UNREACHABLE();
+ return false;
+#endif
+}
+
bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */)
{
const int msgType = msg.message;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index f7d33758a0..247a807af7 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -93,6 +93,7 @@ public:
private:
bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab);
+ bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg);
void updateKeyMap(const MSG &msg);
bool m_useRTLExtensions;
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 3af2cff9a0..37f51e85bd 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -1035,17 +1035,14 @@ bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *p
bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
int cf = getCf(formatetc);
- if (mimeData->hasImage()) {
- if (cf == CF_DIB)
- return true;
- else if (cf == CF_DIBV5) {
- //support DIBV5 conversion only if the image has alpha channel
- QImage image = qvariant_cast<QImage>(mimeData->imageData());
- if (!image.isNull() && image.hasAlphaChannel())
- return true;
- }
- }
- return false;
+ if (!mimeData->hasImage())
+ return false;
+ const QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ if (image.isNull())
+ return false;
+ // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of
+ // transparency in conversion.
+ return cf == CF_DIBV5 || (cf == CF_DIB && !image.hasAlphaChannel());
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
@@ -1442,13 +1439,13 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
\sa QWindowsMime
*/
-QWindowsMimeConverter::QWindowsMimeConverter()
+QWindowsMimeConverter::QWindowsMimeConverter() : m_internalMimeCount(0)
{
}
QWindowsMimeConverter::~QWindowsMimeConverter()
{
- qDeleteAll(m_mimes);
+ qDeleteAll(m_mimes.begin(), m_mimes.begin() + m_internalMimeCount);
}
QWindowsMime * QWindowsMimeConverter::converterToMime(const QString &mimeType, IDataObject *pDataObj) const
@@ -1526,6 +1523,7 @@ void QWindowsMimeConverter::ensureInitialized() const
m_mimes << new QWindowsMimeImage << new QLastResortMimes
<< new QWindowsMimeText << new QWindowsMimeURI
<< new QWindowsMimeHtml << new QBuiltInMimes;
+ m_internalMimeCount = m_mimes.size();
}
}
@@ -1552,4 +1550,10 @@ QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
return QVariant();
}
+void QWindowsMimeConverter::registerMime(QWindowsMime *mime)
+{
+ ensureInitialized();
+ m_mimes.append(mime);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index cd0fb4d8b3..e2818422bf 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -89,12 +89,14 @@ public:
QVariant convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType,
QString *format = 0) const;
-private:
- typedef QSharedPointer<QWindowsMime> MimePtr;
+ void registerMime(QWindowsMime *mime);
+ void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
+private:
void ensureInitialized() const;
mutable QList<QWindowsMime *> m_mimes;
+ mutable int m_internalMimeCount;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 06c0122bbb..ce28166e4f 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -42,24 +42,45 @@
#include "qwindowsnativeinterface.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
-
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLContext>
-#endif
-
-#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
-# include "qwindowsglcontext.h"
-#endif
-
-#if !defined(QT_NO_OPENGL)
-# include <QtGui/QOpenGLFunctions>
-#endif
+#include "qwindowsopenglcontext.h"
+#include "qwindowsintegration.h"
+#include "qwindowsmime.h"
#include <QtGui/QWindow>
+#include <QtGui/QOpenGLContext>
QT_BEGIN_NAMESPACE
+enum ResourceType {
+ RenderingContextType,
+ EglContextType,
+ EglDisplayType,
+ EglConfigType,
+ HandleType,
+ GlHandleType,
+ GetDCType,
+ ReleaseDCType
+};
+
+static int resourceType(const QByteArray &key)
+{
+ static const QByteArray names[] = { // match ResourceType
+ "renderingcontext",
+ "eglcontext",
+ "egldisplay",
+ "eglconfig",
+ "handle",
+ "glhandle",
+ "getdc",
+ "releasedc"
+ };
+ const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
+ const QByteArray *result = std::find(names, end, key);
+ if (result == end)
+ result = std::find(names, end, key.toLower());
+ return int(result - names);
+}
+
void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
{
if (!window || !window->handle()) {
@@ -67,14 +88,15 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
return 0;
}
QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
- if (resource == "handle")
+ int type = resourceType(resource);
+ if (type == HandleType)
return bw->handle();
switch (window->surfaceType()) {
case QWindow::RasterSurface:
case QWindow::RasterGLSurface:
- if (resource == "getDC")
+ if (type == GetDCType)
return bw->getDC();
- if (resource == "releaseDC") {
+ if (type == ReleaseDCType) {
bw->releaseDC();
return 0;
}
@@ -117,6 +139,16 @@ QVariantMap QWindowsNativeInterface::windowProperties(QPlatformWindow *window) c
return result;
}
+void *QWindowsNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
+{
+#ifndef QT_NO_OPENGL
+ if (resourceType(resource) == GlHandleType)
+ return QWindowsIntegration::staticOpenGLContext()->moduleHandle();
+#endif
+
+ return 0;
+}
+
#ifndef QT_NO_OPENGL
void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
{
@@ -124,24 +156,19 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
qWarning("%s: '%s' requested for null context or context without handle.", __FUNCTION__, resource.constData());
return 0;
}
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) {
- QWindowsEGLContext *windowsEglContext = static_cast<QWindowsEGLContext *>(context->handle());
- if (resource == QByteArrayLiteral("eglDisplay"))
- return windowsEglContext->eglDisplay();
- if (resource == QByteArrayLiteral("eglContext"))
- return windowsEglContext->eglContext();
- if (resource == QByteArrayLiteral("eglConfig"))
- return windowsEglContext->eglConfig();
- }
-#endif // QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC
-#if !defined(QT_OPENGL_ES_2)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
- if (resource == QByteArrayLiteral("renderingContext"))
- return windowsContext->renderingContext();
+
+ QWindowsOpenGLContext *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
+ switch (resourceType(resource)) {
+ case RenderingContextType: // Fall through.
+ case EglContextType:
+ return glcontext->nativeContext();
+ case EglDisplayType:
+ return glcontext->nativeDisplay();
+ case EglConfigType:
+ return glcontext->nativeConfig();
+ default:
+ break;
}
-#endif // QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
return 0;
@@ -182,4 +209,19 @@ void QWindowsNativeInterface::setAsyncExpose(bool value)
QWindowsContext::instance()->setAsyncExpose(value);
}
+void QWindowsNativeInterface::registerWindowsMime(void *mimeIn)
+{
+ QWindowsContext::instance()->mimeConverter().registerMime(reinterpret_cast<QWindowsMime *>(mimeIn));
+}
+
+void QWindowsNativeInterface::unregisterWindowsMime(void *mimeIn)
+{
+ QWindowsContext::instance()->mimeConverter().unregisterMime(reinterpret_cast<QWindowsMime *>(mimeIn));
+}
+
+int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
+{
+ return QWindowsMime::registerMimeType(mimeType);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index 20100d0f49..1afa0571a0 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -66,11 +66,13 @@ class QWindowsNativeInterface : public QPlatformNativeInterface
{
Q_OBJECT
Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose)
+
public:
+ void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
#ifndef QT_NO_OPENGL
- virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
#endif
- virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
const QString &windowName,
@@ -80,13 +82,17 @@ public:
Q_INVOKABLE void beep() { MessageBeep(MB_OK); } // For QApplication
+ Q_INVOKABLE void registerWindowsMime(void *mimeIn);
+ Q_INVOKABLE void unregisterWindowsMime(void *mime);
+ Q_INVOKABLE int registerMimeType(const QString &mimeType);
+
bool asyncExpose() const;
void setAsyncExpose(bool value);
- QVariantMap windowProperties(QPlatformWindow *window) const;
- QVariant windowProperty(QPlatformWindow *window, const QString &name) const;
- QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const;
- void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
+ QVariantMap windowProperties(QPlatformWindow *window) const Q_DECL_OVERRIDE;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name) const Q_DECL_OVERRIDE;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE;
+ void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
new file mode 100644
index 0000000000..555af72f37
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 QWINDOWSOPENGLCONTEXT_H
+#define QWINDOWSOPENGLCONTEXT_H
+
+#include <QtGui/QOpenGLContext>
+#include <qpa/qplatformopenglcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_OPENGL
+
+class QWindowsOpenGLContext;
+
+class QWindowsStaticOpenGLContext
+{
+public:
+ static QWindowsStaticOpenGLContext *create();
+ virtual ~QWindowsStaticOpenGLContext() { }
+
+ virtual QWindowsOpenGLContext *createContext(QOpenGLContext *context) = 0;
+ virtual void *moduleHandle() const = 0;
+ virtual QOpenGLContext::OpenGLModuleType moduleType() const = 0;
+ virtual bool supportsThreadedOpenGL() const { return false; }
+
+ // If the windowing system interface needs explicitly created window surfaces (like EGL),
+ // reimplement these.
+ virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; }
+ virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
+};
+
+class QWindowsOpenGLContext : public QPlatformOpenGLContext
+{
+public:
+ virtual ~QWindowsOpenGLContext() { }
+
+ // Returns the native context handle (e.g. HGLRC for WGL, EGLContext for EGL).
+ virtual void *nativeContext() const = 0;
+
+ // These should be implemented only for some winsys interfaces, for example EGL.
+ // For others, like WGL, they are not relevant.
+ virtual void *nativeDisplay() const { return 0; }
+ virtual void *nativeConfig() const { return 0; }
+};
+
+#endif // QT_NO_OPENGL
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSOPENGLCONTEXT_H
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
new file mode 100644
index 0000000000..9ee62e6d56
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "qwindowsopengltester.h"
+#include "qt_windows.h"
+#include "qwindowscontext.h"
+
+QT_BEGIN_NAMESPACE
+
+bool QWindowsOpenGLTester::testDesktopGL()
+{
+ HMODULE lib = 0;
+ HWND wnd = 0;
+ HDC dc = 0;
+ HGLRC context = 0;
+ LPCTSTR className = L"qtopengltest";
+
+ HGLRC (WINAPI * CreateContext)(HDC dc) = 0;
+ BOOL (WINAPI * DeleteContext)(HGLRC context) = 0;
+ BOOL (WINAPI * MakeCurrent)(HDC dc, HGLRC context) = 0;
+ PROC (WINAPI * WGL_GetProcAddress)(LPCSTR name) = 0;
+
+ bool result = false;
+
+ // Test #1: Load opengl32.dll and try to resolve an OpenGL 2 function.
+ // This will typically fail on systems that do not have a real OpenGL driver.
+ lib = LoadLibraryA("opengl32.dll");
+ if (lib) {
+ CreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(::GetProcAddress(lib, "wglCreateContext"));
+ if (!CreateContext)
+ goto cleanup;
+ DeleteContext = reinterpret_cast<BOOL (WINAPI *)(HGLRC)>(::GetProcAddress(lib, "wglDeleteContext"));
+ if (!DeleteContext)
+ goto cleanup;
+ MakeCurrent = reinterpret_cast<BOOL (WINAPI *)(HDC, HGLRC)>(::GetProcAddress(lib, "wglMakeCurrent"));
+ if (!MakeCurrent)
+ goto cleanup;
+ WGL_GetProcAddress = reinterpret_cast<PROC (WINAPI *)(LPCSTR)>(::GetProcAddress(lib, "wglGetProcAddress"));
+ if (!WGL_GetProcAddress)
+ goto cleanup;
+
+ WNDCLASS wclass;
+ wclass.cbClsExtra = 0;
+ wclass.cbWndExtra = 0;
+ wclass.hInstance = (HINSTANCE) GetModuleHandle(0);
+ wclass.hIcon = 0;
+ wclass.hCursor = 0;
+ wclass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND);
+ wclass.lpszMenuName = 0;
+ wclass.lpfnWndProc = DefWindowProc;
+ wclass.lpszClassName = className;
+ wclass.style = CS_OWNDC;
+ if (!RegisterClass(&wclass))
+ goto cleanup;
+ wnd = CreateWindow(className, L"qtopenglproxytest", WS_OVERLAPPED,
+ 0, 0, 640, 480, 0, 0, wclass.hInstance, 0);
+ if (!wnd)
+ goto cleanup;
+ dc = GetDC(wnd);
+ if (!dc)
+ goto cleanup;
+
+ PIXELFORMATDESCRIPTOR pfd;
+ memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_GENERIC_FORMAT;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ // Use the GDI functions. Under the hood this will call the wgl variants in opengl32.dll.
+ int pixelFormat = ChoosePixelFormat(dc, &pfd);
+ if (!pixelFormat)
+ goto cleanup;
+ if (!SetPixelFormat(dc, pixelFormat, &pfd))
+ goto cleanup;
+ context = CreateContext(dc);
+ if (!context)
+ goto cleanup;
+ if (!MakeCurrent(dc, context))
+ goto cleanup;
+
+ // Now that there is finally a context current, try doing something useful.
+ if (WGL_GetProcAddress("glCreateShader")) {
+ result = true;
+ qCDebug(lcQpaGl, "OpenGL 2.0 entry points available");
+ } else {
+ qCDebug(lcQpaGl, "OpenGL 2.0 entry points not found");
+ }
+ } else {
+ qCDebug(lcQpaGl, "Failed to load opengl32.dll");
+ }
+
+cleanup:
+ if (MakeCurrent)
+ MakeCurrent(0, 0);
+ if (context)
+ DeleteContext(context);
+ if (dc && wnd)
+ ReleaseDC(wnd, dc);
+ if (wnd) {
+ DestroyWindow(wnd);
+ UnregisterClass(className, GetModuleHandle(0));
+ }
+ // No FreeLibrary. Some implementations, Mesa in particular, deadlock when trying to unload.
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
new file mode 100644
index 0000000000..f7cd7e3005
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 <qtwindowsglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsOpenGLTester
+{
+public:
+ static bool testDesktopGL();
+};
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a6e2aabaf0..bcdb8a2352 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -68,6 +68,21 @@ static inline QDpi deviceDPI(HDC hdc)
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
}
+#ifndef Q_OS_WINCE
+
+static inline QDpi monitorDPI(HMONITOR hMonitor)
+{
+ if (QWindowsContext::shcoredll.isValid()) {
+ UINT dpiX;
+ UINT dpiY;
+ if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY)))
+ return QDpi(dpiX, dpiY);
+ }
+ return QDpi(0, 0);
+}
+
+#endif // !Q_OS_WINCE
+
static inline QSizeF deviceSizeMM(const QSize &pixels, const QDpi &dpi)
{
const qreal inchToMM = 25.4;
@@ -110,7 +125,12 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL);
#endif
if (hdc) {
+#ifndef Q_OS_WINCE
+ const QDpi dpi = monitorDPI(hMonitor);
+ data.dpi = dpi.first ? dpi : deviceDPI(hdc);
+#else
data.dpi = deviceDPI(hdc);
+#endif
data.depth = GetDeviceCaps(hdc, BITSPIXEL);
data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
@@ -387,6 +407,30 @@ static inline int indexOfMonitor(const QList<QWindowsScreenData> &screenData,
return -1;
}
+void QWindowsScreenManager::removeScreen(int index)
+{
+ qCDebug(lcQpaWindows) << "Removing Monitor:" << m_screens.at(index)->data();
+ QScreen *screen = m_screens.at(index)->screen();
+ QScreen *primaryScreen = QGuiApplication::primaryScreen();
+ // QTBUG-38650: When a screen is disconnected, Windows will automatically
+ // move the Window to another screen. This will trigger a geometry change
+ // event, but unfortunately after the screen destruction signal. To prevent
+ // QtGui from automatically hiding the QWindow, pretend all Windows move to
+ // the primary screen first (which is likely the correct, final screen).
+ if (screen != primaryScreen) {
+ unsigned movedWindowCount = 0;
+ foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
+ if (w->screen() == screen && w->handle() && w->type() != Qt::Desktop) {
+ QWindowSystemInterface::handleWindowScreenChanged(w, primaryScreen);
+ ++movedWindowCount;
+ }
+ }
+ if (movedWindowCount)
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
+ delete m_screens.takeAt(index);
+}
+
/*!
\brief Synchronizes the screen list, adds new screens, removes deleted
ones and propagates resolution changes to QWindowSystemInterface.
@@ -412,10 +456,8 @@ bool QWindowsScreenManager::handleScreenChanges()
// temporary lock screen to avoid window recreation (QTBUG-33062).
if (!lockScreen) {
for (int i = m_screens.size() - 1; i >= 0; --i) {
- if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1) {
- qCDebug(lcQpaWindows) << "Removing Monitor: " << m_screens.at(i) ->data();
- delete m_screens.takeAt(i);
- } // not found
+ if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1)
+ removeScreen(i);
} // for existing screens
} // not lock screen
return true;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 930814a17d..c9d8a5662c 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -88,24 +88,24 @@ public:
static QWindowsScreen *screenOf(const QWindow *w = 0);
- virtual QRect geometry() const { return m_data.geometry; }
- virtual QRect availableGeometry() const { return m_data.availableGeometry; }
- virtual int depth() const { return m_data.depth; }
- virtual QImage::Format format() const { return m_data.format; }
- virtual QSizeF physicalSize() const { return m_data.physicalSizeMM; }
- virtual QDpi logicalDpi() const { return m_data.dpi; }
- virtual qreal refreshRate() const { return m_data.refreshRateHz; }
- virtual QString name() const { return m_data.name; }
- virtual Qt::ScreenOrientation primaryOrientation() { return m_data.orientation; }
- virtual QList<QPlatformScreen *> virtualSiblings() const;
- virtual QWindow *topLevelAt(const QPoint &point) const
+ QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
+ QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
+ int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
+ QImage::Format format() const Q_DECL_OVERRIDE { return m_data.format; }
+ QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_data.physicalSizeMM; }
+ QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_data.dpi; }
+ qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; }
+ QString name() const Q_DECL_OVERRIDE { return m_data.name; }
+ Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; }
+ QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE;
+ QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE
{ return QWindowsScreen::findTopLevelAt(point, CWP_SKIPINVISIBLE); }
static QWindow *findTopLevelAt(const QPoint &point, unsigned flags);
static QWindow *windowAt(const QPoint &point, unsigned flags = CWP_SKIPINVISIBLE);
static QWindow *windowUnderMouse(unsigned flags = CWP_SKIPINVISIBLE);
- virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+ QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
inline void handleChanges(const QWindowsScreenData &newData);
@@ -143,6 +143,8 @@ public:
const WindowsScreenList &screens() const { return m_screens; }
private:
+ void removeScreen(int index);
+
WindowsScreenList m_screens;
int m_lastDepth;
WORD m_lastHorizontalResolution;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 8ceab02311..d1737de907 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -465,7 +465,9 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
const double degY = atan(cos(radAzim) / tanAlt);
tiltX = int(degX * (180 / M_PI));
tiltY = int(-degY * (180 / M_PI));
- rotation = packet.pkOrientation.orTwist;
+ rotation = 360.0 - (packet.pkOrientation.orTwist / 10.0);
+ if (rotation > 180.0)
+ rotation -= 360.0;
}
if (QWindowsContext::verbose > 1) {
@@ -477,8 +479,9 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
- QWindowSystemInterface::handleTabletEvent(target, packet.pkButtons, localPos, globalPosF,
+ QWindowSystemInterface::handleTabletEvent(target, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
+ static_cast<Qt::MouseButtons>(packet.pkButtons),
pressureNew, tiltX, tiltY,
tangentialPressure, rotation, z,
m_devices.at(m_currentDevice).uniqueId,
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 9346621d59..4414c71bc0 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -59,17 +59,17 @@ public:
static QWindowsTheme *instance() { return m_instance; }
- virtual bool usePlatformNativeDialog(DialogType type) const;
- virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
- virtual QVariant themeHint(ThemeHint) const;
+ bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE;
+ QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE;
virtual const QPalette *palette(Palette type = SystemPalette) const
{ return m_palettes[type]; }
virtual const QFont *font(Font type = SystemFont) const
{ return m_fonts[type]; }
- virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
- virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
- QPlatformTheme::IconOptions iconOptions = 0) const;
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE;
+ QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size,
+ QPlatformTheme::IconOptions iconOptions = 0) const Q_DECL_OVERRIDE;
void windowsThemeChanged(QWindow *window);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 7d04c99d16..c5978c125c 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -48,15 +48,11 @@
# include "qwindowscursor.h"
#endif
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include "qwindowseglcontext.h"
-# include <QtGui/QOpenGLFunctions>
-#endif
-
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtGui/QRegion>
+#include <QtGui/QOpenGLContext>
#include <private/qsystemlibrary_p.h>
#include <private/qwindow_p.h>
#include <private/qguiapplication_p.h>
@@ -110,6 +106,8 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_CONTEXTHELP";
if (exStyle & WS_EX_LAYERED)
rc += " WS_EX_LAYERED";
+ if (exStyle & WS_EX_DLGMODALFRAME)
+ rc += " WS_EX_DLGMODALFRAME";
return rc;
}
@@ -183,6 +181,14 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
static inline QRect frameGeometry(HWND hwnd, bool topLevel)
{
RECT rect = { 0, 0, 0, 0 };
+#ifndef Q_OS_WINCE
+ if (topLevel) {
+ WINDOWPLACEMENT windowPlacement;
+ GetWindowPlacement(hwnd, &windowPlacement);
+ if (windowPlacement.showCmd == SW_SHOWMINIMIZED)
+ return qrectFromRECT(windowPlacement.rcNormalPosition);
+ }
+#endif // !Q_OS_WINCE
GetWindowRect(hwnd, &rect); // Screen coordinates.
const HWND parent = GetParent(hwnd);
if (parent && !topLevel) {
@@ -513,6 +519,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
+ else if (dialog) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
+ }
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton(w, flags))
@@ -861,15 +871,13 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_opacity(1.0),
m_dropTarget(0),
m_savedStyle(0),
- m_format(aWindow->format()),
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- m_eglSurface(0),
-#endif
+ m_format(aWindow->requestedFormat()),
#ifdef Q_OS_WINCE
m_previouslyHidden(false),
#endif
m_iconSmall(0),
- m_iconBig(0)
+ m_iconBig(0),
+ m_surface(0)
{
// Clear the creation context as the window can be found in QWindowsContext's map.
QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>());
@@ -877,13 +885,14 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
const Qt::WindowType type = aWindow->type();
if (type == Qt::Desktop)
return; // No further handling for Qt::Desktop
+#ifndef QT_NO_OPENGL
if (aWindow->surfaceType() == QWindow::OpenGLSurface) {
- setFlag(OpenGLSurface);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL)
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
+ setFlag(OpenGLSurface);
+ else
setFlag(OpenGL_ES2);
-#endif
}
+#endif // QT_NO_OPENGL
updateDropSite();
#ifndef Q_OS_WINCE
@@ -947,11 +956,10 @@ void QWindowsWindow::destroyWindow()
if (hasMouseCapture())
setMouseGrabEnabled(false);
setDropSiteEnabled(false);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (m_eglSurface) {
- qCDebug(lcQpaGl) << __FUNCTION__ << "Freeing EGL surface " << m_eglSurface << window();
- eglDestroySurface(m_staticEglContext->display(), m_eglSurface);
- m_eglSurface = 0;
+#ifndef QT_NO_OPENGL
+ if (m_surface) {
+ m_data.staticOpenGLContext->destroyWindowSurface(m_surface);
+ m_surface = 0;
}
#endif
#ifdef Q_OS_WINCE
@@ -1383,6 +1391,11 @@ void QWindowsWindow::handleGeometryChange()
&& !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) {
fireExpose(QRegion(m_data.geometry), true);
}
+ if (previousGeometry.topLeft() != m_data.geometry.topLeft()) {
+ QPlatformScreen *newScreen = screenForGeometry(m_data.geometry);
+ if (newScreen != screen())
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ }
if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents();
@@ -1399,15 +1412,29 @@ void QWindowsWindow::setGeometry_sys(const QRect &rect) const
<< margins << " to " <<rect
<< " new frame: " << frameGeometry;
- const bool rc = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
- frameGeometry.width(), frameGeometry.height(), true);
+ bool result = false;
+#ifndef Q_OS_WINCE
+ WINDOWPLACEMENT windowPlacement;
+ GetWindowPlacement(m_data.hwnd, &windowPlacement);
+ // If the window is hidden and in maximized state or minimized, instead of moving the
+ // window, set the normal position of the window.
+ if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(m_data.hwnd))
+ || windowPlacement.showCmd == SW_SHOWMINIMIZED) {
+ windowPlacement.rcNormalPosition = RECTfromQRect(frameGeometry);
+ windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
+ result = SetWindowPlacement(m_data.hwnd, &windowPlacement);
+ } else
+#endif // !Q_OS_WINCE
+ {
+ result = MoveWindow(m_data.hwnd, frameGeometry.x(), frameGeometry.y(),
+ frameGeometry.width(), frameGeometry.height(), true);
+ }
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window()
- << " \n resulting " << rc << geometry_sys();
+ << " \n resulting " << result << geometry_sys();
}
QRect QWindowsWindow::frameGeometry_sys() const
{
- // Warning: Returns bogus values when minimized.
bool isRealTopLevel = window()->isTopLevel() && !m_data.embedded;
return frameGeometry(m_data.hwnd, isRealTopLevel);
}
@@ -1573,23 +1600,9 @@ void QWindowsWindow::setWindowState(Qt::WindowState state)
}
}
-// Return the effective screen for full screen mode in a virtual desktop.
-static const QScreen *effectiveScreen(const QWindow *w)
-{
- QPoint center = w->geometry().center();
- if (!w->isTopLevel())
- center = w->mapToGlobal(center);
- const QScreen *screen = w->screen();
- if (!screen->geometry().contains(center))
- foreach (const QScreen *sibling, screen->virtualSiblings())
- if (sibling->geometry().contains(center))
- return sibling;
- return screen;
-}
-
bool QWindowsWindow::isFullScreen_sys() const
{
- return window()->isTopLevel() && geometry_sys() == effectiveScreen(window())->geometry();
+ return window()->isTopLevel() && geometry_sys() == window()->screen()->geometry();
}
/*!
@@ -1669,7 +1682,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the
// window is in (QTBUG-31166, QTBUG-30724).
- const QScreen *screen = testFlag(WithinCreate) ? window()->screen() : effectiveScreen(window());
+ const QScreen *screen = window()->screen();
const QRect r = screen->geometry();
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
@@ -1939,7 +1952,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
&& (m_data.flags & Qt::FramelessWindowHint)) {
// This block fixes QTBUG-8361: Frameless windows shouldn't cover the
// taskbar when maximized
- const QScreen *screen = effectiveScreen(window());
+ const QScreen *screen = window()->screen();
// Documentation of MINMAXINFO states that it will only work for the primary screen
if (screen && screen == QGuiApplication::primaryScreen()) {
@@ -2144,23 +2157,6 @@ void QWindowsWindow::setEnabled(bool enabled)
setStyle(newStyle);
}
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-EGLSurface QWindowsWindow::ensureEglSurfaceHandle(const QWindowsWindow::QWindowsEGLStaticContextPtr &staticContext, EGLConfig config)
-{
- if (!m_eglSurface) {
- m_staticEglContext = staticContext;
- m_eglSurface = eglCreateWindowSurface(staticContext->display(), config, (EGLNativeWindowType)m_data.hwnd, NULL);
- if (m_eglSurface == EGL_NO_SURFACE)
- qWarning("%s: Could not create the egl surface for %s/'%s' (eglCreateWindowSurface failed): error = 0x%x\n",
- Q_FUNC_INFO, window()->metaObject()->className(),
- qPrintable(window()->objectName()), eglGetError());
-
- qCDebug(lcQpaGl) << __FUNCTION__<<"Created EGL surface "<< m_eglSurface <<window();
- }
- return m_eglSurface;
-}
-#endif // QT_OPENGL_ES_2
-
QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
{
const int iwf = int(wf);
@@ -2272,4 +2268,16 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
}
}
+void *QWindowsWindow::surface(void *nativeConfig)
+{
+#ifdef QT_NO_OPENGL
+ return 0;
+#else
+ if (!m_surface)
+ m_surface = m_data.staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig);
+
+ return m_surface;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index cb437b76d0..19d2236688 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -47,23 +47,15 @@
# include "qplatformfunctions_wince.h"
#endif
#include "qwindowscursor.h"
+#include "qwindowsopenglcontext.h"
#include <qpa/qplatformwindow.h>
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-# include <QtCore/QSharedPointer>
-# include <EGL/egl.h>
-#endif
-
QT_BEGIN_NAMESPACE
class QWindowsOleDropTarget;
class QDebug;
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
-class QWindowsEGLStaticContext;
-#endif
-
struct QWindowsGeometryHint
{
QWindowsGeometryHint() {}
@@ -121,6 +113,9 @@ struct QWindowsWindowData
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd;
bool embedded;
+#ifndef QT_NO_OPENGL
+ QSharedPointer<QWindowsStaticOpenGLContext> staticOpenGLContext;
+#endif // QT_NO_OPENGL
static QWindowsWindowData create(const QWindow *w,
const QWindowsWindowData &parameters,
@@ -130,10 +125,6 @@ struct QWindowsWindowData
class QWindowsWindow : public QPlatformWindow
{
public:
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- typedef QSharedPointer<QWindowsEGLStaticContext> QWindowsEGLStaticContextPtr;
-#endif
-
enum Flags
{
AutoMouseCapture = 0x1, //! Automatic mouse capture on button press.
@@ -160,46 +151,46 @@ public:
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsWindow();
- virtual QSurfaceFormat format() const { return m_format; }
- virtual void setGeometry(const QRect &rect);
- virtual QRect geometry() const { return m_data.geometry; }
+ QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
+ void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
+ QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
QRect normalGeometry() const Q_DECL_OVERRIDE;
- virtual void setVisible(bool visible);
+ void setVisible(bool visible) Q_DECL_OVERRIDE;
bool isVisible() const;
- virtual bool isExposed() const { return testFlag(Exposed); }
- virtual bool isActive() const;
- virtual bool isEmbedded(const QPlatformWindow *parentWindow) const;
- virtual QPoint mapToGlobal(const QPoint &pos) const;
- virtual QPoint mapFromGlobal(const QPoint &pos) const;
+ bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); }
+ bool isActive() const Q_DECL_OVERRIDE;
+ bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE;
+ QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
+ QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
- virtual void setWindowFlags(Qt::WindowFlags flags);
- virtual void setWindowState(Qt::WindowState state);
+ void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
HWND handle() const { return m_data.hwnd; }
- virtual WId winId() const { return WId(m_data.hwnd); }
- virtual void setParent(const QPlatformWindow *window);
+ WId winId() const Q_DECL_OVERRIDE { return WId(m_data.hwnd); }
+ void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
- virtual void setWindowTitle(const QString &title);
- virtual void raise();
- virtual void lower();
+ void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
+ void raise() Q_DECL_OVERRIDE;
+ void lower() Q_DECL_OVERRIDE;
void windowEvent(QEvent *event);
- virtual void propagateSizeHints();
- virtual QMargins frameMargins() const;
+ void propagateSizeHints() Q_DECL_OVERRIDE;
+ QMargins frameMargins() const Q_DECL_OVERRIDE;
- virtual void setOpacity(qreal level);
- virtual void setMask(const QRegion &region);
+ void setOpacity(qreal level) Q_DECL_OVERRIDE;
+ void setMask(const QRegion &region) Q_DECL_OVERRIDE;
qreal opacity() const { return m_opacity; }
- virtual void requestActivateWindow();
+ void requestActivateWindow() Q_DECL_OVERRIDE;
- virtual bool setKeyboardGrabEnabled(bool grab);
- virtual bool setMouseGrabEnabled(bool grab);
+ bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
+ bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
+ bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE;
void setFrameStrutEventsEnabled(bool enabled);
bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); }
@@ -207,11 +198,6 @@ public:
QMargins customMargins() const { return m_data.customMargins; }
void setCustomMargins(const QMargins &m);
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- EGLSurface eglSurfaceHandle() const { return m_eglSurface;}
- EGLSurface ensureEglSurfaceHandle(const QWindowsEGLStaticContextPtr &staticContext, EGLConfig config);
-#endif
-
inline unsigned style() const
{ return GetWindowLongPtr(m_data.hwnd, GWL_STYLE); }
void setStyle(unsigned s) const;
@@ -263,6 +249,8 @@ public:
bool isEnabled() const;
void setWindowIcon(const QIcon &icon);
+ void *surface(void *nativeConfig);
+
#ifndef Q_OS_WINCE
void setAlertState(bool enabled);
bool isAlertState() const { return testFlag(AlertState); }
@@ -302,15 +290,12 @@ private:
unsigned m_savedStyle;
QRect m_savedFrameGeometry;
const QSurfaceFormat m_format;
-#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- EGLSurface m_eglSurface;
- QSharedPointer<QWindowsEGLStaticContext> m_staticEglContext;
-#endif
#ifdef Q_OS_WINCE
bool m_previouslyHidden;
#endif
HICON m_iconSmall;
HICON m_iconBig;
+ void *m_surface;
};
// Debug
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 13799ba1ba..104d882fba 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -66,8 +66,12 @@ HEADERS += \
$$PWD/qwindowsnativeimage.h \
$$PWD/qwindowsnativeinterface.h
+!wince: HEADERS += $$PWD/qwindowsopengltester.h
+
INCLUDEPATH += $$PWD
+contains(QT_CONFIG,opengl): HEADERS += $$PWD/qwindowsopenglcontext.h
+
contains(QT_CONFIG, opengles2) {
SOURCES += $$PWD/qwindowseglcontext.cpp
HEADERS += $$PWD/qwindowseglcontext.h
@@ -78,7 +82,8 @@ contains(QT_CONFIG, opengles2) {
# Dynamic GL needs both WGL and EGL
contains(QT_CONFIG,dynamicgl) {
- SOURCES += $$PWD/qwindowseglcontext.cpp
+ SOURCES += $$PWD/qwindowseglcontext.cpp \
+ $$PWD/qwindowsopengltester.cpp
HEADERS += $$PWD/qwindowseglcontext.h
}
@@ -108,6 +113,10 @@ contains(QT_CONFIG,dynamicgl) {
HEADERS += $$PWD/qwindowssessionmanager.h
}
+!wince*:!contains( DEFINES, QT_NO_IMAGEFORMAT_PNG ) {
+ RESOURCES += $$PWD/cursors.qrc
+}
+
contains(QT_CONFIG, freetype) {
DEFINES *= QT_NO_FONTCONFIG
QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
index f09454ebc3..d2d87bde0b 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.cpp
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -40,40 +40,54 @@
****************************************************************************/
#include "qwinrtcursor.h"
+#include "qwinrtscreen.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
#include <wrl.h>
#include <windows.ui.core.h>
#include <windows.foundation.h>
+using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::Foundation;
-QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+
+class QWinRTCursorPrivate
+{
+public:
+ ComPtr<ICoreCursorFactory> cursorFactory;
+};
-QWinRTCursor::QWinRTCursor(ICoreWindow *window) : m_window(window), m_cursorFactory(nullptr)
+QWinRTCursor::QWinRTCursor()
+ : d_ptr(new QWinRTCursorPrivate)
{
-#ifndef Q_OS_WINPHONE
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(), &m_cursorFactory);
-#endif
+ Q_D(QWinRTCursor);
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Core_CoreCursor).Get(),
+ IID_PPV_ARGS(&d->cursorFactory));
+ Q_ASSERT_SUCCEEDED(hr);
}
QWinRTCursor::~QWinRTCursor()
{
- if (m_cursorFactory)
- m_cursorFactory->Release();
}
#ifndef QT_NO_CURSOR
-void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *)
+void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
-#ifndef Q_OS_WINPHONE
- if (!m_cursorFactory)
- return;
+ Q_D(QWinRTCursor);
+
+ ICoreWindow *coreWindow = static_cast<QWinRTScreen *>(window->screen()->handle())->coreWindow();
CoreCursorType type;
switch (windowCursor ? windowCursor->shape() : Qt::ArrowCursor) {
case Qt::BlankCursor:
- m_window->put_PointerCursor(nullptr);
+ coreWindow->put_PointerCursor(Q_NULLPTR);
return;
default:
case Qt::OpenHandCursor:
@@ -132,24 +146,20 @@ void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *)
break;
}
- ICoreCursor *cursor;
- if (SUCCEEDED(m_cursorFactory->CreateCursor(type, 0, &cursor)))
- m_window->put_PointerCursor(cursor);
-#else // Q_OS_WINPHONE
- Q_UNUSED(windowCursor)
-#endif // Q_OS_WINPHONE
+ ComPtr<ICoreCursor> cursor;
+ HRESULT hr = d->cursorFactory->CreateCursor(type, 0, &cursor);
+ RETURN_VOID_IF_FAILED("Failed to create native cursor.");
+
+ hr = coreWindow->put_PointerCursor(cursor.Get());
+ RETURN_VOID_IF_FAILED("Failed to set native cursor.");
}
#endif // QT_NO_CURSOR
QPoint QWinRTCursor::pos() const
{
-#ifdef Q_OS_WINPHONE
- return QPlatformCursor::pos();
-#else
+ ICoreWindow *coreWindow =
+ static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle())->coreWindow();
Point point;
- m_window->get_PointerPosition(&point);
+ coreWindow->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
index f7b301a98b..a08002f34c 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.h
+++ b/src/plugins/platforms/winrt/qwinrtcursor.h
@@ -44,34 +44,22 @@
#include <qpa/qplatformcursor.h>
-namespace ABI {
- namespace Windows {
- namespace UI {
- namespace Core {
- struct ICoreWindow;
- struct ICoreCursorFactory;
- }
- }
- }
-}
-
-QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+class QWinRTCursorPrivate;
class QWinRTCursor : public QPlatformCursor
{
public:
- explicit QWinRTCursor(ABI::Windows::UI::Core::ICoreWindow *window);
+ explicit QWinRTCursor();
~QWinRTCursor();
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor * windowCursor, QWindow *);
+ void changeCursor(QCursor * windowCursor, QWindow *window);
#endif
QPoint pos() const;
private:
- ABI::Windows::UI::Core::ICoreWindow *m_window;
- ABI::Windows::UI::Core::ICoreCursorFactory *m_cursorFactory;
+ QScopedPointer<QWinRTCursorPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTCursor)
};
-QT_END_NAMESPACE
-
#endif // QWINRTCURSOR_H
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index b3a2cafa2e..53d52a430c 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -48,7 +48,7 @@
#include "qwinrtservices.h"
#include "qwinrteglcontext.h"
#include "qwinrtfontdatabase.h"
-#include "qwinrtplatformtheme.h"
+#include "qwinrttheme.h"
#include <QtGui/QOpenGLContext>
@@ -63,18 +63,6 @@ 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()
@@ -82,26 +70,7 @@ QWinRTIntegration::QWinRTIntegration()
, 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);
+ m_screen = new QWinRTScreen;
screenAdded(m_screen);
m_success = true;
@@ -133,26 +102,7 @@ bool QWinRTIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
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);
+ return QWinRTTheme::styleHint(hint);
}
QPlatformWindow *QWinRTIntegration::createPlatformWindow(QWindow *window) const
@@ -200,7 +150,7 @@ QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &
name) const
{
if (name == QLatin1String("winrt"))
- return new QWinRTPlatformTheme();
+ return new QWinRTTheme();
return 0;
}
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
new file mode 100644
index 0000000000..6de90ba1ec
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "qwinrtmessagedialoghelper.h"
+#include "qwinrttheme.h"
+
+#include <QtCore/qfunctions_winrt.h>
+
+#include <windows.ui.popups.h>
+#include <windows.foundation.h>
+#include <windows.foundation.collections.h>
+#include <wrl.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::UI::Popups;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+typedef IAsyncOperationCompletedHandler<IUICommand *> DialogCompletedHandler;
+
+QT_BEGIN_NAMESPACE
+
+class CommandId : public RuntimeClass<IInspectable>
+{
+public:
+ CommandId(QPlatformDialogHelper::StandardButton button)
+ : button(button) { }
+ QPlatformDialogHelper::StandardButton button;
+};
+
+class QWinRTMessageDialogHelperPrivate
+{
+public:
+ const QWinRTTheme *theme;
+ bool shown;
+ ComPtr<IAsyncInfo> info;
+ QEventLoop loop;
+};
+
+QWinRTMessageDialogHelper::QWinRTMessageDialogHelper(const QWinRTTheme *theme)
+ : QPlatformMessageDialogHelper(), d_ptr(new QWinRTMessageDialogHelperPrivate)
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ d->theme = theme;
+ d->shown = false;
+}
+
+QWinRTMessageDialogHelper::~QWinRTMessageDialogHelper()
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (d->shown)
+ hide();
+}
+
+void QWinRTMessageDialogHelper::exec()
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (!d->shown)
+ show(Qt::Dialog, Qt::ApplicationModal, 0);
+ d->loop.exec();
+}
+
+bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
+{
+ Q_UNUSED(windowFlags)
+ Q_UNUSED(windowModality)
+ Q_UNUSED(parent)
+ Q_D(QWinRTMessageDialogHelper);
+
+ QSharedPointer<QMessageDialogOptions> options = this->options();
+ const QString informativeText = options->informativeText();
+ const QString title = options->windowTitle();
+ const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText);
+
+ HRESULT hr;
+ ComPtr<IMessageDialogFactory> dialogFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_MessageDialog).Get(),
+ IID_PPV_ARGS(&dialogFactory));
+ RETURN_FALSE_IF_FAILED("Failed to create dialog factory");
+
+ ComPtr<IUICommandFactory> commandFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_UICommand).Get(),
+ IID_PPV_ARGS(&commandFactory));
+ RETURN_FALSE_IF_FAILED("Failed to create command factory");
+
+ ComPtr<IMessageDialog> dialog;
+ HStringReference nativeText(reinterpret_cast<LPCWSTR>(text.utf16()), text.size());
+ if (!title.isEmpty()) {
+ HStringReference nativeTitle(reinterpret_cast<LPCWSTR>(title.utf16()), title.size());
+ hr = dialogFactory->CreateWithTitle(nativeText.Get(), nativeTitle.Get(), &dialog);
+ RETURN_FALSE_IF_FAILED("Failed to create dialog with title");
+ } else {
+ hr = dialogFactory->Create(nativeText.Get(), &dialog);
+ RETURN_FALSE_IF_FAILED("Failed to create dialog");
+ }
+
+ // Add Buttons
+ ComPtr<IVector<IUICommand *>> dialogCommands;
+ hr = dialog->get_Commands(&dialogCommands);
+ RETURN_FALSE_IF_FAILED("Failed to get dialog commands");
+
+ // If no button is specified we need to create one to get close notification
+ int buttons = options->standardButtons();
+ if (buttons == 0)
+ buttons = Ok;
+
+ for (int i = FirstButton; i < LastButton; i<<=1) {
+ if (!(buttons & i))
+ continue;
+ // Add native command
+ const QString label = d->theme->standardButtonText(i);
+ HStringReference nativeLabel(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
+ ComPtr<IUICommand> command;
+ hr = commandFactory->Create(nativeLabel.Get(), &command);
+ RETURN_FALSE_IF_FAILED("Failed to create message box command");
+ ComPtr<IInspectable> id = Make<CommandId>(static_cast<StandardButton>(i));
+ hr = command->put_Id(id.Get());
+ RETURN_FALSE_IF_FAILED("Failed to set command ID");
+ hr = dialogCommands->Append(command.Get());
+ if (hr == E_BOUNDS) {
+ qErrnoWarning(hr, "The WinRT message dialog supports a maximum of three buttons");
+ continue;
+ }
+ RETURN_FALSE_IF_FAILED("Failed to append message box command");
+ if (i == Abort || i == Cancel || i == Close) {
+ quint32 size;
+ hr = dialogCommands->get_Size(&size);
+ RETURN_FALSE_IF_FAILED("Failed to get command list size");
+ hr = dialog->put_CancelCommandIndex(size - 1);
+ RETURN_FALSE_IF_FAILED("Failed to set cancel index");
+ }
+ }
+
+ ComPtr<IAsyncOperation<IUICommand *>> op;
+ hr = dialog->ShowAsync(&op);
+ RETURN_FALSE_IF_FAILED("Failed to show dialog");
+ hr = op->put_Completed(Callback<DialogCompletedHandler>(this, &QWinRTMessageDialogHelper::onCompleted).Get());
+ RETURN_FALSE_IF_FAILED("Failed to set dialog callback");
+
+ d->shown = true;
+ hr = op.As(&d->info);
+ RETURN_FALSE_IF_FAILED("Failed to acquire AsyncInfo for MessageDialog");
+
+ return true;
+}
+
+void QWinRTMessageDialogHelper::hide()
+{
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (!d->shown)
+ return;
+
+ HRESULT hr = d->info->Cancel();
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Failed to cancel dialog operation");
+
+ d->shown = false;
+}
+
+HRESULT QWinRTMessageDialogHelper::onCompleted(IAsyncOperation<IUICommand *> *asyncInfo, AsyncStatus status)
+{
+ Q_UNUSED(status);
+ Q_D(QWinRTMessageDialogHelper);
+
+ if (d->loop.isRunning())
+ d->loop.exit();
+
+ d->shown = false;
+
+ if (status == Canceled) {
+ emit reject();
+ return S_OK;
+ }
+
+ HRESULT hr;
+ ComPtr<IUICommand> command;
+ hr = asyncInfo->GetResults(&command);
+ RETURN_OK_IF_FAILED("Failed to get command");
+
+ ComPtr<CommandId> id;
+ hr = command->get_Id(&id);
+ RETURN_OK_IF_FAILED("Failed to get command ID");
+
+ ButtonRole role = buttonRole(id->button);
+ emit clicked(id->button, role);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.h b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
index fbb21ed69c..25199e569c 100644
--- a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
@@ -39,11 +39,10 @@
**
****************************************************************************/
-#ifndef QWINRTPLATFORMMESSAGEDIALOGHELPER_H
-#define QWINRTPLATFORMMESSAGEDIALOGHELPER_H
+#ifndef QWINRTMESSAGEDIALOGHELPER_H
+#define QWINRTMESSAGEDIALOGHELPER_H
#include <qpa/qplatformdialoghelper.h>
-#include <QtCore/QEventLoop>
#include <QtCore/qt_windows.h>
namespace ABI {
@@ -53,19 +52,24 @@ namespace ABI {
struct IUICommand;
}
}
+ namespace Foundation {
+ enum class AsyncStatus;
+ template <typename T> struct IAsyncOperation;
+ }
}
}
QT_BEGIN_NAMESPACE
-struct QWinRTPlatformMessageDialogInfo;
+class QWinRTTheme;
-class QWinRTPlatformMessageDialogHelper : public QPlatformMessageDialogHelper
+class QWinRTMessageDialogHelperPrivate;
+class QWinRTMessageDialogHelper : public QPlatformMessageDialogHelper
{
Q_OBJECT
public:
- explicit QWinRTPlatformMessageDialogHelper();
- ~QWinRTPlatformMessageDialogHelper();
+ explicit QWinRTMessageDialogHelper(const QWinRTTheme *theme);
+ ~QWinRTMessageDialogHelper();
void exec();
bool show(Qt::WindowFlags windowFlags,
@@ -73,13 +77,14 @@ public:
QWindow *parent);
void hide();
- HRESULT onInvoked(ABI::Windows::UI::Popups::IUICommand *command);
private:
- QWinRTPlatformMessageDialogInfo *m_info;
- QEventLoop m_loop;
- bool m_shown;
+ HRESULT onCompleted(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::UI::Popups::IUICommand *> *asyncInfo,
+ ABI::Windows::Foundation::AsyncStatus status);
+
+ QScopedPointer<QWinRTMessageDialogHelperPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTMessageDialogHelper)
};
QT_END_NAMESPACE
-#endif // QWINRTPLATFORMMESSAGEDIALOGHELPER_H
+#endif // QWINRTMESSAGEDIALOGHELPER_H
diff --git a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp
deleted file mode 100644
index c2f884055d..0000000000
--- a/src/plugins/platforms/winrt/qwinrtplatformmessagedialoghelper.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 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 "qwinrtplatformmessagedialoghelper.h"
-
-#include <QtGui/QGuiApplication>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformtheme.h>
-
-#include <asyncinfo.h>
-#include <windows.ui.popups.h>
-#include <windows.foundation.h>
-#include <windows.foundation.collections.h>
-#include <wrl.h>
-
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::Foundation::Collections;
-using namespace ABI::Windows::UI::Popups;
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-
-QT_BEGIN_NAMESPACE
-
-struct QWinRTPlatformMessageDialogInfo
-{
- ComPtr<IAsyncInfo> info;
-};
-
-QWinRTPlatformMessageDialogHelper::QWinRTPlatformMessageDialogHelper() :
- QPlatformMessageDialogHelper(),
- m_info(new QWinRTPlatformMessageDialogInfo),
- m_shown(false)
-{
-}
-
-QWinRTPlatformMessageDialogHelper::~QWinRTPlatformMessageDialogHelper()
-{
- if (m_shown)
- hide();
- delete m_info;
-}
-
-void QWinRTPlatformMessageDialogHelper::exec()
-{
- if (!m_shown)
- show(Qt::Dialog, Qt::ApplicationModal, 0);
- m_loop.exec();
-}
-
-bool QWinRTPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
-{
- Q_UNUSED(windowFlags)
- Q_UNUSED(windowModality)
- Q_UNUSED(parent)
-
- QSharedPointer<QMessageDialogOptions> options = this->options();
-
- const QString informativeText = options->informativeText();
- const QString title = options->windowTitle();
- const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText);
-
-
- ComPtr<IMessageDialogFactory> dialogFactory;
- if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_MessageDialog).Get(), &dialogFactory)))
- return false;
-
- ComPtr<IUICommandFactory> commandFactory;
- if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Popups_UICommand).Get(), &commandFactory)))
- return false;
-
- HString nativeText;
- nativeText.Set(reinterpret_cast<LPCWSTR>(text.utf16()), text.size());
- ComPtr<IMessageDialog> dialog;
-
- if (!title.isEmpty()) {
- HString nativeTitle;
- nativeTitle.Set(reinterpret_cast<LPCWSTR>(title.utf16()), title.size());
- if (FAILED(dialogFactory->CreateWithTitle(nativeText.Get(), nativeTitle.Get(), &dialog)))
- return false;
- } else {
- if (FAILED(dialogFactory->Create(nativeText.Get(), &dialog)))
- return false;
- }
-
- // Add Buttons
- ComPtr<IVector<IUICommand*> > dialogCommands;
- if (FAILED(dialog->get_Commands(&dialogCommands)))
- return false;
-
- // If no button is specified we need to create one to get close notification
- int buttons = options->standardButtons();
- if (buttons == 0)
- buttons = QPlatformDialogHelper::Ok;
-
- for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
- if (buttons & i) {
- // Add native command
- const QString label = QGuiApplicationPrivate::platformTheme()->standardButtonText(i);
-
- HString hLabel;
- hLabel.Set(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
-
- ABI::Windows::UI::Popups::IUICommand *command;
- if (FAILED(commandFactory->CreateWithHandler(hLabel.Get(),
- Callback<IUICommandInvokedHandler>(this, &QWinRTPlatformMessageDialogHelper::onInvoked).Get(),
- &command)))
- return false;
- dialogCommands->Append(command);
- }
- }
-
- ComPtr<IAsyncOperation<IUICommand*> > op;
- if (FAILED(dialog->ShowAsync(&op)))
- return false;
-
- m_shown = true;
- if (FAILED(op.As(&m_info->info))) {
- m_shown = false;
- // The dialog is shown already, so we cannot return false
- qWarning("Failed to acquire AsyncInfo for MessageDialog");
- }
- return true;
-}
-
-void QWinRTPlatformMessageDialogHelper::hide()
-{
- if (!m_shown)
- return;
-
- m_info->info->Cancel();
- m_shown = false;
-}
-
-HRESULT QWinRTPlatformMessageDialogHelper::onInvoked(ABI::Windows::UI::Popups::IUICommand *command)
-{
- HString hLabel;
- UINT32 labelLength;
- command->get_Label(hLabel.GetAddressOf());
- PCWSTR rawString = hLabel.GetRawBuffer(&labelLength);
- QString label = QString::fromWCharArray(rawString, labelLength);
- int buttonId = -1;
- for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
- if ( options()->standardButtons() & i ) {
- if (QGuiApplicationPrivate::platformTheme()->standardButtonText(i) == label) {
- buttonId = i;
- break;
- }
- }
- }
- if (m_loop.isRunning())
- m_loop.exit();
-
- m_shown = false;
-
- if (buttonId < 0) {
- emit reject();
- return S_OK;
- }
-
- QPlatformDialogHelper::StandardButton standardButton = static_cast<QPlatformDialogHelper::StandardButton>(buttonId);
- QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(standardButton);
- emit clicked(standardButton, role);
- return S_OK;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index f948cf9924..cbc7449591 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -51,6 +51,7 @@
#include <QtPlatformSupport/private/qeglconvenience_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/qt_windows.h>
+#include <QtCore/qfunctions_winrt.h>
#include <wrl.h>
#include <windows.system.h>
@@ -93,11 +94,7 @@ typedef ITypedEventHandler<CoreWindow*, PointerEventArgs*> PointerHandler;
typedef ITypedEventHandler<CoreWindow*, WindowSizeChangedEventArgs*> SizeChangedHandler;
typedef ITypedEventHandler<CoreWindow*, VisibilityChangedEventArgs*> VisibilityChangedHandler;
typedef ITypedEventHandler<CoreWindow*, AutomationProviderRequestedEventArgs*> AutomationProviderRequestedHandler;
-#if _MSC_VER <=1700
-typedef IDisplayPropertiesEventHandler DisplayInformationHandler;
-#else
typedef ITypedEventHandler<DisplayInformation*, IInspectable*> DisplayInformationHandler;
-#endif
#ifdef Q_OS_WINPHONE
typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler;
#endif
@@ -419,199 +416,272 @@ static inline Qt::Key qKeyFromCode(quint32 code, int mods)
return static_cast<Qt::Key>(code & 0xff);
}
-QWinRTScreen::QWinRTScreen(ICoreWindow *window)
- : m_coreWindow(window)
- , m_depth(32)
- , m_format(QImage::Format_ARGB32_Premultiplied)
+typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken);
+uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+typedef HRESULT (__stdcall ICoreWindow::*CoreWindowCallbackRemover)(EventRegistrationToken);
+uint qHash(CoreWindowCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+typedef HRESULT (__stdcall IDisplayInformation::*DisplayCallbackRemover)(EventRegistrationToken);
+uint qHash(DisplayCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#ifdef Q_OS_WINPHONE
+typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken);
+uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); }
+#endif
+
+class QWinRTScreenPrivate
+{
+public:
+ ComPtr<ICoreApplication> application;
+ ComPtr<ICoreWindow> coreWindow;
+ ComPtr<IDisplayInformationStatics> displayInformationStatics;
+ ComPtr<IDisplayInformation> displayInformation;
#ifdef Q_OS_WINPHONE
- , m_inputContext(new QWinRTInputContext(m_coreWindow))
+ ComPtr<IHardwareButtonsStatics> hardwareButtons;
+#endif
+
+ QScopedPointer<QWinRTCursor> cursor;
+#ifdef Q_OS_WINPHONE
+ QScopedPointer<QWinRTInputContext> inputContext;
#else
- , m_inputContext(Make<QWinRTInputContext>(m_coreWindow).Detach())
+ ComPtr<QWinRTInputContext> inputContext;
+#endif
+
+ QRectF geometry;
+ QSurfaceFormat surfaceFormat;
+ qreal dpi;
+ qreal devicePixelRatio;
+ Qt::ScreenOrientation nativeOrientation;
+ Qt::ScreenOrientation orientation;
+ QList<QWindow *> visibleWindows;
+#ifndef Q_OS_WINPHONE
+ QHash<quint32, QPair<Qt::Key, QString>> activeKeys;
+#endif
+ QTouchDevice *touchDevice;
+ QHash<quint32, QWindowSystemInterface::TouchPoint> touchPoints;
+
+ EGLDisplay eglDisplay;
+ EGLSurface eglSurface;
+
+ QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
+ QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens;
+ QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens;
+#ifdef Q_OS_WINPHONE
+ QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens;
#endif
- , m_cursor(new QWinRTCursor(window))
- , m_devicePixelRatio(1.0)
- , m_orientation(Qt::PrimaryOrientation)
- , m_touchDevice(Q_NULLPTR)
+};
+
+QWinRTScreen::QWinRTScreen()
+ : d_ptr(new QWinRTScreenPrivate)
{
+ Q_D(QWinRTScreen);
+ d->orientation = Qt::PrimaryOrientation;
+ d->touchDevice = Q_NULLPTR;
+
+ // Obtain the WinRT Application, view, and window
+ HRESULT hr;
+ hr = RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ IID_PPV_ARGS(&d->application));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTScreen::onSuspended).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &d->applicationTokens[&ICoreApplication::remove_Resuming]);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<ICoreApplicationView> view;
+ hr = d->application->GetCurrentView(&view);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = view->get_CoreWindow(&d->coreWindow);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->Activate();
+ Q_ASSERT_SUCCEEDED(hr);
+
+#ifdef Q_OS_WINPHONE
+ d->inputContext.reset(new QWinRTInputContext(d->coreWindow.Get()));
+#else
+ d->inputContext = Make<QWinRTInputContext>(d->coreWindow.Get());
+#endif
+
Rect rect;
- window->get_Bounds(&rect);
- m_geometry = QRectF(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)
+ d->coreWindow->get_Bounds(&rect);
+ d->geometry = QRectF(0, 0, rect.Width, rect.Height);
+
+ d->surfaceFormat.setAlphaBufferSize(0);
+ d->surfaceFormat.setRedBufferSize(8);
+ d->surfaceFormat.setGreenBufferSize(8);
+ d->surfaceFormat.setBlueBufferSize(8);
+ d->surfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+ d->surfaceFormat.setSamples(1);
+ d->surfaceFormat.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ d->surfaceFormat.setDepthBufferSize(24);
+ d->surfaceFormat.setStencilBufferSize(8);
+
+ d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (d->eglDisplay == EGL_NO_DISPLAY)
qFatal("Qt WinRT platform plugin: failed to initialize EGL display.");
- if (!eglInitialize(m_eglDisplay, NULL, NULL))
+ if (!eglInitialize(d->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)
+ d->eglSurface = eglCreateWindowSurface(d->eglDisplay, q_configFromGLFormat(d->eglDisplay, d->surfaceFormat), d->coreWindow.Get(), NULL);
+ if (d->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]);
+ hr = d->coreWindow->add_KeyDown(Callback<KeyHandler>(this, &QWinRTScreen::onKeyDown).Get(), &d->windowTokens[&ICoreWindow::remove_KeyDown]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_KeyUp(Callback<KeyHandler>(this, &QWinRTScreen::onKeyUp).Get(), &d->windowTokens[&ICoreWindow::remove_KeyUp]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_CharacterReceived(Callback<CharacterReceivedHandler>(this, &QWinRTScreen::onCharacterReceived).Get(), &d->windowTokens[&ICoreWindow::remove_CharacterReceived]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerEntered(Callback<PointerHandler>(this, &QWinRTScreen::onPointerEntered).Get(), &d->windowTokens[&ICoreWindow::remove_PointerEntered]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerExited(Callback<PointerHandler>(this, &QWinRTScreen::onPointerExited).Get(), &d->windowTokens[&ICoreWindow::remove_PointerExited]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerMoved(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerMoved]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerPressed(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerReleased(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerReleased]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_PointerWheelChanged(Callback<PointerHandler>(this, &QWinRTScreen::onPointerUpdated).Get(), &d->windowTokens[&ICoreWindow::remove_PointerWheelChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &QWinRTScreen::onSizeChanged).Get(), &d->windowTokens[&ICoreWindow::remove_SizeChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_Activated(Callback<ActivatedHandler>(this, &QWinRTScreen::onActivated).Get(), &d->windowTokens[&ICoreWindow::remove_Activated]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_Closed(Callback<ClosedHandler>(this, &QWinRTScreen::onClosed).Get(), &d->windowTokens[&ICoreWindow::remove_Closed]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_VisibilityChanged(Callback<VisibilityChangedHandler>(this, &QWinRTScreen::onVisibilityChanged).Get(), &d->windowTokens[&ICoreWindow::remove_VisibilityChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->coreWindow->add_AutomationProviderRequested(Callback<AutomationProviderRequestedHandler>(this, &QWinRTScreen::onAutomationProviderRequested).Get(), &d->windowTokens[&ICoreWindow::remove_AutomationProviderRequested]);
+ Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
- ComPtr<IHardwareButtonsStatics> hardwareButtons;
- if (SUCCEEDED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), &hardwareButtons)))
- hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &m_tokens[QEvent::User]);
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), IID_PPV_ARGS(&d->hardwareButtons));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTScreen::onBackButtonPressed).Get(), &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]);
+ Q_ASSERT_SUCCEEDED(hr);
#endif // Q_OS_WINPHONE
- // 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 _MSC_VER<=1700
- HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(),
- &m_displayInformation);
-#else
- HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(),
- &m_displayInformationFactory);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get display information factory.");
- return;
- }
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(),
+ IID_PPV_ARGS(&d->displayInformationStatics));
+ Q_ASSERT_SUCCEEDED(hr);
- hr = m_displayInformationFactory->GetForCurrentView(&m_displayInformation);
-#endif
-
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get display information for the current view.");
- return;
- }
+ hr = d->displayInformationStatics->GetForCurrentView(&d->displayInformation);
+ Q_ASSERT_SUCCEEDED(hr);
// Set native orientation
DisplayOrientations displayOrientation;
- hr = m_displayInformation->get_NativeOrientation(&displayOrientation);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get native orientation.");
- return;
- }
+ hr = d->displayInformation->get_NativeOrientation(&displayOrientation);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
- m_nativeOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
+ hr = d->displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_OrientationChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
- hr = m_displayInformation->add_OrientationChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onOrientationChanged).Get(),
- &m_tokens[QEvent::OrientationChange]);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to add orientation change callback.");
- return;
- }
-
-#if _MSC_VER<=1700
- hr = m_displayInformation->add_LogicalDpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(),
- &m_tokens[QEvent::Type(QEvent::User + 1)]);
-#else
- hr = m_displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(),
- &m_tokens[QEvent::Type(QEvent::User + 1)]);
-#endif
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to add logical dpi change callback.");
- return;
- }
+ hr = d->displayInformation->add_DpiChanged(Callback<DisplayInformationHandler>(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]);
+ Q_ASSERT_SUCCEEDED(hr);
// Set initial orientation & pixel density
-#if _MSC_VER<=1700
- onOrientationChanged(Q_NULLPTR);
- onDpiChanged(Q_NULLPTR);
-#else
onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
onDpiChanged(Q_NULLPTR, Q_NULLPTR);
-#endif
- setOrientationUpdateMask(m_nativeOrientation);
+ setOrientationUpdateMask(d->nativeOrientation);
+}
- if (SUCCEEDED(RoGetActivationFactory(Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
- IID_PPV_ARGS(&m_application)))) {
- m_application->add_Suspending(Callback<SuspendHandler>(this, &QWinRTScreen::onSuspended).Get(), &m_suspendTokens[Qt::ApplicationSuspended]);
- m_application->add_Resuming(Callback<ResumeHandler>(this, &QWinRTScreen::onResume).Get(), &m_suspendTokens[Qt::ApplicationHidden]);
- }
+QWinRTScreen::~QWinRTScreen()
+{
+ Q_D(QWinRTScreen);
+
+ // Unregister callbacks
+ for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i)
+ (d->application.Get()->*i.key())(i.value());
+ for (QHash<CoreWindowCallbackRemover, EventRegistrationToken>::const_iterator i = d->windowTokens.begin(); i != d->windowTokens.end(); ++i)
+ (d->coreWindow.Get()->*i.key())(i.value());
+ for (QHash<DisplayCallbackRemover, EventRegistrationToken>::const_iterator i = d->displayTokens.begin(); i != d->displayTokens.end(); ++i)
+ (d->displayInformation.Get()->*i.key())(i.value());
+#ifdef Q_OS_WINPHONE
+ for (QHash<HardwareButtonsCallbackRemover, EventRegistrationToken>::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i)
+ (d->hardwareButtons.Get()->*i.key())(i.value());
+#endif
}
QRect QWinRTScreen::geometry() const
{
- return m_geometry.toRect();
+ Q_D(const QWinRTScreen);
+ return d->geometry.toRect();
}
int QWinRTScreen::depth() const
{
- return m_depth;
+ return 32;
}
QImage::Format QWinRTScreen::format() const
{
- return m_format;
+ return QImage::Format_ARGB32_Premultiplied;
}
QSurfaceFormat QWinRTScreen::surfaceFormat() const
{
- return m_surfaceFormat;
+ Q_D(const QWinRTScreen);
+ return d->surfaceFormat;
}
QSizeF QWinRTScreen::physicalSize() const
{
- return m_geometry.size() / m_dpi * qreal(25.4);
+ Q_D(const QWinRTScreen);
+ return d->geometry.size() / d->dpi * qreal(25.4);
}
QDpi QWinRTScreen::logicalDpi() const
{
- return QDpi(m_dpi, m_dpi);
+ Q_D(const QWinRTScreen);
+ return QDpi(d->dpi, d->dpi);
}
qreal QWinRTScreen::devicePixelRatio() const
{
- return m_devicePixelRatio;
+ Q_D(const QWinRTScreen);
+ return d->devicePixelRatio;
}
QWinRTInputContext *QWinRTScreen::inputContext() const
{
- return m_inputContext;
+ Q_D(const QWinRTScreen);
+#ifdef Q_OS_WINPHONE
+ return d->inputContext.data();
+#else
+ return d->inputContext.Get();
+#endif
}
QPlatformCursor *QWinRTScreen::cursor() const
{
- return m_cursor;
+ Q_D(const QWinRTScreen);
+ if (!d->cursor)
+ const_cast<QWinRTScreenPrivate *>(d)->cursor.reset(new QWinRTCursor);
+ return d->cursor.data();
}
Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const
{
+ Q_D(const QWinRTScreen);
+
Qt::KeyboardModifiers mods;
CoreVirtualKeyStates mod;
- m_coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_Shift, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::ShiftModifier;
- m_coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_Menu, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::AltModifier;
- m_coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_Control, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::ControlModifier;
- m_coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_LeftWindows, &mod);
if (mod == CoreVirtualKeyStates_Down) {
mods |= Qt::MetaModifier;
} else {
- m_coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod);
+ d->coreWindow->GetAsyncKeyState(VirtualKey_RightWindows, &mod);
if (mod == CoreVirtualKeyStates_Down)
mods |= Qt::MetaModifier;
}
@@ -620,56 +690,63 @@ Qt::KeyboardModifiers QWinRTScreen::keyboardModifiers() const
Qt::ScreenOrientation QWinRTScreen::nativeOrientation() const
{
- return m_nativeOrientation;
+ Q_D(const QWinRTScreen);
+ return d->nativeOrientation;
}
Qt::ScreenOrientation QWinRTScreen::orientation() const
{
- return m_orientation;
+ Q_D(const QWinRTScreen);
+ return d->orientation;
}
void QWinRTScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
{
-#if _MSC_VER<=1700
- m_displayInformation->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
-#else
- m_displayInformationFactory->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
-#endif
+ Q_D(QWinRTScreen);
+
+ HRESULT hr = d->displayInformationStatics->put_AutoRotationPreferences(nativeOrientationsFromQt(mask));
+ RETURN_VOID_IF_FAILED("Failed to set display auto rotation preferences.");
}
ICoreWindow *QWinRTScreen::coreWindow() const
{
- return m_coreWindow;
+ Q_D(const QWinRTScreen);
+ return d->coreWindow.Get();
}
EGLDisplay QWinRTScreen::eglDisplay() const
{
- return m_eglDisplay;
+ Q_D(const QWinRTScreen);
+ return d->eglDisplay;
}
EGLSurface QWinRTScreen::eglSurface() const
{
- return m_eglSurface;
+ Q_D(const QWinRTScreen);
+ return d->eglSurface;
}
QWindow *QWinRTScreen::topWindow() const
{
- return m_visibleWindows.isEmpty() ? 0 : m_visibleWindows.first();
+ Q_D(const QWinRTScreen);
+ return d->visibleWindows.isEmpty() ? 0 : d->visibleWindows.first();
}
void QWinRTScreen::addWindow(QWindow *window)
{
+ Q_D(QWinRTScreen);
if (window == topWindow())
return;
- m_visibleWindows.prepend(window);
+ d->visibleWindows.prepend(window);
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
}
void QWinRTScreen::removeWindow(QWindow *window)
{
+ Q_D(QWinRTScreen);
const bool wasTopWindow = window == topWindow();
- if (!m_visibleWindows.removeAll(window))
+ if (!d->visibleWindows.removeAll(window))
return;
if (wasTopWindow)
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
@@ -678,17 +755,19 @@ void QWinRTScreen::removeWindow(QWindow *window)
void QWinRTScreen::raise(QWindow *window)
{
- m_visibleWindows.removeAll(window);
+ Q_D(QWinRTScreen);
+ d->visibleWindows.removeAll(window);
addWindow(window);
}
void QWinRTScreen::lower(QWindow *window)
{
+ Q_D(QWinRTScreen);
const bool wasTopWindow = window == topWindow();
- if (wasTopWindow && m_visibleWindows.size() == 1)
+ if (wasTopWindow && d->visibleWindows.size() == 1)
return;
- m_visibleWindows.removeAll(window);
- m_visibleWindows.append(window);
+ d->visibleWindows.removeAll(window);
+ d->visibleWindows.append(window);
if (wasTopWindow)
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
@@ -696,18 +775,18 @@ void QWinRTScreen::lower(QWindow *window)
void QWinRTScreen::handleExpose()
{
- if (m_visibleWindows.isEmpty())
+ Q_D(QWinRTScreen);
+ if (d->visibleWindows.isEmpty())
return;
- QList<QWindow *>::const_iterator it = m_visibleWindows.constBegin();
- QWindowSystemInterface::handleExposeEvent(*it, m_geometry.toRect());
- while (++it != m_visibleWindows.constEnd())
+ QList<QWindow *>::const_iterator it = d->visibleWindows.constBegin();
+ QWindowSystemInterface::handleExposeEvent(*it, d->geometry.toRect());
+ while (++it != d->visibleWindows.constEnd())
QWindowSystemInterface::handleExposeEvent(*it, QRegion());
QWindowSystemInterface::flushWindowSystemEvents();
}
-HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args)
+HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args)
{
- Q_UNUSED(window);
VirtualKey virtualKey;
args->get_VirtualKey(&virtualKey);
Qt::Key key = qKeyFromVirtual(virtualKey);
@@ -718,14 +797,14 @@ HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *window, ABI
return S_OK;
}
-HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::Windows::UI::Core::IKeyEventArgs *args)
+HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args)
{
- Q_UNUSED(window);
Qt::KeyboardModifiers mods = keyboardModifiers();
#ifndef Q_OS_WINPHONE
+ Q_D(QWinRTScreen);
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);
+ if (SUCCEEDED(args->get_KeyStatus(&status)) && d->activeKeys.contains(status.ScanCode)) {
+ QPair<Qt::Key, QString> keyStatus = d->activeKeys.take(status.ScanCode);
QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease,
keyStatus.first, mods, keyStatus.second);
return S_OK;
@@ -738,10 +817,8 @@ HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *window, ABI::
return S_OK;
}
-HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceivedEventArgs *args)
+HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, 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
@@ -753,9 +830,10 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceive
QString text = QChar(keyCode);
QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text);
#ifndef Q_OS_WINPHONE
+ Q_D(QWinRTScreen);
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));
+ d->activeKeys.insert(status.ScanCode, qMakePair(key, text));
return S_OK;
}
#endif // !Q_OS_WINPHONE
@@ -763,10 +841,9 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *window, ICharacterReceive
return S_OK;
}
-HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *args)
+HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
{
- Q_UNUSED(window);
- IPointerPoint *pointerPoint;
+ ComPtr<IPointerPoint> pointerPoint;
if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) {
// Assumes full-screen window
Point point;
@@ -774,24 +851,20 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *window, IPointerEventArgs *a
QPoint pos(point.X, point.Y);
QWindowSystemInterface::handleEnterEvent(topWindow(), pos, pos);
- pointerPoint->Release();
}
return S_OK;
}
-HRESULT QWinRTScreen::onPointerExited(ICoreWindow *window, IPointerEventArgs *args)
+HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *)
{
- Q_UNUSED(window);
- Q_UNUSED(args);
QWindowSystemInterface::handleLeaveEvent(0);
return S_OK;
}
-HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *args)
+HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
{
- Q_UNUSED(window);
-
- IPointerPoint *pointerPoint;
+ Q_D(QWinRTScreen);
+ ComPtr<IPointerPoint> pointerPoint;
if (FAILED(args->get_CurrentPoint(&pointerPoint)))
return E_INVALIDARG;
@@ -812,27 +885,18 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
if (modifiers & VirtualKeyModifiers_Windows)
mods |= Qt::MetaModifier;
- IPointerPointProperties *properties;
+ ComPtr<IPointerPointProperties> properties;
if (FAILED(pointerPoint->get_Properties(&properties)))
return E_INVALIDARG;
- PointerDeviceType pointerDeviceType;
-#if defined(Q_OS_WINPHONE) && _MSC_VER <= 1700
- pointerDeviceType = PointerDeviceType_Touch;
-#else
ComPtr<IPointerDevice> pointerDevice;
HRESULT hr = pointerPoint->get_PointerDevice(&pointerDevice);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get pointer device.");
- return S_OK;
- }
+ RETURN_OK_IF_FAILED("Failed to get pointer device.");
+ PointerDeviceType pointerDeviceType;
hr = pointerDevice->get_PointerDeviceType(&pointerDeviceType);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get pointer device type.");
- return S_OK;
- }
-#endif
+ RETURN_OK_IF_FAILED("Failed to get pointer device type.");
+
switch (pointerDeviceType) {
case PointerDeviceType_Mouse: {
qint32 delta;
@@ -872,12 +936,12 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
break;
}
case PointerDeviceType_Touch: {
- if (!m_touchDevice) {
- m_touchDevice = new QTouchDevice;
- m_touchDevice->setName(QStringLiteral("WinRTTouchScreen"));
- m_touchDevice->setType(QTouchDevice::TouchScreen);
- m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition);
- QWindowSystemInterface::registerTouchDevice(m_touchDevice);
+ if (!d->touchDevice) {
+ d->touchDevice = new QTouchDevice;
+ d->touchDevice->setName(QStringLiteral("WinRTTouchScreen"));
+ d->touchDevice->setType(QTouchDevice::TouchScreen);
+ d->touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure | QTouchDevice::NormalizedPosition);
+ QWindowSystemInterface::registerTouchDevice(d->touchDevice);
}
quint32 id;
@@ -889,8 +953,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
float pressure;
properties->get_Pressure(&pressure);
- QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = m_touchPoints.find(id);
- if (it != m_touchPoints.end()) {
+ QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator it = d->touchPoints.find(id);
+ if (it != d->touchPoints.end()) {
boolean isPressed;
#ifndef Q_OS_WINPHONE
pointerPoint->get_IsInContact(&isPressed);
@@ -899,20 +963,20 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
#endif
it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased;
} else {
- it = m_touchPoints.insert(id, QWindowSystemInterface::TouchPoint());
+ it = d->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().normalPosition = QPointF(pos.x()/d->geometry.width(), pos.y()/d->geometry.height());
it.value().pressure = pressure;
- QWindowSystemInterface::handleTouchEvent(topWindow(), m_touchDevice, m_touchPoints.values(), mods);
+ QWindowSystemInterface::handleTouchEvent(topWindow(), d->touchDevice, d->touchPoints.values(), mods);
// Remove released points, station others
- for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = m_touchPoints.begin(); i != m_touchPoints.end();) {
+ for (QHash<quint32, QWindowSystemInterface::TouchPoint>::iterator i = d->touchPoints.begin(); i != d->touchPoints.end();) {
if (i.value().state == Qt::TouchPointReleased)
- i = m_touchPoints.erase(i);
+ i = d->touchPoints.erase(i);
else
(i++).value().state = Qt::TouchPointStationary;
}
@@ -950,46 +1014,42 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *window, IPointerEventArgs *a
}
}
- properties->Release();
- pointerPoint->Release();
-
return S_OK;
}
HRESULT QWinRTScreen::onAutomationProviderRequested(ICoreWindow *, IAutomationProviderRequestedEventArgs *args)
{
+ Q_D(const QWinRTScreen);
#ifndef Q_OS_WINPHONE
- args->put_AutomationProvider(m_inputContext);
+ args->put_AutomationProvider(d->inputContext.Get());
#else
Q_UNUSED(args)
#endif
return S_OK;
}
-HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *window, IWindowSizeChangedEventArgs *args)
+HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
{
- Q_UNUSED(window);
+ Q_D(QWinRTScreen);
Size size;
- if (FAILED(args->get_Size(&size))) {
- qWarning(Q_FUNC_INFO ": failed to get size");
- return S_OK;
- }
+ HRESULT hr = args->get_Size(&size);
+ RETURN_OK_IF_FAILED("Failed to get window size.");
// Regardless of state, all top-level windows are viewport-sized - this might change if
// a more advanced compositor is written.
- m_geometry.setSize(QSizeF(size.Width, size.Height));
- QWindowSystemInterface::handleScreenGeometryChange(screen(), m_geometry.toRect());
- QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), m_geometry.toRect());
+ d->geometry.setSize(QSizeF(size.Width, size.Height));
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), d->geometry.toRect());
+ QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), d->geometry.toRect());
QPlatformScreen::resizeMaximizedWindows();
handleExpose();
return S_OK;
}
-HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs *args)
+HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args)
{
- Q_UNUSED(window);
+ Q_D(QWinRTScreen);
CoreWindowActivationState activationState;
args->get_WindowActivationState(&activationState);
@@ -999,7 +1059,7 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *window, IWindowActivatedEventArgs
}
// Activate topWindow
- if (!m_visibleWindows.isEmpty()) {
+ if (!d->visibleWindows.isEmpty()) {
Qt::FocusReason focusReason = activationState == CoreWindowActivationState_PointerActivated
? Qt::MouseFocusReason : Qt::ActiveWindowFocusReason;
QWindowSystemInterface::handleWindowActivated(topWindow(), focusReason);
@@ -1022,21 +1082,15 @@ HRESULT QWinRTScreen::onResume(IInspectable *, IInspectable *)
return S_OK;
}
-HRESULT QWinRTScreen::onClosed(ICoreWindow *window, ICoreWindowEventArgs *args)
+HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *)
{
- Q_UNUSED(window);
- Q_UNUSED(args);
-
foreach (QWindow *w, QGuiApplication::topLevelWindows())
QWindowSystemInterface::handleCloseEvent(w);
return S_OK;
}
-HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChangedEventArgs *args)
+HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEventArgs *args)
{
- Q_UNUSED(window);
- Q_UNUSED(args);
-
boolean visible;
args->get_Visible(&visible);
QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden);
@@ -1045,60 +1099,48 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *window, IVisibilityChange
return S_OK;
}
-#if _MSC_VER<=1700
-HRESULT QWinRTScreen::onOrientationChanged(IInspectable *)
-#else
HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *)
-#endif
{
+ Q_D(QWinRTScreen);
+
DisplayOrientations displayOrientation;
- m_displayInformation->get_CurrentOrientation(&displayOrientation);
+ HRESULT hr = d->displayInformation->get_CurrentOrientation(&displayOrientation);
+ RETURN_OK_IF_FAILED("Failed to get current orientations.");
+
Qt::ScreenOrientation newOrientation = static_cast<Qt::ScreenOrientation>(static_cast<int>(qtOrientationsFromNative(displayOrientation)));
- if (m_orientation != newOrientation) {
- m_orientation = newOrientation;
- QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation);
+ if (d->orientation != newOrientation) {
+ d->orientation = newOrientation;
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation);
}
return S_OK;
}
-#if _MSC_VER<=1700
-HRESULT QWinRTScreen::onDpiChanged(IInspectable *)
-#else
HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
-#endif
{
-#if defined(Q_OS_WINPHONE) && _MSC_VER>=1800 // WP 8.1
+ Q_D(QWinRTScreen);
+
+ HRESULT hr;
+#ifdef Q_OS_WINPHONE
ComPtr<IDisplayInformation2> displayInformation;
- HRESULT hr = m_displayInformation->QueryInterface(IID_IDisplayInformation2, &displayInformation);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to cast display information.");
- return S_OK;
- }
- hr = displayInformation->get_RawPixelsPerViewPixel(&m_devicePixelRatio);
+ hr = d->displayInformation.As(&displayInformation);
+ RETURN_OK_IF_FAILED("Failed to cast display information.");
+ hr = displayInformation->get_RawPixelsPerViewPixel(&d->devicePixelRatio);
#else
ResolutionScale resolutionScale;
- HRESULT hr = m_displayInformation->get_ResolutionScale(&resolutionScale);
-#endif
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get display resolution scale.");
- return S_OK;
- }
-#if !(defined(Q_OS_WINPHONE) && _MSC_VER>=1800) // !WP8.1
- m_devicePixelRatio = qreal(resolutionScale) / 100;
+ hr = d->displayInformation->get_ResolutionScale(&resolutionScale);
+ d->devicePixelRatio = qreal(resolutionScale) / 100;
#endif
+ RETURN_OK_IF_FAILED("Failed to get resolution scale");
// Correct the scale factor for integer window size
- m_devicePixelRatio = m_devicePixelRatio * ((m_geometry.width()/qRound(m_geometry.width()) +
- m_geometry.height()/qRound(m_geometry.height())) / 2.0);
+ d->devicePixelRatio = d->devicePixelRatio * ((d->geometry.width()/qRound(d->geometry.width()) +
+ d->geometry.height()/qRound(d->geometry.height())) / 2.0);
FLOAT dpi;
- hr = m_displayInformation->get_LogicalDpi(&dpi);
- if (FAILED(hr)) {
- qErrnoWarning(hr, "Failed to get logical DPI.");
- return S_OK;
- }
- m_dpi = dpi;
+ hr = d->displayInformation->get_LogicalDpi(&dpi);
+ RETURN_OK_IF_FAILED("Failed to get logical DPI.");
+ d->dpi = dpi;
return S_OK;
}
@@ -1106,14 +1148,16 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *)
#ifdef Q_OS_WINPHONE
HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
+ Q_D(QWinRTScreen);
+
QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
backPress.setAccepted(false);
backRelease.setAccepted(false);
- QObject *receiver = m_visibleWindows.isEmpty()
+ QObject *receiver = d->visibleWindows.isEmpty()
? static_cast<QObject *>(QGuiApplication::instance())
- : static_cast<QObject *>(m_visibleWindows.first());
+ : static_cast<QObject *>(d->visibleWindows.first());
// If the event is ignored, the app will suspend
QGuiApplication::sendEvent(receiver, &backPress);
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index d39683a960..18745f1017 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -45,19 +45,12 @@
#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 ApplicationModel {
struct ISuspendingEventArgs;
- namespace Core {
- struct ICoreApplication;
- }
}
namespace UI {
namespace Core {
@@ -71,14 +64,9 @@ namespace ABI {
struct IWindowActivatedEventArgs;
struct IWindowSizeChangedEventArgs;
}
- namespace ViewManagement {
- struct IApplicationViewStatics;
- }
}
namespace Graphics {
namespace Display {
- struct IDisplayPropertiesStatics;
- struct IDisplayInformationStatics;
struct IDisplayInformation;
}
}
@@ -99,14 +87,14 @@ QT_BEGIN_NAMESPACE
class QTouchDevice;
class QWinRTEGLContext;
-class QWinRTPageFlipper;
class QWinRTCursor;
class QWinRTInputContext;
-
+class QWinRTScreenPrivate;
class QWinRTScreen : public QPlatformScreen
{
public:
- explicit QWinRTScreen(ABI::Windows::UI::Core::ICoreWindow *window);
+ explicit QWinRTScreen();
+ ~QWinRTScreen();
QRect geometry() const;
int depth() const;
QImage::Format format() const;
@@ -135,69 +123,31 @@ public:
private:
void handleExpose();
- // Event handlers
- QHash<QEvent::Type, EventRegistrationToken> m_tokens;
- QHash<Qt::ApplicationState, EventRegistrationToken> m_suspendTokens;
+ HRESULT onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *);
+ HRESULT onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *);
+ HRESULT onCharacterReceived(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICharacterReceivedEventArgs *);
+ HRESULT onPointerEntered(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IPointerEventArgs *);
+ HRESULT onPointerExited(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IPointerEventArgs *);
+ HRESULT onPointerUpdated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IPointerEventArgs *);
+ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
- 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 onActivated(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowActivatedEventArgs *);
HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
HRESULT onResume(IInspectable *, IInspectable *);
- 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 onClosed(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::ICoreWindowEventArgs *);
+ HRESULT onVisibilityChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IVisibilityChangedEventArgs *);
+ HRESULT onAutomationProviderRequested(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IAutomationProviderRequestedEventArgs *);
-#if _MSC_VER<=1700
- HRESULT onOrientationChanged(IInspectable *);
- HRESULT onDpiChanged(IInspectable *);
-#else
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
-#endif
#ifdef Q_OS_WINPHONE
HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args);
#endif
- ABI::Windows::UI::Core::ICoreWindow *m_coreWindow;
- ABI::Windows::UI::ViewManagement::IApplicationViewStatics *m_applicationView;
- ABI::Windows::ApplicationModel::Core::ICoreApplication *m_application;
-
- QRectF m_geometry;
- QImage::Format m_format;
- QSurfaceFormat m_surfaceFormat;
- qreal m_dpi;
- int m_depth;
- QWinRTInputContext *m_inputContext;
- QWinRTCursor *m_cursor;
- QList<QWindow *> m_visibleWindows;
-
- EGLDisplay m_eglDisplay;
- EGLSurface m_eglSurface;
-
-#if _MSC_VER<=1700
- ABI::Windows::Graphics::Display::IDisplayPropertiesStatics *m_displayInformation;
-#else
- ABI::Windows::Graphics::Display::IDisplayInformationStatics *m_displayInformationFactory;
- ABI::Windows::Graphics::Display::IDisplayInformation *m_displayInformation;
-#endif
- qreal m_devicePixelRatio;
- Qt::ScreenOrientation m_nativeOrientation;
- Qt::ScreenOrientation m_orientation;
-
-#ifndef Q_OS_WINPHONE
- QHash<quint32, QPair<Qt::Key, QString> > m_activeKeys;
-#endif
- QTouchDevice *m_touchDevice;
- QHash<quint32, QWindowSystemInterface::TouchPoint> m_touchPoints;
+ QScopedPointer<QWinRTScreenPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTScreen)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp
index b0f9247d36..6272b46f44 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.cpp
+++ b/src/plugins/platforms/winrt/qwinrtservices.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -43,6 +43,7 @@
#include <QtCore/QUrl>
#include <QtCore/QDir>
#include <QtCore/QCoreApplication>
+#include <QtCore/qfunctions_winrt.h>
#include <wrl.h>
#include <windows.foundation.h>
@@ -56,83 +57,84 @@ using namespace ABI::Windows::System;
QT_BEGIN_NAMESPACE
+class QWinRTServicesPrivate
+{
+public:
+ ComPtr<IUriRuntimeClassFactory> uriFactory;
+ ComPtr<IStorageFileStatics> fileFactory;
+ ComPtr<ILauncherStatics> launcher;
+};
+
QWinRTServices::QWinRTServices()
+ : d_ptr(new QWinRTServicesPrivate)
{
- 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);
+ Q_D(QWinRTServices);
+
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(),
+ IID_PPV_ARGS(&d->uriFactory));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
+
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFile).Get(),
+ IID_PPV_ARGS(&d->fileFactory));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
+
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(),
+ IID_PPV_ARGS(&d->launcher));
+ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
}
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);
+ Q_D(QWinRTServices);
- IUriRuntimeClass *uri;
+ ComPtr<IUriRuntimeClass> uri;
QString urlString = url.toString();
- // ### TODO: Replace with HStringReference when WP8.0 support is removed
- HString uriString;
- uriString.Set((const wchar_t*)urlString.utf16(), urlString.length());
- m_uriFactory->CreateUri(uriString.Get(), &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();
+ HStringReference uriString(reinterpret_cast<LPCWSTR>(urlString.utf16()), urlString.length());
+ HRESULT hr = d->uriFactory->CreateUri(uriString.Get(), &uri);
+ RETURN_FALSE_IF_FAILED("Failed to create URI from QUrl.");
+
+ ComPtr<IAsyncOperation<bool>> op;
+ hr = d->launcher->LaunchUriAsync(uri.Get(), &op);
+ RETURN_FALSE_IF_FAILED("Failed to start URI launch.");
+
+ boolean result;
+ hr = QWinRTFunctions::await(op, &result);
+ RETURN_FALSE_IF_FAILED("Failed to launch URI.");
return result;
}
bool QWinRTServices::openDocument(const QUrl &url)
{
- if (!(m_fileFactory && m_launcher))
- return QPlatformServices::openDocument(url);
-
- const QString pathString = QDir::toNativeSeparators(url.toLocalFile());
- // ### TODO: Replace with HStringReference when WP8.0 support is removed
- HString path;
- path.Set((const wchar_t*)pathString.utf16(), pathString.length());
- IAsyncOperation<StorageFile*> *fileOp;
- m_fileFactory->GetFileFromPathAsync(path.Get(), &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();
+ Q_D(QWinRTServices);
+
+ HRESULT hr;
+ ComPtr<IStorageFile> file;
+ {
+ const QString pathString = QDir::toNativeSeparators(url.toLocalFile());
+ HStringReference path(reinterpret_cast<LPCWSTR>(pathString.utf16()), pathString.length());
+ ComPtr<IAsyncOperation<StorageFile *>> op;
+ hr = d->fileFactory->GetFileFromPathAsync(path.Get(), &op);
+ RETURN_FALSE_IF_FAILED("Failed to initialize file URI.");
+
+ hr = QWinRTFunctions::await(op, file.GetAddressOf());
+ RETURN_FALSE_IF_FAILED("Failed to get file URI.");
+ }
+
+ boolean result;
+ {
+ ComPtr<IAsyncOperation<bool>> op;
+ hr = d->launcher->LaunchFileAsync(file.Get(), &op);
+ RETURN_FALSE_IF_FAILED("Failed to start file launch.");
+
+ hr = QWinRTFunctions::await(op, &result);
+ RETURN_FALSE_IF_FAILED("Failed to launch file.");
+ }
return result;
}
diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h
index 9cc917030a..d3abe6f2bd 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.h
+++ b/src/plugins/platforms/winrt/qwinrtservices.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 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.
@@ -43,23 +43,11 @@
#define QWINRTSERVICES_H
#include <qpa/qplatformservices.h>
+#include <QtCore/QScopedPointer>
-namespace ABI {
- namespace Windows {
- namespace Foundation {
- struct IUriRuntimeClassFactory;
- }
- namespace Storage {
- struct IStorageFileStatics;
- }
- namespace System {
- struct ILauncherStatics;
- }
- }
-}
-
-QT_BEGIN_NAMESPACE
+QT_USE_NAMESPACE
+class QWinRTServicesPrivate;
class QWinRTServices : public QPlatformServices
{
public:
@@ -70,11 +58,8 @@ public:
bool openDocument(const QUrl &url);
private:
- ABI::Windows::Foundation::IUriRuntimeClassFactory *m_uriFactory;
- ABI::Windows::Storage::IStorageFileStatics *m_fileFactory;
- ABI::Windows::System::ILauncherStatics *m_launcher;
+ QScopedPointer<QWinRTServicesPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTServices)
};
-QT_END_NAMESPACE
-
#endif // QWINRTSERVICES_H
diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp
new file mode 100644
index 0000000000..f9c2e21676
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrttheme.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 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 "qwinrttheme.h"
+#include "qwinrtmessagedialoghelper.h"
+
+#include <QtCore/qfunctions_winrt.h>
+#include <QtGui/QPalette>
+
+#include <wrl.h>
+#include <windows.ui.h>
+#include <windows.ui.viewmanagement.h>
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::ViewManagement;
+
+QT_BEGIN_NAMESPACE
+
+static IUISettings *uiSettings()
+{
+ static ComPtr<IUISettings> settings;
+ if (!settings) {
+ HRESULT hr;
+ hr = RoActivateInstance(Wrappers::HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_UISettings).Get(),
+ &settings);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ return settings.Get();
+}
+
+class QWinRTThemePrivate
+{
+public:
+ QPalette palette;
+};
+
+QWinRTTheme::QWinRTTheme()
+ : d_ptr(new QWinRTThemePrivate)
+{
+ Q_D(QWinRTTheme);
+
+ HRESULT hr;
+ union { Color ui; QRgb qt; } color;
+
+ hr = uiSettings()->UIElementColor(UIElementType_ActiveCaption, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::ToolTipBase, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_Background, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::AlternateBase, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_ButtonFace, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::Button, color.qt);
+ d->palette.setColor(QPalette::Midlight, QColor(color.qt).lighter(110));
+ d->palette.setColor(QPalette::Light, QColor(color.qt).lighter(150));
+ d->palette.setColor(QPalette::Mid, QColor(color.qt).dark(130));
+ d->palette.setColor(QPalette::Dark, QColor(color.qt).dark(150));
+
+ hr = uiSettings()->UIElementColor(UIElementType_ButtonText, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::ButtonText, color.qt);
+ d->palette.setColor(QPalette::Text, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_CaptionText, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::ToolTipText, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_Highlight, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::Highlight, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_HighlightText, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::HighlightedText, color.qt);
+
+ hr = uiSettings()->UIElementColor(UIElementType_Window, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::Window, color.qt);
+ d->palette.setColor(QPalette::Base, color.qt);
+
+#ifdef Q_OS_WINPHONE
+ hr = uiSettings()->UIElementColor(UIElementType_TextHigh, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::BrightText, color.qt);
+#else
+ hr = uiSettings()->UIElementColor(UIElementType_Hotlight, &color.ui);
+ Q_ASSERT_SUCCEEDED(hr);
+ d->palette.setColor(QPalette::BrightText, color.qt);
+#endif
+}
+
+bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const
+{
+ static bool useNativeDialogs = qEnvironmentVariableIsSet("QT_USE_WINRT_NATIVE_DIALOGS")
+ ? qgetenv("QT_USE_WINRT_NATIVE_DIALOGS").toInt() : true;
+
+ if (type == MessageDialog)
+ return useNativeDialogs;
+ return false;
+}
+
+QPlatformDialogHelper *QWinRTTheme::createPlatformDialogHelper(DialogType type) const
+{
+ switch (type) {
+ case MessageDialog:
+ return new QWinRTMessageDialogHelper(this);
+ default:
+ break;
+ }
+ return QPlatformTheme::createPlatformDialogHelper(type);
+}
+
+QVariant QWinRTTheme::styleHint(QPlatformIntegration::StyleHint hint)
+{
+ HRESULT hr;
+ switch (hint) {
+ case QPlatformIntegration::CursorFlashTime: {
+ quint32 blinkRate;
+ hr = uiSettings()->get_CaretBlinkRate(&blinkRate);
+ RETURN_IF_FAILED("Failed to get caret blink rate", return defaultThemeHint(CursorFlashTime));
+ return blinkRate;
+ }
+ case QPlatformIntegration::KeyboardInputInterval:
+ return defaultThemeHint(KeyboardInputInterval);
+ case QPlatformIntegration::MouseDoubleClickInterval: {
+ quint32 doubleClickTime;
+ hr = uiSettings()->get_DoubleClickTime(&doubleClickTime);
+ RETURN_IF_FAILED("Failed to get double click time", return defaultThemeHint(MouseDoubleClickInterval));
+ return doubleClickTime;
+ }
+ case QPlatformIntegration::StartDragDistance:
+ return defaultThemeHint(StartDragDistance);
+ case QPlatformIntegration::StartDragTime:
+ return defaultThemeHint(StartDragTime);
+ case QPlatformIntegration::KeyboardAutoRepeatRate:
+ return defaultThemeHint(KeyboardAutoRepeatRate);
+ case QPlatformIntegration::ShowIsFullScreen:
+ return true;
+ case QPlatformIntegration::PasswordMaskDelay:
+ return defaultThemeHint(PasswordMaskDelay);
+ case QPlatformIntegration::FontSmoothingGamma:
+ return qreal(1.7);
+ case QPlatformIntegration::StartDragVelocity:
+ return defaultThemeHint(StartDragVelocity);
+ case QPlatformIntegration::UseRtlExtensions:
+ return false;
+ case QPlatformIntegration::SynthesizeMouseFromTouchEvents:
+ return true;
+ case QPlatformIntegration::PasswordMaskCharacter:
+ return defaultThemeHint(PasswordMaskCharacter);
+ case QPlatformIntegration::SetFocusOnTouchRelease:
+ return false;
+ case QPlatformIntegration::ShowIsMaximized:
+ return false;
+ case MousePressAndHoldInterval:
+ return defaultThemeHint(MousePressAndHoldInterval);
+ default:
+ break;
+ }
+ return QVariant();
+}
+
+const QPalette *QWinRTTheme::palette(Palette type) const
+{
+ Q_D(const QWinRTTheme);
+ if (type == SystemPalette)
+ return &d->palette;
+ return QPlatformTheme::palette(type);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.h
index d4034ec571..f7fd07c70d 100644
--- a/src/plugins/platforms/winrt/qwinrtplatformtheme.cpp
+++ b/src/plugins/platforms/winrt/qwinrttheme.h
@@ -39,38 +39,32 @@
**
****************************************************************************/
-#include "qwinrtplatformtheme.h"
-#include "qwinrtplatformmessagedialoghelper.h"
+#ifndef QWINRTTHEME_H
+#define QWINRTTHEME_H
+
+#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformintegration.h>
QT_BEGIN_NAMESPACE
-QWinRTPlatformTheme::QWinRTPlatformTheme()
+class QWinRTThemePrivate;
+class QWinRTTheme : public QPlatformTheme
{
-}
+public:
+ QWinRTTheme();
-bool QWinRTPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
-{
-#if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700)
- if (type == QPlatformTheme::MessageDialog)
- return true;
-#else
- Q_UNUSED(type)
-#endif // !(Q_OS_WINPHONE && _MSC_VER<=1700)
- return false;
-}
+ bool usePlatformNativeDialog(DialogType type) const;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
-QPlatformDialogHelper *QWinRTPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const
-{
-#if !(defined(Q_OS_WINPHONE) && _MSC_VER<=1700)
- switch (type) {
- case QPlatformTheme::MessageDialog:
- return new QWinRTPlatformMessageDialogHelper();
- default:
- return QPlatformTheme::createPlatformDialogHelper(type);
- }
-#else // !(Q_OS_WINPHONE && _MSC_VER<=1700)
- return QPlatformTheme::createPlatformDialogHelper(type);
-#endif // Q_OS_WINPHONE && _MSC_VER<=1700
-}
+ const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE;
+
+ static QVariant styleHint(QPlatformIntegration::StyleHint hint);
+
+private:
+ QScopedPointer<QWinRTThemePrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QWinRTTheme)
+};
QT_END_NAMESPACE
+
+#endif // QWINRTTHEME_H
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 349cdf11c9..427920a670 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -35,12 +35,13 @@ SOURCES = \
qwinrtfontdatabase.cpp \
qwinrtinputcontext.cpp \
qwinrtintegration.cpp \
- qwinrtplatformmessagedialoghelper.cpp \
- qwinrtplatformtheme.cpp \
+ qwinrtmessagedialoghelper.cpp \
qwinrtscreen.cpp \
qwinrtservices.cpp \
+ qwinrttheme.cpp \
qwinrtwindow.cpp
+
HEADERS = \
qwinrtbackingstore.h \
qwinrtcursor.h \
@@ -49,12 +50,13 @@ HEADERS = \
qwinrtfontdatabase.h \
qwinrtinputcontext.h \
qwinrtintegration.h \
- qwinrtplatformmessagedialoghelper.h \
- qwinrtplatformtheme.h \
+ qwinrtmessagedialoghelper.h \
qwinrtscreen.h \
qwinrtservices.h \
+ qwinrttheme.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
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index 9a56455940..3ce0041aeb 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -54,6 +54,7 @@
#include "qglxintegration.h"
#include <QtPlatformSupport/private/qglxconvenience_p.h>
+#include <QtPlatformHeaders/QGLXNativeContext>
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
#include <dlfcn.h>
@@ -83,31 +84,32 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#endif
-static Window createDummyWindow(QXcbScreen *screen, XVisualInfo *visualInfo)
+static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
{
- Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone);
+ Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
- a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
- a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
+ a.background_pixel = WhitePixel(dpy, screenNumber);
+ a.border_pixel = BlackPixel(dpy, screenNumber);
a.colormap = cmap;
+ a.override_redirect = true;
- Window window = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(),
+ Window window = XCreateWindow(dpy, rootWin,
0, 0, 100, 100,
0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWBackPixel|CWBorderPixel|CWColormap, &a);
+ CWBackPixel|CWBorderPixel|CWColormap|CWOverrideRedirect, &a);
#ifndef QT_NO_DEBUG
- XStoreName(DISPLAY_FROM_XCB(screen), window, "Qt GLX dummy window");
+ XStoreName(dpy, window, "Qt GLX dummy window");
#endif
- XFreeColormap(DISPLAY_FROM_XCB(screen), cmap);
+ XFreeColormap(dpy, cmap);
return window;
}
-static Window createDummyWindow(QXcbScreen *screen, GLXFBConfig config)
+static Window createDummyWindow(Display *dpy, GLXFBConfig config, int screenNumber, Window rootWin)
{
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy, config);
if (!visualInfo)
qFatal("Could not initialize GLX");
- Window window = createDummyWindow(screen, visualInfo);
+ Window window = createDummyWindow(dpy, visualInfo, screenNumber, rootWin);
XFree(visualInfo);
return window;
}
@@ -160,14 +162,25 @@ static void updateFormatFromContext(QSurfaceFormat &format)
}
}
-QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle)
: QPlatformOpenGLContext()
, m_screen(screen)
+ , m_config(0)
, m_context(0)
, m_shareContext(0)
, m_format(format)
, m_isPBufferCurrent(false)
, m_swapInterval(-1)
+ , m_ownsContext(nativeHandle.isNull())
+{
+ if (nativeHandle.isNull())
+ init(screen, share);
+ else
+ init(screen, share, nativeHandle);
+}
+
+void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
{
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -178,6 +191,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),m_format);
+ m_config = config;
XVisualInfo *visualInfo = 0;
Window window = 0; // Temporary window used to query OpenGL context
@@ -195,7 +209,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
&& (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) {
// Try to create an OpenGL context for each known OpenGL version in descending
// order from the requested version.
- const int requestedVersion = format.majorVersion() * 10 + qMin(format.minorVersion(), 9);
+ const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9);
QVector<int> glVersions;
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
@@ -282,10 +296,10 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
// Get the basic surface format details
if (m_context)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config, m_context);
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config);
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(screen, config);
+ window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root());
} else {
// requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
@@ -303,7 +317,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
}
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(screen, visualInfo);
+ window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root());
XFree(visualInfo);
}
@@ -320,9 +334,125 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
XDestroyWindow(DISPLAY_FROM_XCB(screen), window);
}
+void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle)
+{
+ if (!nativeHandle.canConvert<QGLXNativeContext>()) {
+ qWarning("QGLXContext: Requires a QGLXNativeContext");
+ return;
+ }
+ QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>();
+ GLXContext context = handle.context();
+ if (!context) {
+ qWarning("QGLXContext: No GLXContext given");
+ return;
+ }
+
+ // Use the provided Display, if available. If not, use our own. It may still work.
+ Display *dpy = handle.display();
+ if (!dpy)
+ dpy = DISPLAY_FROM_XCB(screen);
+
+ // Legacy contexts created using glXCreateContext are created using a visual
+ // and the FBConfig cannot be queried. The only way to adapt these contexts
+ // is to figure out the visual id.
+ XVisualInfo *vinfo = 0;
+ // If the VisualID is provided use it.
+ VisualID vid = handle.visualId();
+ if (!vid) {
+ // In the absence of the VisualID figure it out from the window.
+ Window wnd = handle.window();
+ if (wnd) {
+ XWindowAttributes attrs;
+ XGetWindowAttributes(dpy, wnd, &attrs);
+ vid = XVisualIDFromVisual(attrs.visual);
+ }
+ }
+ if (vid) {
+ XVisualInfo v;
+ v.screen = screen->screenNumber();
+ v.visualid = vid;
+ int n = 0;
+ vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n);
+ if (n < 1) {
+ XFree(vinfo);
+ vinfo = 0;
+ }
+ }
+
+ // For contexts created with an FBConfig using the modern functions providing the
+ // visual or window is not mandatory. Just query the config from the context.
+ GLXFBConfig config = 0;
+ if (!vinfo) {
+ int configId = 0;
+ if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) {
+ qWarning("QGLXContext: Failed to query config from the provided context");
+ return;
+ }
+
+ GLXFBConfig *configs;
+ int numConfigs = 0;
+ static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
+ configs = glXChooseFBConfig(dpy, screen->screenNumber(), attribs, &numConfigs);
+ if (!configs || numConfigs < 1) {
+ qWarning("QGLXContext: Failed to find config");
+ return;
+ }
+ if (configs && numConfigs > 1) // this is suspicious so warn but let it continue
+ qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId);
+
+ config = configs[0];
+ // Store the config.
+ m_config = config;
+ }
+
+ Q_ASSERT(vinfo || config);
+
+ int screenNumber = DefaultScreen(dpy);
+ Window window;
+ if (vinfo)
+ window = createDummyWindow(dpy, vinfo, screenNumber, RootWindow(dpy, screenNumber));
+ else
+ window = createDummyWindow(dpy, config, screenNumber, RootWindow(dpy, screenNumber));
+ if (!window) {
+ qWarning("QGLXContext: Failed to create dummy window");
+ return;
+ }
+
+ // Update OpenGL version and buffer sizes in our format.
+ if (!glXMakeCurrent(dpy, window, context)) {
+ qWarning("QGLXContext: Failed to make provided context current");
+ return;
+ }
+ m_format = QSurfaceFormat();
+ m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
+ ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
+ updateFormatFromContext(m_format);
+ if (vinfo)
+ qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo);
+ else
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config);
+ glXMakeCurrent(dpy, 0, 0);
+ XDestroyWindow(dpy, window);
+
+ if (vinfo)
+ XFree(vinfo);
+
+ // Success. Store the context. From this point on isValid() is true.
+ m_context = context;
+
+ if (share)
+ m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
+}
+
QGLXContext::~QGLXContext()
{
- glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
+ if (m_ownsContext)
+ glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
+}
+
+QVariant QGLXContext::nativeHandle() const
+{
+ return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context));
}
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
@@ -393,11 +523,11 @@ void QGLXContext::swapBuffers(QPlatformSurface *surface)
if (surface->surface()->surfaceClass() == QSurface::Window) {
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(surface);
- // OpenGL context might be bound to a non-gui thread
- // use QueuedConnection to sync the window from the platformWindow's thread
- // as QXcbWindow is no QObject, a wrapper slot in QXcbConnection is used.
+ // OpenGL context might be bound to a non-gui thread use QueuedConnection to sync
+ // the window from the platformWindow's thread as QXcbWindow is no QObject, an
+ // event is sent to QXcbConnection. (this is faster than a metacall)
if (platformWindow->needsSync())
- QMetaObject::invokeMethod(m_screen->connection(), "syncWindow", Qt::QueuedConnection, Q_ARG(QXcbWindow*, platformWindow));
+ platformWindow->postSyncWindowRequest();
}
}
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index 00bba94ab3..abe3216ad7 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -58,7 +58,8 @@ QT_BEGIN_NAMESPACE
class QGLXContext : public QPlatformOpenGLContext
{
public:
- QGLXContext(QXcbScreen *xd, const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle);
~QGLXContext();
bool makeCurrent(QPlatformSurface *surface);
@@ -71,17 +72,25 @@ public:
bool isValid() const;
GLXContext glxContext() const { return m_context; }
+ GLXFBConfig glxConfig() const { return m_config; }
+
+ QVariant nativeHandle() const;
static bool supportsThreading();
static void queryDummyContext();
private:
+ void init(QXcbScreen *screen, QPlatformOpenGLContext *share);
+ void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
+
QXcbScreen *m_screen;
+ GLXFBConfig m_config;
GLXContext m_context;
GLXContext m_shareContext;
QSurfaceFormat m_format;
bool m_isPBufferCurrent;
int m_swapInterval;
+ bool m_ownsContext;
static bool m_queriedDummyContext;
static bool m_supportsThreading;
};
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index e7f8510706..3b30274f25 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -135,9 +135,10 @@ protected:
(void)formats(); // trigger update of format list
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data();
int size = format_atoms.size() / sizeof(xcb_atom_t);
+ atoms.reserve(size);
for (int i = 0; i < size; ++i)
atoms.append(targets[i]);
@@ -524,7 +525,7 @@ xcb_atom_t QXcbClipboard::sendTargetsSelection(QMimeData *d, xcb_window_t window
QVector<xcb_atom_t> types;
QStringList formats = QInternalMimeData::formatsHelper(d);
for (int i = 0; i < formats.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!types.contains(atoms.at(j)))
types.append(atoms.at(j));
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 7f23c84cb9..a2ce392151 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1842,9 +1842,26 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker()
return m_systemTrayTracker;
}
-void QXcbConnection::syncWindow(QXcbWindow *window)
+bool QXcbConnection::event(QEvent *e)
{
- window->updateSyncRequestCounter();
+ if (e->type() == QEvent::User + 1) {
+ QXcbSyncWindowRequest *ev = static_cast<QXcbSyncWindowRequest *>(e);
+ QXcbWindow *w = ev->window();
+ if (w) {
+ w->updateSyncRequestCounter();
+ ev->invalidate();
+ }
+ return true;
+ }
+ return QObject::event(e);
+}
+
+void QXcbSyncWindowRequest::invalidate()
+{
+ if (m_window) {
+ m_window->clearSyncWindowRequest();
+ m_window = 0;
+ }
}
QXcbConnectionGrabber::QXcbConnectionGrabber(QXcbConnection *connection)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 60a4efff4e..9e9865a2e9 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -355,6 +355,18 @@ public:
typedef QHash<xcb_window_t, QXcbWindowEventListener *> WindowMapper;
+class QXcbSyncWindowRequest : public QEvent
+{
+public:
+ QXcbSyncWindowRequest(QXcbWindow *w) : QEvent(QEvent::Type(QEvent::User + 1)), m_window(w) { }
+
+ QXcbWindow *window() const { return m_window; }
+ void invalidate();
+
+private:
+ QXcbWindow *m_window;
+};
+
class QAbstractEventDispatcher;
class QXcbConnection : public QObject
{
@@ -452,6 +464,7 @@ public:
void setFocusWindow(QXcbWindow *);
QByteArray startupId() const { return m_startupId; }
+ void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
void clearStartupId() { m_startupId.clear(); }
void grabServer();
@@ -467,8 +480,10 @@ public:
QXcbEventReader *eventReader() const { return m_reader; }
+protected:
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+
public slots:
- void syncWindow(QXcbWindow *window);
void flush() { xcb_flush(m_connection); }
private slots:
@@ -508,11 +523,11 @@ private:
#ifndef QT_NO_TABLETEVENT
struct TabletData {
TabletData() : deviceId(0), pointerType(QTabletEvent::UnknownPointer),
- tool(QTabletEvent::Stylus), down(false), serialId(0), inProximity(false) { }
+ tool(QTabletEvent::Stylus), buttons(0), serialId(0), inProximity(false) { }
int deviceId;
QTabletEvent::PointerType pointerType;
QTabletEvent::TabletDevice tool;
- bool down;
+ Qt::MouseButtons buttons;
qint64 serialId;
bool inProximity;
struct ValuatorClassInfo {
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index e21db89a20..512e574859 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -685,6 +685,19 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
#endif // XCB_USE_XINPUT21
}
+static Qt::MouseButton xiToQtMouseButton(uint32_t b) {
+ switch (b) {
+ case 1: return Qt::LeftButton;
+ case 2: return Qt::MiddleButton;
+ case 3: return Qt::RightButton;
+ // 4-7 are for scrolling
+ default: break;
+ }
+ if (b >= 8 && b <= Qt::MaxMouseButton)
+ return static_cast<Qt::MouseButton>(Qt::BackButton << (b - 8));
+ return Qt::NoButton;
+}
+
static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) {
// keep in sync with wacom_intuos_inout() in Linux kernel driver wacom_wac.c
switch (toolId) {
@@ -725,24 +738,22 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
Display *xDisplay = static_cast<Display *>(m_xlib_display);
xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event);
switch (xiEvent->evtype) {
- case XI_ButtonPress: // stylus down
- if (reinterpret_cast<xXIDeviceEvent *>(event)->detail == 1) { // ignore the physical buttons on the stylus
- tabletData->down = true;
- xi2ReportTabletEvent(*tabletData, xiEvent);
- } else
- handled = false;
+ case XI_ButtonPress: {
+ Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+ tabletData->buttons |= b;
+ xi2ReportTabletEvent(*tabletData, xiEvent);
break;
- case XI_ButtonRelease: // stylus up
- if (reinterpret_cast<xXIDeviceEvent *>(event)->detail == 1) {
- tabletData->down = false;
- xi2ReportTabletEvent(*tabletData, xiEvent);
- } else
- handled = false;
+ }
+ case XI_ButtonRelease: {
+ Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+ tabletData->buttons ^= b;
+ xi2ReportTabletEvent(*tabletData, xiEvent);
break;
+ }
case XI_Motion:
- // Report TabletMove only when the stylus is touching the tablet.
- // No possibility to report proximity motion (no suitable Qt event exists yet).
- if (tabletData->down)
+ // Report TabletMove only when the stylus is touching the tablet or any button is pressed.
+ // TODO: report proximity (hover) motion (no suitable Qt event exists yet).
+ if (tabletData->buttons != Qt::NoButton)
xi2ReportTabletEvent(*tabletData, xiEvent);
break;
case XI_PropertyEvent: {
@@ -862,15 +873,16 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event)
}
if (Q_UNLIKELY(debug_xinput))
- qDebug("XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f pressure %4.2lf tilt %d, %d rotation %6.2lf",
- ev->deviceid, tabletData.tool, ev->type, ev->sequenceNumber, ev->detail,
+ qDebug("XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
+ ev->deviceid, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y),
fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y),
- pressure, xTilt, yTilt, rotation);
+ (int)tabletData.buttons, pressure, xTilt, yTilt, rotation);
- QWindowSystemInterface::handleTabletEvent(window, tabletData.down, local, global,
+ QWindowSystemInterface::handleTabletEvent(window, local, global,
tabletData.tool, tabletData.pointerType,
- pressure, xTilt, yTilt, tangentialPressure,
+ tabletData.buttons, pressure,
+ xTilt, yTilt, tangentialPressure,
rotation, 0, tabletData.serialId);
}
#endif // QT_NO_TABLETEVENT
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 4f0f57c375..bd28548cba 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -183,7 +183,7 @@ void QXcbDrag::startDrag()
QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!drag_types.contains(atoms.at(j)))
drag_types.append(atoms.at(j));
@@ -1010,9 +1010,6 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
// current_target = 0;
// current_proxy_target = 0;
- if (t.drag)
- t.drag->deleteLater();
-
// current_target = target;
// current_proxy_target = proxy_target;
// current_embedding_widget = embedding_widget;
@@ -1211,7 +1208,7 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type r
return result;
}
- QList<xcb_atom_t> atoms = drag->xdnd_types;
+ QVector<xcb_atom_t> atoms = drag->xdnd_types;
QByteArray encoding;
xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding);
if (a == XCB_NONE)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index d94c42696f..7b0d337e7c 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -46,7 +46,6 @@
#include <private/qsimpledrag_p.h>
#include <qxcbobject.h>
#include <xcb/xcb.h>
-#include <qlist.h>
#include <qpoint.h>
#include <qrect.h>
#include <qsharedpointer.h>
@@ -127,7 +126,7 @@ private:
// the types in this drop. 100 is no good, but at least it's big.
enum { xdnd_max_type = 100 };
- QList<xcb_atom_t> xdnd_types;
+ QVector<xcb_atom_t> xdnd_types;
// timestamp from XdndPosition and XdndDroptime for retrieving the data
xcb_timestamp_t target_time;
@@ -160,7 +159,7 @@ private:
QPointer<QDrag> drag;
QTime time;
};
- QList<Transaction> transactions;
+ QVector<Transaction> transactions;
int transaction_expiry_timer;
void restartDropExpiryTimer();
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 181d99e85b..bc800524ef 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -68,6 +68,14 @@ QImage::Format qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t d
&& visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
return QImage::Format_ARGB32_Premultiplied;
+ if (depth == 30 && format->bits_per_pixel == 32 && visual->red_mask == 0x3ff
+ && visual->green_mask == 0x0ffc00 && visual->blue_mask == 0x3ff00000)
+ return QImage::Format_BGR30;
+
+ if (depth == 30 && format->bits_per_pixel == 32 && visual->blue_mask == 0x3ff
+ && visual->green_mask == 0x0ffc00 && visual->red_mask == 0x3ff00000)
+ return QImage::Format_RGB30;
+
if (depth == 24 && format->bits_per_pixel == 32 && visual->red_mask == 0xff0000
&& visual->green_mask == 0xff00 && visual->blue_mask == 0xff)
return QImage::Format_RGB32;
@@ -147,6 +155,13 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
p[x] |= 0xff000000;
p += bytes_per_line / 4;
}
+ } else if (format == QImage::Format_BGR30 || format == QImage::Format_RGB30) {
+ QRgb *p = (QRgb *)image.bits();
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x)
+ p[x] |= 0xc0000000;
+ p += bytes_per_line / 4;
+ }
}
result = QPixmap::fromImage(image.copy());
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 1b1c20f02c..f537a38962 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -83,6 +83,7 @@
#include "qxcbeglsurface.h"
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
+#include <QtPlatformHeaders/QEGLNativeContext>
#endif
#include <QtGui/QOpenGLContext>
@@ -187,8 +188,8 @@ class QEGLXcbPlatformContext : public QEGLPlatformContext
{
public:
QEGLXcbPlatformContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share,
- EGLDisplay display, QXcbConnection *c)
- : QEGLPlatformContext(glFormat, share, display)
+ EGLDisplay display, QXcbConnection *c, const QVariant &nativeHandle)
+ : QEGLPlatformContext(glFormat, share, display, 0, nativeHandle)
, m_connection(c)
{
Q_XCB_NOOP(m_connection);
@@ -224,6 +225,10 @@ public:
return static_cast<QEGLPbuffer *>(surface)->pbuffer();
}
+ QVariant nativeHandle() const {
+ return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay()));
+ }
+
private:
QXcbConnection *m_connection;
};
@@ -234,10 +239,18 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
{
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
#if defined(XCB_USE_GLX)
- return new QGLXContext(screen, context->format(), context->shareHandle());
+ QGLXContext *platformContext = new QGLXContext(screen, context->format(),
+ context->shareHandle(), context->nativeHandle());
+ context->setNativeHandle(platformContext->nativeHandle());
+ return platformContext;
#elif defined(XCB_USE_EGL)
- return new QEGLXcbPlatformContext(context->format(), context->shareHandle(),
- screen->connection()->egl_display(), screen->connection());
+ QEGLXcbPlatformContext *platformContext = new QEGLXcbPlatformContext(context->format(),
+ context->shareHandle(),
+ screen->connection()->egl_display(),
+ screen->connection(),
+ context->nativeHandle());
+ context->setNativeHandle(platformContext->nativeHandle());
+ return platformContext;
#else
Q_UNUSED(screen);
qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled");
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 4c84b19f82..c52714b456 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -198,8 +198,10 @@
#define XF86XK_MenuKB 0x1008FF65
#define XF86XK_MenuPB 0x1008FF66
#define XF86XK_MySites 0x1008FF67
+#define XF86XK_New 0x1008FF68
#define XF86XK_News 0x1008FF69
#define XF86XK_OfficeHome 0x1008FF6A
+#define XF86XK_Open 0x1008FF6B
#define XF86XK_Option 0x1008FF6C
#define XF86XK_Paste 0x1008FF6D
#define XF86XK_Phone 0x1008FF6E
@@ -497,8 +499,10 @@ static const unsigned int KeyTbl[] = {
XF86XK_MenuKB, Qt::Key_MenuKB,
XF86XK_MenuPB, Qt::Key_MenuPB,
XF86XK_MySites, Qt::Key_MySites,
+ XF86XK_New, Qt::Key_New,
XF86XK_News, Qt::Key_News,
XF86XK_OfficeHome, Qt::Key_OfficeHome,
+ XF86XK_Open, Qt::Key_Open,
XF86XK_Option, Qt::Key_Option,
XF86XK_Paste, Qt::Key_Paste,
XF86XK_Phone, Qt::Key_Phone,
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index b205a63267..c0f6745e7f 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -136,9 +136,10 @@ bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeDa
return ret;
}
-QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
+QVector<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
{
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
+ atoms.reserve(7);
atoms.append(connection->internAtom(format.toLatin1()));
// special cases for strings
@@ -240,7 +241,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
}
xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
{
requestedEncoding->clear();
diff --git a/src/plugins/platforms/xcb/qxcbmime.h b/src/plugins/platforms/xcb/qxcbmime.h
index 4a69a35ced..563716a75b 100644
--- a/src/plugins/platforms/xcb/qxcbmime.h
+++ b/src/plugins/platforms/xcb/qxcbmime.h
@@ -59,14 +59,14 @@ public:
QXcbMime();
~QXcbMime();
- static QList<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
+ static QVector<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
static QString mimeAtomToString(QXcbConnection *connection, xcb_atom_t a);
static bool mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
xcb_atom_t *atomFormat, int *dataFormat);
static QVariant mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
QVariant::Type requestedType, const QByteArray &encoding);
static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
};
#endif // !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index b45bd6a82e..5673d41811 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -60,6 +60,8 @@
#include "qglxintegration.h"
#endif
+#include <QtPlatformHeaders/qxcbwindowfunctions.h>
+
#ifdef XCB_USE_XLIB
# include <X11/Xlib.h>
#else
@@ -77,6 +79,8 @@ static int resourceType(const QByteArray &key)
QByteArrayLiteral("display"), QByteArrayLiteral("egldisplay"),
QByteArrayLiteral("connection"), QByteArrayLiteral("screen"),
QByteArrayLiteral("eglcontext"),
+ QByteArrayLiteral("eglconfig"),
+ QByteArrayLiteral("glxconfig"),
QByteArrayLiteral("glxcontext"), QByteArrayLiteral("apptime"),
QByteArrayLiteral("appusertime"), QByteArrayLiteral("hintstyle"),
QByteArrayLiteral("startupid"), QByteArrayLiteral("traywindow"),
@@ -91,7 +95,9 @@ static int resourceType(const QByteArray &key)
}
QXcbNativeInterface::QXcbNativeInterface() :
- m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t"))
+ m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")),
+ m_sysTraySelectionAtom(XCB_ATOM_NONE),
+ m_systrayVisualId(XCB_NONE)
{
}
@@ -133,6 +139,82 @@ QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window)
return QRect();
}
+xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen)
+{
+ if (m_sysTraySelectionAtom == XCB_ATOM_NONE) {
+ const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1();
+ xcb_intern_atom_cookie_t intern_c =
+ xcb_intern_atom_unchecked(conn, true, net_sys_tray.length(), net_sys_tray);
+
+ xcb_intern_atom_reply_t *intern_r = xcb_intern_atom_reply(conn, intern_c, 0);
+
+ if (!intern_r)
+ return XCB_WINDOW_NONE;
+
+ m_sysTraySelectionAtom = intern_r->atom;
+ free(intern_r);
+ }
+
+ xcb_get_selection_owner_cookie_t sel_owner_c = xcb_get_selection_owner_unchecked(conn, m_sysTraySelectionAtom);
+ xcb_get_selection_owner_reply_t *sel_owner_r = xcb_get_selection_owner_reply(conn, sel_owner_c, 0);
+
+ if (!sel_owner_r)
+ return XCB_WINDOW_NONE;
+
+ xcb_window_t selection_window = sel_owner_r->owner;
+ free(sel_owner_r);
+
+ return selection_window;
+}
+
+bool QXcbNativeInterface::systrayVisualHasAlphaChannel() {
+ const QXcbScreen *screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle());
+
+ if (m_systrayVisualId == XCB_NONE) {
+ xcb_connection_t *xcb_conn = screen->xcb_connection();
+ xcb_atom_t tray_atom = screen->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
+
+ xcb_window_t systray_window = locateSystemTray(xcb_conn, screen);
+ if (systray_window == XCB_WINDOW_NONE)
+ return false;
+
+ // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom
+ xcb_get_property_cookie_t systray_atom_cookie;
+ xcb_get_property_reply_t *systray_atom_reply;
+
+ systray_atom_cookie = xcb_get_property_unchecked(xcb_conn, false, systray_window,
+ tray_atom, XCB_ATOM_VISUALID, 0, 1);
+ systray_atom_reply = xcb_get_property_reply(xcb_conn, systray_atom_cookie, 0);
+
+ if (!systray_atom_reply)
+ return false;
+
+ if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) {
+ xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply);
+ m_systrayVisualId = vids[0];
+ }
+
+ free(systray_atom_reply);
+ }
+
+ if (m_systrayVisualId != XCB_NONE) {
+ quint8 depth = screen->depthOfVisual(m_systrayVisualId);
+ return depth == 32;
+ } else {
+ return false;
+ }
+}
+
+void QXcbNativeInterface::clearRegion(const QWindow *qwindow, const QRect& rect)
+{
+ if (const QPlatformWindow *platformWindow = qwindow->handle()) {
+ const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow);
+ xcb_connection_t *xcb_conn = qxwindow->xcb_connection();
+
+ xcb_clear_area(xcb_conn, false, qxwindow->xcb_window(), rect.x(), rect.y(), rect.width(), rect.height());
+ }
+}
+
void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
{
void *result = 0;
@@ -160,6 +242,12 @@ void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceSt
case EglContext:
result = eglContextForContext(context);
break;
+ case EglConfig:
+ result = eglConfigForContext(context);
+ break;
+ case GLXConfig:
+ result = glxConfigForContext(context);
+ break;
case GLXContext:
result = glxContextForContext(context);
break;
@@ -225,6 +313,14 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr
return result;
}
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+ if (lowerCaseResource == "setstartupid")
+ return NativeResourceForIntegrationFunction(setStartupId);
+ return 0;
+}
+
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource)
{
const QByteArray lowerCaseResource = resource.toLower();
@@ -235,6 +331,14 @@ QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::n
return 0;
}
+QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &function) const
+{
+ if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) {
+ return QFunctionPointer(QXcbWindow::setWmWindowTypeStatic);
+ }
+ return Q_NULLPTR;
+}
+
void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
{
return reinterpret_cast<void *>(quintptr(screen->connection()->time()));
@@ -287,6 +391,15 @@ void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
}
+void QXcbNativeInterface::setStartupId(const char *data)
+{
+ QByteArray startupId(data);
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QXcbConnection *defaultConnection = integration->defaultConnection();
+ if (defaultConnection)
+ defaultConnection->setStartupId(startupId);
+}
+
QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
{
QByteArray lowerCaseResource = resource.toLower();
@@ -353,6 +466,18 @@ void * QXcbNativeInterface::eglContextForContext(QOpenGLContext *context)
#endif
}
+void * QXcbNativeInterface::eglConfigForContext(QOpenGLContext *context)
+{
+ Q_ASSERT(context);
+#if defined(XCB_USE_EGL)
+ QEGLPlatformContext *eglPlatformContext = static_cast<QEGLPlatformContext *>(context->handle());
+ return eglPlatformContext->eglConfig();
+#else
+ Q_UNUSED(context);
+ return 0;
+#endif
+}
+
void *QXcbNativeInterface::glxContextForContext(QOpenGLContext *context)
{
Q_ASSERT(context);
@@ -366,4 +491,17 @@ void *QXcbNativeInterface::glxContextForContext(QOpenGLContext *context)
}
+void *QXcbNativeInterface::glxConfigForContext(QOpenGLContext *context)
+{
+ Q_ASSERT(context);
+#if defined(XCB_USE_GLX)
+ QGLXContext *glxPlatformContext = static_cast<QGLXContext *>(context->handle());
+ return glxPlatformContext->glxConfig();
+#else
+ Q_UNUSED(context);
+ return 0;
+#endif
+
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index fb1a46014c..c63cdf0254 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -63,6 +63,8 @@ public:
Connection,
Screen,
EglContext,
+ EglConfig,
+ GLXConfig,
GLXContext,
AppTime,
AppUserTime,
@@ -77,13 +79,16 @@ public:
QXcbNativeInterface();
void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
- void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
+ void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource);
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) Q_DECL_OVERRIDE;
+ QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+
inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; }
void *displayForWindow(QWindow *window);
@@ -96,13 +101,18 @@ public:
void *startupId();
void *x11Screen();
void *rootWindow();
+ static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
static void setAppUserTime(QScreen *screen, xcb_timestamp_t time);
static void *eglContextForContext(QOpenGLContext *context);
+ static void *eglConfigForContext(QOpenGLContext *context);
static void *glxContextForContext(QOpenGLContext *context);
+ static void *glxConfigForContext(QOpenGLContext *context);
Q_INVOKABLE void beep();
Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const;
+ Q_INVOKABLE void clearRegion(const QWindow *qwindow, const QRect& rect);
+ Q_INVOKABLE bool systrayVisualHasAlphaChannel();
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
@@ -110,8 +120,13 @@ signals:
void systemTrayWindowChanged(QScreen *screen);
private:
+ xcb_window_t locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen);
+
const QByteArray m_genericEventFilterType;
+ xcb_atom_t m_sysTraySelectionAtom;
+ xcb_visualid_t m_systrayVisualId;
+
static QXcbScreen *qPlatformScreenForWindow(QWindow *window);
};
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 01e78465b6..85f4dfbd43 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -200,6 +200,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
while (visualtype_iterator.rem) {
xcb_visualtype_t *visualtype = visualtype_iterator.data;
m_visuals.insert(visualtype->visual_id, *visualtype);
+ m_visualDepths.insert(visualtype->visual_id, depth->depth);
xcb_visualtype_next(&visualtype_iterator);
}
@@ -296,6 +297,14 @@ const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const
return &*it;
}
+quint8 QXcbScreen::depthOfVisual(xcb_visualid_t visualid) const
+{
+ QMap<xcb_visualid_t, quint8>::const_iterator it = m_visualDepths.find(visualid);
+ if (it == m_visualDepths.constEnd())
+ return 0;
+ return *it;
+}
+
QImage::Format QXcbScreen::format() const
{
return QImage::Format_RGB32;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index c36492db64..53ac65bb09 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -93,6 +93,7 @@ public:
bool syncRequestSupported() const { return m_syncRequestSupported; }
const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
+ quint8 depthOfVisual(xcb_visualid_t) const;
QString name() const { return m_outputName; }
@@ -127,6 +128,7 @@ private:
bool m_syncRequestSupported;
xcb_window_t m_clientLeader;
QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
+ QMap<xcb_visualid_t, quint8> m_visualDepths;
QXcbCursor *m_cursor;
int m_refreshRate;
int m_forcedDpi;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 586068d8d9..a127ac0293 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -166,16 +166,36 @@ static inline bool isTransient(const QWindow *w)
|| w->type() == Qt::Popup;
}
-static inline QImage::Format imageFormatForDepth(int depth)
+static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask)
{
switch (depth) {
- case 32: return QImage::Format_ARGB32_Premultiplied;
- case 24: return QImage::Format_RGB32;
- case 16: return QImage::Format_RGB16;
- default:
- qWarning("Unsupported screen depth: %d", depth);
- return QImage::Format_Invalid;
+ case 32:
+ if (blue_mask == 0xff)
+ return QImage::Format_ARGB32_Premultiplied;
+ if (red_mask == 0x3ff)
+ return QImage::Format_A2BGR30_Premultiplied;
+ if (blue_mask == 0x3ff)
+ return QImage::Format_A2RGB30_Premultiplied;
+ break;
+ case 30:
+ if (red_mask == 0x3ff)
+ return QImage::Format_BGR30;
+ if (blue_mask == 0x3ff)
+ return QImage::Format_RGB30;
+ break;
+ case 24:
+ if (blue_mask == 0xff)
+ return QImage::Format_RGB32;
+ break;
+ case 16:
+ if (blue_mask == 0x1f)
+ return QImage::Format_RGB16;
+ break;
+ default:
+ break;
}
+ qWarning("Unsupported screen format: depth: %d, red_mask: %x, blue_mask: %x", depth, red_mask, blue_mask);
+ return QImage::Format_Invalid;
}
static inline bool positionIncludesFrame(QWindow *w)
@@ -183,6 +203,8 @@ static inline bool positionIncludesFrame(QWindow *w)
return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive;
}
+static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
+
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
@@ -201,6 +223,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
#endif
, m_lastWindowStateEvent(-1)
, m_syncState(NoSyncNeeded)
+ , m_pendingSyncRequest(0)
{
m_screen = static_cast<QXcbScreen *>(window->screen()->handle());
@@ -225,7 +248,9 @@ void QXcbWindow::create()
if (type == Qt::Desktop) {
m_window = m_screen->root();
m_depth = m_screen->screen()->root_depth;
- m_imageFormat = imageFormatForDepth(m_depth);
+ m_visualId = m_screen->screen()->root_visual;
+ const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
connection()->addWindowEventListener(m_window, this);
return;
}
@@ -315,7 +340,7 @@ void QXcbWindow::create()
}
if (visualInfo) {
m_depth = visualInfo->depth;
- m_imageFormat = imageFormatForDepth(m_depth);
+ m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask);
Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
@@ -365,7 +390,8 @@ void QXcbWindow::create()
}
}
- m_imageFormat = imageFormatForDepth(m_depth);
+ const xcb_visualtype_t *visual = m_screen->visualForId(m_visualId);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth,
@@ -540,6 +566,9 @@ void QXcbWindow::destroy()
delete m_eglSurface;
m_eglSurface = 0;
#endif
+
+ if (m_pendingSyncRequest)
+ m_pendingSyncRequest->invalidate();
}
void QXcbWindow::setGeometry(const QRect &rect)
@@ -698,6 +727,11 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
+ if (window()->metaObject()->indexOfProperty(wm_window_type_property_id) >= 0) {
+ QXcbWindowFunctions::WmWindowTypes wmWindowTypes(window()->property(wm_window_type_property_id).value<int>());
+ setWmWindowType(wmWindowTypes);
+ }
+
if (connection()->time() != XCB_TIME_CURRENT_TIME)
updateNetWmUserTime(connection()->time());
@@ -1535,6 +1569,130 @@ QXcbEGLSurface *QXcbWindow::eglSurface() const
}
#endif
+void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes)
+{
+ if (window->handle())
+ static_cast<QXcbWindow *>(window->handle())->setWmWindowType(windowTypes);
+ else
+ window->setProperty(wm_window_type_property_id, QVariant::fromValue(static_cast<int>(windowTypes)));
+}
+
+QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const
+{
+ QXcbWindowFunctions::WmWindowTypes result(0);
+
+ xcb_get_property_cookie_t get_cookie =
+ xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE),
+ XCB_ATOM_ATOM, 0, 1024);
+
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
+
+ if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
+ const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply));
+ const xcb_atom_t *types_end = types + reply->length;
+ for (; types != types_end; types++) {
+ QXcbAtom::Atom type = connection()->qatom(*types);
+ switch (type) {
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL:
+ result |= QXcbWindowFunctions::Normal;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP:
+ result |= QXcbWindowFunctions::Desktop;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK:
+ result |= QXcbWindowFunctions::Dock;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR:
+ result |= QXcbWindowFunctions::Toolbar;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_MENU:
+ result |= QXcbWindowFunctions::Menu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY:
+ result |= QXcbWindowFunctions::Utility;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH:
+ result |= QXcbWindowFunctions::Splash;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG:
+ result |= QXcbWindowFunctions::Dialog;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU:
+ result |= QXcbWindowFunctions::DropDownMenu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU:
+ result |= QXcbWindowFunctions::PopupMenu;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP:
+ result |= QXcbWindowFunctions::Tooltip;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION:
+ result |= QXcbWindowFunctions::Notification;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO:
+ result |= QXcbWindowFunctions::Combo;
+ break;
+ case QXcbAtom::_NET_WM_WINDOW_TYPE_DND:
+ result |= QXcbWindowFunctions::Dnd;
+ break;
+ case QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE:
+ result |= QXcbWindowFunctions::KdeOverride;
+ break;
+ default:
+ break;
+ }
+ }
+ free(reply);
+ }
+ return result;
+}
+
+void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types)
+{
+ QVector<xcb_atom_t> atoms;
+
+ if (types & QXcbWindowFunctions::Normal)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
+ if (types & QXcbWindowFunctions::Desktop)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DESKTOP));
+ if (types & QXcbWindowFunctions::Dock)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DOCK));
+ if (types & QXcbWindowFunctions::Toolbar)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLBAR));
+ if (types & QXcbWindowFunctions::Menu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_MENU));
+ if (types & QXcbWindowFunctions::Utility)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_UTILITY));
+ if (types & QXcbWindowFunctions::Splash)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_SPLASH));
+ if (types & QXcbWindowFunctions::Dialog)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DIALOG));
+ if (types & QXcbWindowFunctions::DropDownMenu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DROPDOWN_MENU));
+ if (types & QXcbWindowFunctions::PopupMenu)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_POPUP_MENU));
+ if (types & QXcbWindowFunctions::Tooltip)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_TOOLTIP));
+ if (types & QXcbWindowFunctions::Notification)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NOTIFICATION));
+ if (types & QXcbWindowFunctions::Combo)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_COMBO));
+ if (types & QXcbWindowFunctions::Dnd)
+ atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_DND));
+ if (types & QXcbWindowFunctions::KdeOverride)
+ atoms.append(atom(QXcbAtom::_KDE_NET_WM_WINDOW_TYPE_OVERRIDE));
+
+ if (atoms.isEmpty()) {
+ Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE)));
+ } else {
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
+ atoms.count(), atoms.constData()));
+ }
+ xcb_flush(xcb_connection());
+}
+
class ExposeCompressor
{
public:
@@ -1687,14 +1845,10 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
- if (!m_screen->availableGeometry().intersects(rect)) {
- Q_FOREACH (QPlatformScreen* screen, m_screen->virtualSiblings()) {
- if (screen->availableGeometry().intersects(rect)) {
- m_screen = static_cast<QXcbScreen*>(screen);
- QWindowSystemInterface::handleWindowScreenChanged(window(), m_screen->QPlatformScreen::screen());
- break;
- }
- }
+ QPlatformScreen *newScreen = screenForGeometry(rect);
+ if (newScreen != m_screen) {
+ m_screen = static_cast<QXcbScreen*>(newScreen);
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
m_configureNotifyPending = false;
@@ -2221,4 +2375,13 @@ bool QXcbWindow::needsSync() const
return m_syncState == SyncAndConfigureReceived;
}
+void QXcbWindow::postSyncWindowRequest()
+{
+ if (!m_pendingSyncRequest) {
+ QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
+ m_pendingSyncRequest = e;
+ QCoreApplication::postEvent(m_screen->connection(), e);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index b924ee27e5..a8cadd8e6c 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -51,11 +51,15 @@
#include "qxcbobject.h"
+#include <QtPlatformHeaders/qxcbwindowfunctions.h>
+
QT_BEGIN_NAMESPACE
class QXcbScreen;
class QXcbEGLSurface;
+class QXcbSyncWindowRequest;
class QIcon;
+
class QXcbWindow : public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow
{
public:
@@ -150,8 +154,16 @@ public:
QXcbEGLSurface *eglSurface() const;
#endif
+ static void setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes);
+
+ QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const;
+ void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types);
+
bool needsSync() const;
+ void postSyncWindowRequest();
+ void clearSyncWindowRequest() { m_pendingSyncRequest = 0; }
+
public Q_SLOTS:
void updateSyncRequestCounter();
@@ -228,6 +240,8 @@ private:
SyncAndConfigureReceived
};
SyncState m_syncState;
+
+ QXcbSyncWindowRequest *m_pendingSyncRequest;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 141a6cc0cb..17b40a45e1 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -42,6 +42,7 @@
#include "qxcbxsettings.h"
#include <QtCore/QByteArray>
+#include <QtCore/QtEndian>
#include <X11/extensions/XIproto.h>
@@ -149,47 +150,67 @@ public:
{
if (xSettings.length() < 12)
return;
- // we ignore byteorder for now
- char byteOrder = xSettings.at(1);
- Q_UNUSED(byteOrder);
- uint number_of_settings = *reinterpret_cast<const uint *>(xSettings.mid(8,4).constData());
+ char byteOrder = xSettings.at(0);
+ if (byteOrder != LSBFirst && byteOrder != MSBFirst) {
+ qWarning("%s ByteOrder byte %d not 0 or 1", Q_FUNC_INFO , byteOrder);
+ return;
+ }
+
+#define ADJUST_BO(b, t, x) \
+ ((b == LSBFirst) ? \
+ qFromLittleEndian<t>((const uchar *)(x)) : \
+ qFromBigEndian<t>((const uchar *)(x)))
+#define VALIDATE_LENGTH(x) \
+ if ((size_t)xSettings.length() < (offset + local_offset + 12 + x)) { \
+ qWarning("%s Length %d runs past end of data", Q_FUNC_INFO , x); \
+ return; \
+ }
+ uint number_of_settings = ADJUST_BO(byteOrder, quint32, xSettings.mid(8,4).constData());
const char *data = xSettings.constData() + 12;
size_t offset = 0;
for (uint i = 0; i < number_of_settings; i++) {
int local_offset = 0;
+ VALIDATE_LENGTH(2);
XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
local_offset += 2;
- quint16 name_len = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2);
+ quint16 name_len = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
+ VALIDATE_LENGTH(name_len);
QByteArray name(data + offset + local_offset, name_len);
local_offset += round_to_nearest_multiple_of_4(name_len);
- int last_change_serial = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int last_change_serial = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
Q_UNUSED(last_change_serial);
local_offset += 4;
QVariant value;
if (type == XSettingsTypeString) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset+=4;
+ VALIDATE_LENGTH(value_length);
QByteArray value_string(data + offset + local_offset, value_length);
value.setValue(value_string);
local_offset += round_to_nearest_multiple_of_4(value_length);
} else if (type == XSettingsTypeInteger) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset += 4;
value.setValue(value_length);
} else if (type == XSettingsTypeColor) {
- quint16 red = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2*4);
+ quint16 red = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 green = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 green = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 blue = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 blue = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 alpha= *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 alpha= ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
QColor color_value(red,green,blue,alpha);
value.setValue(color_value);