Merge pull request #391 from EbonJaeger

Re-implement patch for horizontal scrolling and extra mouse buttons
This commit is contained in:
Adrian Lucrèce Céleste 2019-08-22 14:57:46 -04:00 committed by GitHub
commit ccfa10f2a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 111 additions and 81 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ CMakeCache.txt
.vscode/ .vscode/
# Transient in-project-directory dependencies # Transient in-project-directory dependencies
/deps/ /deps/
/out/build/x64-Debug

View File

@ -32,10 +32,13 @@ static const ButtonID kButtonNone = 0;
static const ButtonID kButtonLeft = 1; static const ButtonID kButtonLeft = 1;
static const ButtonID kButtonMiddle = 2; static const ButtonID kButtonMiddle = 2;
static const ButtonID kButtonRight = 3; static const ButtonID kButtonRight = 3;
// mouse button 4
static const ButtonID kButtonExtra0 = 4; static const ButtonID kButtonExtra0 = 4;
// mouse button 5
static const ButtonID kButtonExtra1 = 5;
static const ButtonID kMacButtonRight = 2; static const ButtonID kMacButtonRight = 2;
static const ButtonID kMacButtonMiddle = 3; static const ButtonID kMacButtonMiddle = 3;
//@} //@}
static const UInt8 NumButtonIDs = 5; static const UInt8 NumButtonIDs = 6;

View File

@ -33,6 +33,7 @@
#include "base/IEventQueue.h" #include "base/IEventQueue.h"
#include <malloc.h> #include <malloc.h>
#include <VersionHelpers.h>
// these are only defined when WINVER >= 0x0500 // these are only defined when WINVER >= 0x0500
#if !defined(SPI_GETMOUSESPEED) #if !defined(SPI_GETMOUSESPEED)
@ -45,6 +46,10 @@
#define SPI_GETSCREENSAVERRUNNING 114 #define SPI_GETSCREENSAVERRUNNING 114
#endif #endif
#if !defined(MOUSEEVENTF_HWHEEL)
#define MOUSEEVENTF_HWHEEL 0x1000
#endif
// X button stuff // X button stuff
#if !defined(WM_XBUTTONDOWN) #if !defined(WM_XBUTTONDOWN)
#define WM_XBUTTONDOWN 0x020B #define WM_XBUTTONDOWN 0x020B
@ -296,12 +301,12 @@ MSWindowsDesks::fakeMouseButton(ButtonID button, bool press)
flags = press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; flags = press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
break; break;
case kButtonExtra0 + 0: case kButtonExtra0:
data = XBUTTON1; data = XBUTTON1;
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
break; break;
case kButtonExtra0 + 1: case kButtonExtra1:
data = XBUTTON2; data = XBUTTON2;
flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP;
break; break;
@ -686,10 +691,12 @@ MSWindowsDesks::deskThread(void* vdesk)
break; break;
case BARRIER_MSG_FAKE_WHEEL: case BARRIER_MSG_FAKE_WHEEL:
// XXX -- add support for x-axis scrolling
if (msg.lParam != 0) { if (msg.lParam != 0) {
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, (DWORD)msg.lParam, 0); mouse_event(MOUSEEVENTF_WHEEL, 0, 0, (DWORD)msg.lParam, 0);
} }
else if (IsWindowsVistaOrGreater() && msg.wParam != 0) {
mouse_event(MOUSEEVENTF_HWHEEL, 0, 0, (DWORD)msg.wParam, 0);
}
break; break;
case BARRIER_MSG_CURSOR_POS: { case BARRIER_MSG_CURSOR_POS: {

View File

@ -25,6 +25,10 @@
#include "common/DataDirectories.h" #include "common/DataDirectories.h"
#include "base/Log.h" #include "base/Log.h"
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
// //
// debugging compile flag. when not zero the server doesn't grab // debugging compile flag. when not zero the server doesn't grab
// the keyboard when the mouse leaves the server screen. this // the keyboard when the mouse leaves the server screen. this
@ -473,6 +477,13 @@ mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data)
} }
return (g_mode == kHOOK_RELAY_EVENTS); return (g_mode == kHOOK_RELAY_EVENTS);
case WM_MOUSEHWHEEL:
if (g_mode == kHOOK_RELAY_EVENTS) {
// relay event
PostThreadMessage(g_threadID, BARRIER_MSG_MOUSE_WHEEL, 0, data);
}
return (g_mode == kHOOK_RELAY_EVENTS);
case WM_NCMOUSEMOVE: case WM_NCMOUSEMOVE:
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
if (g_mode == kHOOK_RELAY_EVENTS) { if (g_mode == kHOOK_RELAY_EVENTS) {

View File

@ -952,9 +952,9 @@ MSWindowsScreen::updateButtons()
m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0); m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0);
m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0); m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0);
m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0); m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0);
m_buttons[kButtonExtra0 + 0] = (numButtons >= 4) && m_buttons[kButtonExtra0] = (numButtons >= 4) &&
(GetKeyState(VK_XBUTTON1) < 0); (GetKeyState(VK_XBUTTON1) < 0);
m_buttons[kButtonExtra0 + 1] = (numButtons >= 5) && m_buttons[kButtonExtra1] = (numButtons >= 5) &&
(GetKeyState(VK_XBUTTON2) < 0); (GetKeyState(VK_XBUTTON2) < 0);
} }
@ -1007,8 +1007,7 @@ MSWindowsScreen::onPreDispatchPrimary(HWND,
static_cast<SInt32>(lParam)); static_cast<SInt32>(lParam));
case BARRIER_MSG_MOUSE_WHEEL: case BARRIER_MSG_MOUSE_WHEEL:
// XXX -- support x-axis scrolling return onMouseWheel(static_cast<SInt32>(lParam), static_cast<SInt32>(wParam));
return onMouseWheel(0, static_cast<SInt32>(wParam));
case BARRIER_MSG_PRE_WARP: case BARRIER_MSG_PRE_WARP:
{ {
@ -1670,13 +1669,13 @@ MSWindowsScreen::mapButtonFromEvent(WPARAM msg, LPARAM button) const
switch (button) { switch (button) {
case XBUTTON1: case XBUTTON1:
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) { if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) {
return kButtonExtra0 + 0; return kButtonExtra0;
} }
break; break;
case XBUTTON2: case XBUTTON2:
if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) { if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) {
return kButtonExtra0 + 1; return kButtonExtra1;
} }
break; break;
} }

View File

@ -307,7 +307,7 @@ private:
HotKeyToIDMap m_hotKeyToIDMap; HotKeyToIDMap m_hotKeyToIDMap;
// map of button state // map of button state
bool m_buttons[1 + kButtonExtra0 + 1]; bool m_buttons[NumButtonIDs];
// the system shows the mouse cursor when an internal display count // the system shows the mouse cursor when an internal display count
// is >= 0. this count is maintained per application but there's // is >= 0. this count is maintained per application but there's

View File

@ -422,6 +422,7 @@ OSXScreen::constructMouseButtonEventMap()
{kCGEventRightMouseUp, kCGEventRightMouseDragged, kCGEventRightMouseDown}, {kCGEventRightMouseUp, kCGEventRightMouseDragged, kCGEventRightMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}, {kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}, {kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown},
{kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown} {kCGEventOtherMouseUp, kCGEventOtherMouseDragged, kCGEventOtherMouseDown}
}; };

View File

@ -66,7 +66,8 @@ XWindowsScreen::XWindowsScreen(
IEventQueue* events) : IEventQueue* events) :
m_isPrimary(isPrimary), m_isPrimary(isPrimary),
m_mouseScrollDelta(mouseScrollDelta), m_mouseScrollDelta(mouseScrollDelta),
m_accumulatedScroll(0), m_x_accumulatedScroll(0),
m_y_accumulatedScroll(0),
m_display(NULL), m_display(NULL),
m_root(None), m_root(None),
m_window(None), m_window(None),
@ -829,35 +830,37 @@ XWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
} }
void void
XWindowsScreen::fakeMouseWheel(SInt32, SInt32 yDelta) const XWindowsScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
{ {
// XXX -- support x-axis scrolling int numEvents;
if (yDelta == 0) {
return;
}
int numEvents = accumulateMouseScroll(yDelta); if ((!xDelta && !yDelta) || (xDelta && yDelta)) {
// Invalid scrolling inputs
return;
}
// choose button depending on rotation direction // 4, 5, 6, 7
const unsigned int xButton = mapButtonToX(static_cast<ButtonID>( // up, down, left, right
(numEvents >= 0) ? -1 : -2)); unsigned int xButton;
if (xButton == 0) {
// If we get here, then the XServer does not support the scroll if (yDelta) { // vertical scroll
// wheel buttons, so send PageUp/PageDown keystrokes instead. numEvents = y_accumulateMouseScroll(yDelta);
// Patch by Tom Chadwick. if (numEvents >= 0) {
KeyCode keycode = 0; xButton = 4; // up
if (yDelta >= 0) { }
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Up); else {
} xButton = 5; // down
else { }
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Down); }
} else { // horizontal scroll
if (keycode != 0) { numEvents = x_accumulateMouseScroll(xDelta);
m_impl->XTestFakeKeyEvent(m_display, keycode, True, CurrentTime); if (numEvents >= 0) {
m_impl->XTestFakeKeyEvent(m_display, keycode, False, CurrentTime); xButton = 7; // right
} }
return; else {
} xButton = 6; // left
}
}
numEvents = std::abs(numEvents); numEvents = std::abs(numEvents);
@ -1540,7 +1543,14 @@ XWindowsScreen::onMouseRelease(const XButtonEvent& xbutton)
// wheel backward (toward user) // wheel backward (toward user)
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(0, -120)); sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(0, -120));
} }
// XXX -- support x-axis scrolling else if (xbutton.button == 6) {
// wheel left
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(-120, 0));
}
else if (xbutton.button == 7) {
// wheel right
sendEvent(m_events->forIPrimaryScreen().wheel(), WheelInfo::alloc(120, 0));
}
} }
void void
@ -1613,11 +1623,20 @@ XWindowsScreen::onMouseMove(const XMotionEvent& xmotion)
} }
int int
XWindowsScreen::accumulateMouseScroll(SInt32 yDelta) const XWindowsScreen::x_accumulateMouseScroll(SInt32 xDelta) const
{ {
m_accumulatedScroll += yDelta; m_x_accumulatedScroll += xDelta;
int numEvents = m_accumulatedScroll / m_mouseScrollDelta; int numEvents = m_x_accumulatedScroll / m_mouseScrollDelta;
m_accumulatedScroll -= numEvents * m_mouseScrollDelta; m_x_accumulatedScroll -= numEvents * m_mouseScrollDelta;
return numEvents;
}
int
XWindowsScreen::y_accumulateMouseScroll(SInt32 yDelta) const
{
m_y_accumulatedScroll += yDelta;
int numEvents = m_y_accumulatedScroll / m_mouseScrollDelta;
m_y_accumulatedScroll -= numEvents * m_mouseScrollDelta;
return numEvents; return numEvents;
} }
@ -1840,19 +1859,19 @@ XWindowsScreen::mapButtonFromX(const XButtonEvent* event) const
{ {
unsigned int button = event->button; unsigned int button = event->button;
// first three buttons map to 1, 2, 3 (kButtonLeft, Middle, Right) // http://xahlee.info/linux/linux_x11_mouse_button_number.html
if (button >= 1 && button <= 3) { // and the program `xev`
switch (button)
{
case 1: case 2: case 3: // kButtonLeft, Middle, Right
return static_cast<ButtonID>(button); return static_cast<ButtonID>(button);
} case 4: case 5: case 6: case 7: // scroll up, down, left, right -- ignored here
return kButtonNone;
// buttons 4 and 5 are ignored here. they're used for the wheel. case 8: // mouse button 4
// buttons 6, 7, etc and up map to 4, 5, etc. return kButtonExtra0;
else if (button >= 6) { case 9: // mouse button 5
return static_cast<ButtonID>(button - 2); return kButtonExtra1;
} default: // unknown button
// unknown button
else {
return kButtonNone; return kButtonNone;
} }
} }
@ -1860,30 +1879,17 @@ XWindowsScreen::mapButtonFromX(const XButtonEvent* event) const
unsigned int unsigned int
XWindowsScreen::mapButtonToX(ButtonID id) const XWindowsScreen::mapButtonToX(ButtonID id) const
{ {
// map button -1 to button 4 (+wheel) switch (id)
if (id == static_cast<ButtonID>(-1)) { {
id = 4; case kButtonLeft: case kButtonMiddle: case kButtonRight:
} return id;
case kButtonExtra0:
// map button -2 to button 5 (-wheel) return 8;
else if (id == static_cast<ButtonID>(-2)) { case kButtonExtra1:
id = 5; return 9;
} default:
// map buttons 4, 5, etc. to 6, 7, etc. to make room for buttons
// 4 and 5 used to simulate the mouse wheel.
else if (id >= 4) {
id += 2;
}
// check button is in legal range
if (id < 1 || id > m_buttons.size()) {
// out of range
return 0; return 0;
} }
// map button
return static_cast<unsigned int>(id);
} }
void void

View File

@ -139,7 +139,8 @@ private:
// Returns the number of scroll events needed after the current delta has // Returns the number of scroll events needed after the current delta has
// been taken into account // been taken into account
int accumulateMouseScroll(SInt32 yDelta) const; int x_accumulateMouseScroll(SInt32 xDelta) const;
int y_accumulateMouseScroll(SInt32 yDelta) const;
bool detectXI2(); bool detectXI2();
#ifdef HAVE_XI2 #ifdef HAVE_XI2
@ -183,10 +184,11 @@ private:
// The size of a smallest supported scroll event, in points // The size of a smallest supported scroll event, in points
int m_mouseScrollDelta; int m_mouseScrollDelta;
// Accumulates scrolls of less than m_mouseScrollDelta across multiple // Accumulates scrolls of less than m_?_mouseScrollDelta across multiple
// scroll events. We dispatch a scroll event whenever the accumulated scroll // scroll events. We dispatch a scroll event whenever the accumulated scroll
// becomes larger than m_mouseScrollDelta // becomes larger than m_?_mouseScrollDelta
mutable int m_accumulatedScroll; mutable int m_x_accumulatedScroll;
mutable int m_y_accumulatedScroll;
Display* m_display; Display* m_display;
Window m_root; Window m_root;