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') 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') 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') 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') 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') 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') 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') 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') 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 30e665f7471859cd88f5d5be4008e7b0632bb5c3 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Thu, 27 Dec 2018 01:10:29 +0100 Subject: eglfs_kms: Fix build with -no-opengl This patch amends 259adc5e77a40bc8f0b7e4c17f7a38bfc4ad511b Change-Id: Ie8d8a8e0817cea455eb1fe14501e8429d29428b8 Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp | 2 ++ .../eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp index 402338197d..1e4f4e72c8 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp @@ -118,6 +118,8 @@ QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor"); return new QEglFSCursor(screen); } +#else + Q_UNUSED(screen); #endif return nullptr; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp index a67457a6a5..ab39af6b80 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp @@ -289,7 +289,9 @@ QPlatformCursor *QEglFSKmsEglDeviceIntegration::createCursor(QPlatformScreen *sc { #if QT_CONFIG(opengl) if (screenConfig()->separateScreens()) - return new QEglFSCursor(screen); + return new QEglFSCursor(screen); +#else + Q_UNUSED(screen); #endif return nullptr; } -- cgit v1.2.3 From 730f0df17db53b249b8680a14c40d12107c8e24e Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 22 Jan 2019 12:57:52 +0100 Subject: Windows: Set opengl swap interval whenever we make a new window current Apparently the windows OpenGL implementation associates the swap interval not with the context, but with the window. Fixes: QTBUG-59660 Change-Id: I78c4cc9f8a5815779a7489edfd731a1debb1e590 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs Reviewed-by: Simon Hausmann --- src/plugins/platforms/windows/qwindowsglcontext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 851a6c961e..21cb794196 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1350,10 +1350,10 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) // Set the swap interval if (m_staticContext->wglSwapInternalExt) { const int interval = surface->format().swapInterval(); - if (interval >= 0 && m_swapInterval != interval) { + if (m_swapInterval != interval) m_swapInterval = interval; + if (interval >= 0) m_staticContext->wglSwapInternalExt(interval); - } } return success; -- cgit v1.2.3 From 76ee79b8b9c412a77bb51f127ab102f2451a7bbb Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Thu, 17 Jan 2019 13:32:40 +0100 Subject: qtbearer networkmanager: fix whitespace Change-Id: I7802e33e21fa882468b4c8e68677d4881b95d15c Reviewed-by: Lars Knoll --- src/plugins/bearer/networkmanager/qnetworkmanagerservice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h index 65e618d15f..c879083faf 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h @@ -243,7 +243,7 @@ public: // bool setConnections(); Q_SIGNALS: - void propertiesChanged(QMap ); + void propertiesChanged(QMap); void propertiesReady(); private Q_SLOTS: -- 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') 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 From 19d1fdc5a52039d771d520d0f6c5b98a0e0c4c60 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 24 Jan 2019 09:39:38 +0100 Subject: Windows QPA: Use member initialization in struct WindowCreationData Change-Id: I165e795ea75a8d5cb5d3256b3ef377239d24a245 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowswindow.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f340f16679..7efefa9458 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -482,26 +482,22 @@ struct WindowCreationData typedef QWindowsWindowData WindowData; enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 }; - WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0), - topLevel(false), popup(false), dialog(false), - tool(false), embedded(false), hasAlpha(false) {} - void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); inline WindowData create(const QWindow *w, const WindowData &data, QString title) const; inline void applyWindowFlags(HWND hwnd) const; void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const; Qt::WindowFlags flags; - HWND parentHandle; - Qt::WindowType type; - unsigned style; - unsigned exStyle; - bool topLevel; - bool popup; - bool dialog; - bool tool; - bool embedded; - bool hasAlpha; + HWND parentHandle = nullptr; + Qt::WindowType type = Qt::Widget; + unsigned style = 0; + unsigned exStyle = 0; + bool topLevel = false; + bool popup = false; + bool dialog = false; + bool tool = false; + bool embedded = false; + bool hasAlpha = false; }; QDebug operator<<(QDebug debug, const WindowCreationData &d) -- cgit v1.2.3 From 4aa0bcf5f5266b33faf236e8c914fcf5379abf5b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 22 Jan 2019 14:48:37 +0100 Subject: Windows QPA: Fix tray icon becoming visible before show Use the NIS_HIDDEN flag of the NOTIFYICONDATA structure to prevent it from becoming visible before show when calling NIM_ADD with the icon data. Fixes: QTBUG-73185 Change-Id: If5cc5a4930a889623a5cac84138185ad04765ece Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowssystemtrayicon.cpp | 26 +++++++++++++++++++++- .../platforms/windows/qwindowssystemtrayicon.h | 2 ++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index 3c27f2914d..2b728338ae 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -103,6 +103,13 @@ static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t)); } +static void setIconVisibility(NOTIFYICONDATA &tnd, bool v) +{ + tnd.uFlags |= NIF_STATE; + tnd.dwStateMask = NIS_HIDDEN; + tnd.dwState = v ? 0 : NIS_HIDDEN; +} + // Match the HWND of the dummy window to the instances struct QWindowsHwndSystemTrayIconEntry { @@ -193,12 +200,15 @@ QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon() void QWindowsSystemTrayIcon::init() { qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this; - ensureInstalled(); + m_visible = true; + if (!setIconVisible(m_visible)) + ensureInstalled(); } void QWindowsSystemTrayIcon::cleanup() { qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this; + m_visible = false; ensureCleanup(); } @@ -333,6 +343,18 @@ void QWindowsSystemTrayIcon::ensureCleanup() m_toolTip.clear(); } +bool QWindowsSystemTrayIcon::setIconVisible(bool visible) +{ + if (!isInstalled()) + return false; + NOTIFYICONDATA tnd; + initNotifyIconData(tnd); + tnd.uID = q_uNOTIFYICONID; + tnd.hWnd = m_hwnd; + setIconVisibility(tnd, visible); + return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE; +} + bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg) { NOTIFYICONDATA tnd; @@ -340,6 +362,8 @@ bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg) tnd.uID = q_uNOTIFYICONID; tnd.hWnd = m_hwnd; tnd.uFlags = NIF_SHOWTIP; + if (msg != NIM_DELETE && !m_visible) + setIconVisibility(tnd, m_visible); if (msg == NIM_ADD || msg == NIM_MODIFY) setIconContents(tnd, m_toolTip, m_hIcon); if (!Shell_NotifyIcon(msg, &tnd)) diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h index a8adb9641f..44e1bcc761 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.h +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h @@ -84,6 +84,7 @@ private: bool ensureInstalled(); void ensureCleanup(); bool sendTrayMessage(DWORD msg); + bool setIconVisible(bool visible); HICON createIcon(const QIcon &icon); QIcon m_icon; @@ -92,6 +93,7 @@ private: HICON m_hIcon = nullptr; mutable QPointer m_menu; bool m_ignoreNextMouseRelease = false; + bool m_visible = false; }; #ifndef QT_NO_DEBUG_STREAM -- cgit v1.2.3 From c154766630db37dc7d6f8090609d2d1a5076a733 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 23 Jan 2019 08:38:08 +0100 Subject: Windows QPA: Move the code installing the filter for WM_TASKBARCREATED Previously, the code was in the constructor, where hwnd was 0 and ChangeWindowMessageFilterEx() failed. Move it into QWindowsSystemTrayIcon::ensureInstalled() after the creation of the message window. Change-Id: Iff4c6d6d6b11bdcace7514ad421c96c94e52bbba Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowssystemtrayicon.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index 2b728338ae..b738007f0e 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -183,12 +183,6 @@ static inline HWND createTrayIconMessageWindow() QWindowsSystemTrayIcon::QWindowsSystemTrayIcon() { - // For restoring the tray icon after explorer crashes - if (!MYWM_TASKBARCREATED) - MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); - // Allow the WM_TASKBARCREATED message through the UIPI filter - ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, 0); - qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED; } QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon() @@ -320,6 +314,13 @@ bool QWindowsSystemTrayIcon::ensureInstalled() m_hwnd = createTrayIconMessageWindow(); if (Q_UNLIKELY(m_hwnd == nullptr)) return false; + // For restoring the tray icon after explorer crashes + if (!MYWM_TASKBARCREATED) + MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); + // Allow the WM_TASKBARCREATED message through the UIPI filter + ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, nullptr); + qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED; + QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this}; hwndTrayIconEntries()->append(entry); sendTrayMessage(NIM_ADD); -- cgit v1.2.3 From 4c46e3189ac96c8ebcbe1caa47227c4e086d12ff Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Tue, 22 Jan 2019 20:28:49 +0100 Subject: Windows QPA: Cache "forcedScreenForGLWindow" to avoid overhead The fix for QTBUG-50371 caused an overhead when you hover over a secondary window like a tool tip, menu or combo box due to the forcedScreenForGLWindow() function being called, which loads dx9.dll and sub-dlls and unloads them afterwards. This fix caches the required info on the first call, and only refreshes it when required by a display/settings change. Fixes: QTBUG-73008 Change-Id: Ie604ba4034ad8041b971f5aa46bd43ae03decd55 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowscontext.cpp | 2 ++ src/plugins/platforms/windows/qwindowswindow.cpp | 30 +++++++++++++++++------ src/plugins/platforms/windows/qwindowswindow.h | 5 ++++ 3 files changed, 30 insertions(+), 7 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 1f80ac5872..fee093f675 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1115,8 +1115,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::DisplayChangedEvent: if (QWindowsTheme *t = QWindowsTheme::instance()) t->displayChanged(); + QWindowsWindow::displayChanged(); return d->m_screenManager.handleDisplayChange(wParam, lParam); case QtWindows::SettingChangedEvent: + QWindowsWindow::settingsChanged(); return d->m_screenManager.handleScreenChanges(); default: break; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 7efefa9458..54a4f237ff 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -551,12 +551,6 @@ static QScreen *screenForName(const QWindow *w, const QString &name) return winScreen; } -static QScreen *forcedScreenForGLWindow(const QWindow *w) -{ - const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen; - return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen); -} - static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins) { const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top()); @@ -565,7 +559,7 @@ static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &co return orgPos; // Workaround for QTBUG-50371 - const QScreen *screenForGL = forcedScreenForGLWindow(w); + const QScreen *screenForGL = QWindowsWindow::forcedScreenForGLWindow(w); if (!screenForGL) return orgPos; @@ -1359,6 +1353,28 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled) #endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop) } +bool QWindowsWindow::m_screenForGLInitialized = false; + +void QWindowsWindow::displayChanged() +{ + m_screenForGLInitialized = false; +} + +void QWindowsWindow::settingsChanged() +{ + m_screenForGLInitialized = false; +} + +QScreen *QWindowsWindow::forcedScreenForGLWindow(const QWindow *w) +{ + static QString forceToScreen; + if (!m_screenForGLInitialized) { + forceToScreen = GpuDescription::detect().gpuSuitableScreen; + m_screenForGLInitialized = true; + } + return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen); +} + // Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain. // Returns this window if it is the topmost ancestor. QWindow *QWindowsWindow::topLevelOf(QWindow *w) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e8c30bd44b..b9b398b67b 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -297,6 +297,9 @@ public: void handleHidden(); void handleCompositionSettingsChanged(); + static void displayChanged(); + static void settingsChanged(); + static QScreen *forcedScreenForGLWindow(const QWindow *w); static QWindowsWindow *windowsWindowOf(const QWindow *w); static QWindow *topLevelOf(QWindow *w); static inline void *userDataOf(HWND hwnd); @@ -377,6 +380,8 @@ private: HICON m_iconBig = 0; void *m_surface = nullptr; + static bool m_screenForGLInitialized; + #if QT_CONFIG(vulkan) // note: intentionally not using void * in order to avoid breaking x86 VkSurfaceKHR m_vkSurface = 0; -- cgit v1.2.3 From c4e7f3ab6555c87fb41c5f341524445283720e6a Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 23 Jan 2019 10:40:18 +0100 Subject: QMacStyle: fix PE_PanelLineEdit and PE_FrameLineEdit handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NSTextField (or its cell) that we use to paint PE_FrameLineEdit overpaints whatever fill color QCommonStyle::drawPrimitive(PE_PanelLineEdit) found in opt->palette and using for PE_PanelLineEdit. As a result the ability to customize widget's colors is lost - we always use the system default colors on top of the custom background color. It's not a problem in 'Dark' mode apparently (controls are transparent there anyway). If it's not 'Dark' mode and common style, indeed, wants from QMacStyle to draw PE_FrameLineEdit - we set the correct background color there. Change-Id: Idad853257f637b028af4bd1181d78afdf079f455 Fixes: QTBUG-73183 Fixes: QTBUG-72662 Fixes: QTBUG-72428 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 62 ++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index c2b6fbfead..2b40a9a952 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3217,6 +3217,29 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai static_cast(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel; tf.frame = opt->rect.toCGRect(); d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) { + if (!qt_mac_applicationIsInDarkMode()) { + // In 'Dark' mode controls are transparent, so we do not + // over-paint the (potentially custom) color in the background. + // In 'Light' mode we have to care about the correct + // background color. See the comments below for PE_PanelLineEdit. + CGContextRef cgContext = NSGraphicsContext.currentContext.CGContext; + // See QMacCGContext, here we expect bitmap context created with + // color space 'kCGColorSpaceSRGB', if it's something else - we + // give up. + if (cgContext ? bool(CGBitmapContextGetColorSpace(cgContext)) : false) { + tf.drawsBackground = YES; + const QColor bgColor = frame->palette.brush(QPalette::Base).color(); + tf.backgroundColor = [NSColor colorWithSRGBRed:bgColor.redF() + green:bgColor.greenF() + blue:bgColor.blueF() + alpha:bgColor.alphaF()]; + if (bgColor.alpha() != 255) { + // No way we can have it bezeled and transparent ... + tf.bordered = YES; + } + } + } + [tf.cell drawWithFrame:rect inView:tf]; }); } else { @@ -3225,21 +3248,36 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai } break; case PE_PanelLineEdit: - QCommonStyle::drawPrimitive(pe, opt, p, w); - // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). - // Focus frame is drawn outside the rectangle passed in the option-rect. - if (const QStyleOptionFrame *panel = qstyleoption_cast(opt)) { -#if QT_CONFIG(lineedit) - if ((opt->state & State_HasFocus) && !qobject_cast(w)) { - int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); - int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); - QStyleOptionFrame focusFrame = *panel; - focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); - drawControl(CE_FocusFrame, &focusFrame, p, w); + { + const QStyleOptionFrame *panel = qstyleoption_cast(opt); + if (qt_mac_applicationIsInDarkMode() || (panel && panel->lineWidth <= 0)) { + // QCommonStyle::drawPrimitive(PE_PanelLineEdit) fill the background with + // a proper color, defined in opt->palette and then, if lineWidth > 0, it + // calls QMacStyle::drawPrimitive(PE_FrameLineEdit). We use NSTextFieldCell + // to handle PE_FrameLineEdit, which will use system-default background. + // In 'Dark' mode it's transparent and thus it's not over-painted. + QCommonStyle::drawPrimitive(pe, opt, p, w); + } else { + // In 'Light' mode, if panel->lineWidth > 0, we have to use the correct + // background color when drawing PE_FrameLineEdit, so let's call it + // directly and set the proper color there. + drawPrimitive(PE_FrameLineEdit, opt, p, w); } + + // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). + // Focus frame is drawn outside the rectangle passed in the option-rect. + if (panel) { +#if QT_CONFIG(lineedit) + if ((opt->state & State_HasFocus) && !qobject_cast(w)) { + int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); + int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); + QStyleOptionFrame focusFrame = *panel; + focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); + drawControl(CE_FocusFrame, &focusFrame, p, w); + } #endif + } } - break; case PE_PanelScrollAreaCorner: { const QBrush brush(opt->palette.brush(QPalette::Base)); -- cgit v1.2.3 From c9b9a0ea2f274688da26af20102d349336fdb2a0 Mon Sep 17 00:00:00 2001 From: Elena Zaretskaya Date: Fri, 11 Jan 2019 10:11:03 -0500 Subject: Ability to switch language under platform eglfs/linuxfb I need to change keymap under platforms eglfs and linuxfb (without wayland). I use the function QEglFSFunctions::loadKeymap(const QString&), but there's no way to switch between english and another language than to press AltGr as a modifier. I added the function that allows to change the language. And also added the ability to switch the keymap and language for the platform linuxfb and also added the ability to switch the keymap and language for the platform linuxfb Task-number: QTBUG-72452 Change-Id: I37432cf60d375555bea2bf668ec1387322b4964f Reviewed-by: Laszlo Agocs --- .../platforms/eglfs/api/qeglfsintegration.cpp | 13 ++++++ .../platforms/eglfs/api/qeglfsintegration_p.h | 1 + .../platforms/linuxfb/qlinuxfbintegration.cpp | 49 +++++++++++++++++++--- .../platforms/linuxfb/qlinuxfbintegration.h | 8 +++- 4 files changed, 65 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp index 72420199e3..8ccb0ef2cd 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp @@ -429,6 +429,8 @@ QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function) #if QT_CONFIG(evdev) if (function == QEglFSFunctions::loadKeymapTypeIdentifier()) return QFunctionPointer(loadKeymapStatic); + else if (function == QEglFSFunctions::switchLangTypeIdentifier()) + return QFunctionPointer(switchLangStatic); #endif return qt_egl_device_integration()->platformFunction(function); @@ -447,6 +449,17 @@ void QEglFSIntegration::loadKeymapStatic(const QString &filename) #endif } +void QEglFSIntegration::switchLangStatic() +{ +#if QT_CONFIG(evdev) + QEglFSIntegration *self = static_cast(QGuiApplicationPrivate::platformIntegration()); + if (self->m_kbdMgr) + self->m_kbdMgr->switchLang(); + else + qWarning("QEglFSIntegration: Cannot switch language, no keyboard handler found"); +#endif +} + void QEglFSIntegration::createInputHandlers() { #if QT_CONFIG(libinput) diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h index c288876678..4b4585d33c 100644 --- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h +++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h @@ -110,6 +110,7 @@ private: EGLNativeDisplayType nativeDisplay() const; void createInputHandlers(); static void loadKeymapStatic(const QString &filename); + static void switchLangStatic(); EGLDisplay m_display; QPlatformInputContext *m_inputContext; diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index f835dbf6d4..9e38900bcd 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -69,12 +69,15 @@ #include #endif +#include + QT_BEGIN_NAMESPACE QLinuxFbIntegration::QLinuxFbIntegration(const QStringList ¶mList) : m_primaryScreen(nullptr), m_fontDb(new QGenericUnixFontDatabase), - m_services(new QGenericUnixServices) + m_services(new QGenericUnixServices), + m_kbdMgr(0) { #if QT_CONFIG(kms) if (qEnvironmentVariableIntValue("QT_QPA_FB_DRM") != 0) @@ -98,8 +101,6 @@ void QLinuxFbIntegration::initialize() m_inputContext = QPlatformInputContextFactory::create(); - m_nativeInterface.reset(new QPlatformNativeInterface); - m_vtHandler.reset(new QFbVtHandler); if (!qEnvironmentVariableIntValue("QT_QPA_FB_DISABLE_INPUT")) @@ -163,7 +164,7 @@ void QLinuxFbIntegration::createInputHandlers() #endif #if QT_CONFIG(evdev) - new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); + m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); #if QT_CONFIG(tslib) if (!useTslib) @@ -174,7 +175,45 @@ void QLinuxFbIntegration::createInputHandlers() QPlatformNativeInterface *QLinuxFbIntegration::nativeInterface() const { - return m_nativeInterface.data(); + return const_cast(this); +} + +QFunctionPointer QLinuxFbIntegration::platformFunction(const QByteArray &function) const +{ +#if QT_CONFIG(evdev) + if (function == QLinuxFbFunctions::loadKeymapTypeIdentifier()) + return QFunctionPointer(loadKeymapStatic); + else if (function == QLinuxFbFunctions::switchLangTypeIdentifier()) + return QFunctionPointer(switchLangStatic); +#else + Q_UNUSED(function) +#endif + + return 0; +} + +void QLinuxFbIntegration::loadKeymapStatic(const QString &filename) +{ +#if QT_CONFIG(evdev) + QLinuxFbIntegration *self = static_cast(QGuiApplicationPrivate::platformIntegration()); + if (self->m_kbdMgr) + self->m_kbdMgr->loadKeymap(filename); + else + qWarning("QLinuxFbIntegration: Cannot load keymap, no keyboard handler found"); +#else + Q_UNUSED(filename); +#endif +} + +void QLinuxFbIntegration::switchLangStatic() +{ +#if QT_CONFIG(evdev) + QLinuxFbIntegration *self = static_cast(QGuiApplicationPrivate::platformIntegration()); + if (self->m_kbdMgr) + self->m_kbdMgr->switchLang(); + else + qWarning("QLinuxFbIntegration: Cannot switch language, no keyboard handler found"); +#endif } QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h index 22578bf980..7a871b3812 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QAbstractEventDispatcher; class QFbScreen; class QFbVtHandler; +class QEvdevKeyboardManager; class QLinuxFbIntegration : public QPlatformIntegration, public QPlatformNativeInterface { @@ -71,15 +72,20 @@ public: QList screens() const; + QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE; + private: void createInputHandlers(); + static void loadKeymapStatic(const QString &filename); + static void switchLangStatic(); QFbScreen *m_primaryScreen; QPlatformInputContext *m_inputContext; QScopedPointer m_fontDb; QScopedPointer m_services; QScopedPointer m_vtHandler; - QScopedPointer m_nativeInterface; + + QEvdevKeyboardManager *m_kbdMgr; }; QT_END_NAMESPACE -- cgit v1.2.3 From 730cbad8824bcfcb7ab60371a6563cfb6dd5658d Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 24 Jan 2019 15:53:28 +0300 Subject: xcb: Avoid repaint lags with DnD The lags can be seen when dragged data is requested for a MIME type. This leads to calling QXcbClipboard::waitForClipboardEvent() which runs a loop in the GUI thread and processes events from QXcbEventQueue. The loop ends when a corresponding event is received, otherwise it makes a delay of 50 ms before the next iteration. Sync with QXcbEventQueue thread by QWaitCondition instead of using the delay. This way the loop will end as soon as possible and Expose events will be processed with minimal delay. Task-number: QTBUG-44849 Fixes: QTBUG-55442 Fixes: QTBUG-62344 Fixes: QTBUG-73253 Change-Id: Ie18d63b51a7260c83d53ffe1169b25e5135dd73b Reviewed-by: Mikhail Svetkin Reviewed-by: Gatis Paeglis Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 5 +++-- src/plugins/platforms/xcb/qxcbeventqueue.cpp | 9 +++++++++ src/plugins/platforms/xcb/qxcbeventqueue.h | 7 +++++++ 3 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index bc92f82d5f..ac8b029916 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -810,8 +810,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i connection()->flush(); - // sleep 50 ms, so we don't use up CPU cycles all the time. - QThread::msleep(50); + const auto elapsed = timer.elapsed(); + if (elapsed < clipboard_timeout) + queue->waitForNewEvents(clipboard_timeout - elapsed); } while (timer.elapsed() < clipboard_timeout); return nullptr; diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp index f6158d3127..acec0486c2 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp +++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp @@ -229,6 +229,8 @@ void QXcbEventQueue::run() enqueueEvent(event); while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection))) enqueueEvent(event); + + m_newEventsCondition.wakeOne(); wakeUpDispatcher(); } @@ -346,6 +348,13 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData, return result; } +void QXcbEventQueue::waitForNewEvents(unsigned long time) +{ + m_newEventsMutex.lock(); + m_newEventsCondition.wait(&m_newEventsMutex, time); + m_newEventsMutex.unlock(); +} + void QXcbEventQueue::sendCloseConnectionEvent() const { // A hack to close XCB connection. Apparently XCB does not have any APIs for this? diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.h b/src/plugins/platforms/xcb/qxcbeventqueue.h index 235f2824be..11d0b8e963 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.h +++ b/src/plugins/platforms/xcb/qxcbeventqueue.h @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include @@ -104,6 +106,8 @@ public: bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr, PeekOptions option = PeekDefault, qint32 peekerId = -1); + void waitForNewEvents(unsigned long time = ULONG_MAX); + private: QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event); void dequeueNode(); @@ -131,6 +135,9 @@ private: // debug stats quint64 m_nodesOnHeap = 0; + + QMutex m_newEventsMutex; + QWaitCondition m_newEventsCondition; }; template -- cgit v1.2.3