summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/common/c++11/c++11.cpp10
-rw-r--r--config.tests/qpa/mirclient/mirclient.cpp47
-rw-r--r--config.tests/qpa/mirclient/mirclient.pro4
-rw-r--r--config.tests/unix/syslog/syslog.c42
-rw-r--r--config.tests/unix/syslog/syslog.pro3
-rwxr-xr-xconfigure72
-rw-r--r--mkspecs/common/clang-mac.conf7
-rw-r--r--mkspecs/features/c++11.prf7
-rw-r--r--src/corelib/global/global.pri4
-rw-r--r--src/corelib/global/qlogging.cpp32
-rw-r--r--src/corelib/global/qnamespace.qdoc13
-rw-r--r--src/dbus/qdbuserror.cpp2
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp2
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h44
-rw-r--r--src/gui/opengl/qopengltexture.cpp289
-rw-r--r--src/gui/opengl/qopengltexture.h1
-rw-r--r--src/gui/opengl/qopengltexture_p.h2
-rw-r--r--src/gui/opengl/qopengltexturehelper_p.h37
-rw-r--r--src/gui/painting/qpdf.cpp28
-rw-r--r--src/gui/painting/qpdf_p.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm46
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.cpp129
-rw-r--r--src/plugins/platforms/eglfs/qeglfscursor.h2
-rw-r--r--src/plugins/platforms/mirclient/mirclient.json3
-rw-r--r--src/plugins/platforms/mirclient/mirclient.pro47
-rw-r--r--src/plugins/platforms/mirclient/qmirclientbackingstore.cpp146
-rw-r--r--src/plugins/platforms/mirclient/qmirclientbackingstore.h70
-rw-r--r--src/plugins/platforms/mirclient/qmirclientclipboard.cpp305
-rw-r--r--src/plugins/platforms/mirclient/qmirclientclipboard.h88
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.cpp156
-rw-r--r--src/plugins/platforms/mirclient/qmirclientglcontext.h66
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.cpp520
-rw-r--r--src/plugins/platforms/mirclient/qmirclientinput.h78
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.cpp264
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.h99
-rw-r--r--src/plugins/platforms/mirclient/qmirclientlogging.h60
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp134
-rw-r--r--src/plugins/platforms/mirclient/qmirclientnativeinterface.h66
-rw-r--r--src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h66
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplatformservices.cpp72
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplatformservices.h54
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplugin.cpp61
-rw-r--r--src/plugins/platforms/mirclient/qmirclientplugin.h53
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.cpp296
-rw-r--r--src/plugins/platforms/mirclient/qmirclientscreen.h84
-rw-r--r--src/plugins/platforms/mirclient/qmirclienttheme.cpp64
-rw-r--r--src/plugins/platforms/mirclient/qmirclienttheme.h54
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp452
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h80
-rw-r--r--src/plugins/platforms/platforms.pro2
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json2
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp16
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp3
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h2
-rw-r--r--tests/auto/network/ssl/qsslcertificate/BLACKLIST3
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp9
57 files changed, 4163 insertions, 139 deletions
diff --git a/config.tests/common/c++11/c++11.cpp b/config.tests/common/c++11/c++11.cpp
index 30934951d7..04a83390af 100644
--- a/config.tests/common/c++11/c++11.cpp
+++ b/config.tests/common/c++11/c++11.cpp
@@ -38,12 +38,6 @@
#endif
#include <utility>
-#if defined(__clang__)
-# if __has_feature(cxx_generalized_initializers)
-// On OS X, the libstdc++ headers don't include <initializer_list>
-// This #include here forces a failure unless we're using libc++
-# include <initializer_list>
-# endif
-#endif
+#include <initializer_list>
-int main(int, char **) { return 0; }
+int main(int, char **) { return std::move(0); }
diff --git a/config.tests/qpa/mirclient/mirclient.cpp b/config.tests/qpa/mirclient/mirclient.cpp
new file mode 100644
index 0000000000..c7148e82f9
--- /dev/null
+++ b/config.tests/qpa/mirclient/mirclient.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <mir_toolkit/mir_client_library.h>
+#include <ubuntu/application/lifecycle_delegate.h>
+#include <EGL/egl.h>
+
+static void surfaceCreateCallback(MirSurface*, void*)
+{
+}
+
+
+int main(int, char **)
+{
+ u_application_lifecycle_delegate_new();
+ mir_surface_create(0, surfaceCreateCallback, 0);
+}
diff --git a/config.tests/qpa/mirclient/mirclient.pro b/config.tests/qpa/mirclient/mirclient.pro
new file mode 100644
index 0000000000..b397c2d08a
--- /dev/null
+++ b/config.tests/qpa/mirclient/mirclient.pro
@@ -0,0 +1,4 @@
+SOURCES = mirclient.cpp
+CONFIG += link_pkgconfig
+PKGCONFIG += egl mirclient ubuntu-platform-api
+CONFIG -= qt
diff --git a/config.tests/unix/syslog/syslog.c b/config.tests/unix/syslog/syslog.c
new file mode 100644
index 0000000000..01e4bbaf8c
--- /dev/null
+++ b/config.tests/unix/syslog/syslog.c
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Tasuku Suzuki <stasuku@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <syslog.h>
+
+int main(int argc, char **argv)
+{
+ openlog("qt", 0, LOG_USER);
+ syslog(LOG_INFO, "configure");
+ closelog();
+ return 0;
+}
diff --git a/config.tests/unix/syslog/syslog.pro b/config.tests/unix/syslog/syslog.pro
new file mode 100644
index 0000000000..abe8cc9cd7
--- /dev/null
+++ b/config.tests/unix/syslog/syslog.pro
@@ -0,0 +1,3 @@
+SOURCES = syslog.c
+
+CONFIG -= qt
diff --git a/configure b/configure
index 6c17ac625a..9aac48e15c 100755
--- a/configure
+++ b/configure
@@ -621,6 +621,7 @@ CFG_XFIXES=runtime
CFG_ZLIB=auto
CFG_MTDEV=auto
CFG_JOURNALD=no
+CFG_SYSLOG=no
CFG_SQLITE=qt
CFG_GIF=auto
CFG_PNG=yes
@@ -688,6 +689,7 @@ CFG_EGLFS_VIV=no
CFG_DIRECTFB=auto
CFG_LINUXFB=auto
CFG_KMS=auto
+CFG_MIRCLIENT=auto
CFG_LIBUDEV=auto
CFG_LIBINPUT=auto
CFG_OBSOLETE_WAYLAND=no
@@ -1700,6 +1702,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
+ syslog)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_SYSLOG="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
sqlite)
if [ "$VAL" = "system" ]; then
CFG_SQLITE=system
@@ -1842,6 +1851,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
+ mirclient)
+ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
+ CFG_MIRCLIENT="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
libudev)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_LIBUDEV="$VAL"
@@ -2472,6 +2488,9 @@ Third Party Libraries:
+ -no-journald ........ Do not send logging output to journald.
-journald ........... Send logging output to journald.
+ + -no-syslog .......... Do not send logging output to syslog.
+ -syslog ............. Send logging output to syslog.
+
-no-gif ............. Do not compile GIF reading support.
-no-libpng .......... Do not compile PNG support.
@@ -2639,6 +2658,9 @@ Additional options:
-no-kms ............ Do not compile KMS support.
* -kms ............... Compile KMS support (Requires EGL).
+ * -no-mirclient....... Do not compile Mir client support.
+ -mirclient.......... Compile Mir client support.
+
-qpa <name> ......... Sets the default QPA platform (e.g xcb, cocoa, windows).
-xplatform target ... The target platform when cross-compiling.
@@ -4557,6 +4579,23 @@ if [ "$CFG_JOURNALD" != "no" ]; then
fi
fi
+if [ "$CFG_SYSLOG" != "no" ]; then
+ if compileTest unix/syslog "syslog"; then
+ CFG_SYSLOG=yes
+ QMAKE_CONFIG="$QMAKE_CONFIG syslog"
+ else
+ if [ "$CFG_SYSLOG" != "auto" ] && [ "$CFG_CONFIGURE_EXIT_ON_ERROR" = "yes" ]; then
+ echo "syslog support cannot be enabled due to functionality tests!"
+ echo " Turn on verbose messaging (-v) to $0 to see the final report."
+ echo " If you believe this message is in error you may use the continue"
+ echo " switch (-continue) to $0 to continue."
+ exit 101
+ else
+ CFG_SYSLOG=no
+ fi
+ fi
+fi
+
if [ "$CFG_LARGEFILE" = "auto" ]; then
#Large files should be enabled for all Linux systems
CFG_LARGEFILE=yes
@@ -5241,6 +5280,7 @@ ORIG_CFG_EGLFS="$CFG_EGLFS"
ORIG_CFG_DIRECTFB="$CFG_DIRECTFB"
ORIG_CFG_LINUXFB="$CFG_LINUXFB"
ORIG_CFG_KMS="$CFG_KMS"
+ORIG_CFG_MIRCLIENT="$CFG_MIRCLIENT"
if [ "$CFG_LIBUDEV" != "no" ]; then
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists libudev 2>/dev/null; then
@@ -5523,6 +5563,20 @@ if [ "$CFG_KMS" != "no" ]; then
fi
fi
+if [ "$CFG_MIRCLIENT" != "no" ]; then
+ if compileTest qpa/mirclient "Mir client"; then
+ CFG_MIRCLIENT=yes
+ elif [ "$CFG_MIRCLIENT" = "yes" ]; then
+ echo " Mir client support cannot be enabled due to functionality tests!"
+ echo " Turn on verbose messaging (-v) to $0 to see the final report."
+ echo " If you believe this message is in error you may use the continue"
+ echo " switch (-continue) to $0 to continue."
+ exit 101
+ else
+ CFG_MIRCLIENT=no
+ fi
+fi
+
# Detect libxkbcommon
MIN_REQ_XKBCOMMON="0.4.1"
# currently only xcb platform plugin supports building xkbcommon
@@ -5693,11 +5747,14 @@ fi
if [ "$CFG_KMS" = "yes" ]; then
QT_CONFIG="$QT_CONFIG kms"
fi
+if [ "$CFG_MIRCLIENT" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG mirclient"
+fi
if [ "$XPLATFORM_MAC" = "no" ] && [ "$XPLATFORM_MINGW" = "no" ] && [ "$XPLATFORM_QNX" = "no" ] && [ "$XPLATFORM_ANDROID" = "no" ] && [ "$XPLATFORM_HAIKU" = "no" ]; then
- if [ "$CFG_XCB" = "no" ] && [ "$CFG_EGLFS" = "no" ] && [ "$CFG_DIRECTFB" = "no" ] && [ "$CFG_LINUXFB" = "no" ] && [ "$CFG_KMS" = "no" ]; then
+ if [ "$CFG_XCB" = "no" ] && [ "$CFG_EGLFS" = "no" ] && [ "$CFG_DIRECTFB" = "no" ] && [ "$CFG_LINUXFB" = "no" ] && [ "$CFG_KMS" = "no" ] && [ "$CFG_MIRCLIENT" = "no" ]; then
if [ "$QPA_PLATFORM_GUARD" = "yes" ] &&
- ( [ "$ORIG_CFG_XCB" = "auto" ] || [ "$ORIG_CFG_EGLFS" = "auto" ] || [ "$ORIG_CFG_DIRECTFB" = "auto" ] || [ "$ORIG_CFG_LINUXFB" = "auto" ] || [ "$ORIG_CFG_KMS" = "auto" ] ); then
+ ( [ "$ORIG_CFG_XCB" = "auto" ] || [ "$ORIG_CFG_EGLFS" = "auto" ] || [ "$ORIG_CFG_DIRECTFB" = "auto" ] || [ "$ORIG_CFG_LINUXFB" = "auto" ] || [ "$ORIG_CFG_KMS" = "auto" ] || [ "$ORIG_CFG_MIRCLIENT" = "auto" ] ); then
echo "No QPA platform plugin enabled!"
echo " If you really want to build without a QPA platform plugin you must pass"
echo " -no-qpa-platform-guard to configure. Doing this will"
@@ -7078,8 +7135,10 @@ report_support " Image formats:"
report_support_plugin " GIF .................." "$CFG_GIF" qt QtGui
report_support_plugin " JPEG ................." "$CFG_JPEG" "$CFG_LIBJPEG" QtGui
report_support_plugin " PNG .................." "$CFG_PNG" "$CFG_LIBPNG" QtGui
-report_support " journald ..............." "$CFG_JOURNALD"
report_support " libinput................" "$CFG_LIBINPUT"
+report_support " Logging backends:"
+report_support " journald ..............." "$CFG_JOURNALD"
+report_support " syslog ..............." "$CFG_SYSLOG"
report_support " mtdev .................." "$CFG_MTDEV" yes "system library"
report_support " Networking:"
[ "$XPLATFORM_MAC" = "yes" ] && \
@@ -7112,6 +7171,7 @@ report_support " EGLFS Mali ........." "$CFG_EGLFS_MALI"
report_support " EGLFS Raspberry Pi ." "$CFG_EGLFS_BRCM"
report_support " EGLFS X11 .........." "$CFG_EGL_X"
report_support " LinuxFB .............." "$CFG_LINUXFB"
+report_support " Mir client............" "$CFG_MIRCLIENT"
report_support " XCB .................." "$CFG_XCB" system "system library" qt "bundled copy"
if [ "$CFG_XCB" != "no" ]; then
report_support " EGL on X ..........." "$CFG_EGL_X"
@@ -7169,12 +7229,12 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo "For example:"
echo " OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto' ./configure -openssl-linked"
fi
-if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SLOG2" = "yes" ]; then
+if [ "$CFG_JOURNALD" = "yes" ] || [ "$CFG_SYSLOG" = "yes" ] || [ "$CFG_SLOG2" = "yes" ]; then
echo
- echo "NOTE: journald or slog2 integration is enabled."
+ echo "NOTE: journald, syslog or slog2 integration is enabled."
echo "If your users intend on developing applications against this build,"
echo "ensure that the IDEs they use either set QT_LOGGING_TO_CONSOLE to 1"
- echo "or the IDE is able to read the logged output from journald or slog2."
+ echo "or the IDE is able to read the logged output from journald, syslog or slog2."
fi
if [ "$CFG_XKBCOMMON" = "qt" ] && [ "$CFG_XKB_CONFIG_ROOT" = "not found" ]; then
echo
diff --git a/mkspecs/common/clang-mac.conf b/mkspecs/common/clang-mac.conf
index 1e51142f02..d95e982b14 100644
--- a/mkspecs/common/clang-mac.conf
+++ b/mkspecs/common/clang-mac.conf
@@ -6,7 +6,6 @@ QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvm.clang.1_0
-QMAKE_CXXFLAGS_CXX11 += -stdlib=libc++
-QMAKE_CXXFLAGS_GNUCXX11 += -stdlib=libc++
-QMAKE_LFLAGS_CXX11 += -stdlib=libc++
-QMAKE_LFLAGS_GNUCXX11+= -stdlib=libc++
+QMAKE_CXXFLAGS += -stdlib=libc++
+QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++
+QMAKE_LFLAGS += -stdlib=libc++
diff --git a/mkspecs/features/c++11.prf b/mkspecs/features/c++11.prf
index 3f31f8ea82..c8a86548ee 100644
--- a/mkspecs/features/c++11.prf
+++ b/mkspecs/features/c++11.prf
@@ -7,10 +7,3 @@ strict_c++|isEmpty(QMAKE_CXXFLAGS_GNUCXX11) {
QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CXXFLAGS_GNUCXX11
QMAKE_LFLAGS += $$QMAKE_LFLAGS_GNUCXX11
}
-
-contains(QMAKE_LFLAGS, -stdlib=libc++) {
- equals(QMAKE_MACOSX_DEPLOYMENT_TARGET, 10.6): \
- QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
- contains(QMAKE_IOS_DEPLOYMENT_TARGET, ^4.*): \
- QMAKE_IOS_DEPLOYMENT_TARGET = 5.0
-}
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 6a8104bee2..43f3a86544 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -54,3 +54,7 @@ journald {
PKGCONFIG_PRIVATE += libsystemd-journal
DEFINES += QT_USE_JOURNALD
}
+
+syslog {
+ DEFINES += QT_USE_SYSLOG
+}
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index fca8656f9b..20c31f7ef8 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -65,6 +65,9 @@
# include <systemd/sd-journal.h>
# include <syslog.h>
#endif
+#if defined(QT_USE_SYSLOG) && !defined(QT_BOOTSTRAPPED)
+# include <syslog.h>
+#endif
#ifdef Q_OS_UNIX
# include <sys/types.h>
# include <sys/stat.h>
@@ -1436,6 +1439,32 @@ static void systemd_default_message_handler(QtMsgType type,
}
#endif
+#ifdef QT_USE_SYSLOG
+static void syslog_default_message_handler(QtMsgType type, const char *message)
+{
+ int priority = LOG_INFO; // Informational
+ switch (type) {
+ case QtDebugMsg:
+ priority = LOG_DEBUG; // Debug-level messages
+ break;
+ case QtInfoMsg:
+ priority = LOG_INFO; // Informational conditions
+ break;
+ case QtWarningMsg:
+ priority = LOG_WARNING; // Warning conditions
+ break;
+ case QtCriticalMsg:
+ priority = LOG_CRIT; // Critical conditions
+ break;
+ case QtFatalMsg:
+ priority = LOG_ALERT; // Action must be taken immediately
+ break;
+ }
+
+ syslog(priority, "%s", message);
+}
+#endif
+
#ifdef Q_OS_ANDROID
static void android_default_message_handler(QtMsgType type,
const QMessageLogContext &context,
@@ -1481,6 +1510,9 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
#elif defined(QT_USE_JOURNALD) && !defined(QT_BOOTSTRAPPED)
systemd_default_message_handler(type, context, logMessage);
return;
+#elif defined(QT_USE_SYSLOG) && !defined(QT_BOOTSTRAPPED)
+ syslog_default_message_handler(type, logMessage.toUtf8().constData());
+ return;
#elif defined(Q_OS_ANDROID)
android_default_message_handler(type, context, logMessage);
return;
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index aeff9502fe..a912e65d30 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -170,12 +170,13 @@
\value AA_UseDesktopOpenGL Forces the usage of desktop OpenGL (for example,
\e opengl32.dll or \e libGL.so) on platforms that use dynamic loading
- of the OpenGL implementation.
- This value has been added in Qt 5.3.
+ of the OpenGL implementation. This value has been added in Qt 5.3.
+ This attribute must be set before Q(Gui)Application is constructed.
\value AA_UseOpenGLES Forces the usage of OpenGL ES 2.0 or higher on
platforms that use dynamic loading of the OpenGL implementation.
- This value has been added in Qt 5.3.
+ This value has been added in Qt 5.3. This attribute must be set
+ before Q(Gui)Application is constructed.
\value AA_UseSoftwareOpenGL Forces the usage of a software based OpenGL
implementation on platforms that use dynamic loading of the OpenGL
@@ -186,13 +187,15 @@
\c opengl32sw.dll and can be overridden by setting the environment
variable \e QT_OPENGL_DLL. See the platform-specific pages, for
instance \l{Qt for Windows}, for more information. This value has
- been added in Qt 5.4.
+ been added in Qt 5.4. This attribute must be set before
+ Q(Gui)Application is constructed.
\value AA_ShareOpenGLContexts Enables resource sharing between the OpenGL
contexts used by classes like QOpenGLWidget and QQuickWidget. This
allows sharing OpenGL resources, like textures, between QOpenGLWidget
instances that belong to different top-level windows. This value has
- been added in Qt 5.4.
+ been added in Qt 5.4. This attribute must be set before
+ Q(Gui)Application is constructed.
\value AA_SetPalette Indicates whether a palette was explicitly set on the
QApplication/QGuiApplication. This value has been added in Qt 5.5.
diff --git a/src/dbus/qdbuserror.cpp b/src/dbus/qdbuserror.cpp
index 2b13f90fac..40e97ae483 100644
--- a/src/dbus/qdbuserror.cpp
+++ b/src/dbus/qdbuserror.cpp
@@ -142,6 +142,7 @@ static inline const char *get(QDBusError::ErrorType code)
return errorMessages_string + errorMessages_indices[intcode];
}
+#ifndef QT_BOOTSTRAPPED
static inline QDBusError::ErrorType get(const char *name)
{
if (!name || !*name)
@@ -151,6 +152,7 @@ static inline QDBusError::ErrorType get(const char *name)
return QDBusError::ErrorType(i + int(QDBusError::Other));
return QDBusError::Other;
}
+#endif
/*!
\class QDBusError
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 19e3045fc9..de586ac46c 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcScaling, "qt.scaling");
+#ifndef QT_NO_HIGHDPISCALING
static const char legacyDevicePixelEnvVar[] = "QT_DEVICE_PIXEL_RATIO";
static const char scaleFactorEnvVar[] = "QT_SCALE_FACTOR";
static const char autoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR";
@@ -317,4 +318,5 @@ QPoint QHighDpiScaling::origin(const QPlatformScreen *platformScreen)
return platformScreen->geometry().topLeft();
}
+#endif //QT_NO_HIGHDPISCALING
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index c79540d9e4..9e33787f53 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -62,6 +62,7 @@ class QScreen;
class QPlatformScreen;
typedef QPair<qreal, qreal> QDpi;
+#ifndef QT_NO_HIGHDPISCALING
class Q_GUI_EXPORT QHighDpiScaling {
public:
static void initHighDpiScaling();
@@ -464,7 +465,50 @@ QVector<T> toNativePixels(const QVector<T> &pointValues, const QWindow *window)
}
} // namespace QHighDpi
+#else // QT_NO_HIGHDPISCALING
+class Q_GUI_EXPORT QHighDpiScaling {
+public:
+ static inline void initHighDpiScaling() {}
+ static inline void updateHighDpiScaling() {}
+ static inline void setGlobalFactor(qreal) {}
+ static inline void setScreenFactor(QScreen *, qreal) {}
+
+ static inline bool isActive() { return false; }
+ static inline qreal factor(const QWindow *) { return 1.0; }
+ static inline qreal factor(const QScreen *) { return 1.0; }
+ static inline qreal factor(const QPlatformScreen *) { return 1.0; }
+ static inline QPoint origin(const QScreen *) { return QPoint(); }
+ static inline QPoint origin(const QPlatformScreen *) { return QPoint(); }
+ static inline QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *) { return pos; }
+ static inline QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *) { return pos; }
+ static inline QDpi logicalDpi() { return QDpi(-1,-1); }
+};
+namespace QHighDpi {
+ template <typename T> inline
+ T toNative(const T &value, ...) { return value; }
+ template <typename T> inline
+ T fromNative(const T &value, ...) { return value; }
+
+ template <typename T> inline
+ T fromNativeLocalPosition(const T &value, ...) { return value; }
+ template <typename T> inline
+ T toNativeLocalPosition(const T &value, ...) { return value; }
+
+ template <typename T> inline
+ T fromNativeLocalRegion(const T &value, ...) { return value; }
+ template <typename T> inline
+ T toNativeLocalRegion(const T &value, ...) { return value; }
+
+ template <typename T> inline
+ T fromNativeScreenGeometry(const T &value, ...) { return value; }
+
+ template <typename T, typename U> inline
+ T toNativePixels(const T &value, const U*) {return value;}
+ template <typename T, typename U> inline
+ T fromNativePixels(const T &value, const U*) {return value;}
+}
+#endif // QT_NO_HIGHDPISCALING
QT_END_NAMESPACE
#endif // QHIGHDPISCALING_P_H
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 5271826015..301b2ad13d 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -401,6 +401,9 @@ static bool isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat)
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
return true;
+ case QOpenGLTexture::RGB8_ETC1:
+ return false;
+
case QOpenGLTexture::DepthFormat:
case QOpenGLTexture::AlphaFormat:
@@ -442,20 +445,23 @@ static bool isTextureTargetMultisample(QOpenGLTexture::Target target)
return false;
}
-void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
+bool QOpenGLTexturePrivate::isUsingImmutableStorage() const
{
- // Resolve the actual number of mipmap levels we can use
- mipLevels = evaluateMipLevels();
-
// Use immutable storage whenever possible, falling back to mutable
// Note that if multisample textures are not supported at all, we'll still fail into
// the mutable storage allocation
- const bool useImmutableStorage = isSizedTextureFormat(format)
+ return isSizedTextureFormat(format)
&& (isTextureTargetMultisample(target)
? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
: features.testFlag(QOpenGLTexture::ImmutableStorage));
+}
+
+void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
+{
+ // Resolve the actual number of mipmap levels we can use
+ mipLevels = evaluateMipLevels();
- if (useImmutableStorage)
+ if (isUsingImmutableStorage())
allocateImmutableStorage();
else
allocateMutableStorage(pixelFormat, pixelType);
@@ -663,6 +669,7 @@ static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpen
case QOpenGLTexture::SRGB_Alpha_DXT3:
case QOpenGLTexture::SRGB_Alpha_DXT5:
case QOpenGLTexture::SRGB_BP_UNorm:
+ case QOpenGLTexture::RGB8_ETC1:
return QOpenGLTexture::RGBA;
case QOpenGLTexture::R11_EAC_UNorm:
@@ -840,6 +847,7 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
case QOpenGLTexture::RGBA8_ETC2_EAC:
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGB8_ETC1:
return QOpenGLTexture::UInt8;
case QOpenGLTexture::DepthFormat:
@@ -857,8 +865,133 @@ static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTe
return QOpenGLTexture::NoPixelType;
}
+static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+
+ case QOpenGLTexture::R8_UNorm:
+ case QOpenGLTexture::RG8_UNorm:
+ case QOpenGLTexture::RGB8_UNorm:
+ case QOpenGLTexture::RGBA8_UNorm:
+ case QOpenGLTexture::R16_UNorm:
+ case QOpenGLTexture::RG16_UNorm:
+ case QOpenGLTexture::RGB16_UNorm:
+ case QOpenGLTexture::RGBA16_UNorm:
+ case QOpenGLTexture::R8_SNorm:
+ case QOpenGLTexture::RG8_SNorm:
+ case QOpenGLTexture::RGB8_SNorm:
+ case QOpenGLTexture::RGBA8_SNorm:
+ case QOpenGLTexture::R16_SNorm:
+ case QOpenGLTexture::RG16_SNorm:
+ case QOpenGLTexture::RGB16_SNorm:
+ case QOpenGLTexture::RGBA16_SNorm:
+ case QOpenGLTexture::R8U:
+ case QOpenGLTexture::RG8U:
+ case QOpenGLTexture::RGB8U:
+ case QOpenGLTexture::RGBA8U:
+ case QOpenGLTexture::R16U:
+ case QOpenGLTexture::RG16U:
+ case QOpenGLTexture::RGB16U:
+ case QOpenGLTexture::RGBA16U:
+ case QOpenGLTexture::R32U:
+ case QOpenGLTexture::RG32U:
+ case QOpenGLTexture::RGB32U:
+ case QOpenGLTexture::RGBA32U:
+ case QOpenGLTexture::R8I:
+ case QOpenGLTexture::RG8I:
+ case QOpenGLTexture::RGB8I:
+ case QOpenGLTexture::RGBA8I:
+ case QOpenGLTexture::R16I:
+ case QOpenGLTexture::RG16I:
+ case QOpenGLTexture::RGB16I:
+ case QOpenGLTexture::RGBA16I:
+ case QOpenGLTexture::R32I:
+ case QOpenGLTexture::RG32I:
+ case QOpenGLTexture::RGB32I:
+ case QOpenGLTexture::RGBA32I:
+ case QOpenGLTexture::R16F:
+ case QOpenGLTexture::RG16F:
+ case QOpenGLTexture::RGB16F:
+ case QOpenGLTexture::RGBA16F:
+ case QOpenGLTexture::R32F:
+ case QOpenGLTexture::RG32F:
+ case QOpenGLTexture::RGB32F:
+ case QOpenGLTexture::RGBA32F:
+ case QOpenGLTexture::RGB9E5:
+ case QOpenGLTexture::RG11B10F:
+ case QOpenGLTexture::RG3B2:
+ case QOpenGLTexture::R5G6B5:
+ case QOpenGLTexture::RGB5A1:
+ case QOpenGLTexture::RGBA4:
+ case QOpenGLTexture::RGB10A2:
+
+ case QOpenGLTexture::D16:
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ case QOpenGLTexture::D32F:
+
+ case QOpenGLTexture::D24S8:
+ case QOpenGLTexture::D32FS8X24:
+
+ case QOpenGLTexture::S8:
+ return false;
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ case QOpenGLTexture::RG11_EAC_UNorm:
+ case QOpenGLTexture::RG11_EAC_SNorm:
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGB8_ETC1:
+ return true;
+
+ case QOpenGLTexture::DepthFormat:
+ case QOpenGLTexture::AlphaFormat:
+ case QOpenGLTexture::RGBFormat:
+ case QOpenGLTexture::RGBAFormat:
+ case QOpenGLTexture::LuminanceFormat:
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return false;
+ }
+
+ Q_UNREACHABLE();
+ return false;
+}
+
void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
{
+ // There is no way to allocate mutable storage for compressed textures in in
+ // versions older than OpenGL 3.1 and OpenGL ES 3.0, because the older specs
+ // do not mandate accepting null data pointers for glCompressedTexImage*D,
+ // unlike glTexImage*D (which in turn does not accept compressed formats).
+ if (isCompressedFormat(format)) {
+ storageAllocated = true;
+ return;
+ }
+
switch (target) {
case QOpenGLTexture::TargetBuffer:
// Buffer textures get their storage from an external OpenGL buffer
@@ -1196,86 +1329,121 @@ void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, QOpenGLTe
int dataSize, const void *data,
const QOpenGLPixelTransferOptions * const options)
{
+ if (!isCompressedFormat(format)) {
+ qWarning("Cannot set compressed data for non-compressed format 0x%x", format);
+ return;
+ }
+
+ const bool needsFullSpec = !isUsingImmutableStorage(); // was allocateStorage() a no-op?
+
switch (target) {
case QOpenGLTexture::Target1D:
Q_UNUSED(layer);
Q_UNUSED(cubeFace);
- texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
- 0, mipLevelSize( mipLevel, dimensions[0] ),
- format, dataSize, data, options);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage1D(textureId, target, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
+ 0, mipLevelSize( mipLevel, dimensions[0] ),
+ format, dataSize, data, options);
+ }
break;
case QOpenGLTexture::Target1DArray:
Q_UNUSED(cubeFace);
- texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
- 0, layer,
- mipLevelSize(mipLevel, dimensions[0]),
- 1,
- format, dataSize, data, options);
+ if (!needsFullSpec) {
+ texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ 1,
+ format, dataSize, data, options);
+ }
break;
case QOpenGLTexture::Target2D:
Q_UNUSED(layer);
Q_UNUSED(cubeFace);
- texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
- 0, 0,
- mipLevelSize(mipLevel, dimensions[0]),
- mipLevelSize(mipLevel, dimensions[1]),
- format, dataSize, data, options);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage2D(textureId, target, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ 0, 0,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ format, dataSize, data, options);
+ }
break;
case QOpenGLTexture::Target2DArray:
Q_UNUSED(cubeFace);
- texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
- 0, 0, layer,
- mipLevelSize(mipLevel, dimensions[0]),
- mipLevelSize(mipLevel, dimensions[1]),
- 1,
- format, dataSize, data, options);
+ if (!needsFullSpec) {
+ texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ 1,
+ format, dataSize, data, options);
+ }
break;
case QOpenGLTexture::Target3D:
Q_UNUSED(cubeFace);
- texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
- 0, 0, layer,
- mipLevelSize(mipLevel, dimensions[0]),
- mipLevelSize(mipLevel, dimensions[1]),
- mipLevelSize(mipLevel, dimensions[2]),
- format, dataSize, data, options);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage3D(textureId, target, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ mipLevelSize(mipLevel, dimensions[2]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ mipLevelSize(mipLevel, dimensions[2]),
+ format, dataSize, data, options);
+ }
break;
case QOpenGLTexture::TargetCubeMap:
Q_UNUSED(layer);
- texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
- 0, 0,
- mipLevelSize(mipLevel, dimensions[0]),
- mipLevelSize(mipLevel, dimensions[1]),
- format, dataSize, data, options);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ 0, 0,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ format, dataSize, data, options);
+ }
break;
case QOpenGLTexture::TargetCubeMapArray: {
int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
int layerFace = 6 * layer + faceIndex;
- texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
- 0, 0, layerFace,
- mipLevelSize(mipLevel, dimensions[0]),
- mipLevelSize(mipLevel, dimensions[1]),
- 1,
- format, dataSize, data, options);
+ if (!needsFullSpec) {
+ texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layerFace,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ 1,
+ format, dataSize, data, options);
+ }
break;
}
case QOpenGLTexture::TargetRectangle:
- Q_UNUSED(mipLevel);
- Q_UNUSED(layer);
- Q_UNUSED(cubeFace);
- texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, 0,
- 0, 0,
- dimensions[0],
- dimensions[1],
- format, dataSize, data, options);
- break;
-
case QOpenGLTexture::Target2DMultisample:
case QOpenGLTexture::Target2DMultisampleArray:
case QOpenGLTexture::TargetBuffer:
@@ -1857,6 +2025,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
\value SRGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
\value RGBA8_ETC2_EAC Equivalent to GL_COMPRESSED_RGBA8_ETC2_EAC
\value SRGB8_Alpha8_ETC2_EAC Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ \value RGB8_ETC1 Equivalent to GL_ETC1_RGB8_OES
\value SRGB8 Equivalent to GL_SRGB8
\value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8
@@ -2394,6 +2563,7 @@ void QOpenGLTexture::setFormat(TextureFormat format)
case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
case QOpenGLTexture::RGBA8_ETC2_EAC:
case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGB8_ETC1:
case RG3B2:
case R5G6B5:
case RGB5A1:
@@ -3458,6 +3628,8 @@ QPair<int, int> QOpenGLTexture::mipLevelRange() const
The automatic mipmap generation is enabled by default.
+ \note Mipmap generation is not supported for compressed textures with OpenGL ES 2.0.
+
\sa isAutoMipMapGenerationEnabled(), generateMipMaps()
*/
void QOpenGLTexture::setAutoMipMapGenerationEnabled(bool enabled)
@@ -3483,6 +3655,9 @@ bool QOpenGLTexture::isAutoMipMapGenerationEnabled() const
have disabled automatic mipmap generation then you need to call this function
or the overload to create the mipmap chain.
+ \note Mipmap generation is not supported for compressed textures with OpenGL
+ ES 2.0.
+
\sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
*/
void QOpenGLTexture::generateMipMaps()
@@ -3490,6 +3665,11 @@ void QOpenGLTexture::generateMipMaps()
Q_D(QOpenGLTexture);
Q_ASSERT(d->texFuncs);
Q_ASSERT(d->textureId);
+ if (isCompressedFormat(d->format)) {
+ if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
+ if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3)
+ return;
+ }
d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
}
@@ -3510,6 +3690,11 @@ void QOpenGLTexture::generateMipMaps(int baseLevel, bool resetBaseLevel)
Q_D(QOpenGLTexture);
Q_ASSERT(d->texFuncs);
Q_ASSERT(d->textureId);
+ if (isCompressedFormat(d->format)) {
+ if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
+ if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3)
+ return;
+ }
int oldBaseLevel;
if (resetBaseLevel)
oldBaseLevel = mipBaseLevel();
diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h
index baab2d634f..ec52a192fa 100644
--- a/src/gui/opengl/qopengltexture.h
+++ b/src/gui/opengl/qopengltexture.h
@@ -196,6 +196,7 @@ public:
SRGB8_PunchThrough_Alpha1_ETC2 = 0x9277, // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
RGBA8_ETC2_EAC = 0x9278, // GL_COMPRESSED_RGBA8_ETC2_EAC
SRGB8_Alpha8_ETC2_EAC = 0x9279, // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ RGB8_ETC1 = 0x8D64, // GL_ETC1_RGB8_OES
// sRGB formats
SRGB8 = 0x8C41, // GL_SRGB8
diff --git a/src/gui/opengl/qopengltexture_p.h b/src/gui/opengl/qopengltexture_p.h
index be4bf0e93c..ac9d44db42 100644
--- a/src/gui/opengl/qopengltexture_p.h
+++ b/src/gui/opengl/qopengltexture_p.h
@@ -117,6 +117,8 @@ public:
return std::floor(double(qMax(1, baseLevelSize >> mipLevel)));
}
+ bool isUsingImmutableStorage() const;
+
QOpenGLTexture *q_ptr;
QOpenGLContext *context;
QOpenGLTexture::Target target;
diff --git a/src/gui/opengl/qopengltexturehelper_p.h b/src/gui/opengl/qopengltexturehelper_p.h
index 5a56516b49..d659fcedfb 100644
--- a/src/gui/opengl/qopengltexturehelper_p.h
+++ b/src/gui/opengl/qopengltexturehelper_p.h
@@ -253,23 +253,48 @@ public:
inline void glCompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLenum internalFormat, GLsizei width,
- GLint border, GLsizei imageSize, const GLvoid *bits)
+ GLint border, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = 0)
{
- (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits);
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits);
+ }
}
inline void glCompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height,
- GLint border, GLsizei imageSize, const GLvoid *bits)
+ GLint border, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = 0)
+
{
- (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits);
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits);
+ }
}
inline void glCompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLsizei imageSize, const GLvoid *bits)
+ GLint border, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = 0)
{
- (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits);
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits);
+ }
}
private:
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 846c513f01..0814e0494d 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -996,6 +996,34 @@ void QPdfEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
*d->currentPage << "Q\n";
}
+void QPdfEngine::drawHyperlink(const QRectF &r, const QUrl &url)
+{
+ Q_D(QPdfEngine);
+
+ const uint annot = d->addXrefEntry(-1);
+ const QByteArray urlascii = url.toEncoded();
+ int len = urlascii.size();
+ QVarLengthArray<char> url_esc(0);
+ for (int j = 0; j < len; j++) {
+ if (urlascii[j] == '(' || urlascii[j] == ')' || urlascii[j] == '\\')
+ url_esc.append('\\');
+ url_esc.append(urlascii[j]);
+ }
+ url_esc.append('\0');
+
+ char buf[256];
+ const QRectF rr = d->pageMatrix().mapRect(r);
+ d->xprintf("<<\n/Type /Annot\n/Subtype /Link\n/Rect [");
+ d->xprintf("%s ", qt_real_to_string(rr.left(), buf));
+ d->xprintf("%s ", qt_real_to_string(rr.top(), buf));
+ d->xprintf("%s ", qt_real_to_string(rr.right(), buf));
+ d->xprintf("%s", qt_real_to_string(rr.bottom(), buf));
+ d->xprintf("]\n/Border [0 0 0]\n/A <<\n");
+ d->xprintf("/Type /Action\n/S /URI\n/URI (%s)\n", url_esc.constData());
+ d->xprintf(">>\n>>\n");
+ d->xprintf("endobj\n");
+ d->currentPage->annotations.append(annot);
+}
void QPdfEngine::updateState(const QPaintEngineState &state)
{
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index 2b50cdc6f7..de30744ca2 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -188,6 +188,8 @@ public:
Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
void drawTiledPixmap (const QRectF & rectangle, const QPixmap & pixmap, const QPointF & point) Q_DECL_OVERRIDE;
+ void drawHyperlink(const QRectF &r, const QUrl &url);
+
void updateState(const QPaintEngineState &state) Q_DECL_OVERRIDE;
int metric(QPaintDevice::PaintDeviceMetric metricType) const;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 9f74828f2d..51679116b5 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -237,7 +237,7 @@ protected:
bool shouldUseNSPanel();
- QRect windowGeometry() const;
+ QRect nativeWindowGeometry() const;
QCocoaWindow *parentCocoaWindow() const;
void syncWindowState(Qt::WindowState newState);
void reinsertChildWindow(QCocoaWindow *child);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index e1d09c0400..5606f050a3 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -606,7 +606,7 @@ void QCocoaWindow::show(bool becauseOfAncestor)
&& !m_hiddenByClipping) { // ... NOR clipped
if (m_isNSWindowChild) {
m_hiddenByAncestor = false;
- setCocoaGeometry(window()->geometry());
+ setCocoaGeometry(windowGeometry());
}
if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status
[m_nsWindow orderFront:nil];
@@ -645,7 +645,7 @@ void QCocoaWindow::setVisible(bool visible)
if (parentCocoaWindow) {
// The parent window might have moved while this window was hidden,
// update the window geometry if there is a parent.
- setGeometry(window()->geometry());
+ setGeometry(windowGeometry());
if (window()->type() == Qt::Popup) {
// QTBUG-30266: a window should not be resizable while a transient popup is open
@@ -864,8 +864,8 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
// no-WindowMaximizeButtonHint windows. From a Qt perspective it migth be expected
// that the button would be removed in the latter case, but disabling it is more
// in line with the platform style guidelines.
- bool fixedSizeNoZoom = (window()->minimumSize().isValid() && window()->maximumSize().isValid()
- && window()->minimumSize() == window()->maximumSize());
+ bool fixedSizeNoZoom = (windowMinimumSize().isValid() && windowMaximumSize().isValid()
+ && windowMinimumSize() == windowMaximumSize());
bool customizeNoZoom = ((flags & Qt::CustomizeWindowHint) && !(flags & Qt::WindowMaximizeButtonHint));
[[m_nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)];
}
@@ -1054,20 +1054,20 @@ void QCocoaWindow::propagateSizeHints()
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
qDebug() << "QCocoaWindow::propagateSizeHints" << this;
- qDebug() << " min/max " << window()->minimumSize() << window()->maximumSize();
- qDebug() << "size increment" << window()->sizeIncrement();
- qDebug() << " basesize" << window()->baseSize();
- qDebug() << " geometry" << geometry();
+ qDebug() << " min/max" << windowMinimumSize() << windowMaximumSize();
+ qDebug() << "size increment" << windowSizeIncrement();
+ qDebug() << " basesize" << windowBaseSize();
+ qDebug() << " geometry" << windowGeometry();
#endif
// Set the minimum content size.
- const QSize minimumSize = window()->minimumSize();
+ const QSize minimumSize = windowMinimumSize();
if (!minimumSize.isValid()) // minimumSize is (-1, -1) when not set. Make that (0, 0) for Cocoa.
[m_nsWindow setContentMinSize : NSMakeSize(0.0, 0.0)];
[m_nsWindow setContentMinSize : NSMakeSize(minimumSize.width(), minimumSize.height())];
// Set the maximum content size.
- const QSize maximumSize = window()->maximumSize();
+ const QSize maximumSize = windowMaximumSize();
[m_nsWindow setContentMaxSize : NSMakeSize(maximumSize.width(), maximumSize.height())];
// The window may end up with a fixed size; in this case the zoom button should be disabled.
@@ -1075,13 +1075,14 @@ void QCocoaWindow::propagateSizeHints()
// sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be
// resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case.
- if (!window()->sizeIncrement().isEmpty())
- [m_nsWindow setResizeIncrements : qt_mac_toNSSize(window()->sizeIncrement())];
+ const QSize sizeIncrement = windowSizeIncrement();
+ if (!sizeIncrement.isEmpty())
+ [m_nsWindow setResizeIncrements : qt_mac_toNSSize(sizeIncrement)];
else
[m_nsWindow setResizeIncrements : NSMakeSize(1.0, 1.0)];
QRect rect = geometry();
- QSize baseSize = window()->baseSize();
+ QSize baseSize = windowBaseSize();
if (!baseSize.isNull() && baseSize.isValid()) {
[m_nsWindow setFrame:NSMakeRect(rect.x(), rect.y(), baseSize.width(), baseSize.height()) display:YES];
}
@@ -1327,7 +1328,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
| NSWindowCollectionBehaviorFullScreenAuxiliary;
m_nsWindow.animationBehavior = NSWindowAnimationBehaviorNone;
m_nsWindow.collectionBehavior = collectionBehavior;
- setCocoaGeometry(window()->geometry());
+ setCocoaGeometry(windowGeometry());
QList<QCocoaWindow *> &siblings = m_parentCocoaWindow->m_childWindows;
if (siblings.contains(this)) {
@@ -1341,7 +1342,7 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
} else {
// Child windows have no NSWindow, link the NSViews instead.
[m_parentCocoaWindow->m_contentView addSubview : m_contentView];
- QRect rect = window()->geometry();
+ QRect rect = windowGeometry();
// Prevent setting a (0,0) window size; causes opengl context
// "Invalid Drawable" warnings.
if (rect.isNull())
@@ -1393,7 +1394,7 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
{
QMacAutoReleasePool pool;
- QRect rect = initialGeometry(window(), window()->geometry(), defaultWindowWidth, defaultWindowHeight);
+ QRect rect = initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight);
NSRect frame = qt_mac_flipRect(rect);
Qt::WindowType type = window()->type();
@@ -1489,7 +1490,7 @@ void QCocoaWindow::removeMonitor()
}
// Returns the current global screen geometry for the nswindow associated with this window.
-QRect QCocoaWindow::windowGeometry() const
+QRect QCocoaWindow::nativeWindowGeometry() const
{
if (!m_nsWindow || m_isNSWindowChild)
return geometry();
@@ -1572,7 +1573,7 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
if (m_normalGeometry.width() < 0) {
m_oldWindowFlags = m_windowFlags;
window()->setFlags(window()->flags() | Qt::FramelessWindowHint);
- m_normalGeometry = windowGeometry();
+ m_normalGeometry = nativeWindowGeometry();
setGeometry(screen->geometry());
m_presentationOptions = [NSApp presentationOptions];
[NSApp setPresentationOptions : m_presentationOptions | NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock];
@@ -1850,12 +1851,11 @@ QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffset() const
{
if (!m_contentView)
return QPoint();
- NSPoint origin = [m_contentView isFlipped] ?
- NSMakePoint(0, [m_contentView frame].size.height) :
- NSMakePoint(0, 0);
- NSPoint windowPoint = [m_contentView convertPoint:origin toView:nil];
+ const NSPoint origin = [m_contentView isFlipped] ? NSMakePoint(0, [m_contentView frame].size.height)
+ : NSMakePoint(0, 0);
+ const NSRect visibleRect = [m_contentView visibleRect];
- return QPoint(-std::min((int)windowPoint.x, 0), -std::min((int)windowPoint.y,0));
+ return QPoint(visibleRect.origin.x, -visibleRect.origin.y + (origin.y - visibleRect.size.height));
}
QMargins QCocoaWindow::frameMargins() const
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.cpp b/src/plugins/platforms/eglfs/qeglfscursor.cpp
index d81aa2eaf2..eea130a754 100644
--- a/src/plugins/platforms/eglfs/qeglfscursor.cpp
+++ b/src/plugins/platforms/eglfs/qeglfscursor.cpp
@@ -43,6 +43,11 @@
#include <QtCore/QJsonObject>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qopenglvertexarrayobject_p.h>
+
+#ifndef GL_VERTEX_ARRAY_BINDING
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#endif
QT_BEGIN_NAMESPACE
@@ -50,8 +55,6 @@ QEglFSCursor::QEglFSCursor(QPlatformScreen *screen)
: m_visible(true),
m_screen(static_cast<QEglFSScreen *>(screen)),
m_program(0),
- m_vertexCoordEntry(0),
- m_textureCoordEntry(0),
m_textureEntry(0),
m_deviceListener(0),
m_updateRequested(false)
@@ -134,10 +137,10 @@ void QEglFSCursor::createShaderPrograms()
m_program = new QOpenGLShaderProgram;
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+ m_program->bindAttributeLocation("vertexCoordEntry", 0);
+ m_program->bindAttributeLocation("textureCoordEntry", 1);
m_program->link();
- m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry");
- m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry");
m_textureEntry = m_program->uniformLocation("texture");
}
@@ -322,8 +325,105 @@ void QEglFSCursor::paintOnScreen()
draw(r);
}
+// In order to prevent breaking code doing custom OpenGL rendering while
+// expecting the state in the context unchanged, save and restore all the state
+// we touch. The exception is Qt Quick where the scenegraph is known to be able
+// to deal with the changes we make.
+struct StateSaver
+{
+ StateSaver() {
+ f = QOpenGLContext::currentContext()->functions();
+ vaoHelper = new QOpenGLVertexArrayObjectHelper(QOpenGLContext::currentContext());
+
+ static bool windowsChecked = false;
+ static bool shouldSave = true;
+ if (!windowsChecked) {
+ windowsChecked = true;
+ QWindowList windows = QGuiApplication::allWindows();
+ if (!windows.isEmpty() && windows[0]->inherits("QQuickWindow"))
+ shouldSave = false;
+ }
+ saved = shouldSave;
+ if (!shouldSave)
+ return;
+
+ f->glGetIntegerv(GL_CURRENT_PROGRAM, &program);
+ f->glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
+ f->glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
+ f->glGetIntegerv(GL_FRONT_FACE, &frontFace);
+ cull = f->glIsEnabled(GL_CULL_FACE);
+ depthTest = f->glIsEnabled(GL_DEPTH_TEST);
+ blend = f->glIsEnabled(GL_BLEND);
+ f->glGetIntegerv(GL_BLEND_SRC_RGB, blendFunc);
+ f->glGetIntegerv(GL_BLEND_SRC_ALPHA, blendFunc + 1);
+ f->glGetIntegerv(GL_BLEND_DST_RGB, blendFunc + 2);
+ f->glGetIntegerv(GL_BLEND_DST_ALPHA, blendFunc + 3);
+ f->glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBuf);
+ if (vaoHelper->isValid())
+ f->glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vao);
+ for (int i = 0; i < 2; ++i) {
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &va[i].enabled);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &va[i].size);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &va[i].type);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &va[i].normalized);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &va[i].stride);
+ f->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &va[i].buffer);
+ f->glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &va[i].pointer);
+ }
+ }
+ ~StateSaver() {
+ if (saved) {
+ f->glUseProgram(program);
+ f->glBindTexture(GL_TEXTURE_2D, texture);
+ f->glActiveTexture(activeTexture);
+ f->glFrontFace(frontFace);
+ if (cull)
+ f->glEnable(GL_CULL_FACE);
+ else
+ f->glDisable(GL_CULL_FACE);
+ if (depthTest)
+ f->glEnable(GL_DEPTH_TEST);
+ else
+ f->glDisable(GL_DEPTH_TEST);
+ if (blend)
+ f->glEnable(GL_BLEND);
+ else
+ f->glDisable(GL_BLEND);
+ f->glBlendFuncSeparate(blendFunc[0], blendFunc[1], blendFunc[2], blendFunc[3]);
+ f->glBindBuffer(GL_ARRAY_BUFFER, arrayBuf);
+ if (vaoHelper->isValid())
+ vaoHelper->glBindVertexArray(vao);
+ for (int i = 0; i < 2; ++i) {
+ if (va[i].enabled)
+ f->glEnableVertexAttribArray(i);
+ else
+ f->glDisableVertexAttribArray(i);
+ f->glBindBuffer(GL_ARRAY_BUFFER, va[i].buffer);
+ f->glVertexAttribPointer(i, va[i].size, va[i].type, va[i].normalized, va[i].stride, va[i].pointer);
+ }
+ }
+ delete vaoHelper;
+ }
+ QOpenGLFunctions *f;
+ QOpenGLVertexArrayObjectHelper *vaoHelper;
+ bool saved;
+ GLint program;
+ GLint texture;
+ GLint activeTexture;
+ GLint frontFace;
+ bool cull;
+ bool depthTest;
+ bool blend;
+ GLint blendFunc[4];
+ GLint vao;
+ GLint arrayBuf;
+ struct { GLint enabled, type, size, normalized, stride, buffer; GLvoid *pointer; } va[2];
+};
+
void QEglFSCursor::draw(const QRectF &r)
{
+ StateSaver stateSaver;
+
if (!m_program) {
// one time initialization
initializeOpenGLFunctions();
@@ -373,13 +473,16 @@ void QEglFSCursor::draw(const QRectF &r)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_cursor.texture);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- m_program->enableAttributeArray(m_vertexCoordEntry);
- m_program->enableAttributeArray(m_textureCoordEntry);
+ if (stateSaver.vaoHelper->isValid())
+ stateSaver.vaoHelper->glBindVertexArray(0);
- m_program->setAttributeArray(m_vertexCoordEntry, cursorCoordinates, 2);
- m_program->setAttributeArray(m_textureCoordEntry, textureCoordinates, 2);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ m_program->enableAttributeArray(0);
+ m_program->enableAttributeArray(1);
+ m_program->setAttributeArray(0, cursorCoordinates, 2);
+ m_program->setAttributeArray(1, textureCoordinates, 2);
m_program->setUniformValue(m_textureEntry, 0);
@@ -388,13 +491,11 @@ void QEglFSCursor::draw(const QRectF &r)
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST); // disable depth testing to make sure cursor is always on top
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- glDisable(GL_BLEND);
- glBindTexture(GL_TEXTURE_2D, 0);
- m_program->disableAttributeArray(m_textureCoordEntry);
- m_program->disableAttributeArray(m_vertexCoordEntry);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ m_program->disableAttributeArray(0);
+ m_program->disableAttributeArray(1);
m_program->release();
}
diff --git a/src/plugins/platforms/eglfs/qeglfscursor.h b/src/plugins/platforms/eglfs/qeglfscursor.h
index 048f276137..be5db41b37 100644
--- a/src/plugins/platforms/eglfs/qeglfscursor.h
+++ b/src/plugins/platforms/eglfs/qeglfscursor.h
@@ -131,8 +131,6 @@ private:
bool m_visible;
QEglFSScreen *m_screen;
QOpenGLShaderProgram *m_program;
- int m_vertexCoordEntry;
- int m_textureCoordEntry;
int m_textureEntry;
QEglFSCursorDeviceListener *m_deviceListener;
bool m_updateRequested;
diff --git a/src/plugins/platforms/mirclient/mirclient.json b/src/plugins/platforms/mirclient/mirclient.json
new file mode 100644
index 0000000000..c31558a2f1
--- /dev/null
+++ b/src/plugins/platforms/mirclient/mirclient.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "mirclient" ]
+}
diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro
new file mode 100644
index 0000000000..033ce579b9
--- /dev/null
+++ b/src/plugins/platforms/mirclient/mirclient.pro
@@ -0,0 +1,47 @@
+TARGET = mirclient
+TEMPLATE = lib
+
+PLUGIN_TYPE = platforms
+PLUGIN_CLASS_NAME = MirServerIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
+load(qt_plugin)
+
+QT += core-private gui-private platformsupport-private dbus
+
+CONFIG += qpa/genericunixfontdatabase
+
+DEFINES += MESA_EGL_NO_X11_HEADERS
+# CONFIG += c++11 # only enables C++0x
+QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall
+QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined
+
+CONFIG += link_pkgconfig
+PKGCONFIG += egl mirclient ubuntu-platform-api
+
+SOURCES = \
+ qmirclientbackingstore.cpp \
+ qmirclientclipboard.cpp \
+ qmirclientglcontext.cpp \
+ qmirclientinput.cpp \
+ qmirclientintegration.cpp \
+ qmirclientnativeinterface.cpp \
+ qmirclientplatformservices.cpp \
+ qmirclientplugin.cpp \
+ qmirclientscreen.cpp \
+ qmirclienttheme.cpp \
+ qmirclientwindow.cpp
+
+HEADERS = \
+ qmirclientbackingstore.h \
+ qmirclientclipboard.h \
+ qmirclientglcontext.h \
+ qmirclientinput.h \
+ qmirclientintegration.h \
+ qmirclientlogging.h \
+ qmirclientnativeinterface.h \
+ qmirclientorientationchangeevent_p.h \
+ qmirclientplatformservices.h \
+ qmirclientplugin.h \
+ qmirclientscreen.h \
+ qmirclienttheme.h \
+ qmirclientwindow.h
diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp
new file mode 100644
index 0000000000..daa0b229ec
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientbackingstore.h"
+#include "qmirclientlogging.h"
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/private/qopengltextureblitter_p.h>
+#include <QtGui/qopenglfunctions.h>
+
+QMirClientBackingStore::QMirClientBackingStore(QWindow* window)
+ : QPlatformBackingStore(window)
+ , mContext(new QOpenGLContext)
+ , mTexture(new QOpenGLTexture(QOpenGLTexture::Target2D))
+ , mBlitter(new QOpenGLTextureBlitter)
+{
+ mContext->setFormat(window->requestedFormat());
+ mContext->setScreen(window->screen());
+ mContext->create();
+
+ window->setSurfaceType(QSurface::OpenGLSurface);
+}
+
+QMirClientBackingStore::~QMirClientBackingStore()
+{
+}
+
+void QMirClientBackingStore::flush(QWindow* window, const QRegion& region, const QPoint& offset)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+ mContext->makeCurrent(window);
+ glViewport(0, 0, window->width(), window->height());
+
+ updateTexture();
+
+ if (!mBlitter->isCreated())
+ mBlitter->create();
+
+ mBlitter->bind();
+ mBlitter->setSwizzleRB(true);
+ mBlitter->blit(mTexture->textureId(), QMatrix4x4(), QOpenGLTextureBlitter::OriginTopLeft);
+ mBlitter->release();
+
+ mContext->swapBuffers(window);
+}
+
+void QMirClientBackingStore::updateTexture()
+{
+ if (mDirty.isNull())
+ return;
+
+ if (!mTexture->isCreated()) {
+ mTexture->setMinificationFilter(QOpenGLTexture::Nearest);
+ mTexture->setMagnificationFilter(QOpenGLTexture::Nearest);
+ mTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
+ mTexture->setData(mImage, QOpenGLTexture::DontGenerateMipMaps);
+ mTexture->create();
+ }
+ mTexture->bind();
+
+ QRegion fixed;
+ QRect imageRect = mImage.rect();
+
+ Q_FOREACH (const QRect &rect, mDirty.rects()) {
+ // intersect with image rect to be sure
+ QRect r = imageRect & rect;
+
+ // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy
+ if (r.width() >= imageRect.width() / 2) {
+ r.setX(0);
+ r.setWidth(imageRect.width());
+ }
+
+ fixed |= r;
+ }
+
+ Q_FOREACH (const QRect &rect, fixed.rects()) {
+ // if the sub-rect is full-width we can pass the image data directly to
+ // OpenGL instead of copying, since there is no gap between scanlines
+ if (rect.width() == imageRect.width()) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ mImage.constScanLine(rect.y()));
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ mImage.copy(rect).constBits());
+ }
+ }
+ /* End of code taken from QEGLPlatformBackingStore */
+
+ mDirty = QRegion();
+}
+
+
+void QMirClientBackingStore::beginPaint(const QRegion& region)
+{
+ mDirty |= region;
+}
+
+void QMirClientBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/)
+{
+ mImage = QImage(size, QImage::Format_RGB32);
+
+ if (mTexture->isCreated())
+ mTexture->destroy();
+}
+
+QPaintDevice* QMirClientBackingStore::paintDevice()
+{
+ return &mImage;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.h b/src/plugins/platforms/mirclient/qmirclientbackingstore.h
new file mode 100644
index 0000000000..22b8bf9bc5
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientbackingstore.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTBACKINGSTORE_H
+#define QMIRCLIENTBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+
+class QOpenGLContext;
+class QOpenGLTexture;
+class QOpenGLTextureBlitter;
+
+class QMirClientBackingStore : public QPlatformBackingStore
+{
+public:
+ QMirClientBackingStore(QWindow* window);
+ virtual ~QMirClientBackingStore();
+
+ // QPlatformBackingStore methods.
+ void beginPaint(const QRegion&) override;
+ void flush(QWindow* window, const QRegion& region, const QPoint& offset) override;
+ void resize(const QSize& size, const QRegion& staticContents) override;
+ QPaintDevice* paintDevice() override;
+
+protected:
+ void updateTexture();
+
+private:
+ QScopedPointer<QOpenGLContext> mContext;
+ QScopedPointer<QOpenGLTexture> mTexture;
+ QScopedPointer<QOpenGLTextureBlitter> mBlitter;
+ QImage mImage;
+ QRegion mDirty;
+};
+
+#endif // QMIRCLIENTBACKINGSTORE_H
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
new file mode 100644
index 0000000000..aa2ddf2103
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientclipboard.h"
+
+#include <QtCore/QMimeData>
+#include <QtCore/QStringList>
+#include <QDBusInterface>
+#include <QDBusPendingCallWatcher>
+#include <QDBusPendingReply>
+
+// FIXME(loicm) The clipboard data format is not defined by Ubuntu Platform API
+// which makes it impossible to have non-Qt applications communicate with Qt
+// applications through the clipboard API. The solution would be to have
+// Ubuntu Platform define the data format or propose an API that supports
+// embedding different mime types in the clipboard.
+
+// Data format:
+// number of mime types (sizeof(int))
+// data layout ((4 * sizeof(int)) * number of mime types)
+// mime type string offset (sizeof(int))
+// mime type string size (sizeof(int))
+// data offset (sizeof(int))
+// data size (sizeof(int))
+// data (n bytes)
+
+namespace {
+
+const int maxFormatsCount = 16;
+const int maxBufferSize = 4 * 1024 * 1024; // 4 Mb
+
+}
+
+QMirClientClipboard::QMirClientClipboard()
+ : mMimeData(new QMimeData)
+ , mIsOutdated(true)
+ , mUpdatesDisabled(false)
+ , mDBusSetupDone(false)
+{
+}
+
+QMirClientClipboard::~QMirClientClipboard()
+{
+ delete mMimeData;
+}
+
+void QMirClientClipboard::requestDBusClipboardContents()
+{
+ if (!mDBusSetupDone) {
+ setupDBus();
+ }
+
+ if (!mPendingGetContentsCall.isNull())
+ return;
+
+ QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("GetContents");
+
+ mPendingGetContentsCall = new QDBusPendingCallWatcher(pendingCall, this);
+
+ QObject::connect(mPendingGetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*)));
+}
+
+void QMirClientClipboard::onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher* call)
+{
+ Q_ASSERT(call == mPendingGetContentsCall.data());
+
+ QDBusPendingReply<QByteArray> reply = *call;
+ if (reply.isError()) {
+ qCritical("QMirClientClipboard - Failed to get system clipboard contents via D-Bus. %s, %s",
+ qPrintable(reply.error().name()), qPrintable(reply.error().message()));
+ // TODO: Might try again later a number of times...
+ } else {
+ QByteArray serializedMimeData = reply.argumentAt<0>();
+ updateMimeData(serializedMimeData);
+ }
+ call->deleteLater();
+}
+
+void QMirClientClipboard::onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher *call)
+{
+ QDBusPendingReply<void> reply = *call;
+ if (reply.isError()) {
+ qCritical("QMirClientClipboard - Failed to set the system clipboard contents via D-Bus. %s, %s",
+ qPrintable(reply.error().name()), qPrintable(reply.error().message()));
+ // TODO: Might try again later a number of times...
+ }
+ call->deleteLater();
+}
+
+void QMirClientClipboard::updateMimeData(const QByteArray &serializedMimeData)
+{
+ if (mUpdatesDisabled)
+ return;
+
+ QMimeData *newMimeData = deserializeMimeData(serializedMimeData);
+ if (newMimeData) {
+ delete mMimeData;
+ mMimeData = newMimeData;
+ mIsOutdated = false;
+ emitChanged(QClipboard::Clipboard);
+ } else {
+ qWarning("QMirClientClipboard - Got invalid serialized mime data. Ignoring it.");
+ }
+}
+
+void QMirClientClipboard::setupDBus()
+{
+ QDBusConnection dbusConnection = QDBusConnection::sessionBus();
+
+ bool ok = dbusConnection.connect(
+ "com.canonical.QtMir",
+ "/com/canonical/QtMir/Clipboard",
+ "com.canonical.QtMir.Clipboard",
+ "ContentsChanged",
+ this, SLOT(updateMimeData(QByteArray)));
+ if (!ok) {
+ qCritical("QMirClientClipboard - Failed to connect to ContentsChanged signal form the D-Bus system clipboard.");
+ }
+
+ mDBusClipboard = new QDBusInterface("com.canonical.QtMir",
+ "/com/canonical/QtMir/Clipboard",
+ "com.canonical.QtMir.Clipboard",
+ dbusConnection);
+
+ mDBusSetupDone = true;
+}
+
+QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const
+{
+ const QStringList formats = mimeData->formats();
+ const int formatCount = qMin(formats.size(), maxFormatsCount);
+ const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int));
+ int bufferSize = headerSize;
+
+ for (int i = 0; i < formatCount; i++)
+ bufferSize += formats[i].size() + mimeData->data(formats[i]).size();
+
+ QByteArray serializedMimeData;
+ if (bufferSize <= maxBufferSize) {
+ // Serialize data.
+ serializedMimeData.resize(bufferSize);
+ {
+ char *buffer = serializedMimeData.data();
+ int* header = reinterpret_cast<int*>(serializedMimeData.data());
+ int offset = headerSize;
+ header[0] = formatCount;
+ for (int i = 0; i < formatCount; i++) {
+ const int formatOffset = offset;
+ const int formatSize = formats[i].size();
+ const int dataOffset = offset + formatSize;
+ const int dataSize = mimeData->data(formats[i]).size();
+ memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize);
+ memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize);
+ header[i*4+1] = formatOffset;
+ header[i*4+2] = formatSize;
+ header[i*4+3] = dataOffset;
+ header[i*4+4] = dataSize;
+ offset += formatSize + dataSize;
+ }
+ }
+ } else {
+ qWarning("QMirClientClipboard: Not sending contents (%d bytes) to the global clipboard as it's"
+ " bigger than the maximum allowed size of %d bytes", bufferSize, maxBufferSize);
+ }
+
+ return serializedMimeData;
+}
+
+QMimeData *QMirClientClipboard::deserializeMimeData(const QByteArray &serializedMimeData) const
+{
+ if (static_cast<std::size_t>(serializedMimeData.size()) < sizeof(int)) {
+ // Data is invalid
+ return nullptr;
+ }
+
+ QMimeData *mimeData = new QMimeData;
+
+ const char* const buffer = serializedMimeData.constData();
+ const int* const header = reinterpret_cast<const int*>(serializedMimeData.constData());
+
+ const int count = qMin(header[0], maxFormatsCount);
+
+ for (int i = 0; i < count; i++) {
+ const int formatOffset = header[i*4+1];
+ const int formatSize = header[i*4+2];
+ const int dataOffset = header[i*4+3];
+ const int dataSize = header[i*4+4];
+
+ if (formatOffset + formatSize <= serializedMimeData.size()
+ && dataOffset + dataSize <= serializedMimeData.size()) {
+
+ QString mimeType = QString::fromLatin1(&buffer[formatOffset], formatSize);
+ QByteArray mimeDataBytes(&buffer[dataOffset], dataSize);
+
+ mimeData->setData(mimeType, mimeDataBytes);
+ }
+ }
+
+ return mimeData;
+}
+
+QMimeData* QMirClientClipboard::mimeData(QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return nullptr;
+
+ if (mIsOutdated && mPendingGetContentsCall.isNull()) {
+ requestDBusClipboardContents();
+ }
+
+ // Return whatever we have at the moment instead of blocking until we have something.
+ //
+ // This might be called during app startup just for the sake of checking if some
+ // "Paste" UI control should be enabled or not.
+ // We will emit QClipboard::changed() once we finally have something.
+ return mMimeData;
+}
+
+void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode)
+{
+ if (mode != QClipboard::Clipboard)
+ return;
+
+ if (!mPendingGetContentsCall.isNull()) {
+ // Ignore whatever comes from the system clipboard as we are going to change it anyway
+ QObject::disconnect(mPendingGetContentsCall.data(), 0, this, 0);
+ mUpdatesDisabled = true;
+ mPendingGetContentsCall->waitForFinished();
+ mUpdatesDisabled = false;
+ delete mPendingGetContentsCall.data();
+ }
+
+ QByteArray serializedMimeData = serializeMimeData(mimeData);
+ if (!serializedMimeData.isEmpty()) {
+ setDBusClipboardContents(serializedMimeData);
+ }
+
+ mMimeData = mimeData;
+ emitChanged(QClipboard::Clipboard);
+}
+
+bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const
+{
+ return mode == QClipboard::Clipboard;
+}
+
+bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const
+{
+ Q_UNUSED(mode);
+ return false;
+}
+
+void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardContents)
+{
+ if (!mPendingSetContentsCall.isNull()) {
+ // Ignore any previous set call as we are going to overwrite it anyway
+ QObject::disconnect(mPendingSetContentsCall.data(), 0, this, 0);
+ mUpdatesDisabled = true;
+ mPendingSetContentsCall->waitForFinished();
+ mUpdatesDisabled = false;
+ delete mPendingSetContentsCall.data();
+ }
+
+ QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("SetContents", clipboardContents);
+
+ mPendingSetContentsCall = new QDBusPendingCallWatcher(pendingCall, this);
+
+ QObject::connect(mPendingSetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*)));
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.h b/src/plugins/platforms/mirclient/qmirclientclipboard.h
new file mode 100644
index 0000000000..d3d3d400d2
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientclipboard.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTCLIPBOARD_H
+#define QMIRCLIENTCLIPBOARD_H
+
+#include <qpa/qplatformclipboard.h>
+
+#include <QMimeData>
+#include <QPointer>
+class QDBusInterface;
+class QDBusPendingCallWatcher;
+
+class QMirClientClipboard : public QObject, public QPlatformClipboard
+{
+ Q_OBJECT
+public:
+ QMirClientClipboard();
+ virtual ~QMirClientClipboard();
+
+ // QPlatformClipboard methods.
+ QMimeData* mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+ void setMimeData(QMimeData* data, QClipboard::Mode mode = QClipboard::Clipboard) override;
+ bool supportsMode(QClipboard::Mode mode) const override;
+ bool ownsMode(QClipboard::Mode mode) const override;
+
+ void requestDBusClipboardContents();
+
+private Q_SLOTS:
+ void onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*);
+ void onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*);
+ void updateMimeData(const QByteArray &serializedMimeData);
+
+private:
+ void setupDBus();
+
+ QByteArray serializeMimeData(QMimeData *mimeData) const;
+ QMimeData *deserializeMimeData(const QByteArray &serializedMimeData) const;
+
+ void setDBusClipboardContents(const QByteArray &clipboardContents);
+
+ QMimeData *mMimeData;
+ bool mIsOutdated;
+
+ QPointer<QDBusInterface> mDBusClipboard;
+
+ QPointer<QDBusPendingCallWatcher> mPendingGetContentsCall;
+ QPointer<QDBusPendingCallWatcher> mPendingSetContentsCall;
+
+ bool mUpdatesDisabled;
+ bool mDBusSetupDone;
+};
+
+#endif // QMIRCLIENTCLIPBOARD_H
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
new file mode 100644
index 0000000000..bfba5051e5
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientglcontext.h"
+#include "qmirclientwindow.h"
+#include "qmirclientlogging.h"
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+
+#if !defined(QT_NO_DEBUG)
+static void printOpenGLESConfig() {
+ static bool once = true;
+ if (once) {
+ const char* string = (const char*) glGetString(GL_VENDOR);
+ LOG("OpenGL ES vendor: %s", string);
+ string = (const char*) glGetString(GL_RENDERER);
+ LOG("OpenGL ES renderer: %s", string);
+ string = (const char*) glGetString(GL_VERSION);
+ LOG("OpenGL ES version: %s", string);
+ string = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
+ LOG("OpenGL ES Shading Language version: %s", string);
+ string = (const char*) glGetString(GL_EXTENSIONS);
+ LOG("OpenGL ES extensions: %s", string);
+ once = false;
+ }
+}
+#endif
+
+static EGLenum api_in_use()
+{
+#ifdef QTUBUNTU_USE_OPENGL
+ return EGL_OPENGL_API;
+#else
+ return EGL_OPENGL_ES_API;
+#endif
+}
+
+QMirClientOpenGLContext::QMirClientOpenGLContext(QMirClientScreen* screen, QMirClientOpenGLContext* share)
+{
+ ASSERT(screen != NULL);
+ mEglDisplay = screen->eglDisplay();
+ mScreen = screen;
+
+ // Create an OpenGL ES 2 context.
+ QVector<EGLint> attribs;
+ attribs.append(EGL_CONTEXT_CLIENT_VERSION);
+ attribs.append(2);
+ attribs.append(EGL_NONE);
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+
+ mEglContext = eglCreateContext(mEglDisplay, screen->eglConfig(), share ? share->eglContext() : EGL_NO_CONTEXT,
+ attribs.constData());
+ DASSERT(mEglContext != EGL_NO_CONTEXT);
+}
+
+QMirClientOpenGLContext::~QMirClientOpenGLContext()
+{
+ ASSERT(eglDestroyContext(mEglDisplay, mEglContext) == EGL_TRUE);
+}
+
+bool QMirClientOpenGLContext::makeCurrent(QPlatformSurface* surface)
+{
+ DASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface);
+ EGLSurface eglSurface = static_cast<QMirClientWindow*>(surface)->eglSurface();
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+ eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+ ASSERT(eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext) == EGL_TRUE);
+ printOpenGLESConfig();
+#endif
+ return true;
+}
+
+void QMirClientOpenGLContext::doneCurrent()
+{
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+ ASSERT(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE);
+#endif
+}
+
+void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface)
+{
+ QMirClientWindow *ubuntuWindow = static_cast<QMirClientWindow*>(surface);
+
+ EGLSurface eglSurface = ubuntuWindow->eglSurface();
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+ eglSwapBuffers(mEglDisplay, eglSurface);
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+ ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE);
+#endif
+
+ // "Technique" copied from mir, in examples/eglapp.c around line 96
+ EGLint newBufferWidth = -1;
+ EGLint newBufferHeight = -1;
+ /*
+ * Querying the surface (actually the current buffer) dimensions here is
+ * the only truly safe way to be sure that the dimensions we think we
+ * have are those of the buffer being rendered to. But this should be
+ * improved in future; https://bugs.launchpad.net/mir/+bug/1194384
+ */
+ eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &newBufferWidth);
+ eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &newBufferHeight);
+
+ ubuntuWindow->onBuffersSwapped_threadSafe(newBufferWidth, newBufferHeight);
+}
+
+void (*QMirClientOpenGLContext::getProcAddress(const QByteArray& procName)) ()
+{
+#if defined(QT_NO_DEBUG)
+ eglBindAPI(api_in_use());
+#else
+ ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
+#endif
+ return eglGetProcAddress(procName.constData());
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.h b/src/plugins/platforms/mirclient/qmirclientglcontext.h
new file mode 100644
index 0000000000..cc40298259
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientglcontext.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTGLCONTEXT_H
+#define QMIRCLIENTGLCONTEXT_H
+
+#include <qpa/qplatformopenglcontext.h>
+#include "qmirclientscreen.h"
+
+class QMirClientOpenGLContext : public QPlatformOpenGLContext
+{
+public:
+ QMirClientOpenGLContext(QMirClientScreen* screen, QMirClientOpenGLContext* share);
+ virtual ~QMirClientOpenGLContext();
+
+ // QPlatformOpenGLContext methods.
+ QSurfaceFormat format() const override { return mScreen->surfaceFormat(); }
+ void swapBuffers(QPlatformSurface* surface) override;
+ bool makeCurrent(QPlatformSurface* surface) override;
+ void doneCurrent() override;
+ bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; }
+ void (*getProcAddress(const QByteArray& procName)) ();
+
+ EGLContext eglContext() const { return mEglContext; }
+
+private:
+ QMirClientScreen* mScreen;
+ EGLContext mEglContext;
+ EGLDisplay mEglDisplay;
+};
+
+#endif // QMIRCLIENTGLCONTEXT_H
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp
new file mode 100644
index 0000000000..56bc21f420
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientinput.cpp
@@ -0,0 +1,520 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Local
+#include "qmirclientinput.h"
+#include "qmirclientintegration.h"
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclientwindow.h"
+#include "qmirclientlogging.h"
+#include "qmirclientorientationchangeevent_p.h"
+
+// Qt
+#if !defined(QT_NO_DEBUG)
+#include <QtCore/QThread>
+#endif
+#include <QtCore/qglobal.h>
+#include <QtCore/QCoreApplication>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatforminputcontext.h>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+
+#include <mir_toolkit/mir_client_library.h>
+
+#define LOG_EVENTS 0
+
+// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
+static const uint32_t KeyTable[] = {
+ XKB_KEY_Escape, Qt::Key_Escape,
+ XKB_KEY_Tab, Qt::Key_Tab,
+ XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
+ XKB_KEY_BackSpace, Qt::Key_Backspace,
+ XKB_KEY_Return, Qt::Key_Return,
+ XKB_KEY_Insert, Qt::Key_Insert,
+ XKB_KEY_Delete, Qt::Key_Delete,
+ XKB_KEY_Clear, Qt::Key_Delete,
+ XKB_KEY_Pause, Qt::Key_Pause,
+ XKB_KEY_Print, Qt::Key_Print,
+
+ XKB_KEY_Home, Qt::Key_Home,
+ XKB_KEY_End, Qt::Key_End,
+ XKB_KEY_Left, Qt::Key_Left,
+ XKB_KEY_Up, Qt::Key_Up,
+ XKB_KEY_Right, Qt::Key_Right,
+ XKB_KEY_Down, Qt::Key_Down,
+ XKB_KEY_Prior, Qt::Key_PageUp,
+ XKB_KEY_Next, Qt::Key_PageDown,
+
+ XKB_KEY_Shift_L, Qt::Key_Shift,
+ XKB_KEY_Shift_R, Qt::Key_Shift,
+ XKB_KEY_Shift_Lock, Qt::Key_Shift,
+ XKB_KEY_Control_L, Qt::Key_Control,
+ XKB_KEY_Control_R, Qt::Key_Control,
+ XKB_KEY_Meta_L, Qt::Key_Meta,
+ XKB_KEY_Meta_R, Qt::Key_Meta,
+ XKB_KEY_Alt_L, Qt::Key_Alt,
+ XKB_KEY_Alt_R, Qt::Key_Alt,
+ XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
+ XKB_KEY_Num_Lock, Qt::Key_NumLock,
+ XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
+ XKB_KEY_Super_L, Qt::Key_Super_L,
+ XKB_KEY_Super_R, Qt::Key_Super_R,
+ XKB_KEY_Menu, Qt::Key_Menu,
+ XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
+ XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
+ XKB_KEY_Help, Qt::Key_Help,
+
+ XKB_KEY_KP_Space, Qt::Key_Space,
+ XKB_KEY_KP_Tab, Qt::Key_Tab,
+ XKB_KEY_KP_Enter, Qt::Key_Enter,
+ XKB_KEY_KP_Home, Qt::Key_Home,
+ XKB_KEY_KP_Left, Qt::Key_Left,
+ XKB_KEY_KP_Up, Qt::Key_Up,
+ XKB_KEY_KP_Right, Qt::Key_Right,
+ XKB_KEY_KP_Down, Qt::Key_Down,
+ XKB_KEY_KP_Prior, Qt::Key_PageUp,
+ XKB_KEY_KP_Next, Qt::Key_PageDown,
+ XKB_KEY_KP_End, Qt::Key_End,
+ XKB_KEY_KP_Begin, Qt::Key_Clear,
+ XKB_KEY_KP_Insert, Qt::Key_Insert,
+ XKB_KEY_KP_Delete, Qt::Key_Delete,
+ XKB_KEY_KP_Equal, Qt::Key_Equal,
+ XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
+ XKB_KEY_KP_Add, Qt::Key_Plus,
+ XKB_KEY_KP_Separator, Qt::Key_Comma,
+ XKB_KEY_KP_Subtract, Qt::Key_Minus,
+ XKB_KEY_KP_Decimal, Qt::Key_Period,
+ XKB_KEY_KP_Divide, Qt::Key_Slash,
+
+ XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
+ XKB_KEY_Multi_key, Qt::Key_Multi_key,
+ XKB_KEY_Codeinput, Qt::Key_Codeinput,
+ XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
+ XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
+ XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
+
+ XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
+ XKB_KEY_script_switch, Qt::Key_Mode_switch,
+ XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
+ XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
+ XKB_KEY_XF86PowerOff, Qt::Key_PowerOff,
+ XKB_KEY_XF86PowerDown, Qt::Key_PowerDown,
+
+ 0, 0
+};
+
+class QMirClientEvent : public QEvent
+{
+public:
+ QMirClientEvent(QMirClientWindow* window, const MirEvent *event, QEvent::Type type)
+ : QEvent(type), window(window) {
+ nativeEvent = mir_event_ref(event);
+ }
+ ~QMirClientEvent()
+ {
+ mir_event_unref(nativeEvent);
+ }
+
+ QPointer<QMirClientWindow> window;
+ const MirEvent *nativeEvent;
+};
+
+QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration)
+ : QObject(nullptr)
+ , mIntegration(integration)
+ , mEventFilterType(static_cast<QMirClientNativeInterface*>(
+ integration->nativeInterface())->genericEventFilterType())
+ , mEventType(static_cast<QEvent::Type>(QEvent::registerEventType()))
+{
+ // Initialize touch device.
+ mTouchDevice = new QTouchDevice;
+ mTouchDevice->setType(QTouchDevice::TouchScreen);
+ mTouchDevice->setCapabilities(
+ QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
+ QTouchDevice::NormalizedPosition);
+ QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+}
+
+QMirClientInput::~QMirClientInput()
+{
+ // Qt will take care of deleting mTouchDevice.
+}
+
+#if (LOG_EVENTS != 0)
+static const char* nativeEventTypeToStr(MirEventType t)
+{
+ switch (t)
+ {
+ case mir_event_type_key:
+ return "mir_event_type_key";
+ case mir_event_type_motion:
+ return "mir_event_type_motion";
+ case mir_event_type_surface:
+ return "mir_event_type_surface";
+ case mir_event_type_resize:
+ return "mir_event_type_resize";
+ case mir_event_type_prompt_session_state_change:
+ return "mir_event_type_prompt_session_state_change";
+ case mir_event_type_orientation:
+ return "mir_event_type_orientation";
+ case mir_event_type_close_surface:
+ return "mir_event_type_close_surface";
+ case mir_event_type_input:
+ return "mir_event_type_input";
+ default:
+ DLOG("Invalid event type %d", t);
+ return "invalid";
+ }
+}
+#endif // LOG_EVENTS != 0
+
+void QMirClientInput::customEvent(QEvent* event)
+{
+ DASSERT(QThread::currentThread() == thread());
+ QMirClientEvent* ubuntuEvent = static_cast<QMirClientEvent*>(event);
+ const MirEvent *nativeEvent = ubuntuEvent->nativeEvent;
+
+ if ((ubuntuEvent->window == nullptr) || (ubuntuEvent->window->window() == nullptr)) {
+ qWarning() << "Attempted to deliver an event to a non-existent window, ignoring.";
+ return;
+ }
+
+ // Event filtering.
+ long result;
+ if (QWindowSystemInterface::handleNativeEvent(
+ ubuntuEvent->window->window(), mEventFilterType,
+ const_cast<void *>(static_cast<const void *>(nativeEvent)), &result) == true) {
+ DLOG("event filtered out by native interface");
+ return;
+ }
+
+ #if (LOG_EVENTS != 0)
+ LOG("QMirClientInput::customEvent(type=%s)", nativeEventTypeToStr(mir_event_get_type(nativeEvent)));
+ #endif
+
+ // Event dispatching.
+ switch (mir_event_get_type(nativeEvent))
+ {
+ case mir_event_type_input:
+ dispatchInputEvent(ubuntuEvent->window->window(), mir_event_get_input_event(nativeEvent));
+ break;
+ case mir_event_type_resize:
+ {
+ Q_ASSERT(ubuntuEvent->window->screen() == mIntegration->screen());
+
+ auto resizeEvent = mir_event_get_resize_event(nativeEvent);
+
+ mIntegration->screen()->handleWindowSurfaceResize(
+ mir_resize_event_get_width(resizeEvent),
+ mir_resize_event_get_height(resizeEvent));
+
+ ubuntuEvent->window->handleSurfaceResize(mir_resize_event_get_width(resizeEvent),
+ mir_resize_event_get_height(resizeEvent));
+ break;
+ }
+ case mir_event_type_surface:
+ {
+ auto surfaceEvent = mir_event_get_surface_event(nativeEvent);
+ if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) {
+ ubuntuEvent->window->handleSurfaceFocusChange(mir_surface_event_get_attribute_value(surfaceEvent) ==
+ mir_surface_focused);
+ }
+ break;
+ }
+ case mir_event_type_orientation:
+ dispatchOrientationEvent(ubuntuEvent->window->window(), mir_event_get_orientation_event(nativeEvent));
+ break;
+ case mir_event_type_close_surface:
+ QWindowSystemInterface::handleCloseEvent(ubuntuEvent->window->window());
+ break;
+ default:
+ DLOG("unhandled event type: %d", static_cast<int>(mir_event_get_type(nativeEvent)));
+ }
+}
+
+void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent *event)
+{
+ QWindow *window = platformWindow->window();
+
+ QCoreApplication::postEvent(this, new QMirClientEvent(
+ platformWindow, event, mEventType));
+
+ if ((window->flags().testFlag(Qt::WindowTransparentForInput)) && window->parent()) {
+ QCoreApplication::postEvent(this, new QMirClientEvent(
+ static_cast<QMirClientWindow*>(platformWindow->QPlatformWindow::parent()),
+ event, mEventType));
+ }
+}
+
+void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *ev)
+{
+ switch (mir_input_event_get_type(ev))
+ {
+ case mir_input_event_type_key:
+ dispatchKeyEvent(window, ev);
+ break;
+ case mir_input_event_type_touch:
+ dispatchTouchEvent(window, ev);
+ break;
+ case mir_input_event_type_pointer:
+ dispatchPointerEvent(window, ev);
+ break;
+ default:
+ break;
+ }
+}
+
+void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev)
+{
+ const MirTouchEvent *tev = mir_input_event_get_touch_event(ev);
+
+ // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
+ // needs to be fixed as soon as the compat input lib adds query support.
+ const float kMaxPressure = 1.28;
+ const QRect kWindowGeometry = window->geometry();
+ QList<QWindowSystemInterface::TouchPoint> touchPoints;
+
+
+ // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
+ // as Qt::TouchPointMoved
+ const unsigned int kPointerCount = mir_touch_event_point_count(tev);
+ for (unsigned int i = 0; i < kPointerCount; ++i) {
+ QWindowSystemInterface::TouchPoint touchPoint;
+
+ const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x();
+ const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere
+ const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);
+ const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);
+ const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
+ touchPoint.id = mir_touch_event_id(tev, i);
+ touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
+ touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
+ touchPoint.pressure = kP / kMaxPressure;
+
+ MirTouchAction touch_action = mir_touch_event_action(tev, i);
+ switch (touch_action)
+ {
+ case mir_touch_action_down:
+ touchPoint.state = Qt::TouchPointPressed;
+ break;
+ case mir_touch_action_up:
+ touchPoint.state = Qt::TouchPointReleased;
+ break;
+ case mir_touch_action_change:
+ default:
+ touchPoint.state = Qt::TouchPointMoved;
+ }
+
+ touchPoints.append(touchPoint);
+ }
+
+ ulong timestamp = mir_input_event_get_event_time(ev) / 1000000;
+ QWindowSystemInterface::handleTouchEvent(window, timestamp,
+ mTouchDevice, touchPoints);
+}
+
+static uint32_t translateKeysym(uint32_t sym, char *string, size_t size)
+{
+ Q_UNUSED(size);
+ string[0] = '\0';
+
+ if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35)
+ return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
+
+ for (int i = 0; KeyTable[i]; i += 2) {
+ if (sym == KeyTable[i])
+ return KeyTable[i + 1];
+ }
+
+ string[0] = sym;
+ string[1] = '\0';
+ return toupper(sym);
+}
+
+namespace
+{
+Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers)
+{
+ Qt::KeyboardModifiers q_modifiers = Qt::NoModifier;
+ if (modifiers & mir_input_event_modifier_shift) {
+ q_modifiers |= Qt::ShiftModifier;
+ }
+ if (modifiers & mir_input_event_modifier_ctrl) {
+ q_modifiers |= Qt::ControlModifier;
+ }
+ if (modifiers & mir_input_event_modifier_alt) {
+ q_modifiers |= Qt::AltModifier;
+ }
+ if (modifiers & mir_input_event_modifier_meta) {
+ q_modifiers |= Qt::MetaModifier;
+ }
+ return q_modifiers;
+}
+}
+
+void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event)
+{
+ const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event);
+
+ ulong timestamp = mir_input_event_get_event_time(event) / 1000000;
+ xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event);
+
+ // Key modifier and unicode index mapping.
+ auto modifiers = qt_modifiers_from_mir(mir_keyboard_event_modifiers(key_event));
+
+ MirKeyboardAction action = mir_keyboard_event_action(key_event);
+ QEvent::Type keyType = action == mir_keyboard_action_up
+ ? QEvent::KeyRelease : QEvent::KeyPress;
+
+ char s[2];
+ int sym = translateKeysym(xk_sym, s, sizeof(s));
+ QString text = QString::fromLatin1(s);
+
+ bool is_auto_rep = action == mir_keyboard_action_repeat;
+
+ QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ if (context) {
+ QKeyEvent qKeyEvent(keyType, sym, modifiers, text, is_auto_rep);
+ qKeyEvent.setTimestamp(timestamp);
+ if (context->filterEvent(&qKeyEvent)) {
+ DLOG("key event filtered out by input context");
+ return;
+ }
+ }
+
+ QWindowSystemInterface::handleKeyEvent(window, timestamp, keyType, sym, modifiers, text, is_auto_rep);
+}
+
+namespace
+{
+Qt::MouseButtons extract_buttons(const MirPointerEvent *pev)
+{
+ Qt::MouseButtons buttons = Qt::NoButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
+ buttons |= Qt::LeftButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
+ buttons |= Qt::RightButton;
+ if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
+ buttons |= Qt::MidButton;
+
+ // TODO: Should mir back and forward buttons exist?
+ // should they be Qt::X button 1 and 2?
+ return buttons;
+}
+}
+
+void QMirClientInput::dispatchPointerEvent(QWindow *window, const MirInputEvent *ev)
+{
+ auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
+
+ auto pev = mir_input_event_get_pointer_event(ev);
+ auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
+ auto buttons = extract_buttons(pev);
+
+ auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
+ mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
+
+ QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */,
+ buttons, modifiers);
+}
+
+#if (LOG_EVENTS != 0)
+static const char* nativeOrientationDirectionToStr(MirOrientation orientation)
+{
+ switch (orientation) {
+ case mir_orientation_normal:
+ return "Normal";
+ break;
+ case mir_orientation_left:
+ return "Left";
+ break;
+ case mir_orientation_inverted:
+ return "Inverted";
+ break;
+ case mir_orientation_right:
+ return "Right";
+ break;
+ default:
+ return "INVALID!";
+ }
+}
+#endif
+
+void QMirClientInput::dispatchOrientationEvent(QWindow *window, const MirOrientationEvent *event)
+{
+ MirOrientation mir_orientation = mir_orientation_event_get_direction(event);
+ #if (LOG_EVENTS != 0)
+ // Orientation event logging.
+ LOG("ORIENTATION direction: %s", nativeOrientationDirectionToStr(mir_orientation));
+ #endif
+
+ if (!window->screen()) {
+ DLOG("Window has no associated screen, dropping orientation event");
+ return;
+ }
+
+ OrientationChangeEvent::Orientation orientation;
+ switch (mir_orientation) {
+ case mir_orientation_normal:
+ orientation = OrientationChangeEvent::TopUp;
+ break;
+ case mir_orientation_left:
+ orientation = OrientationChangeEvent::LeftUp;
+ break;
+ case mir_orientation_inverted:
+ orientation = OrientationChangeEvent::TopDown;
+ break;
+ case mir_orientation_right:
+ orientation = OrientationChangeEvent::RightUp;
+ break;
+ default:
+ DLOG("No such orientation %d", mir_orientation);
+ return;
+ }
+
+ // Dispatch orientation event to [Platform]Screen, as that is where Qt reads it. Screen will handle
+ // notifying Qt of the actual orientation change - done to prevent multiple Windows each creating
+ // an identical orientation change event and passing it directly to Qt.
+ // [Platform]Screen can also factor in the native orientation.
+ QCoreApplication::postEvent(static_cast<QMirClientScreen*>(window->screen()->handle()),
+ new OrientationChangeEvent(OrientationChangeEvent::mType, orientation));
+}
+
diff --git a/src/plugins/platforms/mirclient/qmirclientinput.h b/src/plugins/platforms/mirclient/qmirclientinput.h
new file mode 100644
index 0000000000..c987d18c12
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientinput.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTINPUT_H
+#define QMIRCLIENTINPUT_H
+
+// Qt
+#include <qpa/qwindowsysteminterface.h>
+
+#include <mir_toolkit/mir_client_library.h>
+
+class QMirClientClientIntegration;
+class QMirClientWindow;
+
+class QMirClientInput : public QObject
+{
+ Q_OBJECT
+
+public:
+ QMirClientInput(QMirClientClientIntegration* integration);
+ virtual ~QMirClientInput();
+
+ // QObject methods.
+ void customEvent(QEvent* event) override;
+
+ void postEvent(QMirClientWindow* window, const MirEvent *event);
+ QMirClientClientIntegration* integration() const { return mIntegration; }
+
+protected:
+ void dispatchKeyEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchPointerEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchTouchEvent(QWindow *window, const MirInputEvent *event);
+ void dispatchInputEvent(QWindow *window, const MirInputEvent *event);
+
+ void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event);
+
+private:
+ QMirClientClientIntegration* mIntegration;
+ QTouchDevice* mTouchDevice;
+ const QByteArray mEventFilterType;
+ const QEvent::Type mEventType;
+};
+
+#endif // QMIRCLIENTINPUT_H
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
new file mode 100644
index 0000000000..a234f4eac6
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Qt
+#include <QGuiApplication>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qplatforminputcontext.h>
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+#include <QOpenGLContext>
+
+// Local
+#include "qmirclientbackingstore.h"
+#include "qmirclientclipboard.h"
+#include "qmirclientglcontext.h"
+#include "qmirclientinput.h"
+#include "qmirclientintegration.h"
+#include "qmirclientlogging.h"
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclienttheme.h"
+#include "qmirclientwindow.h"
+
+// platform-api
+#include <ubuntu/application/lifecycle_delegate.h>
+#include <ubuntu/application/id.h>
+#include <ubuntu/application/options.h>
+
+static void resumedCallback(const UApplicationOptions *options, void* context)
+{
+ Q_UNUSED(options)
+ Q_UNUSED(context)
+ DASSERT(context != NULL);
+ QCoreApplication::postEvent(QCoreApplication::instance(),
+ new QEvent(QEvent::ApplicationActivate));
+}
+
+static void aboutToStopCallback(UApplicationArchive *archive, void* context)
+{
+ Q_UNUSED(archive)
+ DASSERT(context != NULL);
+ QMirClientClientIntegration* integration = static_cast<QMirClientClientIntegration*>(context);
+ integration->inputContext()->hideInputPanel();
+ QCoreApplication::postEvent(QCoreApplication::instance(),
+ new QEvent(QEvent::ApplicationDeactivate));
+}
+
+QMirClientClientIntegration::QMirClientClientIntegration()
+ : QPlatformIntegration()
+ , mNativeInterface(new QMirClientNativeInterface)
+ , mFontDb(new QGenericUnixFontDatabase)
+ , mServices(new QMirClientPlatformServices)
+ , mClipboard(new QMirClientClipboard)
+ , mScaleFactor(1.0)
+{
+ setupOptions();
+ setupDescription();
+
+ // Create new application instance
+ mInstance = u_application_instance_new_from_description_with_options(mDesc, mOptions);
+
+ if (mInstance == nullptr)
+ qFatal("QMirClientClientIntegration: connection to Mir server failed. Check that a Mir server is\n"
+ "running, and the correct socket is being used and is accessible. The shell may have\n"
+ "rejected the incoming connection, so check its log file");
+
+ // Create default screen.
+ mScreen = new QMirClientScreen(u_application_instance_get_mir_connection(mInstance));
+ screenAdded(mScreen);
+
+ // Initialize input.
+ if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_INPUT")) {
+ mInput = new QMirClientInput(this);
+ mInputContext = QPlatformInputContextFactory::create();
+ } else {
+ mInput = nullptr;
+ mInputContext = nullptr;
+ }
+
+ // compute the scale factor
+ const int defaultGridUnit = 8;
+ int gridUnit = defaultGridUnit;
+ QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
+ if (!gridUnitString.isEmpty()) {
+ bool ok;
+ gridUnit = gridUnitString.toInt(&ok);
+ if (!ok) {
+ gridUnit = defaultGridUnit;
+ }
+ }
+ mScaleFactor = static_cast<qreal>(gridUnit) / defaultGridUnit;
+}
+
+QMirClientClientIntegration::~QMirClientClientIntegration()
+{
+ delete mInput;
+ delete mInputContext;
+ delete mScreen;
+ delete mServices;
+}
+
+QPlatformServices *QMirClientClientIntegration::services() const
+{
+ return mServices;
+}
+
+void QMirClientClientIntegration::setupOptions()
+{
+ QStringList args = QCoreApplication::arguments();
+ int argc = args.size() + 1;
+ char **argv = new char*[argc];
+ for (int i = 0; i < argc - 1; i++)
+ argv[i] = qstrdup(args.at(i).toLocal8Bit());
+ argv[argc - 1] = nullptr;
+
+ mOptions = u_application_options_new_from_cmd_line(argc - 1, argv);
+
+ for (int i = 0; i < argc; i++)
+ delete [] argv[i];
+ delete [] argv;
+}
+
+void QMirClientClientIntegration::setupDescription()
+{
+ mDesc = u_application_description_new();
+ UApplicationId* id = u_application_id_new_from_stringn("QtUbuntu", 8);
+ u_application_description_set_application_id(mDesc, id);
+
+ UApplicationLifecycleDelegate* delegate = u_application_lifecycle_delegate_new();
+ u_application_lifecycle_delegate_set_application_resumed_cb(delegate, &resumedCallback);
+ u_application_lifecycle_delegate_set_application_about_to_stop_cb(delegate, &aboutToStopCallback);
+ u_application_lifecycle_delegate_set_context(delegate, this);
+ u_application_description_set_application_lifecycle_delegate(mDesc, delegate);
+}
+
+QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) const
+{
+ return const_cast<QMirClientClientIntegration*>(this)->createPlatformWindow(window);
+}
+
+QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window)
+{
+ QPlatformWindow* platformWindow = new QMirClientWindow(
+ window, mClipboard, static_cast<QMirClientScreen*>(mScreen), mInput, u_application_instance_get_mir_connection(mInstance));
+ platformWindow->requestActivateWindow();
+ return platformWindow;
+}
+
+bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps:
+ return true;
+ break;
+
+ case OpenGL:
+ return true;
+ break;
+
+ case ThreadedOpenGL:
+ if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) {
+ return true;
+ } else {
+ DLOG("ubuntumirclient: disabled threaded OpenGL");
+ return false;
+ }
+ break;
+
+ default:
+ return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QAbstractEventDispatcher *QMirClientClientIntegration::createEventDispatcher() const
+{
+ return createUnixEventDispatcher();
+}
+
+QPlatformBackingStore* QMirClientClientIntegration::createPlatformBackingStore(QWindow* window) const
+{
+ return new QMirClientBackingStore(window);
+}
+
+QPlatformOpenGLContext* QMirClientClientIntegration::createPlatformOpenGLContext(
+ QOpenGLContext* context) const
+{
+ return const_cast<QMirClientClientIntegration*>(this)->createPlatformOpenGLContext(context);
+}
+
+QPlatformOpenGLContext* QMirClientClientIntegration::createPlatformOpenGLContext(
+ QOpenGLContext* context)
+{
+ return new QMirClientOpenGLContext(static_cast<QMirClientScreen*>(context->screen()->handle()),
+ static_cast<QMirClientOpenGLContext*>(context->shareHandle()));
+}
+
+QStringList QMirClientClientIntegration::themeNames() const
+{
+ return QStringList(QMirClientTheme::name);
+}
+
+QPlatformTheme* QMirClientClientIntegration::createPlatformTheme(const QString& name) const
+{
+ Q_UNUSED(name);
+ return new QMirClientTheme;
+}
+
+QVariant QMirClientClientIntegration::styleHint(StyleHint hint) const
+{
+ switch (hint) {
+ case QPlatformIntegration::StartDragDistance: {
+ // default is 10 pixels (see QPlatformTheme::defaultThemeHint)
+ return 10.0 * mScaleFactor;
+ }
+ case QPlatformIntegration::PasswordMaskDelay: {
+ // return time in milliseconds - 1 second
+ return QVariant(1000);
+ }
+ default:
+ break;
+ }
+ return QPlatformIntegration::styleHint(hint);
+}
+
+QPlatformClipboard* QMirClientClientIntegration::clipboard() const
+{
+ return mClipboard.data();
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.h b/src/plugins/platforms/mirclient/qmirclientintegration.h
new file mode 100644
index 0000000000..2960209691
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTINTEGRATION_H
+#define QMIRCLIENTINTEGRATION_H
+
+#include <qpa/qplatformintegration.h>
+#include <QSharedPointer>
+
+#include "qmirclientplatformservices.h"
+
+// platform-api
+#include <ubuntu/application/description.h>
+#include <ubuntu/application/instance.h>
+
+class QMirClientClipboard;
+class QMirClientInput;
+class QMirClientScreen;
+
+class QMirClientClientIntegration : public QPlatformIntegration {
+public:
+ QMirClientClientIntegration();
+ virtual ~QMirClientClientIntegration();
+
+ // QPlatformIntegration methods.
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
+ QPlatformNativeInterface* nativeInterface() const override { return mNativeInterface; }
+ QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override;
+ QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override;
+ QPlatformFontDatabase* fontDatabase() const override { return mFontDb; }
+ QStringList themeNames() const override;
+ QPlatformTheme* createPlatformTheme(const QString& name) const override;
+ QVariant styleHint(StyleHint hint) const override;
+ QPlatformServices *services() const override;
+ QPlatformWindow* createPlatformWindow(QWindow* window) const override;
+ QPlatformInputContext* inputContext() const override { return mInputContext; }
+ QPlatformClipboard* clipboard() const override;
+
+ QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context);
+ QPlatformWindow* createPlatformWindow(QWindow* window);
+ QMirClientScreen* screen() const { return mScreen; }
+
+private:
+ void setupOptions();
+ void setupDescription();
+
+ QPlatformNativeInterface* mNativeInterface;
+ QPlatformFontDatabase* mFontDb;
+
+ QMirClientPlatformServices* mServices;
+
+ QMirClientScreen* mScreen;
+ QMirClientInput* mInput;
+ QPlatformInputContext* mInputContext;
+ QSharedPointer<QMirClientClipboard> mClipboard;
+ qreal mScaleFactor;
+
+ // Platform API stuff
+ UApplicationOptions* mOptions;
+ UApplicationDescription* mDesc;
+ UApplicationInstance* mInstance;
+};
+
+#endif // QMIRCLIENTINTEGRATION_H
diff --git a/src/plugins/platforms/mirclient/qmirclientlogging.h b/src/plugins/platforms/mirclient/qmirclientlogging.h
new file mode 100644
index 0000000000..80914d28b9
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientlogging.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTLOGGING_H
+#define QMIRCLIENTLOGGING_H
+
+// Logging and assertion macros.
+#define LOG(...) qDebug(__VA_ARGS__)
+#define LOG_IF(cond,...) do { if (cond) qDebug(__VA_ARGS__); } while (0)
+#define ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
+#define NOT_REACHED() qt_assert("Not reached!",__FILE__,__LINE__)
+
+// Logging and assertion macros are compiled out for release builds.
+#if !defined(QT_NO_DEBUG)
+#define DLOG(...) LOG(__VA_ARGS__)
+#define DLOG_IF(cond,...) LOG_IF((cond), __VA_ARGS__)
+#define DASSERT(cond) ASSERT((cond))
+#define DNOT_REACHED() NOT_REACHED()
+#else
+#define DLOG(...) qt_noop()
+#define DLOG_IF(cond,...) qt_noop()
+#define DASSERT(cond) qt_noop()
+#define DNOT_REACHED() qt_noop()
+#endif
+
+#endif // QMIRCLIENTLOGGING_H
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
new file mode 100644
index 0000000000..a0bb932df3
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Qt
+#include <private/qguiapplication_p.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qscreen.h>
+#include <QtCore/QMap>
+
+// Local
+#include "qmirclientnativeinterface.h"
+#include "qmirclientscreen.h"
+#include "qmirclientglcontext.h"
+
+class QMirClientResourceMap : public QMap<QByteArray, QMirClientNativeInterface::ResourceType>
+{
+public:
+ QMirClientResourceMap()
+ : QMap<QByteArray, QMirClientNativeInterface::ResourceType>() {
+ insert("egldisplay", QMirClientNativeInterface::EglDisplay);
+ insert("eglcontext", QMirClientNativeInterface::EglContext);
+ insert("nativeorientation", QMirClientNativeInterface::NativeOrientation);
+ insert("display", QMirClientNativeInterface::Display);
+ }
+};
+
+Q_GLOBAL_STATIC(QMirClientResourceMap, ubuntuResourceMap)
+
+QMirClientNativeInterface::QMirClientNativeInterface()
+ : mGenericEventFilterType(QByteArrayLiteral("Event"))
+ , mNativeOrientation(nullptr)
+{
+}
+
+QMirClientNativeInterface::~QMirClientNativeInterface()
+{
+ delete mNativeOrientation;
+ mNativeOrientation = nullptr;
+}
+
+void* QMirClientNativeInterface::nativeResourceForContext(
+ const QByteArray& resourceString, QOpenGLContext* context)
+{
+ if (!context)
+ return nullptr;
+
+ const QByteArray kLowerCaseResource = resourceString.toLower();
+
+ if (!ubuntuResourceMap()->contains(kLowerCaseResource))
+ return nullptr;
+
+ const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
+
+ if (kResourceType == QMirClientNativeInterface::EglContext)
+ return static_cast<QMirClientOpenGLContext*>(context->handle())->eglContext();
+ else
+ return nullptr;
+}
+
+void* QMirClientNativeInterface::nativeResourceForWindow(const QByteArray& resourceString, QWindow* window)
+{
+ const QByteArray kLowerCaseResource = resourceString.toLower();
+ if (!ubuntuResourceMap()->contains(kLowerCaseResource))
+ return NULL;
+ const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
+ if (kResourceType == QMirClientNativeInterface::EglDisplay) {
+ if (window) {
+ return static_cast<QMirClientScreen*>(window->screen()->handle())->eglDisplay();
+ } else {
+ return static_cast<QMirClientScreen*>(
+ QGuiApplication::primaryScreen()->handle())->eglDisplay();
+ }
+ } else if (kResourceType == QMirClientNativeInterface::NativeOrientation) {
+ // Return the device's native screen orientation.
+ if (window) {
+ QMirClientScreen *ubuntuScreen = static_cast<QMirClientScreen*>(window->screen()->handle());
+ mNativeOrientation = new Qt::ScreenOrientation(ubuntuScreen->nativeOrientation());
+ } else {
+ QPlatformScreen *platformScreen = QGuiApplication::primaryScreen()->handle();
+ mNativeOrientation = new Qt::ScreenOrientation(platformScreen->nativeOrientation());
+ }
+ return mNativeOrientation;
+ } else {
+ return NULL;
+ }
+}
+
+void* QMirClientNativeInterface::nativeResourceForScreen(const QByteArray& resourceString, QScreen* screen)
+{
+ const QByteArray kLowerCaseResource = resourceString.toLower();
+ if (!ubuntuResourceMap()->contains(kLowerCaseResource))
+ return NULL;
+ const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
+ if (kResourceType == QMirClientNativeInterface::Display) {
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ return static_cast<QMirClientScreen*>(screen->handle())->eglNativeDisplay();
+ } else
+ return NULL;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
new file mode 100644
index 0000000000..84f03bb915
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTNATIVEINTERFACE_H
+#define QMIRCLIENTNATIVEINTERFACE_H
+
+#include <qpa/qplatformnativeinterface.h>
+
+class QMirClientNativeInterface : public QPlatformNativeInterface {
+public:
+ enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display };
+
+ QMirClientNativeInterface();
+ ~QMirClientNativeInterface();
+
+ // QPlatformNativeInterface methods.
+ void* nativeResourceForContext(const QByteArray& resourceString,
+ QOpenGLContext* context) override;
+ void* nativeResourceForWindow(const QByteArray& resourceString,
+ QWindow* window) override;
+ void* nativeResourceForScreen(const QByteArray& resourceString,
+ QScreen* screen) override;
+
+ // New methods.
+ const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; }
+
+private:
+ const QByteArray mGenericEventFilterType;
+ Qt::ScreenOrientation* mNativeOrientation;
+};
+
+#endif // QMIRCLIENTNATIVEINTERFACE_H
diff --git a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
new file mode 100644
index 0000000000..24d7307faa
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
+#define QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
+
+#include <QEvent>
+#include "qmirclientlogging.h"
+
+class OrientationChangeEvent : public QEvent {
+public:
+ enum Orientation {
+ Undefined = 0,
+ TopUp,
+ TopDown,
+ LeftUp,
+ RightUp,
+ FaceUp,
+ FaceDown
+ };
+
+ OrientationChangeEvent(QEvent::Type type, Orientation orientation)
+ : QEvent(type)
+ , mOrientation(orientation)
+ {
+ }
+
+ static const QEvent::Type mType;
+ Orientation mOrientation;
+};
+
+#endif // QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
diff --git a/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp b/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp
new file mode 100644
index 0000000000..d0260c79d3
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplatformservices.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientplatformservices.h"
+
+#include <QUrl>
+
+#include <ubuntu/application/url_dispatcher/service.h>
+#include <ubuntu/application/url_dispatcher/session.h>
+
+bool QMirClientPlatformServices::openUrl(const QUrl &url)
+{
+ return callDispatcher(url);
+}
+
+bool QMirClientPlatformServices::openDocument(const QUrl &url)
+{
+ return callDispatcher(url);
+}
+
+bool QMirClientPlatformServices::callDispatcher(const QUrl &url)
+{
+ UAUrlDispatcherSession* session = ua_url_dispatcher_session();
+ if (!session)
+ return false;
+
+ ua_url_dispatcher_session_open(session, url.toEncoded().constData(), NULL, NULL);
+
+ free(session);
+
+ // We are returning true here because the other option
+ // is spawning a nested event loop and wait for the
+ // callback. But there is no guarantee on how fast
+ // the callback is going to be so we prefer to avoid the
+ // nested event loop. Long term plan is improve Qt API
+ // to support an async openUrl
+ return true;
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientplatformservices.h b/src/plugins/platforms/mirclient/qmirclientplatformservices.h
new file mode 100644
index 0000000000..64a0432d06
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplatformservices.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTPLATFORMSERVICES_H
+#define QMIRCLIENTPLATFORMSERVICES_H
+
+#include <qpa/qplatformservices.h>
+#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
+#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
+
+class QMirClientPlatformServices : public QPlatformServices {
+public:
+ bool openUrl(const QUrl &url) override;
+ bool openDocument(const QUrl &url) override;
+
+private:
+ bool callDispatcher(const QUrl &url);
+};
+
+#endif // QMIRCLIENTPLATFORMSERVICES_H
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp
new file mode 100644
index 0000000000..43d913f8d2
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclientplugin.h"
+#include "qmirclientintegration.h"
+
+QStringList QMirClientIntegrationPlugin::keys() const
+{
+ QStringList list;
+ list << "mirclient";
+ return list;
+}
+
+QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system,
+ const QStringList &)
+{
+ if (system.toLower() == "mirclient") {
+#ifdef PLATFORM_API_TOUCH
+ setenv("UBUNTU_PLATFORM_API_BACKEND", "touch_mirclient", 1);
+#else
+ setenv("UBUNTU_PLATFORM_API_BACKEND", "desktop_mirclient", 1);
+#endif
+ return new QMirClientClientIntegration;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.h b/src/plugins/platforms/mirclient/qmirclientplugin.h
new file mode 100644
index 0000000000..a6f1a1081a
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientplugin.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTPLUGIN_H
+#define QMIRCLIENTPLUGIN_H
+
+#include <qpa/qplatformintegrationplugin.h>
+
+class QMirClientIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirclient.json")
+
+public:
+ QStringList keys() const;
+ QPlatformIntegration* create(const QString&, const QStringList&);
+};
+
+#endif // QMIRCLIENTPLUGIN_H
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
new file mode 100644
index 0000000000..5c4b1cd0d6
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientscreen.cpp
@@ -0,0 +1,296 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <mir_toolkit/mir_client_library.h>
+
+// Qt
+#include <QCoreApplication>
+#include <QtCore/qmath.h>
+#include <QScreen>
+#include <QThread>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtPlatformSupport/private/qeglconvenience_p.h>
+
+// local
+#include "qmirclientscreen.h"
+#include "qmirclientlogging.h"
+#include "qmirclientorientationchangeevent_p.h"
+
+#include "memory"
+
+static const int kSwapInterval = 1;
+
+#if !defined(QT_NO_DEBUG)
+
+static const char *orientationToStr(Qt::ScreenOrientation orientation) {
+ switch (orientation) {
+ case Qt::PrimaryOrientation:
+ return "primary";
+ case Qt::PortraitOrientation:
+ return "portrait";
+ case Qt::LandscapeOrientation:
+ return "landscape";
+ case Qt::InvertedPortraitOrientation:
+ return "inverted portrait";
+ case Qt::InvertedLandscapeOrientation:
+ return "inverted landscape";
+ default:
+ return "INVALID!";
+ }
+}
+
+static void printEglConfig(EGLDisplay display, EGLConfig config) {
+ DASSERT(display != EGL_NO_DISPLAY);
+ DASSERT(config != nullptr);
+ static const struct { const EGLint attrib; const char* name; } kAttribs[] = {
+ { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" },
+ { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" },
+ { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" },
+ { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" },
+ { EGL_RED_SIZE, "EGL_RED_SIZE" },
+ { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" },
+ { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" },
+ { EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT" },
+ { EGL_CONFIG_ID, "EGL_CONFIG_ID" },
+ { EGL_LEVEL, "EGL_LEVEL" },
+ { EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT" },
+ { EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS" },
+ { EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH" },
+ { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" },
+ { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" },
+ { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" },
+ { EGL_SAMPLES, "EGL_SAMPLES" },
+ { EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS" },
+ { EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE" },
+ { EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE" },
+ { EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE" },
+ { EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE" },
+ { EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE" },
+ { EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB" },
+ { EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA" },
+ { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" },
+ { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" },
+ { -1, NULL }
+ };
+ const char* string = eglQueryString(display, EGL_VENDOR);
+ LOG("EGL vendor: %s", string);
+ string = eglQueryString(display, EGL_VERSION);
+ LOG("EGL version: %s", string);
+ string = eglQueryString(display, EGL_EXTENSIONS);
+ LOG("EGL extensions: %s", string);
+ LOG("EGL configuration attibutes:");
+ for (int index = 0; kAttribs[index].attrib != -1; index++) {
+ EGLint value;
+ if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value))
+ LOG(" %s: %d", kAttribs[index].name, static_cast<int>(value));
+ }
+}
+#endif
+
+
+const QEvent::Type OrientationChangeEvent::mType =
+ static_cast<QEvent::Type>(QEvent::registerEventType());
+
+static const MirDisplayOutput *find_active_output(
+ const MirDisplayConfiguration *conf)
+{
+ const MirDisplayOutput *output = NULL;
+ for (uint32_t d = 0; d < conf->num_outputs; d++)
+ {
+ const MirDisplayOutput *out = conf->outputs + d;
+
+ if (out->used &&
+ out->connected &&
+ out->num_modes &&
+ out->current_mode < out->num_modes)
+ {
+ output = out;
+ break;
+ }
+ }
+
+ return output;
+}
+
+QMirClientScreen::QMirClientScreen(MirConnection *connection)
+ : mFormat(QImage::Format_RGB32)
+ , mDepth(32)
+ , mSurfaceFormat()
+ , mEglDisplay(EGL_NO_DISPLAY)
+ , mEglConfig(nullptr)
+{
+ // Initialize EGL.
+ ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE);
+
+ mEglNativeDisplay = mir_connection_get_egl_native_display(connection);
+ ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
+ ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
+
+ // Configure EGL buffers format.
+ mSurfaceFormat.setRedBufferSize(8);
+ mSurfaceFormat.setGreenBufferSize(8);
+ mSurfaceFormat.setBlueBufferSize(8);
+ mSurfaceFormat.setAlphaBufferSize(8);
+ mSurfaceFormat.setDepthBufferSize(24);
+ mSurfaceFormat.setStencilBufferSize(8);
+ if (!qEnvironmentVariableIsEmpty("QTUBUNTU_MULTISAMPLE")) {
+ mSurfaceFormat.setSamples(4);
+ DLOG("ubuntumirclient: setting MSAA to 4 samples");
+ }
+#ifdef QTUBUNTU_USE_OPENGL
+ mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
+#else
+ mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+#endif
+ mEglConfig = q_configFromGLFormat(mEglDisplay, mSurfaceFormat, true);
+
+ #if !defined(QT_NO_DEBUG)
+ printEglConfig(mEglDisplay, mEglConfig);
+ #endif
+
+ // Set vblank swap interval.
+ int swapInterval = kSwapInterval;
+ QByteArray swapIntervalString = qgetenv("QTUBUNTU_SWAPINTERVAL");
+ if (!swapIntervalString.isEmpty()) {
+ bool ok;
+ swapInterval = swapIntervalString.toInt(&ok);
+ if (!ok)
+ swapInterval = kSwapInterval;
+ }
+ DLOG("ubuntumirclient: setting swap interval to %d", swapInterval);
+ eglSwapInterval(mEglDisplay, swapInterval);
+
+ // Get screen resolution.
+ auto configDeleter = [](MirDisplayConfiguration *config) { mir_display_config_destroy(config); };
+ using configUp = std::unique_ptr<MirDisplayConfiguration, decltype(configDeleter)>;
+ configUp displayConfig(mir_connection_create_display_config(connection), configDeleter);
+ ASSERT(displayConfig != nullptr);
+
+ auto const displayOutput = find_active_output(displayConfig.get());
+ ASSERT(displayOutput != nullptr);
+
+ const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode];
+ const int kScreenWidth = mode->horizontal_resolution;
+ const int kScreenHeight = mode->vertical_resolution;
+ DASSERT(kScreenWidth > 0 && kScreenHeight > 0);
+
+ DLOG("ubuntumirclient: screen resolution: %dx%d", kScreenWidth, kScreenHeight);
+
+ mGeometry = QRect(0, 0, kScreenWidth, kScreenHeight);
+
+ DLOG("QQMirClientScreen::QQMirClientScreen (this=%p)", this);
+
+ // Set the default orientation based on the initial screen dimmensions.
+ mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
+
+ // If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait
+ mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
+}
+
+QMirClientScreen::~QMirClientScreen()
+{
+ eglTerminate(mEglDisplay);
+}
+
+void QMirClientScreen::customEvent(QEvent* event) {
+ DASSERT(QThread::currentThread() == thread());
+
+ OrientationChangeEvent* oReadingEvent = static_cast<OrientationChangeEvent*>(event);
+ switch (oReadingEvent->mOrientation) {
+ case OrientationChangeEvent::LeftUp: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::InvertedPortraitOrientation : Qt::LandscapeOrientation;
+ break;
+ }
+ case OrientationChangeEvent::TopUp: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::LandscapeOrientation : Qt::PortraitOrientation;
+ break;
+ }
+ case OrientationChangeEvent::RightUp: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::PortraitOrientation : Qt::InvertedLandscapeOrientation;
+ break;
+ }
+ case OrientationChangeEvent::TopDown: {
+ mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
+ Qt::InvertedLandscapeOrientation : Qt::InvertedPortraitOrientation;
+ break;
+ }
+ default: {
+ DLOG("QMirClientScreen::customEvent - Unknown orientation.");
+ return;
+ }
+ }
+
+ // Raise the event signal so that client apps know the orientation changed
+ DLOG("QMirClientScreen::customEvent - handling orientation change to %s", orientationToStr(mCurrentOrientation));
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
+}
+
+void QMirClientScreen::handleWindowSurfaceResize(int windowWidth, int windowHeight)
+{
+ if ((windowWidth > windowHeight && mGeometry.width() < mGeometry.height())
+ || (windowWidth < windowHeight && mGeometry.width() > mGeometry.height())) {
+
+ // The window aspect ratio differ's from the screen one. This means that
+ // unity8 has rotated the window in its scene.
+ // As there's no way to express window rotation in Qt's API, we have
+ // Flip QScreen's dimensions so that orientation properties match
+ // (primaryOrientation particularly).
+ // FIXME: This assumes a phone scenario. Won't work, or make sense,
+ // on the desktop
+
+ QRect currGeometry = mGeometry;
+ mGeometry.setWidth(currGeometry.height());
+ mGeometry.setHeight(currGeometry.width());
+
+ DLOG("QMirClientScreen::handleWindowSurfaceResize - new screen geometry (w=%d, h=%d)",
+ mGeometry.width(), mGeometry.height());
+ QWindowSystemInterface::handleScreenGeometryChange(screen(),
+ mGeometry /* newGeometry */,
+ mGeometry /* newAvailableGeometry */);
+
+ if (mGeometry.width() < mGeometry.height()) {
+ mCurrentOrientation = Qt::PortraitOrientation;
+ } else {
+ mCurrentOrientation = Qt::LandscapeOrientation;
+ }
+ DLOG("QMirClientScreen::handleWindowSurfaceResize - new orientation %s",orientationToStr(mCurrentOrientation));
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.h b/src/plugins/platforms/mirclient/qmirclientscreen.h
new file mode 100644
index 0000000000..5d9325354f
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientscreen.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTSCREEN_H
+#define QMIRCLIENTSCREEN_H
+
+#include <qpa/qplatformscreen.h>
+#include <QSurfaceFormat>
+#include <EGL/egl.h>
+
+struct MirConnection;
+
+class QMirClientScreen : public QObject, public QPlatformScreen
+{
+ Q_OBJECT
+public:
+ QMirClientScreen(MirConnection *connection);
+ virtual ~QMirClientScreen();
+
+ // QPlatformScreen methods.
+ QImage::Format format() const override { return mFormat; }
+ int depth() const override { return mDepth; }
+ QRect geometry() const override { return mGeometry; }
+ QRect availableGeometry() const override { return mGeometry; }
+ Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }
+ Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }
+
+ // New methods.
+ QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; }
+ EGLDisplay eglDisplay() const { return mEglDisplay; }
+ EGLConfig eglConfig() const { return mEglConfig; }
+ EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
+ void handleWindowSurfaceResize(int width, int height);
+
+ // QObject methods.
+ void customEvent(QEvent* event);
+
+private:
+ QRect mGeometry;
+ Qt::ScreenOrientation mNativeOrientation;
+ Qt::ScreenOrientation mCurrentOrientation;
+ QImage::Format mFormat;
+ int mDepth;
+ QSurfaceFormat mSurfaceFormat;
+ EGLDisplay mEglDisplay;
+ EGLConfig mEglConfig;
+ EGLNativeDisplayType mEglNativeDisplay;
+};
+
+#endif // QMIRCLIENTSCREEN_H
diff --git a/src/plugins/platforms/mirclient/qmirclienttheme.cpp b/src/plugins/platforms/mirclient/qmirclienttheme.cpp
new file mode 100644
index 0000000000..c15da23945
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclienttheme.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qmirclienttheme.h"
+
+#include <QtCore/QVariant>
+
+const char *QMirClientTheme::name = "ubuntu";
+
+QMirClientTheme::QMirClientTheme()
+{
+}
+
+QMirClientTheme::~QMirClientTheme()
+{
+}
+
+QVariant QMirClientTheme::themeHint(ThemeHint hint) const
+{
+ if (hint == QPlatformTheme::SystemIconThemeName) {
+ QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME");
+ if (iconTheme.isEmpty()) {
+ return QVariant(QStringLiteral("ubuntu-mobile"));
+ } else {
+ return QVariant(QString(iconTheme));
+ }
+ } else {
+ return QGenericUnixTheme::themeHint(hint);
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclienttheme.h b/src/plugins/platforms/mirclient/qmirclienttheme.h
new file mode 100644
index 0000000000..8f330395a0
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclienttheme.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTTHEME_H
+#define QMIRCLIENTTHEME_H
+
+#include <QtPlatformSupport/private/qgenericunixthemes_p.h>
+
+class QMirClientTheme : public QGenericUnixTheme
+{
+public:
+ static const char* name;
+ QMirClientTheme();
+ virtual ~QMirClientTheme();
+
+ // From QPlatformTheme
+ QVariant themeHint(ThemeHint hint) const override;
+};
+
+#endif // QMIRCLIENTTHEME_H
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
new file mode 100644
index 0000000000..f3fd1e756d
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
@@ -0,0 +1,452 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+// Local
+#include "qmirclientclipboard.h"
+#include "qmirclientinput.h"
+#include "qmirclientwindow.h"
+#include "qmirclientscreen.h"
+#include "qmirclientlogging.h"
+
+// Qt
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QSize>
+#include <QtMath>
+
+// Platform API
+#include <ubuntu/application/instance.h>
+
+#include <EGL/egl.h>
+
+#define IS_OPAQUE_FLAG 1
+
+namespace
+{
+MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
+{
+ switch (state) {
+ case Qt::WindowNoState:
+ return mir_surface_state_restored;
+
+ case Qt::WindowFullScreen:
+ return mir_surface_state_fullscreen;
+
+ case Qt::WindowMaximized:
+ return mir_surface_state_maximized;
+
+ case Qt::WindowMinimized:
+ return mir_surface_state_minimized;
+
+ default:
+ LOG("Unexpected Qt::WindowState: %d", state);
+ return mir_surface_state_restored;
+ }
+}
+
+#if !defined(QT_NO_DEBUG)
+const char *qtWindowStateToStr(Qt::WindowState state)
+{
+ switch (state) {
+ case Qt::WindowNoState:
+ return "NoState";
+
+ case Qt::WindowFullScreen:
+ return "FullScreen";
+
+ case Qt::WindowMaximized:
+ return "Maximized";
+
+ case Qt::WindowMinimized:
+ return "Minimized";
+
+ default:
+ return "!?";
+ }
+}
+#endif
+
+} // anonymous namespace
+
+class QMirClientWindowPrivate
+{
+public:
+ void createEGLSurface(EGLNativeWindowType nativeWindow);
+ void destroyEGLSurface();
+ int panelHeight();
+
+ QMirClientScreen* screen;
+ EGLSurface eglSurface;
+ WId id;
+ QMirClientInput* input;
+ Qt::WindowState state;
+ MirConnection *connection;
+ MirSurface* surface;
+ QSize bufferSize;
+ QMutex mutex;
+ QSharedPointer<QMirClientClipboard> clipboard;
+};
+
+static void eventCallback(MirSurface* surface, const MirEvent *event, void* context)
+{
+ (void) surface;
+ DASSERT(context != NULL);
+ QMirClientWindow* platformWindow = static_cast<QMirClientWindow*>(context);
+ platformWindow->priv()->input->postEvent(platformWindow, event);
+}
+
+static void surfaceCreateCallback(MirSurface* surface, void* context)
+{
+ DASSERT(context != NULL);
+ QMirClientWindow* platformWindow = static_cast<QMirClientWindow*>(context);
+ platformWindow->priv()->surface = surface;
+
+ mir_surface_set_event_handler(surface, eventCallback, context);
+}
+
+QMirClientWindow::QMirClientWindow(QWindow* w, QSharedPointer<QMirClientClipboard> clipboard, QMirClientScreen* screen,
+ QMirClientInput* input, MirConnection* connection)
+ : QObject(nullptr), QPlatformWindow(w)
+{
+ DASSERT(screen != NULL);
+
+ d = new QMirClientWindowPrivate;
+ d->screen = screen;
+ d->eglSurface = EGL_NO_SURFACE;
+ d->input = input;
+ d->state = window()->windowState();
+ d->connection = connection;
+ d->clipboard = clipboard;
+
+ static int id = 1;
+ d->id = id++;
+
+ // Use client geometry if set explicitly, use available screen geometry otherwise.
+ QPlatformWindow::setGeometry(window()->geometry() != screen->geometry() ?
+ window()->geometry() : screen->availableGeometry());
+ createWindow();
+ DLOG("QMirClientWindow::QMirClientWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input);
+}
+
+QMirClientWindow::~QMirClientWindow()
+{
+ DLOG("QMirClientWindow::~QMirClientWindow");
+ d->destroyEGLSurface();
+
+ mir_surface_release_sync(d->surface);
+
+ delete d;
+}
+
+void QMirClientWindowPrivate::createEGLSurface(EGLNativeWindowType nativeWindow)
+{
+ DLOG("QMirClientWindowPrivate::createEGLSurface (this=%p, nativeWindow=%p)",
+ this, reinterpret_cast<void*>(nativeWindow));
+
+ eglSurface = eglCreateWindowSurface(screen->eglDisplay(), screen->eglConfig(),
+ nativeWindow, nullptr);
+
+ DASSERT(eglSurface != EGL_NO_SURFACE);
+}
+
+void QMirClientWindowPrivate::destroyEGLSurface()
+{
+ DLOG("QMirClientWindowPrivate::destroyEGLSurface (this=%p)", this);
+ if (eglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(screen->eglDisplay(), eglSurface);
+ eglSurface = EGL_NO_SURFACE;
+ }
+}
+
+// FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
+// we need to guess the panel height (3GU + 2DP)
+int QMirClientWindowPrivate::panelHeight()
+{
+ const int defaultGridUnit = 8;
+ int gridUnit = defaultGridUnit;
+ QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
+ if (!gridUnitString.isEmpty()) {
+ bool ok;
+ gridUnit = gridUnitString.toInt(&ok);
+ if (!ok) {
+ gridUnit = defaultGridUnit;
+ }
+ }
+ qreal densityPixelRatio = static_cast<qreal>(gridUnit) / defaultGridUnit;
+ return gridUnit * 3 + qFloor(densityPixelRatio) * 2;
+}
+
+namespace
+{
+static MirPixelFormat
+mir_choose_default_pixel_format(MirConnection *connection)
+{
+ MirPixelFormat format[mir_pixel_formats];
+ unsigned int nformats;
+
+ mir_connection_get_available_surface_formats(connection,
+ format, mir_pixel_formats, &nformats);
+
+ return format[0];
+}
+}
+
+void QMirClientWindow::createWindow()
+{
+ DLOG("QMirClientWindow::createWindow (this=%p)", this);
+
+ // FIXME: remove this remnant of an old platform-api enum - needs ubuntu-keyboard update
+ const int SCREEN_KEYBOARD_ROLE = 7;
+ // Get surface role and flags.
+ QVariant roleVariant = window()->property("role");
+ int role = roleVariant.isValid() ? roleVariant.toUInt() : 1; // 1 is the default role for apps.
+ QVariant opaqueVariant = window()->property("opaque");
+ uint flags = opaqueVariant.isValid() ?
+ opaqueVariant.toUInt() ? static_cast<uint>(IS_OPAQUE_FLAG) : 0 : 0;
+
+ // FIXME(loicm) Opaque flag is forced for now for non-system sessions (applications) for
+ // performance reasons.
+ flags |= static_cast<uint>(IS_OPAQUE_FLAG);
+
+ const QByteArray title = (!window()->title().isNull()) ? window()->title().toUtf8() : "Window 1"; // legacy title
+ const int panelHeight = d->panelHeight();
+
+#if !defined(QT_NO_DEBUG)
+ LOG("panelHeight: '%d'", panelHeight);
+ LOG("role: '%d'", role);
+ LOG("flags: '%s'", (flags & static_cast<uint>(1)) ? "Opaque" : "NotOpaque");
+ LOG("title: '%s'", title.constData());
+#endif
+
+ // Get surface geometry.
+ QRect geometry;
+ if (d->state == Qt::WindowFullScreen) {
+ printf("QMirClientWindow - fullscreen geometry\n");
+ geometry = screen()->geometry();
+ } else if (d->state == Qt::WindowMaximized) {
+ printf("QMirClientWindow - maximized geometry\n");
+ geometry = screen()->availableGeometry();
+ /*
+ * FIXME: Autopilot relies on being able to convert coordinates relative of the window
+ * into absolute screen coordinates. Mir does not allow this, see bug lp:1346633
+ * Until there's a correct way to perform this transformation agreed, this horrible hack
+ * guesses the transformation heuristically.
+ *
+ * Assumption: this method only used on phone devices!
+ */
+ geometry.setY(panelHeight);
+ } else {
+ printf("QMirClientWindow - regular geometry\n");
+ geometry = this->geometry();
+ geometry.setY(panelHeight);
+ }
+
+ DLOG("[ubuntumirclient QPA] creating surface at (%d, %d) with size (%d, %d) with title '%s'\n",
+ geometry.x(), geometry.y(), geometry.width(), geometry.height(), title.data());
+
+ MirSurfaceSpec *spec;
+ if (role == SCREEN_KEYBOARD_ROLE)
+ {
+ spec = mir_connection_create_spec_for_input_method(d->connection, geometry.width(),
+ geometry.height(), mir_choose_default_pixel_format(d->connection));
+ }
+ else
+ {
+ spec = mir_connection_create_spec_for_normal_surface(d->connection, geometry.width(),
+ geometry.height(), mir_choose_default_pixel_format(d->connection));
+ }
+ mir_surface_spec_set_name(spec, title.data());
+
+ // Create platform window
+ mir_wait_for(mir_surface_create(spec, surfaceCreateCallback, this));
+ mir_surface_spec_release(spec);
+
+ DASSERT(d->surface != NULL);
+ d->createEGLSurface((EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(d->surface)));
+
+ if (d->state == Qt::WindowFullScreen) {
+ // TODO: We could set this on creation once surface spec supports it (mps already up)
+ mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_fullscreen));
+ }
+
+ // Window manager can give us a final size different from what we asked for
+ // so let's check what we ended up getting
+ {
+ MirSurfaceParameters parameters;
+ mir_surface_get_parameters(d->surface, &parameters);
+
+ geometry.setWidth(parameters.width);
+ geometry.setHeight(parameters.height);
+ }
+
+ DLOG("[ubuntumirclient QPA] created surface has size (%d, %d)",
+ geometry.width(), geometry.height());
+
+ // Assume that the buffer size matches the surface size at creation time
+ d->bufferSize = geometry.size();
+
+ // Tell Qt about the geometry.
+ QWindowSystemInterface::handleGeometryChange(window(), geometry);
+ QPlatformWindow::setGeometry(geometry);
+}
+
+void QMirClientWindow::moveResize(const QRect& rect)
+{
+ (void) rect;
+ // TODO: Not yet supported by mir.
+}
+
+void QMirClientWindow::handleSurfaceResize(int width, int height)
+{
+ QMutexLocker(&d->mutex);
+ LOG("QMirClientWindow::handleSurfaceResize(width=%d, height=%d)", width, height);
+
+ // The current buffer size hasn't actually changed. so just render on it and swap
+ // buffers in the hope that the next buffer will match the surface size advertised
+ // in this event.
+ // But since this event is processed by a thread different from the one that swaps
+ // buffers, you can never know if this information is already outdated as there's
+ // no synchronicity whatsoever between the processing of resize events and the
+ // consumption of buffers.
+ if (d->bufferSize.width() != width || d->bufferSize.height() != height) {
+ QWindowSystemInterface::handleExposeEvent(window(), geometry());
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
+}
+
+void QMirClientWindow::handleSurfaceFocusChange(bool focused)
+{
+ LOG("QMirClientWindow::handleSurfaceFocusChange(focused=%s)", focused ? "true" : "false");
+ QWindow *activatedWindow = focused ? window() : nullptr;
+
+ // System clipboard contents might have changed while this window was unfocused and wihtout
+ // this process getting notified about it because it might have been suspended (due to
+ // application lifecycle policies), thus unable to listen to any changes notified through
+ // D-Bus.
+ // Therefore let's ensure we are up to date with the system clipboard now that we are getting
+ // focused again.
+ if (focused) {
+ d->clipboard->requestDBusClipboardContents();
+ }
+
+ QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason);
+}
+
+void QMirClientWindow::setWindowState(Qt::WindowState state)
+{
+ QMutexLocker(&d->mutex);
+ DLOG("QMirClientWindow::setWindowState (this=%p, %s)", this, qtWindowStateToStr(state));
+
+ if (state == d->state)
+ return;
+
+ // TODO: Perhaps we should check if the states are applied?
+ mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(state)));
+ d->state = state;
+}
+
+void QMirClientWindow::setGeometry(const QRect& rect)
+{
+ DLOG("QMirClientWindow::setGeometry (this=%p)", this);
+
+ bool doMoveResize;
+
+ {
+ QMutexLocker(&d->mutex);
+ QPlatformWindow::setGeometry(rect);
+ doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized;
+ }
+
+ if (doMoveResize) {
+ moveResize(rect);
+ }
+}
+
+void QMirClientWindow::setVisible(bool visible)
+{
+ QMutexLocker(&d->mutex);
+ DLOG("QMirClientWindow::setVisible (this=%p, visible=%s)", this, visible ? "true" : "false");
+
+ if (visible) {
+ mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(d->state)));
+
+ QWindowSystemInterface::handleExposeEvent(window(), QRect());
+ QWindowSystemInterface::flushWindowSystemEvents();
+ } else {
+ // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized.
+ // Will have to change qtmir and unity8 for that.
+ mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_minimized));
+ }
+}
+
+void* QMirClientWindow::eglSurface() const
+{
+ return d->eglSurface;
+}
+
+WId QMirClientWindow::winId() const
+{
+ return d->id;
+}
+
+void QMirClientWindow::onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight)
+{
+ QMutexLocker(&d->mutex);
+
+ bool sizeKnown = newBufferWidth > 0 && newBufferHeight > 0;
+
+ if (sizeKnown && (d->bufferSize.width() != newBufferWidth ||
+ d->bufferSize.height() != newBufferHeight)) {
+
+ DLOG("QMirClientWindow::onBuffersSwapped_threadSafe - buffer size changed from (%d,%d) to (%d,%d)",
+ d->bufferSize.width(), d->bufferSize.height(), newBufferWidth, newBufferHeight);
+
+ d->bufferSize.rwidth() = newBufferWidth;
+ d->bufferSize.rheight() = newBufferHeight;
+
+ QRect newGeometry;
+
+ newGeometry = geometry();
+ newGeometry.setWidth(d->bufferSize.width());
+ newGeometry.setHeight(d->bufferSize.height());
+
+ QPlatformWindow::setGeometry(newGeometry);
+ QWindowSystemInterface::handleGeometryChange(window(), newGeometry, QRect());
+ }
+}
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h
new file mode 100644
index 0000000000..f342669544
--- /dev/null
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 Canonical, Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QMIRCLIENTWINDOW_H
+#define QMIRCLIENTWINDOW_H
+
+#include <qpa/qplatformwindow.h>
+#include <QSharedPointer>
+
+#include <mir_toolkit/mir_client_library.h>
+
+class QMirClientClipboard;
+class QMirClientInput;
+class QMirClientScreen;
+class QMirClientWindowPrivate;
+
+class QMirClientWindow : public QObject, public QPlatformWindow
+{
+ Q_OBJECT
+public:
+ QMirClientWindow(QWindow *w, QSharedPointer<QMirClientClipboard> clipboard, QMirClientScreen *screen,
+ QMirClientInput *input, MirConnection *mir_connection);
+ virtual ~QMirClientWindow();
+
+ // QPlatformWindow methods.
+ WId winId() const override;
+ void setGeometry(const QRect&) override;
+ void setWindowState(Qt::WindowState state) override;
+ void setVisible(bool visible) override;
+
+ // New methods.
+ void* eglSurface() const;
+ void handleSurfaceResize(int width, int height);
+ void handleSurfaceFocusChange(bool focused);
+ void onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight);
+
+ QMirClientWindowPrivate* priv() { return d; }
+
+private:
+ void createWindow();
+ void moveResize(const QRect& rect);
+
+ QMirClientWindowPrivate *d;
+};
+
+#endif // QMIRCLIENTWINDOW_H
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index 22d443733e..43bb04e318 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -40,3 +40,5 @@ contains(QT_CONFIG, linuxfb): SUBDIRS += linuxfb
haiku {
SUBDIRS += haiku
}
+
+contains(QT_CONFIG, mirclient): SUBDIRS += mirclient
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
index 7521d25760..b00c9df408 100644
--- a/src/plugins/platforms/windows/openglblacklists/default.json
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -40,7 +40,7 @@
"type": "win"
},
"features": [
- "disable_desktopgl",
+ "disable_desktopgl"
]
}
]
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 4c14123aa7..18d2af5810 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -691,9 +691,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark
else if ((idx = atom->string().indexOf(QStringLiteral("bymodule"))) != -1) {
QString moduleName = atom->string().mid(idx + 8).trimmed();
Node::Genus genus = Node::CPP;
- if (atom->string().startsWith(QStringLiteral("qml")))
+ if (atom->string().startsWith(QLatin1String("qml")))
genus = Node::QML;
- else if (atom->string().startsWith(QStringLiteral("js")))
+ else if (atom->string().startsWith(QLatin1String("js")))
genus = Node::JS;
QDocDatabase* qdb = QDocDatabase::qdocDB();
const CollectionNode* cn = qdb->getCollectionNode(moduleName, genus);
@@ -1667,7 +1667,7 @@ void HtmlGenerator::generateDocumentNode(DocumentNode* dn, CodeMarker* marker)
Generate the TOC for the new doc format.
Don't generate a TOC for the home page.
*/
- if ((dn->name() != QStringLiteral("index.html")))
+ if ((dn->name() != QLatin1String("index.html")))
generateTableOfContents(dn,marker,0);
generateKeywordAnchors(dn);
@@ -4557,11 +4557,11 @@ void HtmlGenerator::generateManifestFile(const QString &manifest, const QString
if (s.length() < 2
|| s.at(0).isDigit()
|| s.at(0) == '-'
- || s == QStringLiteral("qt")
- || s == QStringLiteral("the")
- || s == QStringLiteral("and")
- || s.startsWith(QStringLiteral("example"))
- || s.startsWith(QStringLiteral("chapter")))
+ || s == QLatin1String("qt")
+ || s == QLatin1String("the")
+ || s == QLatin1String("and")
+ || s.startsWith(QLatin1String("example"))
+ || s.startsWith(QLatin1String("chapter")))
tag_it = tags.erase(tag_it);
else if (s != *tag_it) {
modified << s;
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 2a339cda4c..69958636fd 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -763,9 +763,8 @@ QWidgetBackingStore::~QWidgetBackingStore()
#ifndef QT_NO_OPENGL
delete widgetTextures;
- delete dirtyOnScreenWidgets;
#endif
- dirtyOnScreenWidgets = 0;
+ delete dirtyOnScreenWidgets;
}
//parent's coordinates; move whole rect; update parent and widget
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index bcffa3be79..b7ee7e4168 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -301,6 +301,8 @@ private:
friend class QWidgetPrivate;
friend class QWidget;
friend class QBackingStore;
+
+ Q_DISABLE_COPY(QWidgetBackingStore)
};
QT_END_NAMESPACE
diff --git a/tests/auto/network/ssl/qsslcertificate/BLACKLIST b/tests/auto/network/ssl/qsslcertificate/BLACKLIST
new file mode 100644
index 0000000000..2e376fa2a9
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/BLACKLIST
@@ -0,0 +1,3 @@
+# OpenSSL version is too new. Rich will fix :)
+[subjectAndIssuerAttributes]
+osx
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
index 4f66867a35..4c288fffaf 100644
--- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -833,6 +833,9 @@ void tst_QSslCertificate::task256066toPem()
void tst_QSslCertificate::nulInCN()
{
+#ifdef QT_SECURETRANSPORT
+ QSKIP("Generic QSslCertificatePrivate fails this test");
+#endif
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "/more-certificates/badguy-nul-cn.crt");
QCOMPARE(certList.size(), 1);
@@ -849,6 +852,9 @@ void tst_QSslCertificate::nulInCN()
void tst_QSslCertificate::nulInSan()
{
+#ifdef QT_SECURETRANSPORT
+ QSKIP("Generic QSslCertificatePrivate fails this test");
+#endif
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "/more-certificates/badguy-nul-san.crt");
QCOMPARE(certList.size(), 1);
@@ -976,6 +982,9 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
void tst_QSslCertificate::verify()
{
+#ifdef QT_SECURETRANSPORT
+ QSKIP("Not implemented in SecureTransport");
+#endif
QList<QSslError> errors;
QList<QSslCertificate> toVerify;