Windows QPA: Fix duplicate/missing native events
Add utility functions to QWindowsContext input messages sent to native event filters (event dispatcher and window system interface). Do not send input and similar events to the event dispatcher since QEventDispatcherWin32::processEvents() also sends them. Note though that QEventDispatcherWin32 does not receive all windows messages. In QWindowsKeyMapper, send the WM_CHAR/WM_IMECHAR events from where the messages are removed. Task-number: QTBUG-67095 Change-Id: I5f61294fcb3aee7e0eacd840a2010d128cd02a5d Reviewed-by: Andre de la Rocha <andre.rocha@qt.io> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
parent
ab6cc41968
commit
a0a22037cd
@ -246,14 +246,12 @@ struct QWindowsContextPrivate {
|
||||
QScopedPointer<QWindowsTabletSupport> m_tabletSupport;
|
||||
#endif
|
||||
const HRESULT m_oleInitializeResult;
|
||||
const QByteArray m_eventType;
|
||||
QWindow *m_lastActiveWindow = nullptr;
|
||||
bool m_asyncExpose = false;
|
||||
};
|
||||
|
||||
QWindowsContextPrivate::QWindowsContextPrivate()
|
||||
: m_oleInitializeResult(OleInitialize(NULL))
|
||||
, m_eventType(QByteArrayLiteral("windows_generic_MSG"))
|
||||
{
|
||||
QWindowsContext::user32dll.init();
|
||||
QWindowsContext::shcoredll.init();
|
||||
@ -866,6 +864,33 @@ static bool shouldHaveNonClientDpiScaling(const QWindow *window)
|
||||
;
|
||||
}
|
||||
|
||||
static inline bool isInputMessage(UINT m)
|
||||
{
|
||||
switch (m) {
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
case WM_TOUCH:
|
||||
case WM_MOUSEHOVER:
|
||||
case WM_MOUSELEAVE:
|
||||
case WM_NCHITTEST:
|
||||
case WM_NCMOUSEHOVER:
|
||||
case WM_NCMOUSELEAVE:
|
||||
case WM_SIZING:
|
||||
case WM_MOVING:
|
||||
case WM_SYSCOMMAND:
|
||||
case WM_COMMAND:
|
||||
case WM_DWMNCRENDERINGCHANGED:
|
||||
case WM_PAINT:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (m >= WM_MOUSEFIRST && m <= WM_MOUSELAST)
|
||||
|| (m >= WM_NCMOUSEMOVE && m <= WM_NCXBUTTONDBLCLK)
|
||||
|| (m >= WM_KEYFIRST && m <= WM_KEYLAST);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Main windows procedure registered for windows.
|
||||
|
||||
@ -901,21 +926,14 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
||||
QWindowsWindow *platformWindow = findPlatformWindow(hwnd);
|
||||
*platformWindowPtr = platformWindow;
|
||||
|
||||
// Run the native event filters.
|
||||
long filterResult = 0;
|
||||
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
|
||||
if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) {
|
||||
*result = LRESULT(filterResult);
|
||||
// Run the native event filters. QTBUG-67095: Exclude input messages which are sent
|
||||
// by QEventDispatcherWin32::processEvents()
|
||||
if (!isInputMessage(msg.message) && filterNativeEvent(&msg, result))
|
||||
return true;
|
||||
|
||||
if (platformWindow && filterNativeEvent(platformWindow->window(), &msg, result))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (platformWindow) {
|
||||
filterResult = 0;
|
||||
if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) {
|
||||
*result = LRESULT(filterResult);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (et & QtWindows::InputMethodEventFlag) {
|
||||
QWindowsInputContext *windowsInputContext = ::windowsInputContext();
|
||||
// Disable IME assuming this is a special implementation hooking into keyboard input.
|
||||
@ -1393,4 +1411,30 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_generic_MSG"); }
|
||||
|
||||
// Send to QAbstractEventDispatcher
|
||||
bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result)
|
||||
{
|
||||
QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance();
|
||||
long filterResult = 0;
|
||||
if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) {
|
||||
*result = LRESULT(filterResult);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send to QWindowSystemInterface
|
||||
bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result)
|
||||
{
|
||||
long filterResult = 0;
|
||||
if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), &msg, &filterResult)) {
|
||||
*result = LRESULT(filterResult);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -212,6 +212,9 @@ public:
|
||||
|
||||
QTouchDevice *touchDevice() const;
|
||||
|
||||
static bool filterNativeEvent(MSG *msg, LRESULT *result);
|
||||
static bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result);
|
||||
|
||||
private:
|
||||
void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w);
|
||||
#ifndef QT_NO_CONTEXTMENU
|
||||
|
@ -830,7 +830,7 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
|
||||
if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR)
|
||||
return true;
|
||||
|
||||
return translateKeyEventInternal(widget, msg, false);
|
||||
return translateKeyEventInternal(widget, msg, false, result);
|
||||
}
|
||||
|
||||
bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg)
|
||||
@ -862,7 +862,7 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */)
|
||||
bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */, LRESULT *lResult)
|
||||
{
|
||||
const UINT msgType = msg.message;
|
||||
|
||||
@ -1056,6 +1056,10 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
|
||||
|
||||
QChar uch;
|
||||
if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) {
|
||||
if (QWindowsContext::filterNativeEvent(&wm_char, lResult))
|
||||
return true;
|
||||
if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult))
|
||||
return true;
|
||||
// Found a ?_CHAR
|
||||
uch = QChar(ushort(wm_char.wParam));
|
||||
if (uch.isHighSurrogate()) {
|
||||
|
@ -90,7 +90,7 @@ public:
|
||||
QList<int> possibleKeys(const QKeyEvent *e) const;
|
||||
|
||||
private:
|
||||
bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab);
|
||||
bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab, LRESULT *lResult);
|
||||
bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg);
|
||||
void updateKeyMap(const MSG &msg);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user