mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-14 04:30:21 +01:00
switch: only sync the initial state if we know the state is reliable
This changes the default behavior to "disable the touchpad on the first lid close event", thus filtering any laptops where the switch state is buggy and always in "on" state. Devices where we know the lid switch state is reliable can be marked as such. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
3f5e9cb636
commit
5f2402a41a
5 changed files with 105 additions and 4 deletions
40
src/evdev.c
40
src/evdev.c
|
|
@ -1356,6 +1356,25 @@ lid_switch_process(struct evdev_dispatch *evdev_dispatch,
|
|||
}
|
||||
}
|
||||
|
||||
static inline enum switch_reliability
|
||||
evdev_read_switch_reliability_prop(struct evdev_device *device)
|
||||
{
|
||||
const char *prop;
|
||||
enum switch_reliability r;
|
||||
|
||||
prop = udev_device_get_property_value(device->udev_device,
|
||||
"LIBINPUT_ATTR_LID_SWITCH_RELIABILITY");
|
||||
if (!parse_switch_reliability_property(prop, &r)) {
|
||||
log_error(evdev_libinput_context(device),
|
||||
"%s: switch reliability set to unknown value '%s'\n",
|
||||
device->devname,
|
||||
prop);
|
||||
r = RELIABILITY_UNKNOWN;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_destroy(struct evdev_dispatch *evdev_dispatch)
|
||||
{
|
||||
|
|
@ -1372,10 +1391,25 @@ lid_switch_sync_initial_state(struct evdev_device *device,
|
|||
struct lid_switch_dispatch *dispatch =
|
||||
(struct lid_switch_dispatch*)evdev_dispatch;
|
||||
struct libevdev *evdev = device->evdev;
|
||||
bool is_closed = false;
|
||||
|
||||
dispatch->lid_is_closed = libevdev_get_event_value(evdev,
|
||||
EV_SW,
|
||||
SW_LID);
|
||||
/* For the initial state sync, we depend on whether the lid switch
|
||||
* is reliable. If we know it's reliable, we sync as expected.
|
||||
* If we're not sure, we ignore the initial state and only sync on
|
||||
* the first future lid close event. Laptops with a broken switch
|
||||
* that always have the switch in 'on' state thus don't mess up our
|
||||
* touchpad.
|
||||
*/
|
||||
switch(evdev_read_switch_reliability_prop(device)) {
|
||||
case RELIABILITY_UNKNOWN:
|
||||
is_closed = false;
|
||||
break;
|
||||
case RELIABILITY_RELIABLE:
|
||||
is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID);
|
||||
break;
|
||||
}
|
||||
|
||||
dispatch->lid_is_closed = is_closed;
|
||||
if (dispatch->lid_is_closed) {
|
||||
uint64_t time;
|
||||
time = libinput_now(evdev_libinput_context(device));
|
||||
|
|
|
|||
|
|
@ -278,6 +278,23 @@ parse_dimension_property(const char *prop, size_t *w, size_t *h)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
parse_switch_reliability_property(const char *prop,
|
||||
enum switch_reliability *reliability)
|
||||
{
|
||||
if (!prop) {
|
||||
*reliability = RELIABILITY_UNKNOWN;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (streq(prop, "reliable"))
|
||||
*reliability = RELIABILITY_RELIABLE;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next word in a string pointed to by state before the first
|
||||
* separator character. Call repeatedly to tokenize a whole string.
|
||||
|
|
|
|||
|
|
@ -377,6 +377,15 @@ int parse_mouse_wheel_click_count_property(const char *prop);
|
|||
double parse_trackpoint_accel_property(const char *prop);
|
||||
bool parse_dimension_property(const char *prop, size_t *width, size_t *height);
|
||||
|
||||
enum switch_reliability {
|
||||
RELIABILITY_UNKNOWN,
|
||||
RELIABILITY_RELIABLE,
|
||||
};
|
||||
|
||||
bool
|
||||
parse_switch_reliability_property(const char *prop,
|
||||
enum switch_reliability *reliability);
|
||||
|
||||
static inline uint64_t
|
||||
us(uint64_t us)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ static const char udev_rule[] =
|
|||
"KERNEL!=\"event*\", GOTO=\"switch_end\"\n"
|
||||
"\n"
|
||||
"ATTRS{name}==\"litest Lid Switch*\",\\\n"
|
||||
" ENV{ID_INPUT_SWITCH}=\"1\"\n"
|
||||
" ENV{ID_INPUT_SWITCH}=\"1\",\\\n"
|
||||
" ENV{LIBINPUT_ATTR_LID_SWITCH_RELIABILITY}=\"reliable\"\n"
|
||||
"\n"
|
||||
"LABEL=\"switch_end\"";
|
||||
|
||||
|
|
|
|||
|
|
@ -908,6 +908,45 @@ START_TEST(dimension_prop_parser)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
struct parser_test_reliability {
|
||||
char *tag;
|
||||
bool success;
|
||||
enum switch_reliability reliability;
|
||||
};
|
||||
|
||||
START_TEST(reliability_prop_parser)
|
||||
{
|
||||
struct parser_test_reliability tests[] = {
|
||||
{ "reliable", true, RELIABILITY_RELIABLE },
|
||||
{ "unreliable", false, 0 },
|
||||
{ "", false, 0 },
|
||||
{ "0", false, 0 },
|
||||
{ "1", false, 0 },
|
||||
{ NULL, false, 0, }
|
||||
};
|
||||
enum switch_reliability r;
|
||||
bool success;
|
||||
int i;
|
||||
|
||||
for (i = 0; tests[i].tag != NULL; i++) {
|
||||
r = 0xaf;
|
||||
success = parse_switch_reliability_property(tests[i].tag, &r);
|
||||
ck_assert(success == tests[i].success);
|
||||
if (success)
|
||||
ck_assert_int_eq(r, tests[i].reliability);
|
||||
else
|
||||
ck_assert_int_eq(r, 0xaf);
|
||||
}
|
||||
|
||||
success = parse_switch_reliability_property(NULL, &r);
|
||||
ck_assert(success == true);
|
||||
ck_assert_int_eq(r, RELIABILITY_UNKNOWN);
|
||||
|
||||
success = parse_switch_reliability_property("foo", NULL);
|
||||
ck_assert(success == false);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(time_conversion)
|
||||
{
|
||||
ck_assert_int_eq(us(10), 10);
|
||||
|
|
@ -1180,6 +1219,7 @@ litest_setup_tests_misc(void)
|
|||
litest_add_no_device("misc:parser", wheel_click_count_parser);
|
||||
litest_add_no_device("misc:parser", trackpoint_accel_parser);
|
||||
litest_add_no_device("misc:parser", dimension_prop_parser);
|
||||
litest_add_no_device("misc:parser", reliability_prop_parser);
|
||||
litest_add_no_device("misc:parser", safe_atoi_test);
|
||||
litest_add_no_device("misc:parser", safe_atod_test);
|
||||
litest_add_no_device("misc:parser", strsplit_test);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue