From bc997b856aa7b0b2137b568cd3fc6f190cd89f84 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Wed, 12 Dec 2018 15:42:40 +0100 Subject: Windows QPA: Fix touch message queue handling In the handling of pointer messages for touchscreen we use a queue that is flushed when mouse messages synthesized by Windows are received. However, these fake mouse messages should be otherwise ignored. Their handling was causing issues with PointHandler in QtQuick. This change fixes the part of QTBUG-71431 that causes a single touch drag to behave unexpectedly with PointHandler. Task-number: QTBUG-71431 Change-Id: Iccdd554876f411bce2dd1f922a3d889e61b7bb1c Reviewed-by: Miguel Costa --- src/plugins/platforms/windows/qwindowspointerhandler.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 7935d0c36f..3534f06971 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -641,6 +641,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, // Only the primary pointer will generate mouse messages. enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); } else { + flushTouchEvents(m_touchDevice); QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); } @@ -766,6 +767,13 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW if (et != QtWindows::MouseWheelEvent && msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE) return false; + // Ignore messages synthesized from touch/pen (only use them for flushing queues). + const quint64 signatureMask = 0xffffff00; + const quint64 miWpSignature = 0xff515700; + const quint64 extraInfo = quint64(GetMessageExtraInfo()); + if ((extraInfo & signatureMask) == miWpSignature) + return false; + const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); QPoint localPos; QPoint globalPos; -- cgit v1.2.3 From 16aae58e2a5cc324b869568f6fb9cc4bedbc96d9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 18 Dec 2018 08:38:43 -0800 Subject: Fix build with Clang 3.8 Commit 128a6eec065dfe683e6d776183d63908ca02e8fb replaced the static, unsorted list with a sorting implementation via templates. qmakearray_p.h:109:8: fatal error: recursive template instantiation exceeded maximum depth of 256 qmakearray_p.h:111:39: note: during template argument deduction for class template partial specialization 'QuickSortFilter >' [with Predicate = LessThan, Head = Xkb2Qt<269025163, 16777462>, Tail = ...] Fixes: QTBUG-72579 Change-Id: I548dbfddb69b4fd6a0a3fffd15717ac2bf2d7361 Reviewed-by: Gatis Paeglis Reviewed-by: Mikhail Svetkin --- src/plugins/platforms/xcb/xcb_qpa_lib.pro | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 9883617ab6..50b7f7f97d 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -110,4 +110,8 @@ qtConfig(xkb) { qtConfig(dlopen): QMAKE_USE += libdl +# qxcbkeyboard.cpp's KeyTbl has more than 256 levels of expansion and older +# Clang uses that as a limit (it's 1024 in current versions). +clang:!intel_icc: QMAKE_CXXFLAGS += -ftemplate-depth=1024 + load(qt_module) -- cgit v1.2.3 From 29ea287716175b57aa7b050b70eb3eb5c9049464 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Thu, 13 Dec 2018 15:54:35 +0100 Subject: Windows QPA: Avoid duplication of mouse events The code being removed was added as a workaround to support the use of QCursor::setPos() with unit tests. This function was used to move the Windows mouse cursor, internally calling SetCursorPos(), which generates only WM_MOUSE* messages, bypassing the pointer messages. However, the workaround had the unintended effect of generating duplicated mouse events for normal mouse movement, which caused issues like the one described by QTBUG-70974. However, it seems the tests are no longer depending on it, allowing it to be removed. Fixes: QTBUG-70974 Change-Id: Iaf0d64c73951ab1b660e9bb90e7ee009e53fbd3a Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowspointerhandler.cpp | 29 ---------------------- 1 file changed, 29 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 3534f06971..78a8083d5b 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -370,22 +370,6 @@ static Qt::MouseButtons mouseButtonsFromPointerFlags(POINTER_FLAGS pointerFlags) return result; } -static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState) -{ - Qt::MouseButtons result = Qt::NoButton; - if (keyState & MK_LBUTTON) - result |= Qt::LeftButton; - if (keyState & MK_RBUTTON) - result |= Qt::RightButton; - if (keyState & MK_MBUTTON) - result |= Qt::MiddleButton; - if (keyState & MK_XBUTTON1) - result |= Qt::XButton1; - if (keyState & MK_XBUTTON2) - result |= Qt::XButton2; - return result; -} - static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos) { QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT); @@ -816,14 +800,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW return false; } - // Windows sends a mouse move with no buttons pressed to signal "Enter" - // when a window is shown over the cursor. Discard the event and only use - // it for generating QEvent::Enter to be consistent with other platforms - - // X11 and macOS. - static QPoint lastMouseMovePos; - const bool discardEvent = msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos); - lastMouseMovePos = globalPos; - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); if (currentWindowUnderPointer != m_windowUnderPointer) { @@ -846,11 +822,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW m_windowUnderPointer = currentWindowUnderPointer; } - const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); - - if (!discardEvent) - QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove, - keyModifiers, Qt::MouseEventNotSynthesized); return false; } -- cgit v1.2.3 From df27484fc0349bb060e023ac2dce246c1176d838 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Wed, 19 Dec 2018 20:57:25 +0100 Subject: Windows QPA: Fix mouse pointer capture and Enter/Leave events Qt expects the platform plugin to capture the mouse on any button press and keep it captured until buttons are released. The missing capture logic was causing extra Enter/Leave events to be generated. Change-Id: I5a78ea600374701c740f395b38ba5abd51f561d8 Fixes: QTBUG-72600 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowspointerhandler.cpp | 185 +++++++++++++++------ .../platforms/windows/qwindowspointerhandler.h | 4 + 2 files changed, 137 insertions(+), 52 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 78a8083d5b..be67eb0248 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -54,7 +54,6 @@ # include "qwindowsdrag.h" #endif -#include #include #include #include @@ -370,6 +369,22 @@ static Qt::MouseButtons mouseButtonsFromPointerFlags(POINTER_FLAGS pointerFlags) return result; } +static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState) +{ + Qt::MouseButtons result = Qt::NoButton; + if (keyState & MK_LBUTTON) + result |= Qt::LeftButton; + if (keyState & MK_RBUTTON) + result |= Qt::RightButton; + if (keyState & MK_MBUTTON) + result |= Qt::MiddleButton; + if (keyState & MK_XBUTTON1) + result |= Qt::XButton1; + if (keyState & MK_XBUTTON2) + result |= Qt::XButton2; + return result; +} + static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos) { QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT); @@ -411,6 +426,15 @@ static bool isValidWheelReceiver(QWindow *candidate) return false; } +static bool isMenuWindow(QWindow *window) +{ + if (window) + if (QObject *fo = window->focusObject()) + if (fo->inherits("QMenu")) + return true; + return false; +} + static QTouchDevice *createTouchDevice() { const int digitizers = GetSystemMetrics(SM_DIGITIZER); @@ -439,6 +463,103 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice() return m_touchDevice; } +void QWindowsPointerHandler::handleCaptureRelease(QWindow *window, + QWindow *currentWindowUnderPointer, + HWND hwnd, + QEvent::Type eventType, + Qt::MouseButtons mouseButtons) +{ + QWindowsWindow *platformWindow = static_cast(window->handle()); + + // Qt expects the platform plugin to capture the mouse on any button press until release. + if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) { + + platformWindow->setMouseGrabEnabled(true); + platformWindow->setFlag(QWindowsWindow::AutoMouseCapture); + qCDebug(lcQpaEvents) << "Automatic mouse capture " << window; + + // Implement "Click to focus" for native child windows (unless it is a native widget window). + if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window) + window->requestActivate(); + + } else if (platformWindow->hasMouseCapture() + && platformWindow->testFlag(QWindowsWindow::AutoMouseCapture) + && eventType == QEvent::MouseButtonRelease + && !mouseButtons) { + + platformWindow->setMouseGrabEnabled(false); + qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window; + } + + // Enter new window: track to generate leave event. + // If there is an active capture, only track if the current window is capturing, + // so we don't get extra leave when cursor leaves the application. + if (window != m_currentWindow && + (!platformWindow->hasMouseCapture() || currentWindowUnderPointer == window)) { + trackLeave(hwnd); + m_currentWindow = window; + } +} + +void QWindowsPointerHandler::handleEnterLeave(QWindow *window, + QWindow *currentWindowUnderPointer, + QPoint globalPos) +{ + QWindowsWindow *platformWindow = static_cast(window->handle()); + const bool hasCapture = platformWindow->hasMouseCapture(); + + // No enter or leave events are sent as long as there is an autocapturing window. + if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) { + + // Leave is needed if: + // 1) There is no capture and we move from a window to another window. + // Note: Leaving the application entirely is handled in translateMouseEvent(WM_MOUSELEAVE). + // 2) There is capture and we move out of the capturing window. + // 3) There is a new capture and we were over another window. + if ((m_windowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer + && (!hasCapture || window == m_windowUnderPointer)) + || (hasCapture && m_previousCaptureWindow != window && m_windowUnderPointer + && m_windowUnderPointer != window)) { + + qCDebug(lcQpaEvents) << "Leaving window " << m_windowUnderPointer; + QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer); + + if (hasCapture && currentWindowUnderPointer != window) { + // Clear tracking if capturing and current window is not the capturing window + // to avoid leave when mouse actually leaves the application. + m_currentWindow = nullptr; + // We are not officially in any window, but we need to set some cursor to clear + // whatever cursor the left window had, so apply the cursor of the capture window. + platformWindow->applyCursor(); + } + } + + // Enter is needed if: + // 1) There is no capture and we move to a new window. + // 2) There is capture and we move into the capturing window. + // 3) The capture just ended and we are over non-capturing window. + if ((currentWindowUnderPointer && m_windowUnderPointer != currentWindowUnderPointer + && (!hasCapture || currentWindowUnderPointer == window)) + || (m_previousCaptureWindow && !hasCapture && currentWindowUnderPointer + && currentWindowUnderPointer != m_previousCaptureWindow)) { + + QPoint wumLocalPos; + if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) { + wumLocalPos = wumPlatformWindow->mapFromGlobal(globalPos); + wumPlatformWindow->applyCursor(); + } + qCDebug(lcQpaEvents) << "Entering window " << currentWindowUnderPointer; + QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, wumLocalPos, globalPos); + } + + // We need to track m_windowUnderPointer separately from m_currentWindow, as Windows + // mouse tracking will not trigger WM_MOUSELEAVE for leaving window when mouse capture is set. + m_windowUnderPointer = currentWindowUnderPointer; + } + + m_previousCaptureWindow = hasCapture ? window : nullptr; +} + bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo) @@ -448,9 +569,7 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags); - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); - QWindowsWindow *platformWindow = static_cast(window->handle()); switch (msg.message) { case WM_NCPOINTERDOWN: @@ -469,38 +588,17 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h keyModifiers, Qt::MouseEventNotSynthesized); return false; // To allow window dragging, etc. } else { - if (eventType == QEvent::MouseButtonPress) { - // Implement "Click to focus" for native child windows (unless it is a native widget window). - if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window) - window->requestActivate(); - } - if (currentWindowUnderPointer != m_windowUnderPointer) { - if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) { - QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer); - m_currentWindow = nullptr; - } - - if (currentWindowUnderPointer) { - if (currentWindowUnderPointer != m_currentWindow) { - QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos); - m_currentWindow = currentWindowUnderPointer; - if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) - wumPlatformWindow->applyCursor(); - trackLeave(hwnd); - } - } else { - platformWindow->applyCursor(); - } - m_windowUnderPointer = currentWindowUnderPointer; - } + + handleCaptureRelease(window, currentWindowUnderPointer, hwnd, eventType, mouseButtons); + handleEnterLeave(window, currentWindowUnderPointer, globalPos); QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType, keyModifiers, Qt::MouseEventNotSynthesized); // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND // has go to through DefWindowProc() for resizing to work, so we return false here, - // unless the mouse is captured, as it would mess with menu processing. - return msg.message != WM_POINTERDOWN || GetCapture(); + // unless the click was on a menu, as it would mess with menu processing. + return msg.message != WM_POINTERDOWN || isMenuWindow(window); } } case WM_POINTERHWHEEL: @@ -770,7 +868,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW } const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - QWindowsWindow *platformWindow = static_cast(window->handle()); if (et == QtWindows::MouseWheelEvent) { @@ -792,36 +889,20 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW if (msg.message == WM_MOUSELEAVE) { if (window == m_currentWindow) { - QWindowSystemInterface::handleLeaveEvent(window); + QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow; + qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget; + QWindowSystemInterface::handleLeaveEvent(leaveTarget); m_windowUnderPointer = nullptr; m_currentWindow = nullptr; - platformWindow->applyCursor(); } return false; } QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); + const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); - if (currentWindowUnderPointer != m_windowUnderPointer) { - if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) { - QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer); - m_currentWindow = nullptr; - } - - if (currentWindowUnderPointer) { - if (currentWindowUnderPointer != m_currentWindow) { - QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos); - m_currentWindow = currentWindowUnderPointer; - if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer)) - wumPlatformWindow->applyCursor(); - trackLeave(hwnd); - } - } else { - platformWindow->applyCursor(); - } - m_windowUnderPointer = currentWindowUnderPointer; - } - + handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons); + handleEnterLeave(window, currentWindowUnderPointer, globalPos); return false; } diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index 3861ebf919..a586c7863c 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -46,6 +46,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -68,11 +69,14 @@ private: bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo); bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); + void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons); + void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos); QTouchDevice *m_touchDevice = nullptr; QHash m_lastTouchPositions; QPointer m_windowUnderPointer; QPointer m_currentWindow; + QWindow *m_previousCaptureWindow = nullptr; bool m_needsEnterOnPointerUpdate = false; }; -- cgit v1.2.3 From 6191249259719dee6f8f6eb42289e0582f1c02bc Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 3 Jan 2019 13:33:28 +0100 Subject: Use the AndroidDeadlockProtector when using a blockingqueued connection This amends 2afe4a1a074096a3a6476aae21e732c418717da7 to account for cases where it was crashing when it was using the QueuedConnection. The problem came from the fact it was blocking while waiting for a surface update which was pending to come later on, but the Android thread was already blocked which prevented it from being processed. Fixes: QTBUG-72101 Change-Id: I43e355cf1a7792599f23827903d065b1b1298902 Reviewed-by: BogDan Vatra --- src/plugins/platforms/android/qandroidinputcontext.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 7b3546f9bb..394e284bb6 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -99,13 +99,12 @@ static jfieldID m_selectionStartFieldID = 0; static jfieldID m_startOffsetFieldID = 0; static jfieldID m_textFieldID = 0; -Q_DECLARE_METATYPE(std::function) - static void runOnQtThread(const std::function &func) { - const bool block = QGuiApplication::applicationState() >= Qt::ApplicationInactive; - QMetaObject::invokeMethod(m_androidInputContext, "safeCall", - block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, Q_ARG(std::function, func)); + AndroidDeadlockProtector protector; + if (!protector.acquire()) + return; + QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function, func)); } static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) @@ -516,7 +515,6 @@ QAndroidInputContext::QAndroidInputContext() m_handleMode = Hidden; updateSelectionHandles(); }); - qRegisterMetaType>(); } QAndroidInputContext::~QAndroidInputContext() -- cgit v1.2.3 From afb08ac5dae930912768f3f0ae4352189b8c3641 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 7 Jan 2019 13:54:40 +0100 Subject: Use jint instead of jboolean where applicable and initialize variables This amends change c6af7cf666d43c68c90ad829c3a55d84ee8e4a3e which had incorrectly used jboolean to store the result of getCursorCapsMode() and thus lost the information it was passing. The variables are also initialized in case there is a lock problem when calling runOnQtThread. Fixes: QTBUG-72783 Change-Id: Ibdc21e348c25ee4fdff242d14b3722c6551b042c Reviewed-by: BogDan Vatra --- .../platforms/android/qandroidinputcontext.cpp | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 394e284bb6..cdc52e1cb4 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -115,7 +115,7 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ BEGINBATCH"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();}); return res; } @@ -129,7 +129,7 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/) qDebug("@@@ ENDBATCH"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();}); return res; } @@ -148,7 +148,7 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ COMMIT" << str << newCursorPosition; #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);}); return res; } @@ -161,7 +161,7 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ DELETE" << leftLength << rightLength; #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);}); return res; } @@ -174,7 +174,7 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ FINISH"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->finishComposingText();}); return res; } @@ -184,7 +184,7 @@ static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes) if (!m_androidInputContext) return 0; - jboolean res; + jint res = 0; runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);}); return res; } @@ -269,7 +269,7 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SET" << str << newCursorPosition; #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);}); return res; } @@ -282,7 +282,7 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SETR" << start << end; #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);}); return res; } @@ -296,7 +296,7 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SETSEL" << start << end; #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);}); return res; @@ -310,7 +310,7 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ SELALL"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->selectAll();}); return res; } @@ -323,7 +323,7 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->cut();}); return res; } @@ -336,7 +336,7 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->copy();}); return res; } @@ -349,7 +349,7 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->copyURL();}); return res; } @@ -362,7 +362,7 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug("@@@ PASTE"); #endif - jboolean res; + jboolean res = JNI_FALSE; runOnQtThread([&]{res = m_androidInputContext->paste();}); return res; } -- cgit v1.2.3 From 5dadc3d807af89c37b002749d3b39bfc94b10acd Mon Sep 17 00:00:00 2001 From: Andreas Date: Fri, 11 Jan 2019 11:01:04 +0100 Subject: xcb: fix initialization of XRandr and XRender Fixes: QTBUG-72957 Change-Id: Ia698eef5dae4e2d35ca2e565fbdc23da40c83d8a Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbconnection_basic.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp index c69912c361..af72285135 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp @@ -287,7 +287,7 @@ void QXcbBasicConnection::initializeShm() logging->setEnabled(QtMsgType::QtWarningMsg, true); } -void QXcbBasicConnection::initializeXRandr() +void QXcbBasicConnection::initializeXRender() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id); if (!reply || !reply->present) { @@ -303,7 +303,7 @@ void QXcbBasicConnection::initializeXRandr() return; } - m_hasXRandr = true; + m_hasXRender = true; m_xrenderVersion.first = xrenderQuery->major_version; m_xrenderVersion.second = xrenderQuery->minor_version; } @@ -337,7 +337,7 @@ void QXcbBasicConnection::initializeXFixes() m_xfixesFirstEvent = reply->first_event; } -void QXcbBasicConnection::initializeXRender() +void QXcbBasicConnection::initializeXRandr() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id); if (!reply || !reply->present) @@ -352,7 +352,7 @@ void QXcbBasicConnection::initializeXRender() return; } - m_hasXRender = true; + m_hasXRandr = true; m_xrandrFirstEvent = reply->first_event; } -- cgit v1.2.3 From af99497bdbcfb5202bd226b76910de9fd82e0625 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Mon, 7 Jan 2019 16:56:11 +0100 Subject: Windows QPA: Support "press and hold for right-clicking" Windows sends a fake WM_RBUTTONUP/WM_RBUTTONDOWN when the user presses and holds the pen/finger on a tablet/touchscreen, e.g., in order to show a context menu. Windows only sends already synthesized legacy mouse messages for this condition, instead of anything detectable in the pointer messages. So we need to handle these legacy messages in the Windows QPA. Task-number: QTBUG-36162 Change-Id: Ia93c423601e2e8a8baac3f9b7791bf8a3113885a Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowspointerhandler.cpp | 53 ++++++++++++++++------ .../platforms/windows/qwindowspointerhandler.h | 1 + 2 files changed, 39 insertions(+), 15 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index be67eb0248..e428a8cf63 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -200,6 +200,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q return false; } + m_lastPointerType = pointerType; + // Handle non-client pen/touch as generic mouse events for compatibility with QDockWindow. if ((pointerType == QT_PT_TOUCH || pointerType == QT_PT_PEN) && (et & QtWindows::NonClientEventFlag)) { POINTER_INFO pointerInfo; @@ -838,6 +840,16 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin #endif } +static inline bool isMouseEventSynthesizedFromPenOrTouch() +{ + // For details, see + // https://docs.microsoft.com/en-us/windows/desktop/tablet/system-events-and-mouse-messages + const LONG_PTR SIGNATURE_MASK = 0xFFFFFF00; + const LONG_PTR MI_WP_SIGNATURE = 0xFF515700; + + return ((::GetMessageExtraInfo() & SIGNATURE_MASK) == MI_WP_SIGNATURE); +} + // Process old-style mouse messages here. bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) { @@ -846,15 +858,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW flushTabletEvents(); *result = 0; - if (et != QtWindows::MouseWheelEvent && msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE) - return false; - - // Ignore messages synthesized from touch/pen (only use them for flushing queues). - const quint64 signatureMask = 0xffffff00; - const quint64 miWpSignature = 0xff515700; - const quint64 extraInfo = quint64(GetMessageExtraInfo()); - if ((extraInfo & signatureMask) == miWpSignature) - return false; const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); QPoint localPos; @@ -868,6 +871,26 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW } const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); + const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); + + // Handle "press and hold for right-clicking". + // We have to synthesize it here as it only comes from Windows as a fake RMB. + // MS docs say we could use bit 7 from extraInfo to distinguish pen from touch, + // but on the Surface it is set for both. So we use the last pointer type. + if (isMouseEventSynthesizedFromPenOrTouch()) { + if ((msg.message == WM_RBUTTONDOWN || msg.message == WM_RBUTTONUP) + && (((m_lastPointerType == QT_PT_PEN) + && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents)) + || ((m_lastPointerType == QT_PT_TOUCH) + && QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)))) { + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::RightButton, + (msg.message == WM_RBUTTONDOWN) ? QEvent::MouseButtonPress + : QEvent::MouseButtonRelease, + keyModifiers, Qt::MouseEventSynthesizedBySystem); + } + // Messages synthesized from touch/pen are only used for flushing queues and press&hold. + return false; + } if (et == QtWindows::MouseWheelEvent) { @@ -888,6 +911,7 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW } if (msg.message == WM_MOUSELEAVE) { + if (window == m_currentWindow) { QWindow *leaveTarget = m_windowUnderPointer ? m_windowUnderPointer : m_currentWindow; qCDebug(lcQpaEvents) << "Leaving window " << leaveTarget; @@ -895,14 +919,13 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW m_windowUnderPointer = nullptr; m_currentWindow = nullptr; } - return false; - } - QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); - const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam); + } else if (msg.message == WM_MOUSEMOVE) { - handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons); - handleEnterLeave(window, currentWindowUnderPointer, globalPos); + QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos); + handleCaptureRelease(window, currentWindowUnderPointer, hwnd, QEvent::MouseMove, mouseButtons); + handleEnterLeave(window, currentWindowUnderPointer, globalPos); + } return false; } diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index a586c7863c..ec3179e821 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -78,6 +78,7 @@ private: QPointer m_currentWindow; QWindow *m_previousCaptureWindow = nullptr; bool m_needsEnterOnPointerUpdate = false; + DWORD m_lastPointerType = 0; }; QT_END_NAMESPACE -- cgit v1.2.3 From 8c0a7a46c691f7acad169f5949d3b3d76a227614 Mon Sep 17 00:00:00 2001 From: Samuli Piippo Date: Wed, 9 Jan 2019 13:01:01 +0000 Subject: egl_viv: cast EGLNative return types from vivante functions All vivante functions return void* even when the actual native type (EGLNativeDisplayType, EGLNativeWindowType, etc.) might be typedef'ed as something else, as they do when the CFLAGS from egl.pc are now used. Task-number: QTBUG-73038 Change-Id: I7650b691663201d03d8c15ead155aa3c231fba29 Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp | 4 ++-- .../eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp index 763a4a462b..2fc076ad0c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp @@ -65,7 +65,7 @@ void QEglFSVivIntegration::platformInit() VivanteInit(); mNativeDisplay = fbGetDisplay(); #else - mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); + mNativeDisplay = static_cast(fbGetDisplayByIndex(framebufferIndex())); #endif fbGetDisplayGeometry(mNativeDisplay, &width, &height); @@ -88,7 +88,7 @@ EGLNativeWindowType QEglFSVivIntegration::createNativeWindow(QPlatformWindow *wi Q_UNUSED(window) Q_UNUSED(format) - EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); + EGLNativeWindowType eglWindow = static_cast(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height())); return eglWindow; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp index 61e2f17766..3bdae239cd 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.cpp @@ -60,7 +60,7 @@ void QEglFSVivWaylandIntegration::platformInit() } mWaylandDisplay = wl_display_create(); - mNativeDisplay = fbGetDisplay(mWaylandDisplay); + mNativeDisplay = static_cast(fbGetDisplay(mWaylandDisplay)); fbGetDisplayGeometry(mNativeDisplay, &width, &height); mScreenSize.setHeight(height); mScreenSize.setWidth(width); @@ -81,7 +81,7 @@ EGLNativeWindowType QEglFSVivWaylandIntegration::createNativeWindow(QPlatformWin Q_UNUSED(window) Q_UNUSED(format) - EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); + EGLNativeWindowType eglWindow = static_cast(fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height())); return eglWindow; } -- cgit v1.2.3