feat: support horizontal scrolling
fixes: #7220
based on 9f15b1bcf2
Co-authored-by: Evan Maddock <maddock.evan@vivaldi.net>
This commit is contained in:
parent
82588a7fc9
commit
a532f655c1
8 changed files with 69 additions and 38 deletions
|
|
@ -30,6 +30,8 @@ static const ButtonID kMacButtonMiddle = 3;
|
|||
// Only used for X11 Scroll Wheel
|
||||
static const ButtonID kX11ScrollWheelUp = 255;
|
||||
static const ButtonID kX11ScrollWheelDown = 254;
|
||||
static const ButtonID kX11ScrollWheelLeft = 6;
|
||||
static const ButtonID kX11ScrollWheelRight = 7;
|
||||
//@}
|
||||
|
||||
static const uint8_t NumButtonIDs = 6;
|
||||
|
|
|
|||
|
|
@ -100,4 +100,7 @@ protected:
|
|||
Converts a sides mask (e.g. LeftMask | RightMask) to a string representation (e.g. "LR").
|
||||
*/
|
||||
static std::string sidesMaskToString(uint32_t sides);
|
||||
|
||||
// Delta for a "click"
|
||||
static const auto s_scrollDelta = 120;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -672,7 +672,7 @@ void EiScreen::onPointerScrollEvent(ei_event *event)
|
|||
// convert between the two and keep the remainders because
|
||||
// we will very likely get subpixel scroll events.
|
||||
// This means a single pixel is 120/s_pixelToWheelRation in wheel values.
|
||||
const int s_pixelToWheelRatio = 120 / s_pixelsPerWheelClick;
|
||||
const int s_pixelToWheelRatio = s_scrollDelta / s_pixelsPerWheelClick;
|
||||
|
||||
assert(m_isPrimary);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@
|
|||
#define SPI_GETSCREENSAVERRUNNING 114
|
||||
#endif
|
||||
|
||||
#if !defined(MOUSEEVENTF_HWHEEL)
|
||||
#define MOUSEEVENTF_HWHEEL 0x1000
|
||||
#endif
|
||||
|
||||
// X button stuff
|
||||
#if !defined(WM_XBUTTONDOWN)
|
||||
#define WM_XBUTTONDOWN 0x020B
|
||||
|
|
@ -697,6 +701,9 @@ void MSWindowsDesks::deskThread(const void *vdesk)
|
|||
if (msg.lParam != 0) {
|
||||
send_mouse_input(MOUSEEVENTF_WHEEL, 0, 0, (DWORD)msg.lParam);
|
||||
}
|
||||
if (msg.wParam != 0) {
|
||||
send_mouse_input(MOUSEEVENTF_HWHEEL, 0, 0, (DWORD)msg.wParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case DESKFLOW_MSG_CURSOR_POS: {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@
|
|||
#include "base/Log.h"
|
||||
#include "deskflow/ScreenException.h"
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
#define WM_MOUSEHWHEEL 0x020E
|
||||
#endif
|
||||
|
||||
static const char *g_name = "dfwhook";
|
||||
|
||||
static DWORD g_processID = 0;
|
||||
|
|
@ -505,6 +509,13 @@ static bool mouseHookHandler(WPARAM wParam, int32_t x, int32_t y, int32_t data)
|
|||
}
|
||||
return (g_mode == kHOOK_RELAY_EVENTS);
|
||||
|
||||
case WM_MOUSEHWHEEL:
|
||||
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||
// relay event
|
||||
PostThreadMessage(g_threadID, DESKFLOW_MSG_MOUSE_WHEEL, 0, data);
|
||||
}
|
||||
return (g_mode == kHOOK_RELAY_EVENTS);
|
||||
|
||||
case WM_NCMOUSEMOVE:
|
||||
case WM_MOUSEMOVE:
|
||||
if (g_mode == kHOOK_RELAY_EVENTS) {
|
||||
|
|
@ -620,9 +631,10 @@ EHookResult MSWindowsHook::install()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
// check that we got all the hooks we wanted
|
||||
if ((g_mouseLL == nullptr) ||
|
||||
if (
|
||||
(g_mouseLL == nullptr) ||
|
||||
#if !NO_GRAB_KEYBOARD
|
||||
(g_keyboardLL == nullptr)
|
||||
#endif
|
||||
|
|
@ -630,7 +642,7 @@ EHookResult MSWindowsHook::install()
|
|||
uninstall();
|
||||
return kHOOK_FAILED;
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
if (g_keyboardLL != nullptr || g_mouseLL != nullptr) {
|
||||
g_hookThread = GetCurrentThreadId();
|
||||
return kHOOK_OKAY_LL;
|
||||
|
|
|
|||
|
|
@ -897,8 +897,7 @@ bool MSWindowsScreen::onPreDispatchPrimary(HWND, UINT message, WPARAM wParam, LP
|
|||
return onMouseMove(static_cast<int32_t>(wParam), static_cast<int32_t>(lParam));
|
||||
|
||||
case DESKFLOW_MSG_MOUSE_WHEEL:
|
||||
// XXX -- support x-axis scrolling
|
||||
return onMouseWheel(0, static_cast<int32_t>(wParam));
|
||||
return onMouseWheel(static_cast<int32_t>(lParam), static_cast<int32_t>(wParam));
|
||||
|
||||
case DESKFLOW_MSG_PRE_WARP: {
|
||||
// save position to compute delta of next motion
|
||||
|
|
|
|||
|
|
@ -400,6 +400,7 @@ void OSXScreen::constructMouseButtonEventMap()
|
|||
{kCGEventRightMouseUp, kCGEventRightMouseDragged, kCGEventRightMouseDown},
|
||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
|
||||
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}
|
||||
};
|
||||
|
||||
|
|
@ -589,8 +590,9 @@ void OSXScreen::fakeMouseWheel(ScrollDelta delta) const
|
|||
if (delta.x != 0 || delta.y != 0) {
|
||||
// use server's acceleration with a little boost since other platforms
|
||||
// take one wheel step as a larger step than the mac does.
|
||||
delta =
|
||||
applyScrollModifier({static_cast<int32_t>(3.0 * delta.x / 120.0), static_cast<int32_t>(3.0 * delta.y / 120.0)});
|
||||
delta = applyScrollModifier(
|
||||
{static_cast<int32_t>(3.0 * delta.x / s_scrollDelta), static_cast<int32_t>(3.0 * delta.y / s_scrollDelta)}
|
||||
);
|
||||
// create a scroll event, post it and release it. not sure if kCGScrollEventUnitLine
|
||||
// is the right choice here over kCGScrollEventUnitPixel
|
||||
CGEventRef scrollEvent = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitLine, 2, delta.y, delta.x);
|
||||
|
|
|
|||
|
|
@ -786,44 +786,39 @@ void XWindowsScreen::fakeMouseRelativeMove(int32_t dx, int32_t dy) const
|
|||
|
||||
void XWindowsScreen::fakeMouseWheel(ScrollDelta delta) const
|
||||
{
|
||||
// XXX -- support x-axis scrolling
|
||||
if (delta.y == 0) {
|
||||
if (delta.y == 0 && delta.x == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
delta = applyScrollModifier(delta);
|
||||
bool isYScroll = delta.y != 0;
|
||||
int32_t axisDelta = delta.y == 0 ? delta.x : delta.y;
|
||||
|
||||
// choose button depending on rotation direction
|
||||
const unsigned int xButton = mapButtonToX(delta.y >= 0 ? kX11ScrollWheelUp : kX11ScrollWheelDown);
|
||||
if (xButton == 0) {
|
||||
// If we get here, then the XServer does not support the scroll
|
||||
// wheel buttons, so send PageUp/PageDown keystrokes instead.
|
||||
// Patch by Tom Chadwick.
|
||||
KeyCode keycode = 0;
|
||||
if (delta.y >= 0) {
|
||||
keycode = XKeysymToKeycode(m_display, XK_Page_Up);
|
||||
} else {
|
||||
keycode = XKeysymToKeycode(m_display, XK_Page_Down);
|
||||
}
|
||||
if (keycode != 0) {
|
||||
XTestFakeKeyEvent(m_display, keycode, True, CurrentTime);
|
||||
XTestFakeKeyEvent(m_display, keycode, False, CurrentTime);
|
||||
}
|
||||
ButtonID btn = kButtonNone;
|
||||
if (isYScroll) {
|
||||
btn = axisDelta >= 0 ? kX11ScrollWheelUp : kX11ScrollWheelDown;
|
||||
} else {
|
||||
btn = axisDelta >= 0 ? kX11ScrollWheelLeft : kX11ScrollWheelRight;
|
||||
}
|
||||
const unsigned int button = mapButtonToX(btn);
|
||||
|
||||
// If the XServer does not support the Y scroll send PageUp/PageDown keystrokes instead.
|
||||
if (const KeyCode keycode = XKeysymToKeycode(m_display, delta.y >= 0 ? XK_Page_Up : XK_Page_Down);
|
||||
button == 0 && isYScroll && keycode != 0) {
|
||||
XTestFakeKeyEvent(m_display, keycode, True, CurrentTime);
|
||||
XTestFakeKeyEvent(m_display, keycode, False, CurrentTime);
|
||||
return;
|
||||
}
|
||||
|
||||
// now use absolute value of delta
|
||||
if (delta.y < 0) {
|
||||
delta.y = -delta.y;
|
||||
if (axisDelta < 0) {
|
||||
axisDelta = -axisDelta;
|
||||
}
|
||||
|
||||
// Delta for a "click"
|
||||
static const auto s_mouseDelta = 120;
|
||||
|
||||
// send as many clicks as necessary
|
||||
for (; delta.y >= 0; delta.y -= s_mouseDelta) {
|
||||
XTestFakeButtonEvent(m_display, xButton, True, CurrentTime);
|
||||
XTestFakeButtonEvent(m_display, xButton, False, CurrentTime);
|
||||
while (axisDelta >= 0) {
|
||||
XTestFakeButtonEvent(m_display, button, True, CurrentTime);
|
||||
XTestFakeButtonEvent(m_display, button, False, CurrentTime);
|
||||
axisDelta -= s_scrollDelta;
|
||||
}
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
|
@ -1461,12 +1456,17 @@ void XWindowsScreen::onMouseRelease(const XButtonEvent &xbutton)
|
|||
sendEvent(PrimaryScreenButtonUp, ButtonInfo::alloc(button, mask));
|
||||
} else if (xbutton.button == 4) {
|
||||
// wheel forward (away from user)
|
||||
sendEvent(PrimaryScreenWheel, WheelInfo::alloc(0, 120));
|
||||
sendEvent(PrimaryScreenWheel, WheelInfo::alloc(0, s_scrollDelta));
|
||||
} else if (xbutton.button == 5) {
|
||||
// wheel backward (toward user)
|
||||
sendEvent(PrimaryScreenWheel, WheelInfo::alloc(0, -120));
|
||||
sendEvent(PrimaryScreenWheel, WheelInfo::alloc(0, -s_scrollDelta));
|
||||
} else if (xbutton.button == 6) {
|
||||
// wheel tilt left
|
||||
sendEvent(PrimaryScreenWheel, WheelInfo::alloc(-s_scrollDelta, 0));
|
||||
} else if (xbutton.button == 7) {
|
||||
// wheel tilt right
|
||||
sendEvent(PrimaryScreenWheel, WheelInfo::alloc(s_scrollDelta, 0));
|
||||
}
|
||||
// XXX -- support x-axis scrolling
|
||||
}
|
||||
|
||||
void XWindowsScreen::onMouseMove(const XMotionEvent &xmotion)
|
||||
|
|
@ -1740,6 +1740,8 @@ ButtonID XWindowsScreen::mapButtonFromX(const XButtonEvent *event) const
|
|||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 6:
|
||||
case 7:
|
||||
return static_cast<ButtonID>(button); // Handle Left, Middle and Right buttons
|
||||
case 8:
|
||||
return kButtonExtra0; // Mouse 4
|
||||
|
|
@ -1761,6 +1763,10 @@ unsigned int XWindowsScreen::mapButtonToX(ButtonID id) const
|
|||
return 4;
|
||||
case kX11ScrollWheelDown:
|
||||
return 5;
|
||||
case kX11ScrollWheelLeft:
|
||||
return 6;
|
||||
case kX11ScrollWheelRight:
|
||||
return 7;
|
||||
case kButtonExtra0:
|
||||
return 8;
|
||||
case kButtonExtra1:
|
||||
|
|
|
|||
Loading…
Reference in a new issue