mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-05 14:50:15 +01:00
evdev: move lid code to the fallback interface
This was originally designed to deal with devices that only have SW_LID. But it can be moved into the evdev interface to avoid duplication once we have SW_TABLET_MODE. The original assumption of the lid switch device being a standalone device with no other switches is not true, having a separate dispatch hurts us here. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
d9a729e1a7
commit
f0f6326490
5 changed files with 242 additions and 335 deletions
|
|
@ -156,7 +156,6 @@ src_libinput = [
|
|||
'src/libinput-private.h',
|
||||
'src/evdev.c',
|
||||
'src/evdev.h',
|
||||
'src/evdev-lid.c',
|
||||
'src/evdev-middle-button.c',
|
||||
'src/evdev-mt-touchpad.c',
|
||||
'src/evdev-mt-touchpad.h',
|
||||
|
|
|
|||
321
src/evdev-lid.c
321
src/evdev-lid.c
|
|
@ -1,321 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2017 James Ye <jye836@gmail.com>
|
||||
* Copyright © 2017 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libinput.h"
|
||||
#include "evdev.h"
|
||||
#include "libinput-private.h"
|
||||
|
||||
struct lid_switch_dispatch {
|
||||
struct evdev_dispatch base;
|
||||
struct evdev_device *device;
|
||||
enum switch_reliability reliability;
|
||||
|
||||
bool lid_is_closed;
|
||||
bool lid_is_closed_client_state;
|
||||
|
||||
struct {
|
||||
struct evdev_device *keyboard;
|
||||
struct libinput_event_listener listener;
|
||||
} keyboard;
|
||||
};
|
||||
|
||||
static inline struct lid_switch_dispatch*
|
||||
lid_dispatch(struct evdev_dispatch *dispatch)
|
||||
{
|
||||
evdev_verify_dispatch_type(dispatch, DISPATCH_LID_SWITCH);
|
||||
|
||||
return container_of(dispatch, struct lid_switch_dispatch, base);
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_notify_toggle(struct lid_switch_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
if (dispatch->lid_is_closed ^ dispatch->lid_is_closed_client_state) {
|
||||
switch_notify_toggle(&device->base,
|
||||
time,
|
||||
LIBINPUT_SWITCH_LID,
|
||||
dispatch->lid_is_closed);
|
||||
dispatch->lid_is_closed_client_state = dispatch->lid_is_closed;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_keyboard_event(uint64_t time,
|
||||
struct libinput_event *event,
|
||||
void *data)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(data);
|
||||
|
||||
if (!dispatch->lid_is_closed)
|
||||
return;
|
||||
|
||||
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
|
||||
return;
|
||||
|
||||
if (dispatch->reliability == RELIABILITY_WRITE_OPEN) {
|
||||
int fd = libevdev_get_fd(dispatch->device->evdev);
|
||||
struct input_event ev[2] = {
|
||||
{{ 0, 0 }, EV_SW, SW_LID, 0 },
|
||||
{{ 0, 0 }, EV_SYN, SYN_REPORT, 0 },
|
||||
};
|
||||
|
||||
(void)write(fd, ev, sizeof(ev));
|
||||
/* In case write() fails, we sync the lid state manually
|
||||
* regardless. */
|
||||
}
|
||||
|
||||
/* Posting the event here means we preempt the keyboard events that
|
||||
* caused us to wake up, so the lid event is always passed on before
|
||||
* the key event.
|
||||
*/
|
||||
dispatch->lid_is_closed = false;
|
||||
lid_switch_notify_toggle(dispatch, dispatch->device, time);
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_toggle_keyboard_listener(struct lid_switch_dispatch *dispatch,
|
||||
bool is_closed)
|
||||
{
|
||||
if (!dispatch->keyboard.keyboard)
|
||||
return;
|
||||
|
||||
if (is_closed) {
|
||||
libinput_device_add_event_listener(
|
||||
&dispatch->keyboard.keyboard->base,
|
||||
&dispatch->keyboard.listener,
|
||||
lid_switch_keyboard_event,
|
||||
dispatch);
|
||||
} else {
|
||||
libinput_device_remove_event_listener(
|
||||
&dispatch->keyboard.listener);
|
||||
libinput_device_init_event_listener(
|
||||
&dispatch->keyboard.listener);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_process_switch(struct lid_switch_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
bool is_closed;
|
||||
|
||||
switch (e->code) {
|
||||
case SW_LID:
|
||||
is_closed = !!e->value;
|
||||
|
||||
if (dispatch->lid_is_closed == is_closed)
|
||||
return;
|
||||
lid_switch_toggle_keyboard_listener(dispatch,
|
||||
is_closed);
|
||||
|
||||
dispatch->lid_is_closed = is_closed;
|
||||
|
||||
lid_switch_notify_toggle(dispatch, device, time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_process(struct evdev_dispatch *evdev_dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *event,
|
||||
uint64_t time)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(evdev_dispatch);
|
||||
|
||||
switch (event->type) {
|
||||
case EV_SW:
|
||||
lid_switch_process_switch(dispatch, device, event, time);
|
||||
break;
|
||||
case EV_SYN:
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Unknown event type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
evdev_log_error(device,
|
||||
"%s: switch reliability set to unknown value '%s'\n",
|
||||
device->devname,
|
||||
prop);
|
||||
r = RELIABILITY_UNKNOWN;
|
||||
} else if (r == RELIABILITY_WRITE_OPEN) {
|
||||
evdev_log_info(device,
|
||||
"%s: will write switch open events\n",
|
||||
device->devname);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_remove(struct evdev_dispatch *evdev_dispatch)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(evdev_dispatch);
|
||||
|
||||
if (!dispatch->keyboard.keyboard)
|
||||
return;
|
||||
|
||||
libinput_device_remove_event_listener(&dispatch->keyboard.listener);
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_destroy(struct evdev_dispatch *evdev_dispatch)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(evdev_dispatch);
|
||||
|
||||
free(dispatch);
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_pair_keyboard(struct evdev_device *lid_switch,
|
||||
struct evdev_device *keyboard)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch =
|
||||
lid_dispatch(lid_switch->dispatch);
|
||||
|
||||
if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0)
|
||||
return;
|
||||
|
||||
if (dispatch->keyboard.keyboard)
|
||||
return;
|
||||
|
||||
if (keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) {
|
||||
dispatch->keyboard.keyboard = keyboard;
|
||||
evdev_log_debug(lid_switch,
|
||||
"lid: keyboard paired with %s<->%s\n",
|
||||
lid_switch->devname,
|
||||
keyboard->devname);
|
||||
|
||||
/* We need to init the event listener now only if the reported state
|
||||
* is closed. */
|
||||
if (dispatch->lid_is_closed)
|
||||
lid_switch_toggle_keyboard_listener(dispatch,
|
||||
dispatch->lid_is_closed);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_interface_device_added(struct evdev_device *device,
|
||||
struct evdev_device *added_device)
|
||||
{
|
||||
lid_switch_pair_keyboard(device, added_device);
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_interface_device_removed(struct evdev_device *device,
|
||||
struct evdev_device *removed_device)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch);
|
||||
|
||||
if (removed_device == dispatch->keyboard.keyboard) {
|
||||
libinput_device_remove_event_listener(
|
||||
&dispatch->keyboard.listener);
|
||||
libinput_device_init_event_listener(
|
||||
&dispatch->keyboard.listener);
|
||||
dispatch->keyboard.keyboard = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lid_switch_sync_initial_state(struct evdev_device *device,
|
||||
struct evdev_dispatch *evdev_dispatch)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch);
|
||||
struct libevdev *evdev = device->evdev;
|
||||
|
||||
dispatch->reliability = evdev_read_switch_reliability_prop(device);
|
||||
|
||||
dispatch->lid_is_closed = libevdev_get_event_value(evdev, EV_SW, SW_LID);
|
||||
dispatch->lid_is_closed_client_state = false;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if (dispatch->lid_is_closed &&
|
||||
dispatch->reliability == RELIABILITY_RELIABLE) {
|
||||
uint64_t time;
|
||||
time = libinput_now(evdev_libinput_context(device));
|
||||
lid_switch_notify_toggle(dispatch, device, time);
|
||||
}
|
||||
}
|
||||
|
||||
struct evdev_dispatch_interface lid_switch_interface = {
|
||||
lid_switch_process,
|
||||
NULL, /* suspend */
|
||||
lid_switch_remove,
|
||||
lid_switch_destroy,
|
||||
lid_switch_interface_device_added,
|
||||
lid_switch_interface_device_removed,
|
||||
lid_switch_interface_device_removed, /* device_suspended, treat as remove */
|
||||
lid_switch_interface_device_added, /* device_resumed, treat as add */
|
||||
lid_switch_sync_initial_state,
|
||||
NULL, /* toggle_touch */
|
||||
};
|
||||
|
||||
struct evdev_dispatch *
|
||||
evdev_lid_switch_dispatch_create(struct evdev_device *lid_device)
|
||||
{
|
||||
struct lid_switch_dispatch *dispatch;
|
||||
int type;
|
||||
|
||||
dispatch = zalloc(sizeof *dispatch);
|
||||
dispatch->base.dispatch_type = DISPATCH_LID_SWITCH;
|
||||
dispatch->base.interface = &lid_switch_interface;
|
||||
dispatch->device = lid_device;
|
||||
libinput_device_init_event_listener(&dispatch->keyboard.listener);
|
||||
|
||||
evdev_init_sendevents(lid_device, &dispatch->base);
|
||||
|
||||
dispatch->lid_is_closed = false;
|
||||
|
||||
for (type = EV_KEY; type < EV_CNT; type++) {
|
||||
if (type == EV_SW)
|
||||
continue;
|
||||
|
||||
libevdev_disable_event_type(lid_device->evdev, type);
|
||||
}
|
||||
|
||||
return &dispatch->base;
|
||||
}
|
||||
239
src/evdev.c
239
src/evdev.c
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2013 Jonas Ådahl
|
||||
* Copyright © 2013-2015 Red Hat, Inc.
|
||||
* Copyright © 2013-2017 Red Hat, Inc.
|
||||
* Copyright © 2017 James Ye <jye836@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
|
@ -170,6 +171,20 @@ fallback_keyboard_notify_key(struct fallback_dispatch *dispatch,
|
|||
keyboard_notify_key(&device->base, time, key, state);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_lid_notify_toggle(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
uint64_t time)
|
||||
{
|
||||
if (dispatch->lid.is_closed ^ dispatch->lid.is_closed_client_state) {
|
||||
switch_notify_toggle(&device->base,
|
||||
time,
|
||||
LIBINPUT_SWITCH_LID,
|
||||
dispatch->lid.is_closed);
|
||||
dispatch->lid.is_closed_client_state = dispatch->lid.is_closed;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evdev_pointer_notify_physical_button(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
|
|
@ -1086,6 +1101,82 @@ fallback_process_absolute_motion(struct fallback_dispatch *dispatch,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_lid_keyboard_event(uint64_t time,
|
||||
struct libinput_event *event,
|
||||
void *data)
|
||||
{
|
||||
struct fallback_dispatch *dispatch = fallback_dispatch(data);
|
||||
|
||||
if (!dispatch->lid.is_closed)
|
||||
return;
|
||||
|
||||
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
|
||||
return;
|
||||
|
||||
if (dispatch->lid.reliability == RELIABILITY_WRITE_OPEN) {
|
||||
int fd = libevdev_get_fd(dispatch->device->evdev);
|
||||
struct input_event ev[2] = {
|
||||
{{ 0, 0 }, EV_SW, SW_LID, 0 },
|
||||
{{ 0, 0 }, EV_SYN, SYN_REPORT, 0 },
|
||||
};
|
||||
|
||||
(void)write(fd, ev, sizeof(ev));
|
||||
/* In case write() fails, we sync the lid state manually
|
||||
* regardless. */
|
||||
}
|
||||
|
||||
/* Posting the event here means we preempt the keyboard events that
|
||||
* caused us to wake up, so the lid event is always passed on before
|
||||
* the key event.
|
||||
*/
|
||||
dispatch->lid.is_closed = false;
|
||||
fallback_lid_notify_toggle(dispatch, dispatch->device, time);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_lid_toggle_keyboard_listener(struct fallback_dispatch *dispatch,
|
||||
bool is_closed)
|
||||
{
|
||||
if (!dispatch->lid.keyboard)
|
||||
return;
|
||||
|
||||
if (is_closed) {
|
||||
libinput_device_add_event_listener(
|
||||
&dispatch->lid.keyboard->base,
|
||||
&dispatch->lid.listener,
|
||||
fallback_lid_keyboard_event,
|
||||
dispatch);
|
||||
} else {
|
||||
libinput_device_remove_event_listener(
|
||||
&dispatch->lid.listener);
|
||||
libinput_device_init_event_listener(
|
||||
&dispatch->lid.listener);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
fallback_process_switch(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
struct input_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
bool is_closed;
|
||||
|
||||
switch (e->code) {
|
||||
case SW_LID:
|
||||
is_closed = !!e->value;
|
||||
|
||||
if (dispatch->lid.is_closed == is_closed)
|
||||
return;
|
||||
fallback_lid_toggle_keyboard_listener(dispatch, is_closed);
|
||||
|
||||
dispatch->lid.is_closed = is_closed;
|
||||
fallback_lid_notify_toggle(dispatch, device, time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evdev_notify_axis(struct evdev_device *device,
|
||||
uint64_t time,
|
||||
|
|
@ -1317,6 +1408,9 @@ fallback_process(struct evdev_dispatch *evdev_dispatch,
|
|||
case EV_KEY:
|
||||
fallback_process_key(dispatch, device, event, time);
|
||||
break;
|
||||
case EV_SW:
|
||||
fallback_process_switch(dispatch, device, event, time);
|
||||
break;
|
||||
case EV_SYN:
|
||||
sent = fallback_flush_pending_event(dispatch, device, time);
|
||||
switch (sent) {
|
||||
|
|
@ -1434,6 +1528,46 @@ fallback_suspend(struct evdev_dispatch *evdev_dispatch,
|
|||
fallback_return_to_neutral_state(dispatch, device);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_remove(struct evdev_dispatch *evdev_dispatch)
|
||||
{
|
||||
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
|
||||
|
||||
if (!dispatch->lid.keyboard)
|
||||
return;
|
||||
|
||||
libinput_device_remove_event_listener(&dispatch->lid.listener);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_sync_initial_state(struct evdev_device *device,
|
||||
struct evdev_dispatch *evdev_dispatch)
|
||||
{
|
||||
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
|
||||
uint64_t time = libinput_now(evdev_libinput_context(device));
|
||||
|
||||
if (device->tags & EVDEV_TAG_LID_SWITCH) {
|
||||
struct libevdev *evdev = device->evdev;
|
||||
|
||||
dispatch->lid.is_closed = libevdev_get_event_value(evdev,
|
||||
EV_SW,
|
||||
SW_LID);
|
||||
dispatch->lid.is_closed_client_state = false;
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if (dispatch->lid.is_closed &&
|
||||
dispatch->lid.reliability == RELIABILITY_RELIABLE) {
|
||||
fallback_lid_notify_toggle(dispatch, device, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_toggle_touch(struct evdev_dispatch *evdev_dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -1503,16 +1637,68 @@ evdev_calibration_get_default_matrix(struct libinput_device *libinput_device,
|
|||
return !matrix_is_identity(&device->abs.default_calibration);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_lid_pair_keyboard(struct evdev_device *lid_switch,
|
||||
struct evdev_device *keyboard)
|
||||
{
|
||||
struct fallback_dispatch *dispatch =
|
||||
fallback_dispatch(lid_switch->dispatch);
|
||||
|
||||
if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0 ||
|
||||
(lid_switch->tags & EVDEV_TAG_LID_SWITCH) == 0)
|
||||
return;
|
||||
|
||||
if (dispatch->lid.keyboard)
|
||||
return;
|
||||
|
||||
if (keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD) {
|
||||
dispatch->lid.keyboard = keyboard;
|
||||
evdev_log_debug(lid_switch,
|
||||
"lid: keyboard paired with %s<->%s\n",
|
||||
lid_switch->devname,
|
||||
keyboard->devname);
|
||||
|
||||
/* We need to init the event listener now only if the reported state
|
||||
* is closed. */
|
||||
if (dispatch->lid.is_closed)
|
||||
fallback_lid_toggle_keyboard_listener(dispatch,
|
||||
dispatch->lid.is_closed);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_interface_device_added(struct evdev_device *device,
|
||||
struct evdev_device *added_device)
|
||||
{
|
||||
fallback_lid_pair_keyboard(device, added_device);
|
||||
}
|
||||
|
||||
static void
|
||||
fallback_interface_device_removed(struct evdev_device *device,
|
||||
struct evdev_device *removed_device)
|
||||
{
|
||||
struct fallback_dispatch *dispatch =
|
||||
fallback_dispatch(device->dispatch);
|
||||
|
||||
if (removed_device == dispatch->lid.keyboard) {
|
||||
libinput_device_remove_event_listener(
|
||||
&dispatch->lid.listener);
|
||||
libinput_device_init_event_listener(
|
||||
&dispatch->lid.listener);
|
||||
dispatch->lid.keyboard = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct evdev_dispatch_interface fallback_interface = {
|
||||
fallback_process,
|
||||
fallback_suspend,
|
||||
NULL, /* remove */
|
||||
fallback_remove,
|
||||
fallback_destroy,
|
||||
NULL, /* device_added */
|
||||
NULL, /* device_removed */
|
||||
NULL, /* device_suspended */
|
||||
NULL, /* device_resumed */
|
||||
NULL, /* post_added */
|
||||
fallback_interface_device_added,
|
||||
fallback_interface_device_removed,
|
||||
fallback_interface_device_removed, /* device_suspended, treat as remove */
|
||||
fallback_interface_device_added, /* device_resumed, treat as add */
|
||||
fallback_sync_initial_state, /* post_added */
|
||||
fallback_toggle_touch, /* toggle_touch */
|
||||
};
|
||||
|
||||
|
|
@ -1984,6 +2170,40 @@ fallback_dispatch_init_abs(struct fallback_dispatch *dispatch,
|
|||
evdev_device_init_abs_range_warnings(device);
|
||||
}
|
||||
|
||||
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)) {
|
||||
evdev_log_error(device,
|
||||
"%s: switch reliability set to unknown value '%s'\n",
|
||||
device->devname,
|
||||
prop);
|
||||
r = RELIABILITY_UNKNOWN;
|
||||
} else if (r == RELIABILITY_WRITE_OPEN) {
|
||||
evdev_log_info(device,
|
||||
"%s: will write switch open events\n",
|
||||
device->devname);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void
|
||||
fallback_dispatch_init_switch(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
if (device->tags & EVDEV_TAG_LID_SWITCH) {
|
||||
libinput_device_init_event_listener(&dispatch->lid.listener);
|
||||
dispatch->lid.reliability = evdev_read_switch_reliability_prop(device);
|
||||
dispatch->lid.is_closed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct evdev_dispatch *
|
||||
fallback_dispatch_create(struct libinput_device *libinput_device)
|
||||
{
|
||||
|
|
@ -1992,6 +2212,7 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
|||
char timer_name[64];
|
||||
|
||||
dispatch = zalloc(sizeof *dispatch);
|
||||
dispatch->device = evdev_device(libinput_device);
|
||||
dispatch->base.dispatch_type = DISPATCH_FALLBACK;
|
||||
dispatch->base.interface = &fallback_interface;
|
||||
dispatch->pending_event = EVDEV_NONE;
|
||||
|
|
@ -2003,6 +2224,8 @@ fallback_dispatch_create(struct libinput_device *libinput_device)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
fallback_dispatch_init_switch(dispatch, device);
|
||||
|
||||
if (device->left_handed.want_enabled)
|
||||
evdev_init_left_handed(device,
|
||||
evdev_change_to_left_handed);
|
||||
|
|
@ -2894,11 +3117,9 @@ evdev_configure_device(struct evdev_device *device)
|
|||
|
||||
if (udev_tags & EVDEV_UDEV_TAG_SWITCH &&
|
||||
libevdev_has_event_code(evdev, EV_SW, SW_LID)) {
|
||||
dispatch = evdev_lid_switch_dispatch_create(device);
|
||||
device->seat_caps |= EVDEV_DEVICE_SWITCH;
|
||||
evdev_tag_lid_switch(device);
|
||||
evdev_log_info(device, "device is a switch device\n");
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
if (device->seat_caps & EVDEV_DEVICE_POINTER &&
|
||||
|
|
|
|||
10
src/evdev.h
10
src/evdev.h
|
|
@ -345,6 +345,7 @@ evdev_verify_dispatch_type(struct evdev_dispatch *dispatch,
|
|||
|
||||
struct fallback_dispatch {
|
||||
struct evdev_dispatch base;
|
||||
struct evdev_device *device;
|
||||
|
||||
struct libinput_device_config_calibration calibration;
|
||||
|
||||
|
|
@ -391,6 +392,15 @@ struct fallback_dispatch {
|
|||
uint64_t button_up_time;
|
||||
struct libinput_timer timer;
|
||||
} debounce;
|
||||
|
||||
struct {
|
||||
enum switch_reliability reliability;
|
||||
|
||||
bool is_closed;
|
||||
bool is_closed_client_state;
|
||||
struct evdev_device *keyboard;
|
||||
struct libinput_event_listener listener;
|
||||
} lid;
|
||||
};
|
||||
|
||||
static inline struct fallback_dispatch*
|
||||
|
|
|
|||
|
|
@ -604,10 +604,8 @@ START_TEST(lid_key_press)
|
|||
litest_keyboard_key(sw, KEY_POWER, false);
|
||||
libinput_dispatch(li);
|
||||
|
||||
/* We should route the key events correctly, but for now we just
|
||||
* ignore them. This test will fail once the key events are handled
|
||||
* correctly. */
|
||||
litest_assert_empty_queue(li);
|
||||
/* Check that we're routing key events from a lid device too */
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue