Merge pull request #391 from EbonJaeger
Re-implement patch for horizontal scrolling and extra mouse buttons
This commit is contained in:
commit
ccfa10f2a0
|
@ -31,3 +31,4 @@ CMakeCache.txt
|
||||||
.vscode/
|
.vscode/
|
||||||
# Transient in-project-directory dependencies
|
# Transient in-project-directory dependencies
|
||||||
/deps/
|
/deps/
|
||||||
|
/out/build/x64-Debug
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,34 +830,36 @@ 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) {
|
|
||||||
|
if ((!xDelta && !yDelta) || (xDelta && yDelta)) {
|
||||||
|
// Invalid scrolling inputs
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numEvents = accumulateMouseScroll(yDelta);
|
// 4, 5, 6, 7
|
||||||
|
// up, down, left, right
|
||||||
|
unsigned int xButton;
|
||||||
|
|
||||||
// choose button depending on rotation direction
|
if (yDelta) { // vertical scroll
|
||||||
const unsigned int xButton = mapButtonToX(static_cast<ButtonID>(
|
numEvents = y_accumulateMouseScroll(yDelta);
|
||||||
(numEvents >= 0) ? -1 : -2));
|
if (numEvents >= 0) {
|
||||||
if (xButton == 0) {
|
xButton = 4; // up
|
||||||
// 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 (yDelta >= 0) {
|
|
||||||
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Up);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
keycode = m_impl->XKeysymToKeycode(m_display, XK_Page_Down);
|
xButton = 5; // down
|
||||||
}
|
}
|
||||||
if (keycode != 0) {
|
|
||||||
m_impl->XTestFakeKeyEvent(m_display, keycode, True, CurrentTime);
|
|
||||||
m_impl->XTestFakeKeyEvent(m_display, keycode, False, CurrentTime);
|
|
||||||
}
|
}
|
||||||
return;
|
else { // horizontal scroll
|
||||||
|
numEvents = x_accumulateMouseScroll(xDelta);
|
||||||
|
if (numEvents >= 0) {
|
||||||
|
xButton = 7; // right
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue