summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp2
-rw-r--r--src/3rdparty/forkfd/forkfd.c56
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java25
-rw-r--r--src/android/templates/AndroidManifest.xml4
-rw-r--r--src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch57
-rw-r--r--src/angle/src/libGLESv2/libGLESv2.pro2
-rw-r--r--src/corelib/global/qlogging.cpp2
-rw-r--r--src/corelib/global/qtypetraits.h21
-rw-r--r--src/corelib/io/qiodevice.cpp53
-rw-r--r--src/corelib/io/qlockfile.cpp12
-rw-r--r--src/corelib/io/qlockfile_p.h1
-rw-r--r--src/corelib/io/qlockfile_unix.cpp48
-rw-r--r--src/corelib/io/qlockfile_win.cpp45
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp24
-rw-r--r--src/corelib/kernel/qmetatype.h14
-rw-r--r--src/corelib/kernel/qobjectdefs.h1
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp14
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h3
-rw-r--r--src/dbus/qdbus_symbols_p.h3
-rw-r--r--src/gui/kernel/qgenericpluginfactory.cpp8
-rw-r--r--src/gui/kernel/qinputdevicemanager.cpp1
-rw-r--r--src/gui/kernel/qinputdevicemanager_p.h2
-rw-r--r--src/gui/kernel/qopenglwindow.cpp245
-rw-r--r--src/gui/painting/qimagescale.cpp160
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp42
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp67
-rw-r--r--src/gui/painting/qplatformbackingstore.h6
-rw-r--r--src/network/access/qftp.cpp5
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h1
-rw-r--r--src/network/ssl/qsslellipticcurve_dummy.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp18
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositor.cpp31
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp3
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm34
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm19
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp22
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp2
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp79
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h35
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp442
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp31
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp126
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h10
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro5
-rw-r--r--src/tools/moc/preprocessor.cpp8
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp50
-rw-r--r--src/widgets/dialogs/qwizard_win_p.h1
-rw-r--r--src/widgets/itemviews/qheaderview.cpp14
-rw-r--r--src/widgets/itemviews/qtreeview.cpp1
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp6
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp5
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp6
-rw-r--r--src/widgets/widgets/qcombobox.cpp2
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp4
-rw-r--r--src/winmain/qtmain_winrt.cpp38
65 files changed, 1260 insertions, 700 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
index 81b9ea748d..0f70fe4615 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
@@ -38,7 +38,7 @@ class InspectableNativeWindow;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
-#else
+#elif defined(ANGLE_ENABLE_D3D11)
typedef IDXGISwapChain DXGISwapChain;
typedef IDXGIFactory DXGIFactory;
#endif
@@ -60,9 +60,11 @@ class NativeWindow
#endif
static bool isValidNativeWindow(EGLNativeWindowType window);
+#if defined(ANGLE_ENABLE_D3D11)
HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
DXGI_FORMAT format, UINT width, UINT height,
DXGISwapChain** swapChain);
+#endif
inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
index 9d8f0bb96c..0a4f45b5b7 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
@@ -37,6 +37,7 @@ bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
return IsWindow(window) == TRUE;
}
+#if defined(ANGLE_ENABLE_D3D11)
HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
DXGI_FORMAT format, unsigned int width, unsigned int height,
DXGISwapChain** swapChain)
@@ -65,4 +66,5 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
}
+#endif
}
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index 017ae0741e..8d08f403ec 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -63,7 +63,7 @@
# include <Availability.h>
# include <AvailabilityMacros.h>
# if MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
-# define HAVE_BROKEN_WAITID_ALL 1
+# define HAVE_BROKEN_WAITID 1
# endif
#endif
@@ -109,10 +109,10 @@ static struct sigaction old_sigaction;
static pthread_once_t forkfd_initialization = PTHREAD_ONCE_INIT;
static ffd_atomic_int forkfd_status = FFD_ATOMIC_INIT(0);
-#ifdef HAVE_BROKEN_WAITID_ALL
-static int waitid_p_all_works = 0;
+#ifdef HAVE_BROKEN_WAITID
+static int waitid_works = 0;
#else
-static const int waitid_p_all_works = 1;
+static const int waitid_works = 1;
#endif
static ProcessInfo *tryAllocateInSection(Header *header, ProcessInfo entries[], int maxCount)
@@ -183,10 +183,13 @@ static int tryReaping(pid_t pid, siginfo_t *info)
{
/* reap the child */
#ifdef HAVE_WAITID
- // we have waitid(2), which fills in siginfo_t for us
- info->si_pid = 0;
- return waitid(P_PID, pid, info, WEXITED | WNOHANG) == 0 && info->si_pid == pid;
-#else
+ if (waitid_works) {
+ // we have waitid(2), which fills in siginfo_t for us
+ info->si_pid = 0;
+ return waitid(P_PID, pid, info, WEXITED | WNOHANG) == 0 && info->si_pid == pid;
+ }
+#endif
+
int status;
if (waitpid(pid, &status, WNOHANG) <= 0)
return 0; // child did not change state
@@ -206,7 +209,6 @@ static int tryReaping(pid_t pid, siginfo_t *info)
}
return 1;
-#endif
}
static void freeInfo(Header *header, ProcessInfo *entry)
@@ -246,7 +248,7 @@ static void sigchld_handler(int signum)
memset(&info, 0, sizeof info);
#ifdef HAVE_WAITID
- if (!waitid_p_all_works)
+ if (!waitid_works)
goto search_arrays;
/* be optimistic: try to see if we can get the child that exited */
@@ -310,12 +312,14 @@ search_arrays:
if (pid <= 0)
continue;
#ifdef HAVE_WAITID
- /* The child might have been reaped by the block above in another thread,
- * so first check if it's ready and, if it is, lock it */
- if (!isChildReady(pid, &info) ||
- !ffd_atomic_compare_exchange(&children.entries[i].pid, &pid, -1,
- FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
- continue;
+ if (waitid_works) {
+ /* The child might have been reaped by the block above in another thread,
+ * so first check if it's ready and, if it is, lock it */
+ if (!isChildReady(pid, &info) ||
+ !ffd_atomic_compare_exchange(&children.entries[i].pid, &pid, -1,
+ FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
+ continue;
+ }
#endif
if (tryReaping(pid, &info)) {
/* this is our child, send notification and free up this entry */
@@ -331,12 +335,14 @@ search_arrays:
if (pid <= 0)
continue;
#ifdef HAVE_WAITID
- /* The child might have been reaped by the block above in another thread,
- * so first check if it's ready and, if it is, lock it */
- if (!isChildReady(pid, &info) ||
- !ffd_atomic_compare_exchange(&array->entries[i].pid, &pid, -1,
- FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
- continue;
+ if (waitid_works) {
+ /* The child might have been reaped by the block above in another thread,
+ * so first check if it's ready and, if it is, lock it */
+ if (!isChildReady(pid, &info) ||
+ !ffd_atomic_compare_exchange(&array->entries[i].pid, &pid, -1,
+ FFD_ATOMIC_RELAXED, FFD_ATOMIC_RELAXED))
+ continue;
+ }
#endif
if (tryReaping(pid, &info)) {
/* this is our child, send notification and free up this entry */
@@ -357,17 +363,19 @@ chain_handler:
static void forkfd_initialize()
{
-#if defined(HAVE_BROKEN_WAITID_ALL)
+#if defined(HAVE_BROKEN_WAITID)
pid_t pid = fork();
if (pid == 0) {
_exit(0);
} else if (pid > 0) {
siginfo_t info;
waitid(P_ALL, 0, &info, WNOWAIT | WEXITED);
- waitid_p_all_works = (info.si_pid != 0);
+ waitid_works = (info.si_pid != 0);
+ info.si_pid = 0;
// now really reap the child
waitid(P_PID, pid, &info, WEXITED);
+ waitid_works = waitid_works && (info.si_pid != 0);
}
#endif
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index 73140839cc..d6cd49f44c 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -65,7 +65,6 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
-import android.widget.LinearLayout;
import java.io.BufferedReader;
import java.io.DataOutputStream;
@@ -789,29 +788,7 @@ public class QtActivityDelegate
0, 0,
metrics.xdpi, metrics.ydpi, metrics.scaledDensity);
}
-
- ViewGroup layout = null;
m_layout = new QtLayout(m_activity);
- if (Build.VERSION.SDK_INT >= 14) {
- try {
- ActivityInfo activityInfo = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(),
- PackageManager.GET_META_DATA);
- if (activityInfo.metaData == null
- || !activityInfo.metaData.containsKey("android.app.allow_overlapping_system_ui")
- || !activityInfo.metaData.getBoolean("android.app.allow_overlapping_system_ui")) {
- layout = new LinearLayout(m_activity);
- layout.setFitsSystemWindows(true);
- layout.addView(m_layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- if (layout == null)
- layout = m_layout;
-
m_editText = new QtEditText(m_activity, this);
m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
m_surfaces = new HashMap<Integer, QtSurface>();
@@ -834,7 +811,7 @@ public class QtActivityDelegate
Log.w("Qt A11y", "Unknown exception: " + e.toString());
}
- m_activity.setContentView(layout,
+ m_activity.setContentView(m_layout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml
index 779612cdaf..60c612976f 100644
--- a/src/android/templates/AndroidManifest.xml
+++ b/src/android/templates/AndroidManifest.xml
@@ -44,10 +44,6 @@
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
-
- <!-- Show translucent UI on top of Qt's surface when system theme mandates it -->
- <meta-data android:name="android.app.allow_overlapping_system_ui" android:value="false"/>
- <!-- Show translucent UI on top of Qt's surface when system theme mandates it -->
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
diff --git a/src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch b/src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch
new file mode 100644
index 0000000000..eca7d0e162
--- /dev/null
+++ b/src/angle/patches/0007-ANGLE-Fix-compilation-without-d3d11.patch
@@ -0,0 +1,57 @@
+From 1f993a2492a618becd4bf89ef0d6cb5d2c9aa67a Mon Sep 17 00:00:00 2001
+From: Kai Koehne <kai.koehne@theqtcompany.com>
+Date: Mon, 11 May 2015 15:17:12 +0200
+Subject: [PATCH] ANGLE: Fix compilation without d3d11
+
+Change-Id: I0b772698cf521083e5ecf35a395af57100a50131
+---
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 4 +++-
+ .../angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp | 2 ++
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+index 81b9ea7..0f70fe4 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+@@ -38,7 +38,7 @@ class InspectableNativeWindow;
+ using namespace Microsoft::WRL;
+ using namespace Microsoft::WRL::Wrappers;
+
+-#else
++#elif defined(ANGLE_ENABLE_D3D11)
+ typedef IDXGISwapChain DXGISwapChain;
+ typedef IDXGIFactory DXGIFactory;
+ #endif
+@@ -60,9 +60,11 @@ class NativeWindow
+ #endif
+ static bool isValidNativeWindow(EGLNativeWindowType window);
+
++#if defined(ANGLE_ENABLE_D3D11)
+ HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+ DXGI_FORMAT format, UINT width, UINT height,
+ DXGISwapChain** swapChain);
++#endif
+
+ inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+index 9d8f0bb..0a4f45b 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+@@ -37,6 +37,7 @@ bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
+ return IsWindow(window) == TRUE;
+ }
+
++#if defined(ANGLE_ENABLE_D3D11)
+ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+ DXGI_FORMAT format, unsigned int width, unsigned int height,
+ DXGISwapChain** swapChain)
+@@ -65,4 +66,5 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
+
+ return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+ }
++#endif
+ }
+--
+1.9.5.msysgit.0
+
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
index 1bf9af0436..5979b68098 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/libGLESv2/libGLESv2.pro
@@ -329,6 +329,8 @@ angle_d3d11 {
!static {
DEF_FILE = $$ANGLE_DIR/src/libGLESv2/$${TARGET}.def
mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libGLESv2/$${TARGET}_mingw32.def
+} else {
+ DEFINES += DllMain=DllMain_ANGLE # prevent symbol from conflicting with the user's DllMain
}
float_converter.target = float_converter
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 447a875655..88882bbe8f 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1737,7 +1737,7 @@ void qErrnoWarning(int code, const char *msg, ...)
Example:
\code
- QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D{%endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
+ QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
\endcode
The default \a pattern is "%{if-category}%{category}: %{endif}%{message}".
diff --git a/src/corelib/global/qtypetraits.h b/src/corelib/global/qtypetraits.h
index 3a305713e6..488e257e0f 100644
--- a/src/corelib/global/qtypetraits.h
+++ b/src/corelib/global/qtypetraits.h
@@ -506,6 +506,27 @@ Q_STATIC_ASSERT((!is_unsigned<qint64>::value));
Q_STATIC_ASSERT((!is_signed<quint64>::value));
Q_STATIC_ASSERT(( is_signed<qint64>::value));
+template<class T = void> struct is_default_constructible;
+
+template<> struct is_default_constructible<void>
+{
+protected:
+ template<bool> struct test { typedef char type; };
+public:
+ static bool const value = false;
+};
+template<> struct is_default_constructible<>::test<true> { typedef double type; };
+
+template<class T> struct is_default_constructible : is_default_constructible<>
+{
+private:
+ template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U*);
+ template<class U> static char sfinae(...);
+public:
+ static bool const value = sizeof(sfinae<T>(0)) > 1;
+};
+
+
} // namespace QtPrivate
QT_END_NAMESPACE
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index e73a200fb4..b908ae3145 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -38,9 +38,9 @@
#include "qiodevice_p.h"
#include "qfile.h"
#include "qstringlist.h"
+#include "qdir.h"
#include <algorithm>
-#include <limits.h>
#ifdef QIODEVICE_DEBUG
# include <ctype.h>
@@ -80,10 +80,29 @@ void debugBinaryString(const char *data, qint64 maxlen)
#define Q_VOID
+static void checkWarnMessage(const QIODevice *device, const char *function, const char *what)
+{
+ QDebug d = qWarning();
+ d.noquote();
+ d.nospace();
+ d << "QIODevice::" << function;
+#ifndef QT_NO_QOBJECT
+ d << " (" << device->metaObject()->className();
+ if (!device->objectName().isEmpty())
+ d << ", \"" << device->objectName() << '"';
+ if (const QFile *f = qobject_cast<const QFile *>(device))
+ d << ", \"" << QDir::toNativeSeparators(f->fileName()) << '"';
+ d << ')';
+#else
+ Q_UNUSED(device)
+#endif // !QT_NO_QOBJECT
+ d << ": " << what;
+}
+
#define CHECK_MAXLEN(function, returnType) \
do { \
if (maxSize < 0) { \
- qWarning("QIODevice::"#function": Called with maxSize < 0"); \
+ checkWarnMessage(this, #function, "Called with maxSize < 0"); \
return returnType; \
} \
} while (0)
@@ -92,10 +111,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
do { \
if ((d->openMode & WriteOnly) == 0) { \
if (d->openMode == NotOpen) { \
- qWarning("QIODevice::"#function": device not open"); \
+ checkWarnMessage(this, #function, "device not open"); \
return returnType; \
} \
- qWarning("QIODevice::"#function": ReadOnly device"); \
+ checkWarnMessage(this, #function, "ReadOnly device"); \
return returnType; \
} \
} while (0)
@@ -104,10 +123,10 @@ void debugBinaryString(const char *data, qint64 maxlen)
do { \
if ((d->openMode & ReadOnly) == 0) { \
if (d->openMode == NotOpen) { \
- qWarning("QIODevice::"#function": device not open"); \
+ checkWarnMessage(this, #function, "device not open"); \
return returnType; \
} \
- qWarning("QIODevice::"#function": WriteOnly device"); \
+ checkWarnMessage(this, #function, "WriteOnly device"); \
return returnType; \
} \
} while (0)
@@ -462,7 +481,7 @@ void QIODevice::setTextModeEnabled(bool enabled)
{
Q_D(QIODevice);
if (!isOpen()) {
- qWarning("QIODevice::setTextModeEnabled: The device is not open");
+ checkWarnMessage(this, "setTextModeEnabled", "The device is not open");
return;
}
if (enabled)
@@ -621,11 +640,11 @@ bool QIODevice::seek(qint64 pos)
{
Q_D(QIODevice);
if (d->isSequential()) {
- qWarning("QIODevice::seek: Cannot call seek on a sequential device");
+ checkWarnMessage(this, "seek", "Cannot call seek on a sequential device");
return false;
}
if (d->openMode == NotOpen) {
- qWarning("QIODevice::seek: The device is not open");
+ checkWarnMessage(this, "seek", "The device is not open");
return false;
}
if (pos < 0) {
@@ -922,9 +941,9 @@ QByteArray QIODevice::read(qint64 maxSize)
Q_UNUSED(d);
#endif
- if (maxSize != qint64(int(maxSize))) {
- qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
- maxSize = INT_MAX;
+ if (quint64(maxSize) >= QByteArray::MaxSize) {
+ checkWarnMessage(this, "read", "maxSize argument exceeds QByteArray size limit");
+ maxSize = QByteArray::MaxSize - 1;
}
qint64 readBytes = 0;
@@ -976,7 +995,7 @@ QByteArray QIODevice::readAll()
// flush internal read buffer
if (!(d->openMode & Text) && !d->buffer.isEmpty()) {
- if (d->buffer.size() >= INT_MAX)
+ if (quint64(d->buffer.size()) >= QByteArray::MaxSize)
return QByteArray();
result = d->buffer.readAll();
readBytes = result.size();
@@ -1055,7 +1074,7 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize)
{
Q_D(QIODevice);
if (maxSize < 2) {
- qWarning("QIODevice::readLine: Called with maxSize < 2");
+ checkWarnMessage(this, "readLine", "Called with maxSize < 2");
return qint64(-1);
}
@@ -1159,9 +1178,9 @@ QByteArray QIODevice::readLine(qint64 maxSize)
Q_UNUSED(d);
#endif
- if (maxSize > INT_MAX) {
+ if (quint64(maxSize) >= QByteArray::MaxSize) {
qWarning("QIODevice::read: maxSize argument exceeds QByteArray size limit");
- maxSize = INT_MAX;
+ maxSize = QByteArray::MaxSize - 1;
}
result.resize(int(maxSize));
@@ -1169,7 +1188,7 @@ QByteArray QIODevice::readLine(qint64 maxSize)
if (!result.size()) {
// If resize fails or maxSize == 0, read incrementally
if (maxSize == 0)
- maxSize = INT_MAX;
+ maxSize = QByteArray::MaxSize - 1;
// The first iteration needs to leave an extra byte for the terminating null
result.resize(1);
diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp
index 4f5aeff395..2bd996d213 100644
--- a/src/corelib/io/qlockfile.cpp
+++ b/src/corelib/io/qlockfile.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -66,9 +67,12 @@ QT_BEGIN_NAMESPACE
If the process holding the lock crashes, the lock file stays on disk and can prevent
any other process from accessing the shared resource, ever. For this reason, QLockFile
- tries to detect such a "stale" lock file, based on the process ID written into the file,
- and (in case that process ID got reused meanwhile), on the last modification time of
- the lock file (30s by default, for the use case of a short-lived operation).
+ tries to detect such a "stale" lock file, based on the process ID written into the file.
+ To cover the situation that the process ID got reused meanwhile, the current process name is
+ compared to the name of the process that corresponds to the process ID from the lock file.
+ If the process names differ, the lock file is considered stale.
+ Additionally, the last modification time of the lock file (30s by default, for the use case of a
+ short-lived operation) is taken into account.
If the lock file is found to be stale, it will be deleted.
For the use case of protecting a resource over a long time, you should therefore call
@@ -122,7 +126,7 @@ QLockFile::~QLockFile()
The value of \a staleLockTime is used by lock() and tryLock() in order
to determine when an existing lock file is considered stale, i.e. left over
by a crashed process. This is useful for the case where the PID got reused
- meanwhile, so the only way to detect a stale lock file is by the fact that
+ meanwhile, so one way to detect a stale lock file is by the fact that
it has been around for a long time.
\sa staleLockTime()
diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h
index 0cfaa42849..168062f467 100644
--- a/src/corelib/io/qlockfile_p.h
+++ b/src/corelib/io/qlockfile_p.h
@@ -75,6 +75,7 @@ public:
// Returns \c true if the lock belongs to dead PID, or is old.
// The attempt to delete it will tell us if it was really stale or not, though.
bool isApparentlyStale() const;
+ static QString processNameByPid(qint64 pid);
#ifdef Q_OS_UNIX
static int checkFcntlWorksAfterFlock();
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index d1804f2cb6..d6ea2f1f2d 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -48,6 +49,15 @@
#include <signal.h> // kill
#include <unistd.h> // gethostname
+#if defined(Q_OS_OSX)
+# include <libproc.h>
+#elif defined(Q_OS_LINUX)
+# include <unistd.h>
+# include <cstdio>
+#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+# include <sys/user.h>
+#endif
+
QT_BEGIN_NAMESPACE
static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray
@@ -189,12 +199,50 @@ bool QLockFilePrivate::isApparentlyStale() const
if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) {
if (::kill(pid, 0) == -1 && errno == ESRCH)
return true; // PID doesn't exist anymore
+ const QString processName = processNameByPid(pid);
+ if (!processName.isEmpty()) {
+ QFileInfo fi(appname);
+ if (fi.isSymLink())
+ fi.setFile(fi.symLinkTarget());
+ if (processName != fi.fileName())
+ return true; // PID got reused by a different application.
+ }
}
}
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;
}
+QString QLockFilePrivate::processNameByPid(qint64 pid)
+{
+#if defined(Q_OS_OSX)
+ char name[1024];
+ proc_name(pid, name, sizeof(name) / sizeof(char));
+ return QString::fromUtf8(name);
+#elif defined(Q_OS_LINUX)
+ if (!QFile::exists(QStringLiteral("/proc/version")))
+ return QString();
+ char exePath[64];
+ char buf[PATH_MAX];
+ memset(buf, 0, sizeof(buf));
+ sprintf(exePath, "/proc/%lld/exe", pid);
+ if (readlink(exePath, buf, sizeof(buf)) < 0) {
+ // The pid is gone. Return some invalid process name to fail the test.
+ return QStringLiteral("/ERROR/");
+ }
+ return QFileInfo(QString::fromUtf8(buf)).fileName();
+#elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS)
+ kinfo_proc *proc = kinfo_getproc(pid);
+ if (!proc)
+ return QString();
+ QString name = QString::fromUtf8(proc->ki_comm);
+ free(proc);
+ return name;
+#else
+ return QString();
+#endif
+}
+
void QLockFile::unlock()
{
Q_D(QLockFile);
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index 4e0d8134ec..8cbe0a9dfd 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -140,6 +141,9 @@ bool QLockFilePrivate::isApparentlyStale() const
::CloseHandle(procHandle);
if (dwR == WAIT_TIMEOUT)
return true;
+ const QString processName = processNameByPid(pid);
+ if (!processName.isEmpty() && processName != appname)
+ return true; // PID got reused by a different application.
}
}
#else // !Q_OS_WINRT
@@ -151,6 +155,47 @@ bool QLockFilePrivate::isApparentlyStale() const
return staleLockTime > 0 && age > staleLockTime;
}
+QString QLockFilePrivate::processNameByPid(qint64 pid)
+{
+#if !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+ typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD);
+
+ HMODULE hPsapi = LoadLibraryA("psapi");
+ if (!hPsapi)
+ return QString();
+
+ GetModuleFileNameExFunc qGetModuleFileNameEx
+ = (GetModuleFileNameExFunc)GetProcAddress(hPsapi, "GetModuleFileNameExW");
+ if (!qGetModuleFileNameEx) {
+ FreeLibrary(hPsapi);
+ return QString();
+ }
+
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid));
+ if (!hProcess) {
+ FreeLibrary(hPsapi);
+ return QString();
+ }
+ wchar_t buf[MAX_PATH];
+ const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t));
+ CloseHandle(hProcess);
+ FreeLibrary(hPsapi);
+ if (!length)
+ return QString();
+ QString name = QString::fromWCharArray(buf, length);
+ int i = name.lastIndexOf(QLatin1Char('\\'));
+ if (i >= 0)
+ name.remove(0, i + 1);
+ i = name.lastIndexOf(QLatin1Char('.'));
+ if (i >= 0)
+ name.truncate(i);
+ return name;
+#else
+ Q_UNUSED(pid);
+ return QString();
+#endif
+}
+
void QLockFile::unlock()
{
Q_D(QLockFile);
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 7b8f608050..d170e7c0c0 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -67,8 +67,20 @@
#endif
#if defined(Q_OS_BSD4)
-# define QT_STATFSBUF struct statvfs
-# define QT_STATFS ::statvfs
+# if defined(Q_OS_NETBSD)
+ define QT_STATFSBUF struct statvfs
+ define QT_STATFS ::statvfs
+# else
+# define QT_STATFSBUF struct statfs
+# define QT_STATFS ::statfs
+# endif
+
+# if !defined(ST_RDONLY)
+# define ST_RDONLY MNT_RDONLY
+# endif
+# if !defined(_STATFS_F_FLAGS)
+# define _STATFS_F_FLAGS 1
+# endif
#elif defined(Q_OS_ANDROID)
# define QT_STATFS ::statfs
# define QT_STATFSBUF struct statfs
@@ -122,11 +134,7 @@ public:
inline QByteArray device() const;
private:
#if defined(Q_OS_BSD4)
-# if defined(Q_OS_NETBSD)
- struct statvfs *stat_buf;
-# else
- struct statfs *stat_buf;
-# endif
+ QT_STATFSBUF *stat_buf;
int entryCount;
int currentIndex;
#elif defined(Q_OS_SOLARIS)
@@ -501,7 +509,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
-#if defined(Q_OS_ANDROID)
+#if defined(Q_OS_ANDROID) || defined (Q_OS_BSD4)
#if defined(_STATFS_F_FLAGS)
readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
#endif
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index b854dc16fd..1b214e9f74 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1357,12 +1357,16 @@ namespace QtPrivate
enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(yes_type) };
};
+ template<typename T, typename Enable = void>
+ struct IsGadgetHelper { enum { Value = false }; };
+
template<typename T>
- struct IsGadgetHelper
+ struct IsGadgetHelper<T, typename T::QtGadgetHelper>
{
- template<typename X> static typename X::QtGadgetHelper *checkType(X*);
- static char checkType(void*);
- enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(void*) };
+ template <typename X>
+ static char checkType(void (X::*)());
+ static void *checkType(void (T::*)());
+ enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
};
@@ -1769,7 +1773,7 @@ template <typename T>
struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
{
enum {
- Defined = 1
+ Defined = QtPrivate::is_default_constructible<T>::value
};
static int qt_metatype_id()
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 31e8a670e9..4d01264906 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -172,6 +172,7 @@ private: \
#define Q_GADGET \
public: \
static const QMetaObject staticMetaObject; \
+ void qt_check_for_QGADGET_macro(); \
typedef void QtGadgetHelper; \
private: \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
index 255e9557e2..eaa695ef27 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -1362,11 +1362,11 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex
\internal
returns
- 0 if str == QDateTimeEdit::tr("AM")
- 1 if str == QDateTimeEdit::tr("PM")
- 2 if str can become QDateTimeEdit::tr("AM")
- 3 if str can become QDateTimeEdit::tr("PM")
- 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
+ 0 if str == tr("AM")
+ 1 if str == tr("PM")
+ 2 if str can become tr("AM")
+ 3 if str can become tr("PM")
+ 4 if str can become tr("PM") and can become tr("AM")
-1 can't become anything sensible
*/
@@ -1737,9 +1737,9 @@ QDateTime QDateTimeParser::getMaximum() const
QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
{
if (ap == AmText) {
- return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
+ return (cs == UpperCase ? tr("AM") : tr("am"));
} else {
- return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
+ return (cs == UpperCase ? tr("PM") : tr("pm"));
}
}
diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h
index 55dc3bf7a0..9457e35ad5 100644
--- a/src/corelib/tools/qdatetimeparser_p.h
+++ b/src/corelib/tools/qdatetimeparser_p.h
@@ -54,7 +54,7 @@
# include "QtCore/qvariant.h"
#endif
#include "QtCore/qvector.h"
-
+#include "QtCore/qcoreapplication.h"
#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0)
#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999)
@@ -72,6 +72,7 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QDateTimeParser
{
+ Q_DECLARE_TR_FUNCTIONS(QDateTimeParser)
public:
enum Context {
FromString,
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index cec8ad62cb..32b76ee5bd 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -183,9 +183,6 @@ DEFINEFUNC(dbus_bool_t , dbus_connection_add_filter, (DBusConnection
void *user_data,
DBusFreeFunction free_data_function),
(connection, function, user_data, free_data_function), return)
-DEFINEFUNC(dbus_bool_t , dbus_connection_can_send_type, (DBusConnection *connection,
- int type),
- (connection, type), return)
DEFINEFUNC(void , dbus_connection_close, (DBusConnection *connection),
(connection), return)
DEFINEFUNC(DBusDispatchStatus , dbus_connection_dispatch, (DBusConnection *connection),
diff --git a/src/gui/kernel/qgenericpluginfactory.cpp b/src/gui/kernel/qgenericpluginfactory.cpp
index 7e4727df8c..d7b9bfba06 100644
--- a/src/gui/kernel/qgenericpluginfactory.cpp
+++ b/src/gui/kernel/qgenericpluginfactory.cpp
@@ -69,13 +69,13 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
*/
QObject *QGenericPluginFactory::create(const QString& key, const QString &specification)
{
+#if (!defined(Q_OS_WIN32) || defined(QT_SHARED)) && !defined(QT_NO_LIBRARY)
const QString driver = key.toLower();
-
-#if !defined(Q_OS_WIN32) || defined(QT_SHARED)
-#ifndef QT_NO_LIBRARY
if (QObject *object = qLoadPlugin1<QObject, QGenericPlugin>(loader(), driver, specification))
return object;
-#endif
+#else // (!Q_OS_WIN32 || QT_SHARED) && !QT_NO_LIBRARY
+ Q_UNUSED(key)
+ Q_UNUSED(specification)
#endif
return 0;
}
diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp
index d0dd8a4e7c..dbdb03adbb 100644
--- a/src/gui/kernel/qinputdevicemanager.cpp
+++ b/src/gui/kernel/qinputdevicemanager.cpp
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
QInputDeviceManager::QInputDeviceManager(QObject *parent)
: QObject(*new QInputDeviceManagerPrivate, parent)
{
+ qRegisterMetaType<DeviceType>();
}
int QInputDeviceManager::deviceCount(DeviceType type) const
diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h
index 15c84d1a82..d64793c23c 100644
--- a/src/gui/kernel/qinputdevicemanager_p.h
+++ b/src/gui/kernel/qinputdevicemanager_p.h
@@ -77,4 +77,6 @@ signals:
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QInputDeviceManager::DeviceType)
+
#endif // QINPUTDEVICEMANAGER_P_H
diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp
index 7113345a75..b2025faaf1 100644
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -175,141 +175,156 @@ public:
this->shareContext = qt_gl_global_share_context();
}
- ~QOpenGLWindowPrivate()
- {
- Q_Q(QOpenGLWindow);
- if (q->isValid()) {
- q->makeCurrent(); // this works even when the platformwindow is destroyed
- paintDevice.reset(0);
- fbo.reset(0);
- blitter.destroy();
- q->doneCurrent();
- }
- }
+ ~QOpenGLWindowPrivate();
static QOpenGLWindowPrivate *get(QOpenGLWindow *w) { return w->d_func(); }
- void bindFBO()
- {
- if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
- fbo->bind();
- else
- QOpenGLFramebufferObject::bindDefault();
+ void bindFBO();
+ void initialize();
+
+ void beginPaint(const QRegion &region) Q_DECL_OVERRIDE;
+ void endPaint() Q_DECL_OVERRIDE;
+ void flush(const QRegion &region) Q_DECL_OVERRIDE;
+
+ QOpenGLWindow::UpdateBehavior updateBehavior;
+ bool hasFboBlit;
+ QScopedPointer<QOpenGLContext> context;
+ QOpenGLContext *shareContext;
+ QScopedPointer<QOpenGLFramebufferObject> fbo;
+ QScopedPointer<QOpenGLWindowPaintDevice> paintDevice;
+ QOpenGLTextureBlitter blitter;
+ QColor backgroundColor;
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+};
+
+QOpenGLWindowPrivate::~QOpenGLWindowPrivate()
+{
+ Q_Q(QOpenGLWindow);
+ if (q->isValid()) {
+ q->makeCurrent(); // this works even when the platformwindow is destroyed
+ paintDevice.reset(0);
+ fbo.reset(0);
+ blitter.destroy();
+ q->doneCurrent();
}
+}
- void beginPaint(const QRegion &region) Q_DECL_OVERRIDE
- {
- Q_UNUSED(region);
- Q_Q(QOpenGLWindow);
-
- if (!context) {
- context.reset(new QOpenGLContext);
- context->setShareContext(shareContext);
- context->setFormat(q->requestedFormat());
- context->setScreen(q->screen());
- if (!context->create())
- qWarning("QOpenGLWindow::beginPaint: Failed to create context");
- if (!context->makeCurrent(q))
- qWarning("QOpenGLWindow::beginPaint: Failed to make context current");
-
- paintDevice.reset(new QOpenGLWindowPaintDevice(q));
- if (updateBehavior == QOpenGLWindow::PartialUpdateBlit)
- hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
-
- q->initializeGL();
- } else {
- context->makeCurrent(q);
- }
+void QOpenGLWindowPrivate::initialize()
+{
+ Q_Q(QOpenGLWindow);
- const int deviceWidth = q->width() * q->devicePixelRatio();
- const int deviceHeight = q->height() * q->devicePixelRatio();
- const QSize deviceSize(deviceWidth, deviceHeight);
- if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
- if (!fbo || fbo->size() != deviceSize) {
- QOpenGLFramebufferObjectFormat fboFormat;
- fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- if (q->requestedFormat().samples() > 0) {
- if (updateBehavior != QOpenGLWindow::PartialUpdateBlend)
- fboFormat.setSamples(q->requestedFormat().samples());
- else
- qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
- }
- fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));
- markWindowAsDirty();
+ if (context)
+ return;
+
+ context.reset(new QOpenGLContext);
+ context->setShareContext(shareContext);
+ context->setFormat(q->requestedFormat());
+ if (!context->create())
+ qWarning("QOpenGLWindow::beginPaint: Failed to create context");
+ if (!context->makeCurrent(q))
+ qWarning("QOpenGLWindow::beginPaint: Failed to make context current");
+
+ paintDevice.reset(new QOpenGLWindowPaintDevice(q));
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlit)
+ hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
+
+ q->initializeGL();
+}
+
+void QOpenGLWindowPrivate::beginPaint(const QRegion &region)
+{
+ Q_UNUSED(region);
+ Q_Q(QOpenGLWindow);
+
+ initialize();
+ context->makeCurrent(q);
+
+ const int deviceWidth = q->width() * q->devicePixelRatio();
+ const int deviceHeight = q->height() * q->devicePixelRatio();
+ const QSize deviceSize(deviceWidth, deviceHeight);
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
+ if (!fbo || fbo->size() != deviceSize) {
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ if (q->requestedFormat().samples() > 0) {
+ if (updateBehavior != QOpenGLWindow::PartialUpdateBlend)
+ fboFormat.setSamples(q->requestedFormat().samples());
+ else
+ qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
}
- } else {
+ fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));
markWindowAsDirty();
}
+ } else {
+ markWindowAsDirty();
+ }
- paintDevice->setSize(QSize(deviceWidth, deviceHeight));
- paintDevice->setDevicePixelRatio(q->devicePixelRatio());
- context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);
+ paintDevice->setSize(QSize(deviceWidth, deviceHeight));
+ paintDevice->setDevicePixelRatio(q->devicePixelRatio());
+ context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);
- context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
+ context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
- q->paintUnderGL();
+ q->paintUnderGL();
- if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
- fbo->bind();
- }
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+ fbo->bind();
+}
- void endPaint() Q_DECL_OVERRIDE
- {
- Q_Q(QOpenGLWindow);
-
- if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
- fbo->release();
-
- context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
-
- if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
- const int deviceWidth = q->width() * q->devicePixelRatio();
- const int deviceHeight = q->height() * q->devicePixelRatio();
- QOpenGLExtensions extensions(context.data());
- extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());
- extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());
- extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,
- 0, 0, deviceWidth, deviceHeight,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
- if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
- context->functions()->glEnable(GL_BLEND);
- context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
- if (!blitter.isCreated())
- blitter.create();
+void QOpenGLWindowPrivate::endPaint()
+{
+ Q_Q(QOpenGLWindow);
+
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+ fbo->release();
- QRect windowRect(QPoint(0, 0), fbo->size());
- QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);
- blitter.bind();
- blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);
- blitter.release();
+ context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
- if (updateBehavior == QOpenGLWindow::PartialUpdateBlend)
- context->functions()->glDisable(GL_BLEND);
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
+ const int deviceWidth = q->width() * q->devicePixelRatio();
+ const int deviceHeight = q->height() * q->devicePixelRatio();
+ QOpenGLExtensions extensions(context.data());
+ extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());
+ extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());
+ extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,
+ 0, 0, deviceWidth, deviceHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
+ context->functions()->glEnable(GL_BLEND);
+ context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
+ if (!blitter.isCreated())
+ blitter.create();
- q->paintOverGL();
- }
+ QRect windowRect(QPoint(0, 0), fbo->size());
+ QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);
+ blitter.bind();
+ blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);
+ blitter.release();
- void flush(const QRegion &region) Q_DECL_OVERRIDE
- {
- Q_UNUSED(region);
- Q_Q(QOpenGLWindow);
- context->swapBuffers(q);
- emit q->frameSwapped();
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlend)
+ context->functions()->glDisable(GL_BLEND);
}
- QOpenGLWindow::UpdateBehavior updateBehavior;
- bool hasFboBlit;
- QScopedPointer<QOpenGLContext> context;
- QOpenGLContext *shareContext;
- QScopedPointer<QOpenGLFramebufferObject> fbo;
- QScopedPointer<QOpenGLWindowPaintDevice> paintDevice;
- QOpenGLTextureBlitter blitter;
- QColor backgroundColor;
- QScopedPointer<QOffscreenSurface> offscreenSurface;
-};
+ q->paintOverGL();
+}
+
+void QOpenGLWindowPrivate::bindFBO()
+{
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+ fbo->bind();
+ else
+ QOpenGLFramebufferObject::bindDefault();
+}
+
+void QOpenGLWindowPrivate::flush(const QRegion &region)
+{
+ Q_UNUSED(region);
+ Q_Q(QOpenGLWindow);
+ context->swapBuffers(q);
+ emit q->frameSwapped();
+}
void QOpenGLWindowPaintDevice::ensureActiveTarget()
{
@@ -632,6 +647,8 @@ void QOpenGLWindow::paintEvent(QPaintEvent *event)
void QOpenGLWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
+ Q_D(QOpenGLWindow);
+ d->initialize();
resizeGL(width(), height());
}
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 5f1b25e189..9b4eabc552 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -38,22 +38,6 @@
QT_BEGIN_NAMESPACE
-typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow);
-
-static void qt_qimageScaleAARGB(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow);
-
-static void qt_qimageScaleAARGBA(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow);
-
-qt_qimageScaleFunc qt_qimageScaleArgb = qt_qimageScaleAARGBA;
-qt_qimageScaleFunc qt_qimageScaleRgb = qt_qimageScaleAARGB;
-
-
/*
* Copyright (C) 2004, 2005 Daniel M. Duley
*
@@ -115,13 +99,6 @@ using namespace QImageScale;
// Code ported from Imlib...
//
-// FIXME: replace with qRed, etc... These work on pointers to pixels, not
-// pixel values
-#define A_VAL(p) (qAlpha(*p))
-#define R_VAL(p) (qRed(*p))
-#define G_VAL(p) (qGreen(*p))
-#define B_VAL(p) (qBlue(*p))
-
const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int sw, int sh, int dh)
{
@@ -381,46 +358,25 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
}
}
-inline static void qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b, int &a)
-{
- r = R_VAL(pix) * xap;
- g = G_VAL(pix) * xap;
- b = B_VAL(pix) * xap;
- a = A_VAL(pix) * xap;
- int j;
- for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
- pix++;
- r += R_VAL(pix) * Cx;
- g += G_VAL(pix) * Cx;
- b += B_VAL(pix) * Cx;
- a += A_VAL(pix) * Cx;
- }
- pix++;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- a += A_VAL(pix) * j;
-}
-
-inline static void qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b, int &a)
+inline static void qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b, int &a)
{
- r = R_VAL(pix) * yap;
- g = G_VAL(pix) * yap;
- b = B_VAL(pix) * yap;
- a = A_VAL(pix) * yap;
+ r = qRed(*pix) * xyap;
+ g = qGreen(*pix) * xyap;
+ b = qBlue(*pix) * xyap;
+ a = qAlpha(*pix) * xyap;
int j;
- for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
- pix += sow;
- r += R_VAL(pix) * Cy;
- g += G_VAL(pix) * Cy;
- b += B_VAL(pix) * Cy;
- a += A_VAL(pix) * Cy;
- }
- pix += sow;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- a += A_VAL(pix) * j;
+ for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
+ pix += step;
+ r += qRed(*pix) * Cxy;
+ g += qGreen(*pix) * Cxy;
+ b += qBlue(*pix) * Cxy;
+ a += qAlpha(*pix) * Cxy;
+ }
+ pix += step;
+ r += qRed(*pix) * j;
+ g += qGreen(*pix) * j;
+ b += qBlue(*pix) * j;
+ a += qAlpha(*pix) * j;
}
static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
@@ -443,12 +399,12 @@ static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int
for (int x = dxx; x < end; x++) {
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b, a;
- qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, r, g, b, a);
+ qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, r, g, b, a);
int xap = xapoints[x];
if (xap > 0) {
int rr, gg, bb, aa;
- qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+ qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
r = r * (256 - xap);
g = g * (256 - xap);
@@ -484,12 +440,12 @@ static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b, a;
- qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, r, g, b, a);
+ qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, r, g, b, a);
int yap = yapoints[dyy + y];
if (yap > 0) {
int rr, gg, bb, aa;
- qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, rr, gg, bb, aa);
+ qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
r = r * (256 - yap);
g = g * (256 - yap);
@@ -528,7 +484,7 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int rx, gx, bx, ax;
- qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+ qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
int r = ((rx>>4) * yap);
int g = ((gx>>4) * yap);
@@ -538,14 +494,14 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
- qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+ qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * Cy);
g += ((gx>>4) * Cy);
b += ((bx>>4) * Cy);
a += ((ax>>4) * Cy);
}
sptr += sow;
- qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+ qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * j);
g += ((gx>>4) * j);
@@ -609,40 +565,22 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
}
-inline static void qt_qimageScaleAARGB_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b)
+inline static void qt_qimageScaleAARGB_helper(const unsigned int *pix, int xyap, int Cxy, int step, int &r, int &g, int &b)
{
- r = R_VAL(pix) * xap;
- g = G_VAL(pix) * xap;
- b = B_VAL(pix) * xap;
+ r = qRed(*pix) * xyap;
+ g = qGreen(*pix) * xyap;
+ b = qBlue(*pix) * xyap;
int j;
- for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
- pix++;
- r += R_VAL(pix) * Cx;
- g += G_VAL(pix) * Cx;
- b += B_VAL(pix) * Cx;
- }
- pix++;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
-}
-
-inline static void qt_qimageScaleAARGB_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b)
-{
- r = R_VAL(pix) * yap;
- g = G_VAL(pix) * yap;
- b = B_VAL(pix) * yap;
- int j;
- for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
- pix += sow;
- r += R_VAL(pix) * Cy;
- g += G_VAL(pix) * Cy;
- b += B_VAL(pix) * Cy;
- }
- pix += sow;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
+ for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy) {
+ pix += step;
+ r += qRed(*pix) * Cxy;
+ g += qGreen(*pix) * Cxy;
+ b += qBlue(*pix) * Cxy;
+ }
+ pix += step;
+ r += qRed(*pix) * j;
+ g += qGreen(*pix) * j;
+ b += qBlue(*pix) * j;
}
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
@@ -665,12 +603,12 @@ static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *
for (int x = dxx; x < end; x++) {
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b;
- qt_qimageScaleAARGB_helper_y(sptr, yap, Cy, sow, r, g, b);
+ qt_qimageScaleAARGB_helper(sptr, yap, Cy, sow, r, g, b);
int xap = xapoints[x];
if (xap > 0) {
int rr, bb, gg;
- qt_qimageScaleAARGB_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb);
+ qt_qimageScaleAARGB_helper(sptr + 1, yap, Cy, sow, rr, gg, bb);
r = r * (256 - xap);
g = g * (256 - xap);
@@ -704,12 +642,12 @@ static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int r, g, b;
- qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, r, g, b);
+ qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, r, g, b);
int yap = yapoints[dyy + y];
if (yap > 0) {
int rr, bb, gg;
- qt_qimageScaleAARGB_helper_x(sptr + sow, xap, Cx, rr, gg, bb);
+ qt_qimageScaleAARGB_helper(sptr + sow, xap, Cx, 1, rr, gg, bb);
r = r * (256 - yap);
g = g * (256 - yap);
@@ -745,7 +683,7 @@ static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
int rx, gx, bx;
- qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+ qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
int r = (rx >> 4) * yap;
int g = (gx >> 4) * yap;
@@ -754,14 +692,14 @@ static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
- qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+ qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * Cy;
g += (gx >> 4) * Cy;
b += (bx >> 4) * Cy;
}
sptr += sow;
- qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+ qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * j;
g += (gx >> 4) * j;
@@ -794,11 +732,11 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
}
if (src.hasAlphaChannel())
- qt_qimageScaleArgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
- 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
+ qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
+ 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
else
- qt_qimageScaleRgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
- 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
+ qt_qimageScaleAARGB(scaleinfo, (unsigned int *)buffer.scanLine(0),
+ 0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
qimageFreeScaleInfo(scaleinfo);
return buffer;
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
index 565ea4daa1..303e0fd980 100644
--- a/src/gui/painting/qimagescale_sse4.cpp
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -41,33 +41,17 @@ QT_BEGIN_NAMESPACE
using namespace QImageScale;
-inline static __m128i qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, const __m128i vxap, const __m128i vCx)
+inline static __m128i qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step, const __m128i vxyap, const __m128i vCxy)
{
__m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
- __m128i vx = _mm_mullo_epi32(vpix, vxap);
+ __m128i vx = _mm_mullo_epi32(vpix, vxyap);
int i;
- for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
- pix++;
+ for (i = (1 << 14) - xyap; i > Cxy; i -= Cxy) {
+ pix += step;
vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
- vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCx));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCxy));
}
- pix++;
- vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
- vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
- return vx;
-}
-
-inline static __m128i qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, const __m128i vyap, const __m128i vCy)
-{
- __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
- __m128i vx = _mm_mullo_epi32(vpix, vyap);
- int i;
- for (i = (1 << 14) - yap; i > Cy; i -= Cy) {
- pix += sow;
- vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
- vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCy));
- }
- pix += sow;
+ pix += step;
vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
return vx;
@@ -97,13 +81,13 @@ void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *d
unsigned int *dptr = dest + dx + ((y + dy) * dow);
for (int x = dxx; x < end; x++) {
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
- __m128i vx = qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, vyap, vCy);
+ __m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy);
int xap = xapoints[x];
if (xap > 0) {
const __m128i vxap = _mm_set1_epi32(xap);
const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
- __m128i vr = qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, vyap, vCy);
+ __m128i vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, vyap, vCy);
vx = _mm_mullo_epi32(vx, vinvxap);
vr = _mm_mullo_epi32(vr, vxap);
@@ -145,13 +129,13 @@ void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *d
const __m128i vxap = _mm_set1_epi32(xap);
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
- __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
int yap = yapoints[dyy + y];
if (yap > 0) {
const __m128i vyap = _mm_set1_epi32(yap);
const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
- __m128i vr = qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, vxap, vCx);
+ __m128i vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, vxap, vCx);
vx = _mm_mullo_epi32(vx, vinvyap);
vr = _mm_mullo_epi32(vr, vyap);
@@ -194,17 +178,17 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
const __m128i vxap = _mm_set1_epi32(xap);
const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
- __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
__m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
- vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vCy));
}
sptr += sow;
- vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
vr = _mm_srli_epi32(vr, 24);
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 14a9429c71..62492980de 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -83,9 +83,10 @@ public:
struct QBackingstoreTextureInfo
{
- QWidget *widget; // may be null
+ void *source; // may be null
GLuint textureId;
QRect rect;
+ QRect clipRect;
QPlatformTextureList::Flags flags;
};
@@ -124,10 +125,10 @@ GLuint QPlatformTextureList::textureId(int index) const
return d->textures.at(index).textureId;
}
-QWidget *QPlatformTextureList::widget(int index)
+void *QPlatformTextureList::source(int index)
{
Q_D(const QPlatformTextureList);
- return d->textures.at(index).widget;
+ return d->textures.at(index).source;
}
QPlatformTextureList::Flags QPlatformTextureList::flags(int index) const
@@ -142,6 +143,12 @@ QRect QPlatformTextureList::geometry(int index) const
return d->textures.at(index).rect;
}
+QRect QPlatformTextureList::clipRect(int index) const
+{
+ Q_D(const QPlatformTextureList);
+ return d->textures.at(index).clipRect;
+}
+
void QPlatformTextureList::lock(bool on)
{
Q_D(QPlatformTextureList);
@@ -157,13 +164,15 @@ bool QPlatformTextureList::isLocked() const
return d->locked;
}
-void QPlatformTextureList::appendTexture(QWidget *widget, GLuint textureId, const QRect &geometry, Flags flags)
+void QPlatformTextureList::appendTexture(void *source, GLuint textureId, const QRect &geometry,
+ const QRect &clipRect, Flags flags)
{
Q_D(QPlatformTextureList);
QBackingstoreTextureInfo bi;
- bi.widget = widget;
+ bi.source = source;
bi.textureId = textureId;
bi.rect = geometry;
+ bi.clipRect = clipRect;
bi.flags = flags;
d->textures.append(bi);
}
@@ -198,7 +207,7 @@ void QPlatformTextureList::clear()
#ifndef QT_NO_OPENGL
-static QRect deviceRect(const QRect &rect, QWindow *window)
+static inline QRect deviceRect(const QRect &rect, QWindow *window)
{
QRect deviceRect(rect.topLeft() * window->devicePixelRatio(),
rect.size() * window->devicePixelRatio());
@@ -219,6 +228,32 @@ static QRegion deviceRegion(const QRegion &region, QWindow *window)
return deviceRegion;
}
+static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
+{
+ return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
+ topLeftRect.width(), topLeftRect.height());
+}
+
+static void blit(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
+ QOpenGLTextureBlitter *blitter)
+{
+ const QRect rectInWindow = textures->geometry(idx);
+ QRect clipRect = textures->clipRect(idx);
+ if (clipRect.isEmpty())
+ clipRect = QRect(QPoint(0, 0), rectInWindow.size());
+ const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
+ const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
+
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(deviceRect(clippedRectInWindow, window),
+ deviceWindowRect);
+
+ const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window),
+ deviceRect(rectInWindow, window).size(),
+ QOpenGLTextureBlitter::OriginBottomLeft);
+
+ blitter->blit(textures->textureId(idx), target, source);
+}
+
/*!
Flushes the given \a region from the specified \a window onto the
screen, and composes it with the specified \a textures.
@@ -254,15 +289,12 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
d_ptr->blitter->bind();
- QRect windowRect(QPoint(), window->size() * window->devicePixelRatio());
+ const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window);
// Textures for renderToTexture widgets.
for (int i = 0; i < textures->count(); ++i) {
- if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
- QRect targetRect = deviceRect(textures->geometry(i), window);
- QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, windowRect);
- d_ptr->blitter->blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
- }
+ if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
+ blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
}
funcs->glEnable(GL_BLEND);
@@ -272,6 +304,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// semi-transparency even when it is not wanted.
funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+ // Backingstore texture with the normal widgets.
GLuint textureId = 0;
QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft;
if (QPlatformGraphicsBuffer *graphicsBuffer = this->graphicsBuffer()) {
@@ -307,7 +340,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
origin = QOpenGLTextureBlitter::OriginBottomLeft;
textureId = d_ptr->textureId;
} else {
- // Backingstore texture with the normal widgets.
TextureFlags flags = 0;
textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &flags);
d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0;
@@ -316,7 +348,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
}
if (textureId) {
- QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), windowRect);
+ QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), deviceWindowRect);
if (d_ptr->needsSwizzle)
d_ptr->blitter->setSwizzleRB(true);
d_ptr->blitter->blit(textureId, target, origin);
@@ -326,11 +358,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) {
- if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
- QRect targetRect = deviceRect(textures->geometry(i), window);
- QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, windowRect);
- d_ptr->blitter->blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
- }
+ if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
+ blit(textures, i, window, deviceWindowRect, d_ptr->blitter);
}
funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index ae7314b6d0..eac97e9cf6 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -82,12 +82,14 @@ public:
bool isEmpty() const { return count() == 0; }
GLuint textureId(int index) const;
QRect geometry(int index) const;
- QWidget *widget(int index);
+ QRect clipRect(int index) const;
+ void *source(int index);
Flags flags(int index) const;
void lock(bool on);
bool isLocked() const;
- void appendTexture(QWidget *widget, GLuint textureId, const QRect &geometry, Flags flags = 0);
+ void appendTexture(void *source, GLuint textureId, const QRect &geometry,
+ const QRect &clipRect = QRect(), Flags flags = 0);
void clear();
Q_SIGNALS:
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index bb89eece4b..a83d56f31f 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -736,7 +736,10 @@ void QFtpDTP::socketConnectionClosed()
clearData();
}
- bytesFromSocket = socket->readAll();
+ if (socket->isOpen())
+ bytesFromSocket = socket->readAll();
+ else
+ bytesFromSocket.clear();
#if defined(QFTPDTP_DEBUG)
qDebug("QFtpDTP::connectState(CsClosed)");
#endif
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 361fcf7ca2..42920c96f2 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -46,6 +46,7 @@
//
#include <QtCore/QEventLoop>
#include <QtCore/QBuffer>
+#include <QtCore/QMutex>
#include "QtNetwork/qhostaddress.h"
#include "private/qabstractsocketengine_p.h"
#include <wrl.h>
diff --git a/src/network/ssl/qsslellipticcurve_dummy.cpp b/src/network/ssl/qsslellipticcurve_dummy.cpp
index d05c920a49..16b7a3cd00 100644
--- a/src/network/ssl/qsslellipticcurve_dummy.cpp
+++ b/src/network/ssl/qsslellipticcurve_dummy.cpp
@@ -57,7 +57,7 @@ QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
return QSslEllipticCurve();
}
-bool QSslEllipticCurve::isTlsNamedCurve() const
+bool QSslEllipticCurve::isTlsNamedCurve() const Q_DECL_NOTHROW
{
return false;
}
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 637c375311..9a1ae6e008 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -304,19 +304,23 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
for (int x = 0; x < maskWidth; ++x)
src[x] = -src[x]; // convert 0 and 1 into 0 and 255
}
- } else if (mask.format() == QImage::Format_RGB32) {
+ } else if (mask.depth() == 32) {
// Make the alpha component equal to the average of the RGB values.
// This is needed when drawing sub-pixel antialiased text on translucent targets.
for (int y = 0; y < maskHeight; ++y) {
quint32 *src = (quint32 *) mask.scanLine(y);
for (int x = 0; x < maskWidth; ++x) {
- uchar r = src[x] >> 16;
- uchar g = src[x] >> 8;
- uchar b = src[x];
- quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding.
+ int r = qRed(src[x]);
+ int g = qGreen(src[x]);
+ int b = qBlue(src[x]);
+ int avg;
+ if (mask.format() == QImage::Format_RGB32)
+ avg = (r + g + b + 1) / 3; // "+1" for rounding.
+ else // Format_ARGB_Premultiplied
+ avg = qAlpha(src[x]);
if (ctx->contextHandle()->isOpenGLES()) {
// swizzle the bits to accommodate for the GL_RGBA upload.
- src[x] = (avg << 24) | (quint32(r) << 0) | (quint32(g) << 8) | (quint32(b) << 16);
+ src[x] = (avg << 24) | (r << 0) | (g << 8) | (b << 16);
} else {
src[x] = (src[x] & 0x00ffffff) | (avg << 24);
}
@@ -325,7 +329,7 @@ void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed sub
}
funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
- if (mask.format() == QImage::Format_RGB32) {
+ if (mask.depth() == 32) {
GLenum format = GL_RGBA;
#if !defined(QT_OPENGL_ES_2)
if (!ctx->contextHandle()->isOpenGLES())
diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
index 3fd6c999a2..2e386532e2 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
@@ -169,6 +169,29 @@ struct BlendStateBinder
bool m_blend;
};
+static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
+{
+ return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
+ topLeftRect.width(), topLeftRect.height());
+}
+
+static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect, QOpenGLTextureBlitter *blitter)
+{
+ const QRect rectInWindow = textures->geometry(idx);
+ QRect clipRect = textures->clipRect(idx);
+ if (clipRect.isEmpty())
+ clipRect = QRect(QPoint(0, 0), rectInWindow.size());
+
+ const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
+ const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
+
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(clippedRectInWindow, targetWindowRect);
+ const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, rectInWindow.size(),
+ QOpenGLTextureBlitter::OriginBottomLeft);
+
+ blitter->blit(textures->textureId(idx), target, source);
+}
+
void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
{
const QPlatformTextureList *textures = window->textures();
@@ -181,7 +204,6 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
- QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
const float opacity = window->sourceWindow()->opacity();
if (opacity != currentOpacity) {
currentOpacity = opacity;
@@ -191,24 +213,25 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
if (textures->count() > 1 && i == textures->count() - 1) {
// Backingstore for a widget with QOpenGLWidget subwidgets
blend.set(true);
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else if (textures->count() == 1) {
// A regular QWidget window
const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0;
blend.set(translucent);
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
// Texture from an FBO belonging to a QOpenGLWidget
blend.set(false);
- m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
+ clippedBlit(textures, i, targetWindowRect, &m_blitter);
}
}
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
- QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
blend.set(true);
- m_blitter.blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
+ clippedBlit(textures, i, targetWindowRect, &m_blitter);
}
}
diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
index 3caec468a6..8ce1ed2d2b 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp
@@ -175,7 +175,8 @@ void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegi
m_textures->clear();
for (int i = 0; i < textures->count(); ++i)
- m_textures->appendTexture(textures->widget(i), textures->textureId(i), textures->geometry(i), textures->flags(i));
+ m_textures->appendTexture(textures->source(i), textures->textureId(i), textures->geometry(i),
+ textures->clipRect(i), textures->flags(i));
updateTexture();
m_textures->appendTexture(Q_NULLPTR, m_bsTexture, window->geometry());
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
index 9530dd83d0..a30d8f69c4 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.mm
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -85,8 +85,11 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
return self;
}
+static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
+
-(void)dealloc
{
+ listener = nil;
[super dealloc];
}
@@ -117,7 +120,6 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
}
@end
-static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0;
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 09a4c95469..dd2c37d914 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -81,7 +81,7 @@ QT_END_NAMESPACE
}
- (id) initWithMenu:(QCocoaMenu*) m;
-- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier;
+- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier;
@end
@@ -152,11 +152,20 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
// Change the private unicode keys to the ones used in setting the "Key Equivalents"
NSString *characters = qt_mac_removePrivateUnicode([event characters]);
- if ([self hasShortcut:menu
- forKey:characters
- // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
- forModifiers:([event modifierFlags] & (NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask))
- ]) {
+ // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
+ const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
+ if (NSMenuItem *menuItem = [self findItem:menu forKey:characters forModifiers:([event modifierFlags] & mask)]) {
+ if (!menuItem.target) {
+ // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder
+ // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel.
+ // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal
+ // (modal sheet, window modal, application modal).
+ // Whatever the current first responder is, let's give it a chance
+ // and do not touch the Qt's focusObject (which is different from some native view
+ // having a focus inside NSSave/OpenPanel.
+ return YES;
+ }
+
QObject *object = qApp->focusObject();
if (object) {
QChar ch;
@@ -194,22 +203,23 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
return NO;
}
-- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
+- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier
{
for (NSMenuItem *item in [menu itemArray]) {
if (![item isEnabled] || [item isHidden] || [item isSeparatorItem])
continue;
- if ([item hasSubmenu]
- && [self hasShortcut:[item submenu] forKey:key forModifiers:modifier])
- return YES;
+ if ([item hasSubmenu]) {
+ if (NSMenuItem *nested = [self findItem:[item submenu] forKey:key forModifiers:modifier])
+ return nested;
+ }
NSString *menuKey = [item keyEquivalent];
if (menuKey
&& NSOrderedSame == [menuKey compare:key]
&& modifier == [item keyEquivalentModifierMask])
- return YES;
+ return item;
}
- return NO;
+ return nil;
}
@end
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index cbe4227b63..86959869cc 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -799,9 +799,22 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
if (flags & Qt::FramelessWindowHint)
return styleMask;
if ((type & Qt::Popup) == Qt::Popup) {
- if (!windowIsPopupType(type))
- styleMask = (NSUtilityWindowMask | NSResizableWindowMask | NSClosableWindowMask |
- NSMiniaturizableWindowMask | NSTitledWindowMask);
+ if (!windowIsPopupType(type)) {
+ styleMask = NSUtilityWindowMask;
+ if (!(flags & Qt::CustomizeWindowHint)) {
+ styleMask |= NSResizableWindowMask | NSClosableWindowMask |
+ NSMiniaturizableWindowMask | NSTitledWindowMask;
+ } else {
+ if (flags & Qt::WindowMaximizeButtonHint)
+ styleMask |= NSResizableWindowMask;
+ if (flags & Qt::WindowTitleHint)
+ styleMask |= NSTitledWindowMask;
+ if (flags & Qt::WindowCloseButtonHint)
+ styleMask |= NSClosableWindowMask;
+ if (flags & Qt::WindowMinimizeButtonHint)
+ styleMask |= NSMiniaturizableWindowMask;
+ }
+ }
} else {
if (type == Qt::Window && !(flags & Qt::CustomizeWindowHint)) {
styleMask = (NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index d439196dc1..16c05329de 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -358,10 +358,10 @@ public:
} else if (path.isRect() && (q->state()->matrix.type() <= QTransform::TxScale)) {
const qreal * const points = path.points();
D2D_RECT_F rect = {
- points[0], // left
- points[1], // top
- points[2], // right,
- points[5] // bottom
+ FLOAT(points[0]), // left
+ FLOAT(points[1]), // top
+ FLOAT(points[2]), // right,
+ FLOAT(points[5]) // bottom
};
dc()->PushAxisAlignedClip(rect, antialiasMode());
@@ -918,13 +918,13 @@ public:
DWRITE_GLYPH_RUN glyphRun = {
fontFace, // IDWriteFontFace *fontFace;
- fontDef.pixelSize, // FLOAT fontEmSize;
- numGlyphs, // UINT32 glyphCount;
+ FLOAT(fontDef.pixelSize), // FLOAT fontEmSize;
+ UINT32(numGlyphs), // UINT32 glyphCount;
glyphIndices, // const UINT16 *glyphIndices;
glyphAdvances, // const FLOAT *glyphAdvances;
glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets;
FALSE, // BOOL isSideways;
- rtl ? 1 : 0 // UINT32 bidiLevel;
+ rtl ? 1u : 0u // UINT32 bidiLevel;
};
const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing)
@@ -1393,8 +1393,8 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &r)
D2D1_ELLIPSE ellipse = {
to_d2d_point_2f(p),
- r.width() / 2.0,
- r.height() / 2.0
+ FLOAT(r.width() / 2.0),
+ FLOAT(r.height() / 2.0)
};
if (d->brush.brush)
@@ -1421,8 +1421,8 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRect &r)
D2D1_ELLIPSE ellipse = {
to_d2d_point_2f(p),
- r.width() / 2.0,
- r.height() / 2.0
+ FLOAT(r.width() / 2.0),
+ FLOAT(r.height() / 2.0)
};
if (d->brush.brush)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index e762eab711..ba23526447 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -163,7 +163,7 @@ void QWindowsDirect2DWindow::present(const QRegion &region)
const SIZE size = { bounds.width(), bounds.height() };
const POINT ptDst = { bounds.x(), bounds.y() };
const POINT ptSrc = { 0, 0 };
- const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255.0 * opacity(), AC_SRC_ALPHA };
+ const BLENDFUNCTION blend = { AC_SRC_OVER, 0, BYTE(255.0 * opacity()), AC_SRC_ALPHA };
const QRect r = region.boundingRect();
const RECT dirty = { r.left(), r.top(), r.left() + r.width(), r.top() + r.height() };
UPDATELAYEREDWINDOWINFO info = { sizeof(UPDATELAYEREDWINDOWINFO), NULL,
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index 30fdce9fd3..c0d51c94a5 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -35,6 +35,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
#include <QtGui/QOpenGLContext>
#include <QtPlatformSupport/private/qeglplatformcursor_p.h>
#include <QtPlatformSupport/private/qeglconvenience_p.h>
@@ -106,6 +107,7 @@ void QEglFSWindow::create()
if (isRaster()) {
QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
+ context->setShareContext(qt_gl_global_share_context());
context->setFormat(m_format);
context->setScreen(window()->screen());
if (!context->create())
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index 99c44c69ef..5ed8d30e67 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -102,7 +102,7 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out
HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version)
{
- *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR));
+ *version = ::SysAllocString(TEXT(QT_VERSION_STR));
return S_OK;
}
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 0184877fdd..06c9985cac 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -39,7 +39,6 @@
#include <QtGui/QOpenGLContext>
#if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC)
-# define EGL_EGLEXT_PROTOTYPES
# include <QtANGLE/EGL/eglext.h>
#endif
@@ -137,7 +136,6 @@ bool QWindowsLibEGL::init()
eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError);
eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay);
- eglGetPlatformDisplayEXT = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLenum platform, void *native_display, const EGLint *attrib_list)), eglGetPlatformDisplayEXT);
eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize);
eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate);
eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig);
@@ -156,7 +154,15 @@ bool QWindowsLibEGL::init()
eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
- return eglGetError && eglGetDisplay && eglInitialize;
+ if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
+ return false;
+
+ eglGetPlatformDisplayEXT = 0;
+#ifdef EGL_ANGLE_platform_angle
+ eglGetPlatformDisplayEXT = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLenum, void *, const EGLint *)>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
+#endif
+
+ return true;
}
#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
@@ -360,7 +366,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
EGLDisplay display = EGL_NO_DISPLAY;
EGLint major = 0;
EGLint minor = 0;
-#ifdef EGL_ANGLE_platform_angle_opengl
+#ifdef EGL_ANGLE_platform_angle
if (libEGL.eglGetPlatformDisplayEXT
&& (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
const EGLint anglePlatformAttributes[][5] = {
@@ -384,7 +390,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
}
}
}
-#else // EGL_ANGLE_platform_angle_opengl
+#else // EGL_ANGLE_platform_angle
Q_UNUSED(preferredType)
#endif
if (display == EGL_NO_DISPLAY)
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 2b249348c3..d8302c97a7 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -46,7 +46,6 @@ struct QWindowsLibEGL
EGLint (EGLAPIENTRY * eglGetError)(void);
EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id);
- EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor);
EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy);
EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list,
@@ -74,6 +73,8 @@ struct QWindowsLibEGL
EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname);
+ EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
+
private:
#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
void *resolve(const char *name);
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 9691156403..6e58c55bbe 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -34,6 +34,7 @@
#include "qwindowsnativeinterface.h"
#include "qwindowswindow.h"
#include "qwindowscontext.h"
+#include "qwindowsfontdatabase.h"
#include "qwindowsopenglcontext.h"
#include "qwindowsopengltester.h"
#include "qwindowsintegration.h"
@@ -222,6 +223,11 @@ int QWindowsNativeInterface::registerMimeType(const QString &mimeType)
return QWindowsMime::registerMimeType(mimeType);
}
+QFont QWindowsNativeInterface::logFontToQFont(const void *logFont, int verticalDpi)
+{
+ return QWindowsFontDatabase::LOGFONT_to_QFont(*reinterpret_cast<const LOGFONT *>(logFont), verticalDpi);
+}
+
QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const
{
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index be8418b769..97839ae1ae 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -34,6 +34,7 @@
#ifndef QWINDOWSNATIVEINTERFACE_H
#define QWINDOWSNATIVEINTERFACE_H
+#include <QtGui/qfont.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
QT_BEGIN_NAMESPACE
@@ -77,6 +78,7 @@ public:
Q_INVOKABLE void registerWindowsMime(void *mimeIn);
Q_INVOKABLE void unregisterWindowsMime(void *mime);
Q_INVOKABLE int registerMimeType(const QString &mimeType);
+ Q_INVOKABLE QFont logFontToQFont(const void *logFont, int verticalDpi);
bool asyncExpose() const;
void setAsyncExpose(bool value);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 923040fd71..543c08135f 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -438,6 +438,8 @@ QDebug operator<<(QDebug debug, const WindowCreationData &d)
// Fix top level window flags in case only the type flags are passed.
static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
{
+ // Not supported on Windows, also do correction when it is set.
+ flags &= ~Qt::WindowFullscreenButtonHint;
switch (flags) {
case Qt::Window:
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 92d064df9b..80c844e658 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -70,7 +70,6 @@
#endif
#if defined(XCB_USE_XINPUT2)
-#include <X11/extensions/XInput2.h>
#include <X11/extensions/XI2proto.h>
#endif
@@ -457,6 +456,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
, m_focusWindow(0)
, m_systemTrayTracker(0)
, m_glIntegration(Q_NULLPTR)
+ , m_xiGrab(false)
{
#ifdef XCB_USE_XLIB
Display *dpy = XOpenDisplay(m_displayName.constData());
@@ -909,7 +909,7 @@ static Qt::MouseButtons translateMouseButtons(int s)
return ret;
}
-static Qt::MouseButton translateMouseButton(xcb_button_t s)
+Qt::MouseButton QXcbConnection::translateMouseButton(xcb_button_t s)
{
switch (s) {
case 1: return Qt::LeftButton;
@@ -944,39 +944,6 @@ static Qt::MouseButton translateMouseButton(xcb_button_t s)
}
}
-void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev)
-{
- xcb_button_press_event_t *event = (xcb_button_press_event_t *)ev;
-
- // the event explicitly contains the state of the three first buttons,
- // the rest we need to manage ourselves
- m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
- m_buttons |= translateMouseButton(event->detail);
- qCDebug(lcQpaXInput, "xcb: pressed mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons));
-}
-
-void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev)
-{
- xcb_button_release_event_t *event = (xcb_button_release_event_t *)ev;
-
- // the event explicitly contains the state of the three first buttons,
- // the rest we need to manage ourselves
- m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
- m_buttons &= ~translateMouseButton(event->detail);
- qCDebug(lcQpaXInput, "xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons));
-}
-
-void QXcbConnection::handleMotionNotify(xcb_generic_event_t *ev)
-{
- xcb_motion_notify_event_t *event = (xcb_motion_notify_event_t *)ev;
-
- m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state);
-#ifdef Q_XCB_DEBUG
- qCDebug(lcQpaXInput, "xcb: moved mouse to %4d, %4d; button state %X",
- event->event_x, event->event_y, static_cast<unsigned int>(m_buttons));
-#endif
-}
-
#ifndef QT_NO_XKB
namespace {
typedef union {
@@ -1018,18 +985,35 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
switch (response_type) {
case XCB_EXPOSE:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
- case XCB_BUTTON_PRESS:
- m_keyboard->updateXKBStateFromCore(((xcb_button_press_event_t *)event)->state);
- handleButtonPress(event);
+
+ // press/release/motion is only delivered here when XI 2.2+ is _not_ in use
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event;
+ m_keyboard->updateXKBStateFromCore(ev->state);
+ // the event explicitly contains the state of the three first buttons,
+ // the rest we need to manage ourselves
+ m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+ m_buttons |= translateMouseButton(ev->detail);
+ qCDebug(lcQpaXInput, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
- case XCB_BUTTON_RELEASE:
- m_keyboard->updateXKBStateFromCore(((xcb_button_release_event_t *)event)->state);
- handleButtonRelease(event);
+ }
+ case XCB_BUTTON_RELEASE: {
+ xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event;
+ m_keyboard->updateXKBStateFromCore(ev->state);
+ m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+ m_buttons &= ~translateMouseButton(ev->detail);
+ qCDebug(lcQpaXInput, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
- case XCB_MOTION_NOTIFY:
- m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state);
- handleMotionNotify(event);
+ }
+ case XCB_MOTION_NOTIFY: {
+ xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event;
+ m_keyboard->updateXKBStateFromCore(ev->state);
+ m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+ qCDebug(lcQpaXInput, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y,
+ ev->detail, static_cast<unsigned int>(m_buttons));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
+ }
+
case XCB_CONFIGURE_NOTIFY:
HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
case XCB_MAP_NOTIFY:
@@ -1090,6 +1074,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
break;
#if defined(XCB_USE_XINPUT2)
case XCB_GE_GENERIC:
+ // Here the windowEventListener is invoked from xi2HandleEvent()
if (m_xi2Enabled)
xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
break;
@@ -1931,6 +1916,12 @@ void QXcbConnection::initializeXKB()
#endif
}
+bool QXcbConnection::xi2MouseEvents() const
+{
+ static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
+ return mouseViaXI2;
+}
+
#if defined(XCB_USE_XINPUT2)
static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number)
{
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index e4274eca4d..2005ae0701 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -69,7 +69,8 @@
#endif
#endif
struct XInput2TouchDeviceData;
-#endif
+#endif // XCB_USE_XINPUT2
+
struct xcb_randr_get_output_info_reply_t;
//#define Q_XCB_DEBUG
@@ -347,6 +348,7 @@ public:
virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {}
virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {}
virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {}
+ virtual void handleXIMouseEvent(xcb_ge_event_t *) {}
virtual QXcbWindow *toWindow() { return 0; }
};
@@ -413,14 +415,14 @@ public:
void xi2Select(xcb_window_t window);
#endif
#ifdef XCB_USE_XINPUT21
- bool isUsingXInput21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
+ bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
#else
- bool isUsingXInput21() const { return false; }
+ bool isAtLeastXI21() const { return false; }
#endif
#ifdef XCB_USE_XINPUT22
- bool isUsingXInput22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
+ bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
#else
- bool isUsingXInput22() const { return false; }
+ bool isAtLeastXI22() const { return false; }
#endif
void sync();
@@ -457,7 +459,9 @@ public:
xcb_timestamp_t getTimestamp();
+ void setButton(Qt::MouseButton button, bool down) { if (down) m_buttons |= button; else m_buttons &= ~button; }
Qt::MouseButtons buttons() const { return m_buttons; }
+ Qt::MouseButton translateMouseButton(xcb_button_t s);
QXcbWindow *focusWindow() const { return m_focusWindow; }
void setFocusWindow(QXcbWindow *);
@@ -477,11 +481,19 @@ public:
void handleEnterEvent(const xcb_enter_notify_event_t *);
#endif
+#ifdef XCB_USE_XINPUT22
+ bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab);
+#endif
+ Qt::MouseButton xiToQtMouseButton(uint32_t b);
+
QXcbEventReader *eventReader() const { return m_reader; }
bool canGrab() const { return m_canGrabServer; }
QXcbGlIntegration *glIntegration() const { return m_glIntegration; }
+
+ bool xi2MouseEvents() const;
+
protected:
bool event(QEvent *e) Q_DECL_OVERRIDE;
@@ -509,9 +521,6 @@ private:
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
void initializeScreens();
void updateScreens(const xcb_randr_notify_event_t *event);
- void handleButtonPress(xcb_generic_event_t *event);
- void handleButtonRelease(xcb_generic_event_t *event);
- void handleMotionNotify(xcb_generic_event_t *event);
bool m_xi2Enabled;
int m_xi2Minor;
@@ -524,6 +533,9 @@ private:
void xi2HandleHierachyEvent(void *event);
void xi2HandleDeviceChangedEvent(void *event);
int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
+#ifdef XCB_USE_XINPUT22
+ void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
+#endif // XCB_USE_XINPUT22
#ifndef QT_NO_TABLETEVENT
struct TabletData {
TabletData() : deviceId(0), pointerType(QTabletEvent::UnknownPointer),
@@ -543,10 +555,10 @@ private:
};
QHash<int, ValuatorClassInfo> valuatorInfo;
};
- bool xi2HandleTabletEvent(void *event, TabletData *tabletData);
+ bool xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener);
void xi2ReportTabletEvent(TabletData &tabletData, void *event);
QVector<TabletData> m_tabletData;
-#endif
+#endif // !QT_NO_TABLETEVENT
struct ScrollingDevice {
ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { }
int deviceId;
@@ -559,9 +571,7 @@ private:
void updateScrollingDevice(ScrollingDevice& scrollingDevice, int num_classes, void *classes);
void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
QHash<int, ScrollingDevice> m_scrollingDevices;
-#endif // XCB_USE_XINPUT2
-#if defined(XCB_USE_XINPUT2)
static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value);
static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode);
#endif
@@ -633,6 +643,7 @@ private:
QByteArray m_startupId;
QXcbSystemTrayTracker *m_systemTrayTracker;
QXcbGlIntegration *m_glIntegration;
+ bool m_xiGrab;
friend class QXcbEventReader;
};
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index c43816fa05..0e8a162a7d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -43,7 +43,6 @@
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XI2proto.h>
-#define FINGER_MAX_WIDTH_MM 10
struct XInput2TouchDeviceData {
XInput2TouchDeviceData()
@@ -276,34 +275,37 @@ void QXcbConnection::xi2Select(xcb_window_t window)
unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask);
#ifdef XCB_USE_XINPUT22
- if (isUsingXInput22()) {
+ if (isAtLeastXI22()) {
bitMask |= XI_TouchBeginMask;
bitMask |= XI_TouchUpdateMask;
bitMask |= XI_TouchEndMask;
+ bitMask |= XI_PropertyEventMask; // for tablets
+ if (xi2MouseEvents()) {
+ // We want both mouse and touch through XI2 if touch is supported (>= 2.2).
+ // The plain xcb press and motion events will not be delivered after this.
+ bitMask |= XI_ButtonPressMask;
+ bitMask |= XI_ButtonReleaseMask;
+ bitMask |= XI_MotionMask;
+ qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion events in addition to touch");
+ }
XIEventMask mask;
mask.mask_len = sizeof(bitMask);
mask.mask = xiBitMask;
- if (!m_touchDevices.isEmpty()) {
- // If we select for touch events on the master pointer, XInput2
- // will not synthesize mouse events. This means Qt must do it,
- // which is also preferable, since Qt can control better when
- // to do so.
- mask.deviceid = XIAllMasterDevices;
- Status result = XISelectEvents(xDisplay, window, &mask, 1);
- if (result != Success)
- qCDebug(lcQpaXInput, "XInput 2.2: failed to select touch events, window %x, result %d", window, result);
- }
+ // When xi2MouseEvents() is true (the default), pointer emulation for touch and tablet
+ // events will get disabled. This is preferable for touch, as Qt Quick handles touch events
+ // directly while for others QtGui synthesizes mouse events, not so much for tablets. For
+ // the latter we will synthesize the events ourselves.
+ mask.deviceid = XIAllMasterDevices;
+ Status result = XISelectEvents(xDisplay, window, &mask, 1);
+ if (result != Success)
+ qCDebug(lcQpaXInput, "XInput 2.2: failed to select pointer/touch events, window %x, result %d", window, result);
}
#endif // XCB_USE_XINPUT22
+ const bool pointerSelected = isAtLeastXI22() && xi2MouseEvents();
QSet<int> tabletDevices;
#ifndef QT_NO_TABLETEVENT
- // For each tablet, select some additional event types.
- // Press, motion, etc. events must never be selected for _all_ devices
- // as that would render the standard XCB_MOTION_NOTIFY and
- // similar handlers useless and we have no intention to infect
- // all the pure xcb code with Xlib-based XI2.
- if (!m_tabletData.isEmpty()) {
+ if (!m_tabletData.isEmpty() && !pointerSelected) {
unsigned int tabletBitMask;
unsigned char *xiTabletBitMask = reinterpret_cast<unsigned char *>(&tabletBitMask);
QVector<XIEventMask> xiEventMask(m_tabletData.count());
@@ -324,7 +326,8 @@ void QXcbConnection::xi2Select(xcb_window_t window)
#ifdef XCB_USE_XINPUT21
// Enable each scroll device
- if (!m_scrollingDevices.isEmpty()) {
+ if (!m_scrollingDevices.isEmpty() && !pointerSelected) {
+ // Only when XI2 mouse events are not enabled, otherwise motion and release are selected already.
QVector<XIEventMask> xiEventMask(m_scrollingDevices.size());
unsigned int scrollBitMask;
unsigned char *xiScrollBitMask = reinterpret_cast<unsigned char *>(&scrollBitMask);
@@ -426,7 +429,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
dev->size.width() > 10000 || dev->size.height() > 10000)
dev->size = QSizeF(130, 110);
}
- if (!isUsingXInput22() || type == QTouchDevice::TouchPad)
+ if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
caps |= QTouchDevice::MouseEmulation;
if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
@@ -448,7 +451,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
}
#if defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT)
-static qreal fixed1616ToReal(FP1616 val)
+static inline qreal fixed1616ToReal(FP1616 val)
{
return qreal(val) / 0x10000;
}
@@ -469,163 +472,280 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) {
xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ int sourceDeviceId = xiEvent->deviceid; // may be the master id
+ xXIDeviceEvent *xiDeviceEvent = 0;
+ QXcbWindowEventListener *eventListener = 0;
- if (xiEvent->evtype == XI_HierarchyChanged) {
+ switch (xiEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ case XI_TouchBegin:
+ case XI_TouchUpdate:
+ case XI_TouchEnd:
+ {
+ xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ eventListener = windowEventListenerFromId(xiDeviceEvent->event);
+ if (eventListener) {
+ long result = 0;
+ if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
+ return;
+ }
+ sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
+ break;
+ }
+ case XI_HierarchyChanged:
xi2HandleHierachyEvent(xiEvent);
return;
- }
- if (xiEvent->evtype == XI_DeviceChanged) {
+ case XI_DeviceChanged:
xi2HandleDeviceChangedEvent(xiEvent);
return;
+ default:
+ break;
}
#ifndef QT_NO_TABLETEVENT
for (int i = 0; i < m_tabletData.count(); ++i) {
- if (m_tabletData.at(i).deviceId == xiEvent->deviceid) {
- if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i]))
+ if (m_tabletData.at(i).deviceId == sourceDeviceId) {
+ if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener))
return;
}
}
#endif // QT_NO_TABLETEVENT
#ifdef XCB_USE_XINPUT21
- QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->deviceid);
+ QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
if (device != m_scrollingDevices.end())
xi2HandleScrollEvent(xiEvent, device.value());
#endif // XCB_USE_XINPUT21
#ifdef XCB_USE_XINPUT22
- if (xiEvent->evtype == XI_TouchBegin || xiEvent->evtype == XI_TouchUpdate || xiEvent->evtype == XI_TouchEnd) {
- xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
- if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f",
- event->event_type, xiEvent->sequenceNumber, xiDeviceEvent->detail,
- fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
- fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y) );
-
- if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
- XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
- Q_ASSERT(dev);
- const bool firstTouch = m_touchPoints.isEmpty();
- if (xiEvent->evtype == XI_TouchBegin) {
- QWindowSystemInterface::TouchPoint tp;
- tp.id = xiDeviceEvent->detail % INT_MAX;
- tp.state = Qt::TouchPointPressed;
- tp.pressure = -1.0;
- m_touchPoints[tp.id] = tp;
- }
- QWindowSystemInterface::TouchPoint &touchPoint = m_touchPoints[xiDeviceEvent->detail];
- qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
- qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
- qreal nx = -1.0, ny = -1.0, w = 0.0, h = 0.0;
- QXcbScreen* screen = m_screens.at(0);
- for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
- XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
- if (classinfo->type == XIValuatorClass) {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
- int n = vci->number;
- double value;
- if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
- continue;
- if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput, " valuator %20s value %lf from range %lf -> %lf",
- atomName(vci->label).constData(), value, vci->min, vci->max );
- if (vci->label == atom(QXcbAtom::RelX)) {
- nx = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::RelY)) {
- ny = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsX)) {
- nx = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsY)) {
- ny = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
- nx = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
- ny = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
- // Convert the value within its range as a fraction of a finger's max (contact patch)
- // width in mm, and from there to pixels depending on screen resolution
- w = valuatorNormalized(value, vci) * FINGER_MAX_WIDTH_MM *
- screen->geometry().width() / screen->physicalSize().width();
- } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) {
- h = valuatorNormalized(value, vci) * FINGER_MAX_WIDTH_MM *
- screen->geometry().height() / screen->physicalSize().height();
- } else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
- vci->label == atom(QXcbAtom::AbsPressure)) {
- touchPoint.pressure = valuatorNormalized(value, vci);
- }
- }
- }
- // If any value was not updated, use the last-known value.
- if (nx == -1.0) {
- x = touchPoint.area.center().x();
- nx = x / screen->geometry().width();
- }
- if (ny == -1.0) {
- y = touchPoint.area.center().y();
- ny = y / screen->geometry().height();
- }
- if (xiEvent->evtype != XI_TouchEnd) {
- if (w == 0.0)
- w = touchPoint.area.width();
- if (h == 0.0)
- h = touchPoint.area.height();
- }
-
- switch (xiEvent->evtype) {
- case XI_TouchBegin:
- if (firstTouch) {
- dev->firstPressedPosition = QPointF(x, y);
- dev->firstPressedNormalPosition = QPointF(nx, ny);
- }
- dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y));
- break;
- case XI_TouchUpdate:
- if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
- qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
- dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
- qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
- dev->size.height() * screen->geometry().height() / screen->physicalSize().height();
- x = dev->firstPressedPosition.x() + dx;
- y = dev->firstPressedPosition.y() + dy;
- touchPoint.state = Qt::TouchPointMoved;
- } else if (touchPoint.area.center() != QPoint(x, y)) {
- touchPoint.state = Qt::TouchPointMoved;
- dev->pointPressedPosition[touchPoint.id] = QPointF(x, y);
- }
- break;
- case XI_TouchEnd:
- touchPoint.state = Qt::TouchPointReleased;
- if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
- qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
- dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
- qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
- dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
- x = dev->firstPressedPosition.x() + dx;
- y = dev->firstPressedPosition.y() + dy;
- }
- dev->pointPressedPosition.remove(touchPoint.id);
- }
- touchPoint.area = QRectF(x - w/2, y - h/2, w, h);
- touchPoint.normalPosition = QPointF(nx, ny);
+ if (xiDeviceEvent) {
+ switch (xiDeviceEvent->evtype) {
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ if (xi2MouseEvents() && eventListener)
+ eventListener->handleXIMouseEvent(event);
+ break;
+ case XI_TouchBegin:
+ case XI_TouchUpdate:
+ case XI_TouchEnd:
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
- qCDebug(lcQpaXInput) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition <<
- " area " << touchPoint.area << " pressure " << touchPoint.pressure;
- QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiEvent->time, dev->qtTouchDevice, m_touchPoints.values());
- if (touchPoint.state == Qt::TouchPointReleased)
- // If a touchpoint was released, we can forget it, because the ID won't be reused.
- m_touchPoints.remove(touchPoint.id);
- else
- // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent
- // with this touch point if the next XI2 event is about a different touch point.
- touchPoint.state = Qt::TouchPointStationary;
+ qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
+ event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
+ fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
+ fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
+ if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
+ xi2ProcessTouch(xiDeviceEvent, platformWindow);
+ break;
}
}
#endif // XCB_USE_XINPUT22
}
}
+#ifdef XCB_USE_XINPUT22
+void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow)
+{
+ xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent);
+ XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
+ Q_ASSERT(dev);
+ const bool firstTouch = m_touchPoints.isEmpty();
+ if (xiDeviceEvent->evtype == XI_TouchBegin) {
+ QWindowSystemInterface::TouchPoint tp;
+ tp.id = xiDeviceEvent->detail % INT_MAX;
+ tp.state = Qt::TouchPointPressed;
+ tp.pressure = -1.0;
+ m_touchPoints[tp.id] = tp;
+ }
+ QWindowSystemInterface::TouchPoint &touchPoint = m_touchPoints[xiDeviceEvent->detail];
+ qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
+ qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
+ qreal nx = -1.0, ny = -1.0, d = 0.0;
+ QXcbScreen* screen = m_screens.at(0);
+ for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
+ XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
+ if (classinfo->type == XIValuatorClass) {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ int n = vci->number;
+ double value;
+ if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
+ continue;
+ if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
+ qCDebug(lcQpaXInput, " valuator %20s value %lf from range %lf -> %lf",
+ atomName(vci->label).constData(), value, vci->min, vci->max );
+ if (vci->label == atom(QXcbAtom::RelX)) {
+ nx = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::RelY)) {
+ ny = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsX)) {
+ nx = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsY)) {
+ ny = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
+ nx = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
+ ny = valuatorNormalized(value, vci);
+ } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
+ d = valuatorNormalized(value, vci) * screen->geometry().width();
+ } else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
+ vci->label == atom(QXcbAtom::AbsPressure)) {
+ touchPoint.pressure = valuatorNormalized(value, vci);
+ }
+ }
+ }
+ // If any value was not updated, use the last-known value.
+ if (nx == -1.0) {
+ x = touchPoint.area.center().x();
+ nx = x / screen->geometry().width();
+ }
+ if (ny == -1.0) {
+ y = touchPoint.area.center().y();
+ ny = y / screen->geometry().height();
+ }
+ if (xiDeviceEvent->evtype != XI_TouchEnd) {
+ if (d == 0.0)
+ d = touchPoint.area.width();
+ }
+
+ switch (xiDeviceEvent->evtype) {
+ case XI_TouchBegin:
+ if (firstTouch) {
+ dev->firstPressedPosition = QPointF(x, y);
+ dev->firstPressedNormalPosition = QPointF(nx, ny);
+ }
+ dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y));
+
+ // Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence
+ // will get replayed when the grab ends.
+ if (m_xiGrab) {
+ // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2)
+ // http://lists.x.org/archives/xorg-devel/2014-July/043059.html
+#ifndef LIBXI_MAJOR
+ static bool allowTouchWarningShown = false;
+ if (!allowTouchWarningShown) {
+ allowTouchWarningShown = true;
+ qWarning("Skipping XIAllowTouchEvents() because it was not possible to detect libXi version at build time."
+ " Minimum libXi version required is 1.7.4."
+ " Expect issues with touch behavior.");
+ }
+#elif LIBXI_MAJOR == 1 && (LIBXI_MINOR < 7 || (LIBXI_MINOR == 7 && LIBXI_PATCH < 4))
+ static bool allowTouchWarningShown = false;
+ if (!allowTouchWarningShown) {
+ allowTouchWarningShown = true;
+ qWarning("Skipping XIAllowTouchEvents() due to not having libXi >= 1.7.4."
+ " libXi version at build time was %d.%d.%d."
+ " Expect issues with touch behavior.", LIBXI_MAJOR, LIBXI_MINOR, LIBXI_PATCH);
+ }
+#else
+ XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid,
+ xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch);
+#endif
+ }
+ break;
+ case XI_TouchUpdate:
+ if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
+ qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
+ dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+ qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
+ dev->size.height() * screen->geometry().height() / screen->physicalSize().height();
+ x = dev->firstPressedPosition.x() + dx;
+ y = dev->firstPressedPosition.y() + dy;
+ touchPoint.state = Qt::TouchPointMoved;
+ } else if (touchPoint.area.center() != QPoint(x, y)) {
+ touchPoint.state = Qt::TouchPointMoved;
+ dev->pointPressedPosition[touchPoint.id] = QPointF(x, y);
+ }
+ break;
+ case XI_TouchEnd:
+ touchPoint.state = Qt::TouchPointReleased;
+ if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
+ qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
+ dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+ qreal dy = (ny - dev->firstPressedNormalPosition.y()) *
+ dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
+ x = dev->firstPressedPosition.x() + dx;
+ y = dev->firstPressedPosition.y() + dy;
+ }
+ dev->pointPressedPosition.remove(touchPoint.id);
+ }
+ touchPoint.area = QRectF(x - d/2, y - d/2, d, d);
+ touchPoint.normalPosition = QPointF(nx, ny);
+
+ if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
+ qCDebug(lcQpaXInput) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition <<
+ " area " << touchPoint.area << " pressure " << touchPoint.pressure;
+ QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiDeviceEvent->time, dev->qtTouchDevice, m_touchPoints.values());
+ if (touchPoint.state == Qt::TouchPointReleased)
+ // If a touchpoint was released, we can forget it, because the ID won't be reused.
+ m_touchPoints.remove(touchPoint.id);
+ else
+ // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent
+ // with this touch point if the next XI2 event is about a different touch point.
+ touchPoint.state = Qt::TouchPointStationary;
+}
+
+bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
+{
+ if (grab && !canGrab())
+ return false;
+
+ int num_devices = 0;
+ Display *xDisplay = static_cast<Display *>(xlib_display());
+ XIDeviceInfo *info = XIQueryDevice(xDisplay, XIAllMasterDevices, &num_devices);
+ if (!info)
+ return false;
+
+ XIEventMask evmask;
+ unsigned char mask[XIMaskLen(XI_LASTEVENT)];
+ evmask.mask = mask;
+ evmask.mask_len = sizeof(mask);
+ memset(mask, 0, sizeof(mask));
+ evmask.deviceid = XIAllMasterDevices;
+
+ XISetMask(mask, XI_ButtonPress);
+ XISetMask(mask, XI_ButtonRelease);
+ XISetMask(mask, XI_Motion);
+ XISetMask(mask, XI_TouchBegin);
+ XISetMask(mask, XI_TouchUpdate);
+ XISetMask(mask, XI_TouchEnd);
+
+ bool grabbed = true;
+ for (int i = 0; i < num_devices; i++) {
+ int id = info[i].deviceid, n = 0;
+ XIDeviceInfo *deviceInfo = XIQueryDevice(xDisplay, id, &n);
+ if (deviceInfo) {
+ const bool grabbable = deviceInfo->use != XIMasterKeyboard;
+ XIFreeDeviceInfo(deviceInfo);
+ if (!grabbable)
+ continue;
+ }
+ if (!grab) {
+ Status result = XIUngrabDevice(xDisplay, id, CurrentTime);
+ if (result != Success) {
+ grabbed = false;
+ qCDebug(lcQpaXInput, "XInput 2.2: failed to ungrab events for device %d (result %d)", id, result);
+ }
+ } else {
+ Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, XIGrabModeAsync,
+ XIGrabModeAsync, False, &evmask);
+ if (result != Success) {
+ grabbed = false;
+ qCDebug(lcQpaXInput, "XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result);
+ }
+ }
+ }
+
+ XIFreeDeviceInfo(info);
+
+ m_xiGrab = grabbed;
+
+ return grabbed;
+}
+#endif // XCB_USE_XINPUT22
+
void QXcbConnection::xi2HandleHierachyEvent(void *event)
{
xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event);
@@ -794,7 +914,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
#endif // XCB_USE_XINPUT21
}
-static Qt::MouseButton xiToQtMouseButton(uint32_t b) {
+Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b)
+{
switch (b) {
case 1: return Qt::LeftButton;
case 2: return Qt::MiddleButton;
@@ -841,20 +962,29 @@ static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) {
}
#ifndef QT_NO_TABLETEVENT
-bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
+bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener)
{
bool handled = true;
Display *xDisplay = static_cast<Display *>(m_xlib_display);
xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event);
+ xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(xiEvent);
+
+#ifdef XCB_USE_XINPUT22
+ // Synthesize mouse events since otherwise there are no mouse events from
+ // the pen on the XI 2.2+ path.
+ if (xi2MouseEvents() && eventListener)
+ eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t *>(event));
+#endif
+
switch (xiEvent->evtype) {
case XI_ButtonPress: {
- Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+ Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
tabletData->buttons |= b;
xi2ReportTabletEvent(*tabletData, xiEvent);
break;
}
case XI_ButtonRelease: {
- Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail);
+ Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
tabletData->buttons ^= b;
xi2ReportTabletEvent(*tabletData, xiEvent);
break;
@@ -917,7 +1047,7 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData)
// TODO maybe have a hash of tabletData->deviceId to device data so we can
// look up the tablet name here, and distinguish multiple tablets
qCDebug(lcQpaXInput, "XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d",
- ev->deviceid, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
+ tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool);
}
XFree(data);
@@ -981,7 +1111,7 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event)
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
- ev->deviceid, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
+ tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail,
fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y),
fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y),
(int)tabletData.buttons, pressure, xTilt, yTilt, rotation);
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 6a9ef5869e..2d96ed1c21 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -47,6 +47,12 @@
#include <stdio.h>
#include <X11/keysym.h>
+#ifdef XCB_USE_XINPUT22
+#include <X11/extensions/XI2proto.h>
+#undef KeyPress
+#undef KeyRelease
+#endif
+
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
@@ -791,6 +797,31 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
}
}
+void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
+{
+#ifdef XCB_USE_XINPUT22
+ if (m_config && !connection()->hasXKB()) {
+ xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
+ xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
+ const xkb_state_component newState = xkb_state_update_mask(xkb_state,
+ mods->base_mods,
+ mods->latched_mods,
+ mods->locked_mods,
+ group->base_group,
+ group->latched_group,
+ group->locked_group);
+
+ if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
+ //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
+ }
+ }
+#else
+ Q_UNUSED(modInfo);
+ Q_UNUSED(groupInfo);
+ Q_ASSERT(false); // this can't be
+#endif
+}
+
quint32 QXcbKeyboard::xkbModMask(quint16 state)
{
quint32 xkb_mask = 0;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 2281674e2f..d2e37d624c 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -68,6 +68,7 @@ public:
void updateXKBMods();
quint32 xkbModMask(quint16 state);
void updateXKBStateFromCore(quint16 state);
+ void updateXKBStateFromXI(void *modInfo, void *groupInfo);
#ifndef QT_NO_XKB
// when XKEYBOARD is present on the X server
int coreDeviceId() const { return core_device_id; }
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 3188a7f19d..d1b688857d 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -96,6 +96,7 @@
#if defined(XCB_USE_XINPUT2)
#include <X11/extensions/XInput2.h>
+#include <X11/extensions/XI2proto.h>
#endif
#define XCOORD_MAX 16383
@@ -2106,16 +2107,17 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event)
}
}
-void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
+void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
{
- const bool isWheel = event->detail >= 4 && event->detail <= 7;
+ const bool isWheel = detail >= 4 && detail <= 7;
if (!isWheel && window() != QGuiApplication::focusWindow()) {
QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver();
if (!(w->flags() & Qt::WindowDoesNotAcceptFocus))
w->requestActivate();
}
- updateNetWmUserTime(event->time);
+ updateNetWmUserTime(timestamp);
if (m_embedded) {
if (window() != QGuiApplication::focusWindow()) {
@@ -2126,53 +2128,125 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
}
}
const int dpr = int(devicePixelRatio());
- QPoint local(event->event_x/dpr, event->event_y/dpr);
- QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
-
- Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+ QPoint local(event_x / dpr, event_y / dpr);
+ QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y));
if (isWheel) {
- if (!connection()->isUsingXInput21()) {
+ if (!connection()->isAtLeastXI21()) {
// Logic borrowed from qapplication_x11.cpp
- int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
- bool hor = (((event->detail == 4 || event->detail == 5)
+ int delta = 120 * ((detail == 4 || detail == 6) ? 1 : -1);
+ bool hor = (((detail == 4 || detail == 5)
&& (modifiers & Qt::AltModifier))
- || (event->detail == 6 || event->detail == 7));
+ || (detail == 6 || detail == 7));
- QWindowSystemInterface::handleWheelEvent(window(), event->time,
+ QWindowSystemInterface::handleWheelEvent(window(), timestamp,
local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers);
}
return;
}
- handleMouseEvent(event->time, local, global, modifiers);
+ handleMouseEvent(timestamp, local, global, modifiers);
}
-void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
+void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
{
const int dpr = int(devicePixelRatio());
- QPoint local(event->event_x/dpr, event->event_y/dpr);
- QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
- Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+ QPoint local(event_x / dpr, event_y / dpr);
+ QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y));
- if (event->detail >= 4 && event->detail <= 7) {
+ if (detail >= 4 && detail <= 7) {
// mouse wheel, handled in handleButtonPressEvent()
return;
}
- handleMouseEvent(event->time, local, global, modifiers);
+ handleMouseEvent(timestamp, local, global, modifiers);
}
-void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
+void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
+ Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp)
{
- const int dpr = int(devicePixelRatio());
- QPoint local(event->event_x/dpr, event->event_y/dpr);
if (!xcbScreen())
return;
- QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
+ const int dpr = int(devicePixelRatio());
+ QPoint local(event_x / dpr, event_y / dpr);
+ QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y));
+ handleMouseEvent(timestamp, local, global, modifiers);
+}
+
+// Handlers for plain xcb events. Used only when XI 2.2 or newer is not available.
+void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
+{
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+ handleButtonPressEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail,
+ modifiers, event->time);
+}
- handleMouseEvent(event->time, local, global, modifiers);
+void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event)
+{
+ Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+ handleButtonReleaseEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail,
+ modifiers, event->time);
+}
+
+void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
+{
+ Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
+ handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers, event->time);
+}
+
+#ifdef XCB_USE_XINPUT22
+static inline int fixed1616ToInt(FP1616 val)
+{
+ return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF);
+}
+#endif
+
+// With XI 2.2+ press/release/motion comes here instead of the above handlers.
+void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event)
+{
+#ifdef XCB_USE_XINPUT22
+ QXcbConnection *conn = connection();
+ xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event);
+ const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods);
+ const int event_x = fixed1616ToInt(ev->event_x);
+ const int event_y = fixed1616ToInt(ev->event_y);
+ const int root_x = fixed1616ToInt(ev->root_x);
+ const int root_y = fixed1616ToInt(ev->root_y);
+
+ conn->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
+
+ const Qt::MouseButton button = conn->xiToQtMouseButton(ev->detail);
+
+ if (ev->buttons_len > 0) {
+ unsigned char *buttonMask = (unsigned char *) &ev[1];
+ for (int i = 1; i <= 15; ++i)
+ conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
+ }
+
+ switch (ev->evtype) {
+ case XI_ButtonPress:
+ qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button);
+ conn->setButton(button, true);
+ handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
+ break;
+ case XI_ButtonRelease:
+ qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button);
+ conn->setButton(button, false);
+ handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time);
+ break;
+ case XI_Motion:
+ qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y);
+ handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time);
+ break;
+ default:
+ qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
+ break;
+ }
+#else
+ Q_UNUSED(event);
+ Q_ASSERT(false); // this can't be
+#endif
}
QXcbWindow *QXcbWindow::toWindow() { return this; }
@@ -2356,6 +2430,10 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
bool QXcbWindow::setMouseGrabEnabled(bool grab)
{
+#ifdef XCB_USE_XINPUT22
+ if (connection()->xi2MouseEvents())
+ return connection()->xi2SetMouseGrabEnabled(m_window, grab);
+#endif
if (grab && !connection()->canGrab())
return false;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 512bc54255..e62bfcba64 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -131,6 +131,7 @@ public:
void handleFocusInEvent(const xcb_focus_in_event_t *event) Q_DECL_OVERRIDE;
void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE;
void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE;
+ void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE;
QXcbWindow *toWindow() Q_DECL_OVERRIDE;
@@ -199,6 +200,15 @@ protected:
void doFocusIn();
void doFocusOut();
+ void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
+
+ void handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y,
+ int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
+
+ void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y,
+ Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp);
+
xcb_window_t m_window;
QXcbScreen *m_xcbScreen;
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index fd704dd904..12987567ff 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -59,6 +59,11 @@ contains(QT_CONFIG, xcb-xlib) {
DEFINES += XCB_USE_XINPUT2
SOURCES += qxcbconnection_xi2.cpp
LIBS += -lXi
+ !isEmpty(QMAKE_LIBXI_VERSION_MAJOR) {
+ DEFINES += LIBXI_MAJOR=$$QMAKE_LIBXI_VERSION_MAJOR \
+ LIBXI_MINOR=$$QMAKE_LIBXI_VERSION_MINOR \
+ LIBXI_PATCH=$$QMAKE_LIBXI_VERSION_PATCH
+ }
}
}
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index 51873033c7..f253c49995 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -661,8 +661,10 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
expansion += s;
}
} else if (mode == Hash) {
- if (index < 0)
+ if (index < 0 || index >= arguments.size()) {
that->error("'#' is not followed by a macro parameter");
+ continue;
+ }
const Symbols &arg = arguments.at(index);
QByteArray stringified;
@@ -681,7 +683,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
expansion.pop_back();
Symbol next = s;
- if (index >= 0) {
+ if (index >= 0 && index < arguments.size()) {
const Symbols &arg = arguments.at(index);
if (arg.size() == 0) {
mode = Normal;
@@ -703,7 +705,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
expansion += next;
}
- if (index >= 0) {
+ if (index >= 0 && index < arguments.size()) {
const Symbols &arg = arguments.at(index);
for (int i = 1; i < arg.size(); ++i)
expansion += arg.at(i);
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index 701fea1c03..a4b37f360b 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -361,6 +361,36 @@ bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type)
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
+static LOGFONT getCaptionLogFont(HANDLE hTheme)
+{
+ LOGFONT result = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
+
+ if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &result))) {
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = sizeof(NONCLIENTMETRICS);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
+ result = ncm.lfMessageFont;
+ }
+ return result;
+}
+
+static bool getCaptionQFont(int dpi, QFont *result)
+{
+ if (!pOpenThemeData)
+ return false;
+ const HANDLE hTheme =
+ pOpenThemeData(QApplicationPrivate::getHWNDForWidget(QApplication::desktop()), L"WINDOW");
+ if (!hTheme)
+ return false;
+ // Call into QWindowsNativeInterface to convert the LOGFONT into a QFont.
+ const LOGFONT logFont = getCaptionLogFont(hTheme);
+ QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
+ return ni && QMetaObject::invokeMethod(ni, "logFontToQFont", Qt::DirectConnection,
+ Q_RETURN_ARG(QFont, *result),
+ Q_ARG(const void *, &logFont),
+ Q_ARG(int, dpi));
+}
+
void QVistaHelper::drawTitleBar(QPainter *painter)
{
Q_ASSERT(backButton_);
@@ -378,7 +408,9 @@ void QVistaHelper::drawTitleBar(QPainter *painter)
const int verticalCenter = (btnTop + btnHeight / 2) - 1;
const QString text = wizard->window()->windowTitle();
- const QFont font = QApplication::font("QMdiSubWindowTitleBar");
+ QFont font;
+ if (!isWindow || !getCaptionQFont(wizard->logicalDpiY() * wizard->devicePixelRatio(), &font))
+ font = QApplication::font("QMdiSubWindowTitleBar");
const QFontMetrics fontMetrics(font);
const QRect brect = fontMetrics.boundingRect(text);
int textHeight = brect.height();
@@ -649,19 +681,6 @@ bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
return false;
}
-HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
-{
- LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } };
-
- if (!hTheme || FAILED(pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf))) {
- NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
- lf = ncm.lfMessageFont;
- }
- return CreateFontIndirect(&lf);
-}
-
// Return a HDC for the wizard along with the transformation if the
// wizard is a child window.
HDC QVistaHelper::backingStoreDC(const QWidget *wizard, QPoint *offset)
@@ -713,7 +732,8 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q
bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
// Set up the DC
- HFONT hCaptionFont = getCaptionFont(hTheme);
+ const LOGFONT captionLogFont = getCaptionLogFont(hTheme);
+ const HFONT hCaptionFont = CreateFontIndirect(&captionLogFont);
HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont);
diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h
index 8c36472bee..84b795d506 100644
--- a/src/widgets/dialogs/qwizard_win_p.h
+++ b/src/widgets/dialogs/qwizard_win_p.h
@@ -105,7 +105,6 @@ public:
static HDC backingStoreDC(const QWidget *wizard, QPoint *offset);
private:
- static HFONT getCaptionFont(HANDLE hTheme);
HWND wizardHWND() const;
bool drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc);
static bool drawBlackRect(const QRect &rect, HDC hdc);
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 66ff472724..bca315f80b 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -1879,13 +1879,13 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent,
// insert sections into hiddenSectionSize
QHash<int, int> newHiddenSectionSize; // from logical index to section size
- for (int i = 0; i < logicalFirst; ++i)
- if (isSectionHidden(i))
- newHiddenSectionSize[i] = d->hiddenSectionSize[i];
- for (int j = logicalLast + 1; j < d->sectionCount(); ++j)
- if (isSectionHidden(j))
- newHiddenSectionSize[j] = d->hiddenSectionSize[j - insertCount];
- d->hiddenSectionSize = newHiddenSectionSize;
+ for (QHash<int, int>::const_iterator it = d->hiddenSectionSize.cbegin(),
+ end = d->hiddenSectionSize.cend(); it != end; ++it) {
+ const int oldIndex = it.key();
+ const int newIndex = (oldIndex < logicalFirst) ? oldIndex : oldIndex + insertCount;
+ newHiddenSectionSize[newIndex] = it.value();
+ }
+ d->hiddenSectionSize.swap(newHiddenSectionSize);
d->doDelayedResizeSections();
emit sectionCountChanged(oldCount, count());
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 43db43fcd4..9b3e270fdd 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -3658,6 +3658,7 @@ void QTreeViewPrivate::updateScrollBars()
if (!viewportSize.isValid())
viewportSize = QSize(0, 0);
+ executePostedLayout();
if (viewItems.isEmpty()) {
q->doItemsLayout();
}
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index b8df25b38f..9bfdc62e60 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -104,6 +104,12 @@ QT_BEGIN_NAMESPACE
non-sharable. To overcome this issue, prefer using
QSurfaceFormat::setDefaultFormat() instead of setFormat().
+ \note Calling QSurfaceFormat::setDefaultFormat() before constructing
+ the QApplication instance is mandatory on some platforms (for example,
+ OS X) when an OpenGL core profile context is requested. This is to
+ ensure that resource sharing between contexts stays functional as all
+ internal contexts are created using the correct version and profile.
+
\section1 Painting Techniques
As described above, subclass QOpenGLWidget to render pure 3D content in the
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 485cf82078..d1070839fa 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -962,7 +962,8 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
QPlatformTextureList::Flags flags = 0;
if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
flags |= QPlatformTextureList::StacksOnTop;
- widgetTextures->appendTexture(widget, wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()), flags);
+ const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
+ widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
}
for (int i = 0; i < wd->children.size(); ++i) {
@@ -1156,7 +1157,7 @@ void QWidgetBackingStore::doSync()
#ifndef QT_NO_OPENGL
if (widgetTextures && widgetTextures->count()) {
for (int i = 0; i < widgetTextures->count(); ++i) {
- QWidget *w = widgetTextures->widget(i);
+ QWidget *w = static_cast<QWidget *>(widgetTextures->source(i));
if (dirtyRenderToTextureWidgets.contains(w)) {
const QRect rect = widgetTextures->geometry(i); // mapped to the tlw already
dirty += rect;
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index f715d93298..daa8ab12a9 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -250,8 +250,6 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
int state = option->state;
if (!QWindowsVistaStylePrivate::useVista()) {
- foreach (const QObject *target, d->animationTargets())
- d->stopAnimation(target);
QWindowsStyle::drawPrimitive(element, option, painter, widget);
return;
}
@@ -810,8 +808,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
if (!QWindowsVistaStylePrivate::useVista()) {
- foreach (const QObject *target, d->animationTargets())
- d->stopAnimation(target);
QWindowsStyle::drawControl(element, option, painter, widget);
return;
}
@@ -1494,8 +1490,6 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
{
QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
if (!QWindowsVistaStylePrivate::useVista()) {
- foreach (const QObject *target, d->animationTargets())
- d->stopAnimation(target);
QWindowsStyle::drawComplexControl(control, option, painter, widget);
return;
}
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index 76f923904d..ef80e359df 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -3034,7 +3034,7 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
QStyle::SubControl sc = q->style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, e->pos(), q);
if (e->button() == Qt::LeftButton
- && sc != QStyle::SC_None
+ && !(sc == QStyle::SC_None && e->type() == QEvent::MouseButtonRelease)
&& (sc == QStyle::SC_ComboBoxArrow || !q->isEditable())
&& !viewContainer()->isVisible()) {
if (sc == QStyle::SC_ComboBoxArrow)
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index b1749fa5d3..a8da78a025 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -2316,9 +2316,9 @@ void QDateTimeEdit::paintEvent(QPaintEvent *event)
QString QDateTimeEditPrivate::getAmPmText(AmPm ap, Case cs) const
{
if (ap == AmText) {
- return (cs == UpperCase ? QDateTimeEdit::tr("AM") : QDateTimeEdit::tr("am"));
+ return (cs == UpperCase ? QDateTimeParser::tr("AM") : QDateTimeParser::tr("am"));
} else {
- return (cs == UpperCase ? QDateTimeEdit::tr("PM") : QDateTimeEdit::tr("pm"));
+ return (cs == UpperCase ? QDateTimeParser::tr("PM") : QDateTimeParser::tr("pm"));
}
}
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index 5a44df622a..e68da520e7 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -222,11 +222,49 @@ private:
// Main entry point for Appx containers
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
+#if _MSC_VER < 1900
int argc = 0;
char **argv, **env;
_startupinfo info = { _query_new_mode() };
if (int init = __getmainargs(&argc, &argv, &env, false, &info))
return init;
+#else
+ QByteArray commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8();
+ QVarLengthArray<char *> args;
+ args.append(commandLine.data());
+ bool quote = false;
+ bool escape = false;
+ for (int i = 0; i < commandLine.size(); ++i) {
+ switch (commandLine.at(i)) {
+ case '\\':
+ escape = true;
+ break;
+ case '"':
+ if (escape) {
+ escape = false;
+ break;
+ }
+ quote = !quote;
+ commandLine[i] = '\0';
+ break;
+ case ' ':
+ if (quote)
+ break;
+ commandLine[i] = '\0';
+ if (args.last()[0] != '\0')
+ args.append(commandLine.data() + i + 1);
+ // fall through
+ default:
+ if (args.last()[0] == '\0')
+ args.last() = commandLine.data() + i;
+ escape = false; // only quotes are escaped
+ break;
+ }
+ }
+ int argc = args.size();
+ char **argv = args.data();
+ char **env = Q_NULLPTR;
+#endif // _MSC_VER >= 1900
for (int i = 0; env && env[i]; ++i) {
QByteArray var(env[i]);