mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
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>
This commit is contained in:
parent
dbfebb44b7
commit
3cb5ff0220
@ -37,6 +37,7 @@ struct lenovo_drvdata_tpkbd {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct lenovo_drvdata_cptkbd {
|
struct lenovo_drvdata_cptkbd {
|
||||||
|
u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
|
||||||
bool fn_lock;
|
bool fn_lock;
|
||||||
int sensitivity;
|
int sensitivity;
|
||||||
};
|
};
|
||||||
@ -316,6 +317,53 @@ static int lenovo_raw_event(struct hid_device *hdev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lenovo_event_cptkbd(struct hid_device *hdev,
|
||||||
|
struct hid_field *field, struct hid_usage *usage, __s32 value)
|
||||||
|
{
|
||||||
|
struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
|
/* "wheel" scroll events */
|
||||||
|
if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
|
||||||
|
usage->code == REL_HWHEEL)) {
|
||||||
|
/* Scroll events disable middle-click event */
|
||||||
|
cptkbd_data->middlebutton_state = 2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Middle click events */
|
||||||
|
if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
|
||||||
|
if (value == 1) {
|
||||||
|
cptkbd_data->middlebutton_state = 1;
|
||||||
|
} else if (value == 0) {
|
||||||
|
if (cptkbd_data->middlebutton_state == 1) {
|
||||||
|
/* No scrolling inbetween, send middle-click */
|
||||||
|
input_event(field->hidinput->input,
|
||||||
|
EV_KEY, BTN_MIDDLE, 1);
|
||||||
|
input_sync(field->hidinput->input);
|
||||||
|
input_event(field->hidinput->input,
|
||||||
|
EV_KEY, BTN_MIDDLE, 0);
|
||||||
|
input_sync(field->hidinput->input);
|
||||||
|
}
|
||||||
|
cptkbd_data->middlebutton_state = 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
|
||||||
|
struct hid_usage *usage, __s32 value)
|
||||||
|
{
|
||||||
|
switch (hdev->product) {
|
||||||
|
case USB_DEVICE_ID_LENOVO_CUSBKBD:
|
||||||
|
case USB_DEVICE_ID_LENOVO_CBTKBD:
|
||||||
|
return lenovo_event_cptkbd(hdev, field, usage, value);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int lenovo_features_set_tpkbd(struct hid_device *hdev)
|
static int lenovo_features_set_tpkbd(struct hid_device *hdev)
|
||||||
{
|
{
|
||||||
struct hid_report *report;
|
struct hid_report *report;
|
||||||
@ -708,6 +756,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
|
|||||||
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
|
hid_warn(hdev, "Failed to switch middle button: %d\n", ret);
|
||||||
|
|
||||||
/* Set keyboard settings to known state */
|
/* Set keyboard settings to known state */
|
||||||
|
cptkbd_data->middlebutton_state = 0;
|
||||||
cptkbd_data->fn_lock = true;
|
cptkbd_data->fn_lock = true;
|
||||||
cptkbd_data->sensitivity = 0x05;
|
cptkbd_data->sensitivity = 0x05;
|
||||||
lenovo_features_set_cptkbd(hdev);
|
lenovo_features_set_cptkbd(hdev);
|
||||||
@ -835,6 +884,7 @@ static struct hid_driver lenovo_driver = {
|
|||||||
.probe = lenovo_probe,
|
.probe = lenovo_probe,
|
||||||
.remove = lenovo_remove,
|
.remove = lenovo_remove,
|
||||||
.raw_event = lenovo_raw_event,
|
.raw_event = lenovo_raw_event,
|
||||||
|
.event = lenovo_event,
|
||||||
.report_fixup = lenovo_report_fixup,
|
.report_fixup = lenovo_report_fixup,
|
||||||
};
|
};
|
||||||
module_hid_driver(lenovo_driver);
|
module_hid_driver(lenovo_driver);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user