diff options
author | Jamie Lentin <jm@lentin.co.uk> | 2015-08-11 17:40:52 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-08-12 08:32:31 -0400 |
commit | 3cb5ff0220e31bd1043bb18fd5765c9f86928491 (patch) | |
tree | 70369e3713cd7b5f2235e16c605566e6a083a91e | |
parent | dbfebb44b7c650dd134a8be07f9afd5862150987 (diff) |
HID: lenovo: Hide middle-button press until release
Don't relay a middle button press to userspace until release, and then
only if there was no scroll events inbetween. This is closer to what
Xorg's wheel emulation does, and avoids spurious middle-click pastes.
Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-lenovo.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index d40221d78188..e4bc6cb6d7fa 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c | |||
@@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd { | |||
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct lenovo_drvdata_cptkbd { | 39 | struct lenovo_drvdata_cptkbd { |
40 | u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */ | ||
40 | bool fn_lock; | 41 | bool fn_lock; |
41 | int sensitivity; | 42 | int sensitivity; |
42 | }; | 43 | }; |
@@ -316,6 +317,53 @@ static int lenovo_raw_event(struct hid_device *hdev, | |||
316 | return 0; | 317 | return 0; |
317 | } | 318 | } |
318 | 319 | ||
320 | static int lenovo_event_cptkbd(struct hid_device *hdev, | ||
321 | struct hid_field *field, struct hid_usage *usage, __s32 value) | ||
322 | { | ||
323 | struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); | ||
324 | |||
325 | /* "wheel" scroll events */ | ||
326 | if (usage->type == EV_REL && (usage->code == REL_WHEEL || | ||
327 | usage->code == REL_HWHEEL)) { | ||
328 | /* Scroll events disable middle-click event */ | ||
329 | cptkbd_data->middlebutton_state = 2; | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* Middle click events */ | ||
334 | if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) { | ||
335 | if (value == 1) { | ||
336 | cptkbd_data->middlebutton_state = 1; | ||
337 | } else if (value == 0) { | ||
338 | if (cptkbd_data->middlebutton_state == 1) { | ||
339 | /* No scrolling inbetween, send middle-click */ | ||
340 | input_event(field->hidinput->input, | ||
341 | EV_KEY, BTN_MIDDLE, 1); | ||
342 | input_sync(field->hidinput->input); | ||
343 | input_event(field->hidinput->input, | ||
344 | EV_KEY, BTN_MIDDLE, 0); | ||
345 | input_sync(field->hidinput->input); | ||
346 | } | ||
347 | cptkbd_data->middlebutton_state = 0; | ||
348 | } | ||
349 | return 1; | ||
350 | } | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static int lenovo_event(struct hid_device *hdev, struct hid_field *field, | ||
356 | struct hid_usage *usage, __s32 value) | ||
357 | { | ||
358 | switch (hdev->product) { | ||
359 | case USB_DEVICE_ID_LENOVO_CUSBKBD: | ||
360 | case USB_DEVICE_ID_LENOVO_CBTKBD: | ||
361 | return lenovo_event_cptkbd(hdev, field, usage, value); | ||
362 | default: | ||
363 | return 0; | ||
364 | } | ||
365 | } | ||
366 | |||
319 | static int lenovo_features_set_tpkbd(struct hid_device *hdev) | 367 | static int lenovo_features_set_tpkbd(struct hid_device *hdev) |
320 | { | 368 | { |
321 | struct hid_report *report; | 369 | struct hid_report *report; |
@@ -708,6 +756,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev) | |||
708 | hid_warn(hdev, "Failed to switch middle button: %d\n", ret); | 756 | hid_warn(hdev, "Failed to switch middle button: %d\n", ret); |
709 | 757 | ||
710 | /* Set keyboard settings to known state */ | 758 | /* Set keyboard settings to known state */ |
759 | cptkbd_data->middlebutton_state = 0; | ||
711 | cptkbd_data->fn_lock = true; | 760 | cptkbd_data->fn_lock = true; |
712 | cptkbd_data->sensitivity = 0x05; | 761 | cptkbd_data->sensitivity = 0x05; |
713 | lenovo_features_set_cptkbd(hdev); | 762 | lenovo_features_set_cptkbd(hdev); |
@@ -835,6 +884,7 @@ static struct hid_driver lenovo_driver = { | |||
835 | .probe = lenovo_probe, | 884 | .probe = lenovo_probe, |
836 | .remove = lenovo_remove, | 885 | .remove = lenovo_remove, |
837 | .raw_event = lenovo_raw_event, | 886 | .raw_event = lenovo_raw_event, |
887 | .event = lenovo_event, | ||
838 | .report_fixup = lenovo_report_fixup, | 888 | .report_fixup = lenovo_report_fixup, |
839 | }; | 889 | }; |
840 | module_hid_driver(lenovo_driver); | 890 | module_hid_driver(lenovo_driver); |