Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse Wheel Bug Fixes #169

Open
wants to merge 2 commits into
base: 1.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
35 changes: 23 additions & 12 deletions src/darwin/dispatch_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,32 +623,46 @@ bool dispatch_mouse_wheel(uint64_t timestamp, CGEventRef event_ref) {
CGEventSourceRef source = CGEventCreateSourceFromEvent(event_ref);
double ppl = CGEventSourceGetPixelsPerLine(source);

unsigned int wheel_amount = 10;
if (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventIsContinuous) != 0) {
// continuous device (trackpad)
ppl *= 1;
wheel_amount = 1;

ppl *= wheel_amount;
uio_event.data.wheel.type = WHEEL_BLOCK_SCROLL;

if (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventDeltaAxis1) != 0) {
uio_event.data.wheel.direction = WHEEL_VERTICAL_DIRECTION;
uio_event.data.wheel.rotation = (int16_t) (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventPointDeltaAxis1) * ppl * 1);
uio_event.data.wheel.rotation = (int16_t) (
CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventPointDeltaAxis1) * ppl * wheel_amount
);
} else if (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventDeltaAxis2) != 0) {
uio_event.data.wheel.direction = WHEEL_HORIZONTAL_DIRECTION;
uio_event.data.wheel.rotation = (int16_t) (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventPointDeltaAxis2) * ppl * 1);
uio_event.data.wheel.rotation = (int16_t) (
CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventPointDeltaAxis2) * ppl * wheel_amount
);
}
} else {
// non-continuous device (wheel mice)
ppl *= 10;
wheel_amount = 10;

ppl *= wheel_amount;
uio_event.data.wheel.type = WHEEL_UNIT_SCROLL;

if (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventDeltaAxis1) != 0) {
uio_event.data.wheel.direction = WHEEL_VERTICAL_DIRECTION;
uio_event.data.wheel.rotation = (int16_t) (CGEventGetDoubleValueField(event_ref, kCGScrollWheelEventFixedPtDeltaAxis1) * ppl * 10);
uio_event.data.wheel.rotation = (int16_t) (
CGEventGetDoubleValueField(event_ref, kCGScrollWheelEventFixedPtDeltaAxis1) * ppl * wheel_amount
);
} else if (CGEventGetIntegerValueField(event_ref, kCGScrollWheelEventDeltaAxis2) != 0) {
uio_event.data.wheel.direction = WHEEL_HORIZONTAL_DIRECTION;
uio_event.data.wheel.rotation = (int16_t) (CGEventGetDoubleValueField(event_ref, kCGScrollWheelEventFixedPtDeltaAxis2) * ppl * 10);
uio_event.data.wheel.rotation = (int16_t) (
CGEventGetDoubleValueField(event_ref, kCGScrollWheelEventFixedPtDeltaAxis2) * ppl * wheel_amount
);
}
}

uio_event.data.wheel.amount = (uint8_t) wheel_amount;
uio_event.data.wheel.delta = (uint16_t) ppl;

if (source) {
Expand All @@ -657,12 +671,9 @@ bool dispatch_mouse_wheel(uint64_t timestamp, CGEventRef event_ref) {

logger(LOG_LEVEL_DEBUG, "%s [%u]: Mouse wheel %i / %u of type %u in the %u direction at %u, %u.\n",
__FUNCTION__, __LINE__,
uio_event.data.wheel.rotation,
uio_event.data.wheel.delta,
uio_event.data.wheel.type,
uio_event.data.wheel.direction,
uio_event.data.wheel.x,
uio_event.data.wheel.y);
uio_event.data.wheel.rotation, uio_event.data.wheel.delta,
uio_event.data.wheel.type, uio_event.data.wheel.direction,
uio_event.data.wheel.x, uio_event.data.wheel.y);

// Fire mouse wheel event.
dispatch_event(&uio_event);
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
12 changes: 7 additions & 5 deletions src/windows/dispatch_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,11 @@ bool dispatch_mouse_wheel(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint8_t di
uio_event.data.wheel.x = (int16_t) mshook->pt.x;
uio_event.data.wheel.y = (int16_t) mshook->pt.y;

/* Delta GET_WHEEL_DELTA_WPARAM(mshook->mouseData)
* A positive value indicates that the wheel was rotated
* forward, away from the user; a negative value indicates that
* the wheel was rotated backward, toward the user. One wheel
* click is defined as WHEEL_DELTA, which is 120. */
/* The GET_WHEEL_DELTA_WPARAM(mshook->mouseData) macro returns the high-order word of mouseData which represents
* the wheel delta.
* A positive value indicates that the wheel was rotated forward, away from the user.
* A negative value indicates that the wheel was rotated backward, toward the user.
* One wheel click is defined as WHEEL_DELTA, which is 120. */
uio_event.data.wheel.rotation = (int16_t) GET_WHEEL_DELTA_WPARAM(mshook->mouseData);
uio_event.data.wheel.delta = WHEEL_DELTA;

Expand All @@ -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 @@ -182,7 +182,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