Skip to content

Commit d4b9f10

Browse files
JoseExpositoJiri Kosina
authored andcommitted
HID: magicmouse: enable high-resolution scroll
The Magic Mouse, generations 1 and 2, doesn't have a physical scroll wheel, instead, the REL_WHEEL and REL_HWHEEL events are emulated when sliding a finger on the surface of the mouse. However, the smooth movement of the finger is transformed into a step based scroll on the screen, leading to a suboptimal user experience. Emulate high-resolution scroll by sending REL_WHEEL_HI_RES and REL_HWHEEL_HI_RES events so the scroll on the screen is closer to the finger movement. Signed-off-by: José Expósito <jose.exposito89@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent df04fbe commit d4b9f10

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

drivers/hid/hid-magicmouse.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie
6868
#define TOUCH_STATE_START 0x30
6969
#define TOUCH_STATE_DRAG 0x40
7070

71+
/* Number of high-resolution events for each low-resolution detent. */
72+
#define SCROLL_HR_STEPS 10
73+
#define SCROLL_HR_MULT (120 / SCROLL_HR_STEPS)
7174
#define SCROLL_ACCEL_DEFAULT 7
7275

7376
/* Touch surface information. Dimension is in hundredths of a mm, min and max
@@ -126,6 +129,8 @@ struct magicmouse_sc {
126129
short y;
127130
short scroll_x;
128131
short scroll_y;
132+
short scroll_x_hr;
133+
short scroll_y_hr;
129134
u8 size;
130135
} touches[16];
131136
int tracking_ids[16];
@@ -248,12 +253,18 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
248253
unsigned long now = jiffies;
249254
int step_x = msc->touches[id].scroll_x - x;
250255
int step_y = msc->touches[id].scroll_y - y;
256+
int step_hr = ((64 - (int)scroll_speed) * msc->scroll_accel) /
257+
SCROLL_HR_STEPS;
258+
int step_x_hr = msc->touches[id].scroll_x_hr - x;
259+
int step_y_hr = msc->touches[id].scroll_y_hr - y;
251260

252261
/* Calculate and apply the scroll motion. */
253262
switch (state) {
254263
case TOUCH_STATE_START:
255264
msc->touches[id].scroll_x = x;
256265
msc->touches[id].scroll_y = y;
266+
msc->touches[id].scroll_x_hr = x;
267+
msc->touches[id].scroll_y_hr = y;
257268

258269
/* Reset acceleration after half a second. */
259270
if (scroll_acceleration && time_before(now,
@@ -280,6 +291,24 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
280291
msc->scroll_jiffies = now;
281292
input_report_rel(input, REL_WHEEL, step_y);
282293
}
294+
295+
step_x_hr /= step_hr;
296+
if (step_x_hr != 0) {
297+
msc->touches[id].scroll_x_hr -= step_x_hr *
298+
step_hr;
299+
input_report_rel(input,
300+
REL_HWHEEL_HI_RES,
301+
-step_x_hr * SCROLL_HR_MULT);
302+
}
303+
304+
step_y_hr /= step_hr;
305+
if (step_y_hr != 0) {
306+
msc->touches[id].scroll_y_hr -= step_y_hr *
307+
step_hr;
308+
input_report_rel(input,
309+
REL_WHEEL_HI_RES,
310+
step_y_hr * SCROLL_HR_MULT);
311+
}
283312
break;
284313
}
285314
}
@@ -481,6 +510,8 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
481510
if (emulate_scroll_wheel) {
482511
__set_bit(REL_WHEEL, input->relbit);
483512
__set_bit(REL_HWHEEL, input->relbit);
513+
__set_bit(REL_WHEEL_HI_RES, input->relbit);
514+
__set_bit(REL_HWHEEL_HI_RES, input->relbit);
484515
}
485516
} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
486517
/* setting the device name to ensure the same driver settings

0 commit comments

Comments
 (0)