Skip to content

Commit

Permalink
Mouse Wheel Bug Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kwhat committed Apr 16, 2024
1 parent 117cef0 commit dbb8ba3
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 28 deletions.
1 change: 1 addition & 0 deletions include/uiohook.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ typedef struct _mouse_wheel_event_data {
int16_t x;
int16_t y;
uint8_t type;
uint8_t amount;
int16_t rotation;
uint16_t delta;
uint8_t direction;
Expand Down
2 changes: 1 addition & 1 deletion src/darwin/post_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ static int post_mouse_wheel_event(uiohook_event * const event, CGEventSourceRef

CGEventRef cg_event = CGEventCreateScrollWheelEvent(
src,
kCGScrollEventUnitLine,
scroll_unit,
// TODO Currently only support 1 wheel axis.
(CGWheelCount) 1, // 1 for Y-only, 2 for Y-X, 3 for Y-X-Z
event->data.wheel.rotation // TODO Is this value correct? Do we need PPL?
Expand Down
2 changes: 2 additions & 0 deletions src/windows/dispatch_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,13 +412,15 @@ bool dispatch_mouse_wheel(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint8_t di

uio_event.data.wheel.type = WHEEL_BLOCK_SCROLL;
uio_event.data.wheel.rotation *= 1;
uio_event.data.wheel.amount = 1;
} else {
/* If this number is 0, no scrolling should occur.
* If the number of lines to scroll is greater than the number of lines viewable, the scroll operation
* should also be interpreted as a page down or page up operation. */

uio_event.data.wheel.type = WHEEL_UNIT_SCROLL;
uio_event.data.wheel.rotation *= wheel_amount;
uio_event.data.wheel.amount = wheel_amount;
}

// Set the direction based on what event was received.
Expand Down
4 changes: 3 additions & 1 deletion src/windows/post_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ static int map_mouse_event(uiohook_event * const event, INPUT * const input) {
case EVENT_MOUSE_WHEEL:
input->mi.dwFlags = MOUSEEVENTF_WHEEL;

// type, amount and rotation?
// TODO What are we going to do about delta=? We could normalize with rotation *= (120 / delta)
// TODO What are we going to do about type=WHEEL_BLOCK_SCROLL?
// TODO What are we going to do about amount=? Is this really a setting, not event property?
input->mi.mouseData = event->data.wheel.rotation;
break;

Expand Down
5 changes: 3 additions & 2 deletions src/x11/dispatch_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,14 @@ static bool dispatch_mouse_wheel_rotated(XButtonEvent * const x_event) {
/* Some scroll wheel properties are available via the new XInput2 (XI2) extension. Unfortunately the extension is
* not available on my development platform at this time. For the time being we will just use the Windows default
* value of 3. */
uio_event.data.wheel.amount = WHEEL_AMOUNT;
uio_event.data.wheel.delta = 100;
if (x_event->button == WheelDown || x_event->button == WheelLeft) {
// Wheel Rotated Up and Away.
uio_event.data.wheel.rotation = -3 * uio_event.data.wheel.delta;
uio_event.data.wheel.rotation = -1 * uio_event.data.wheel.delta;
} else { // event.button == WheelUp || event.button == WheelRight
// Wheel Rotated Down and Towards.
uio_event.data.wheel.rotation = 3 * uio_event.data.wheel.delta;
uio_event.data.wheel.rotation = uio_event.data.wheel.delta;
}

if (x_event->button == WheelUp || x_event->button == WheelDown) {
Expand Down
3 changes: 3 additions & 0 deletions src/x11/input_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#define XButton1 8
#define XButton2 9

// The static number of clicks for X11 because it is a non-configurable amount.
#define WHEEL_AMOUNT 3

// For this struct, refer to libxnee, requires Xlibint.h
typedef union {
unsigned char type;
Expand Down
51 changes: 27 additions & 24 deletions src/x11/post_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,40 +119,43 @@ static int post_mouse_button_event(uiohook_event * const event) {
static int post_mouse_wheel_event(uiohook_event * const event) {
int status = UIOHOOK_FAILURE;

XButtonEvent btn_event = {
.serial = 0,
.send_event = False,
.display = helper_disp,
if (event->data.wheel.delta > 0) {
XButtonEvent btn_event = {
.serial = 0,
.send_event = False,
.display = helper_disp,

.window = None, /* “event” window it is reported relative to */
.root = None, /* root window that the event occurred on */
.subwindow = XDefaultRootWindow(helper_disp), /* child window */
.window = None, /* “event” window it is reported relative to */
.root = None, /* root window that the event occurred on */
.subwindow = XDefaultRootWindow(helper_disp), /* child window */

.time = CurrentTime,
.time = CurrentTime,

.x = event->data.wheel.x, /* pointer x, y coordinates in event window */
.y = event->data.wheel.y,
.x = event->data.wheel.x, /* pointer x, y coordinates in event window */
.y = event->data.wheel.y,

.x_root = 0, /* coordinates relative to root */
.y_root = 0,
.x_root = 0, /* coordinates relative to root */
.y_root = 0,

.state = 0x00, /* key or button mask */
.same_screen = True
};
.state = 0x00, /* key or button mask */
.same_screen = True
};

// Wheel events should be the same as click events on X11.
// type, amount and rotation
unsigned int button = button_map_lookup(event->data.wheel.rotation < 0 ? WheelUp : WheelDown);
unsigned int button = button_map_lookup(event->data.wheel.rotation < 0 ? WheelUp : WheelDown);

if (XTestFakeButtonEvent(helper_disp, button, True, 0) != 0) {
// X11 does not support a rotation amount so we will emulate the number of rotations based on the static wheel amount.
// TODO What are we going to do about type=WHEEL_BLOCK_SCROLL?
// TODO What are we going to do about amount=? Is this really a setting, not event property?
status = UIOHOOK_SUCCESS;
for (int i = abs(event->data.wheel.rotation) / (event->data.wheel.delta * event->data.wheel.amount); i > 0 && status == UIOHOOK_SUCCESS; i--) {
// Wheel events are be the same as click events on X11.
if (!XTestFakeButtonEvent(helper_disp, button, True, 0) || !XTestFakeButtonEvent(helper_disp, button, False, 0)) {
status = UIOHOOK_FAILURE;
}
}
}

if (status == UIOHOOK_SUCCESS && XTestFakeButtonEvent(helper_disp, button, False, 0) == 0) {
status = UIOHOOK_FAILURE;
}

return UIOHOOK_SUCCESS;
return status;
}

static int post_mouse_motion_event(uiohook_event * const event) {
Expand Down

0 comments on commit dbb8ba3

Please sign in to comment.