Windows: Add support for horizontal scroll on some touchpads.

While most (all?) touchpads send WM_MOUSEWHEEL for vertical scroll
the story is quite different for horizontal scroll. Some of them
send WM_HSCROLL instead of WM_MOUSEHWHEEL.

Some of them even send left/right key event but those are lost cases.

Task-number: QTBUG-45120
Change-Id: I3bf86e25a6f4f3ba03ac7e89a23f4b7bc432f2de
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
bb10
Sérgio Martins 2015-03-25 13:37:31 +00:00
parent eea5a6ea15
commit f451d48005
4 changed files with 69 additions and 18 deletions

View File

@ -57,7 +57,8 @@ enum
TouchEventFlag = 0x400000,
ClipboardEventFlag = 0x800000,
ApplicationEventFlag = 0x1000000,
ThemingEventFlag = 0x2000000
ThemingEventFlag = 0x2000000,
GenericEventFlag = 0x4000000, // Misc
};
enum WindowsEventType // Simplify event types
@ -108,6 +109,7 @@ enum WindowsEventType // Simplify event types
CompositionSettingsChanged = ThemingEventFlag + 2,
DisplayChangedEvent = 437,
SettingChangedEvent = DisplayChangedEvent + 1,
ScrollEvent = GenericEventFlag + 1,
ContextMenu = 123,
GestureEvent = 124,
UnknownEvent = 542
@ -145,6 +147,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::CursorEvent;
case WM_MOUSELEAVE:
return QtWindows::MouseEvent;
case WM_HSCROLL:
return QtWindows::ScrollEvent;
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
return QtWindows::MouseWheelEvent;

View File

@ -1031,6 +1031,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
QWindowsWindow::baseWindowOf(platformWindow->window())->applyCursor();
return true;
}
#endif
case QtWindows::ScrollEvent:
#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER)
return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
#else
return d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
#endif
case QtWindows::MouseWheelEvent:
case QtWindows::MouseEvent:

View File

@ -42,6 +42,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtGui/QCursor>
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
@ -375,6 +376,31 @@ static bool isValidWheelReceiver(QWindow *candidate)
return false;
}
static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int delta,
Qt::Orientation orientation, Qt::KeyboardModifiers mods)
{
// Redirect wheel event to one of the following, in order of preference:
// 1) The window under mouse
// 2) The window receiving the event
// If a window is blocked by modality, it can't get the event.
QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE);
bool handleEvent = true;
if (!isValidWheelReceiver(receiver)) {
receiver = window;
if (!isValidWheelReceiver(receiver))
handleEvent = false;
}
if (handleEvent) {
const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor();
QWindowSystemInterface::handleWheelEvent(receiver,
posDip, globalPos / QWindowsScaling::factor(),
delta / QWindowsScaling::factor(),
orientation, mods);
}
}
bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND,
MSG msg, LRESULT *)
{
@ -397,26 +423,39 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND,
if (msg.message == WM_MOUSEHWHEEL)
delta = -delta;
// Redirect wheel event to one of the following, in order of preference:
// 1) The window under mouse
// 2) The window receiving the event
// If a window is blocked by modality, it can't get the event.
const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE);
bool handleEvent = true;
if (!isValidWheelReceiver(receiver)) {
receiver = window;
if (!isValidWheelReceiver(receiver))
handleEvent = false;
redirectWheelEvent(window, globalPos, delta, orientation, mods);
return true;
}
bool QWindowsMouseHandler::translateScrollEvent(QWindow *window, HWND,
MSG msg, LRESULT *)
{
// This is a workaround against some touchpads that send WM_HSCROLL instead of WM_MOUSEHWHEEL.
// We could also handle vertical scroll here but there's no reason to, there's no bug for vertical
// (broken vertical scroll would have been noticed long time ago), so lets keep the change small
// and minimize the chance for regressions.
int delta = 0;
switch (LOWORD(msg.wParam)) {
case SB_LINELEFT:
delta = 120;
break;
case SB_LINERIGHT:
delta = -120;
break;
case SB_PAGELEFT:
delta = 240;
break;
case SB_PAGERIGHT:
delta = -240;
break;
default:
return false;
}
if (handleEvent) {
const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor();
QWindowSystemInterface::handleWheelEvent(receiver,
posDip, globalPos / QWindowsScaling::factor(),
delta / QWindowsScaling::factor(),
orientation, mods);
}
redirectWheelEvent(window, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier);
return true;
}

View File

@ -59,6 +59,8 @@ public:
bool translateTouchEvent(QWindow *widget, HWND hwnd,
QtWindows::WindowsEventType t, MSG msg,
LRESULT *result);
bool translateScrollEvent(QWindow *window, HWND hwnd,
MSG msg, LRESULT *result);
static inline Qt::MouseButtons keyStateToMouseButtons(int);
static inline Qt::KeyboardModifiers keyStateToModifiers(int);