mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-01 04:40:09 +01:00
Merge branch 'wip/keyboard-integration-property'
This commit is contained in:
commit
f139d8fbc3
8 changed files with 147 additions and 50 deletions
|
|
@ -34,6 +34,7 @@ struct lid_switch_dispatch {
|
|||
enum switch_reliability reliability;
|
||||
|
||||
bool lid_is_closed;
|
||||
bool lid_is_closed_client_state;
|
||||
|
||||
struct {
|
||||
struct evdev_device *keyboard;
|
||||
|
|
@ -49,6 +50,20 @@ lid_dispatch(struct evdev_dispatch *dispatch)
|
|||
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,
|
||||
|
|
@ -74,11 +89,12 @@ lid_switch_keyboard_event(uint64_t time,
|
|||
* 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;
|
||||
switch_notify_toggle(&dispatch->device->base,
|
||||
time,
|
||||
LIBINPUT_SWITCH_LID,
|
||||
dispatch->lid_is_closed);
|
||||
lid_switch_notify_toggle(dispatch, dispatch->device, time);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -116,16 +132,12 @@ lid_switch_process_switch(struct lid_switch_dispatch *dispatch,
|
|||
|
||||
if (dispatch->lid_is_closed == is_closed)
|
||||
return;
|
||||
|
||||
lid_switch_toggle_keyboard_listener(dispatch,
|
||||
is_closed);
|
||||
|
||||
dispatch->lid_is_closed = is_closed;
|
||||
|
||||
switch_notify_toggle(&device->base,
|
||||
time,
|
||||
LIBINPUT_SWITCH_LID,
|
||||
dispatch->lid_is_closed);
|
||||
lid_switch_notify_toggle(dispatch, device, time);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -198,29 +210,26 @@ lid_switch_pair_keyboard(struct evdev_device *lid_switch,
|
|||
{
|
||||
struct lid_switch_dispatch *dispatch =
|
||||
lid_dispatch(lid_switch->dispatch);
|
||||
unsigned int bus_kbd = libevdev_get_id_bustype(keyboard->evdev);
|
||||
|
||||
if ((keyboard->tags & EVDEV_TAG_KEYBOARD) == 0)
|
||||
return;
|
||||
|
||||
/* If we already have a keyboard paired, override it if the new one
|
||||
* is a serio device. Otherwise keep the current one */
|
||||
if (dispatch->keyboard.keyboard) {
|
||||
if (bus_kbd != BUS_I8042)
|
||||
return;
|
||||
if (dispatch->keyboard.keyboard)
|
||||
return;
|
||||
|
||||
libinput_device_remove_event_listener(&dispatch->keyboard.listener);
|
||||
libinput_device_init_event_listener(&dispatch->keyboard.listener);
|
||||
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);
|
||||
}
|
||||
|
||||
dispatch->keyboard.keyboard = keyboard;
|
||||
evdev_log_debug(lid_switch,
|
||||
"lid: keyboard paired with %s<->%s\n",
|
||||
lid_switch->devname,
|
||||
keyboard->devname);
|
||||
|
||||
/* We don't init the event listener yet - we don't care about
|
||||
* keyboard events until the lid is closed */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -251,10 +260,12 @@ lid_switch_sync_initial_state(struct evdev_device *device,
|
|||
{
|
||||
struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch);
|
||||
struct libevdev *evdev = device->evdev;
|
||||
bool is_closed = false;
|
||||
|
||||
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
|
||||
|
|
@ -262,24 +273,11 @@ lid_switch_sync_initial_state(struct evdev_device *device,
|
|||
* that always have the switch in 'on' state thus don't mess up our
|
||||
* touchpad.
|
||||
*/
|
||||
switch(dispatch->reliability) {
|
||||
case RELIABILITY_UNKNOWN:
|
||||
case RELIABILITY_WRITE_OPEN:
|
||||
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) {
|
||||
if (dispatch->lid_is_closed &&
|
||||
dispatch->reliability == RELIABILITY_RELIABLE) {
|
||||
uint64_t time;
|
||||
time = libinput_now(evdev_libinput_context(device));
|
||||
switch_notify_toggle(&device->base,
|
||||
time,
|
||||
LIBINPUT_SWITCH_LID,
|
||||
LIBINPUT_SWITCH_STATE_ON);
|
||||
lid_switch_notify_toggle(dispatch, device, time);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1601,8 +1601,7 @@ tp_want_dwt(struct evdev_device *touchpad,
|
|||
/* For Apple touchpads, always use its internal keyboard */
|
||||
if (vendor_tp == VENDOR_ID_APPLE) {
|
||||
return vendor_kbd == vendor_tp &&
|
||||
keyboard->model_flags &
|
||||
EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD;
|
||||
keyboard->tags & EVDEV_TAG_INTERNAL_KEYBOARD;
|
||||
}
|
||||
|
||||
/* everything else we don't really know, so we have to assume
|
||||
|
|
|
|||
31
src/evdev.c
31
src/evdev.c
|
|
@ -1089,10 +1089,25 @@ evdev_tag_trackpoint(struct evdev_device *device,
|
|||
device->tags |= EVDEV_TAG_TRACKPOINT;
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_tag_keyboard_internal(struct evdev_device *device)
|
||||
{
|
||||
device->tags |= EVDEV_TAG_INTERNAL_KEYBOARD;
|
||||
device->tags &= ~EVDEV_TAG_EXTERNAL_KEYBOARD;
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_tag_keyboard_external(struct evdev_device *device)
|
||||
{
|
||||
device->tags |= EVDEV_TAG_EXTERNAL_KEYBOARD;
|
||||
device->tags &= ~EVDEV_TAG_INTERNAL_KEYBOARD;
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_tag_keyboard(struct evdev_device *device,
|
||||
struct udev_device *udev_device)
|
||||
{
|
||||
const char *prop;
|
||||
int code;
|
||||
|
||||
if (!libevdev_has_event_type(device->evdev, EV_KEY))
|
||||
|
|
@ -1105,6 +1120,21 @@ evdev_tag_keyboard(struct evdev_device *device,
|
|||
return;
|
||||
}
|
||||
|
||||
/* This should eventually become ID_INPUT_KEYBOARD_INTEGRATION */
|
||||
prop = udev_device_get_property_value(udev_device,
|
||||
"LIBINPUT_ATTR_KEYBOARD_INTEGRATION");
|
||||
if (prop) {
|
||||
if (streq(prop, "internal")) {
|
||||
evdev_tag_keyboard_internal(device);
|
||||
} else if (streq(prop, "external")) {
|
||||
evdev_tag_keyboard_external(device);
|
||||
} else {
|
||||
evdev_log_info(device,
|
||||
"tagged with unknown value %s\n",
|
||||
prop);
|
||||
}
|
||||
}
|
||||
|
||||
device->tags |= EVDEV_TAG_KEYBOARD;
|
||||
}
|
||||
|
||||
|
|
@ -2251,7 +2281,6 @@ evdev_read_model_flags(struct evdev_device *device)
|
|||
MODEL(ALPS_TOUCHPAD),
|
||||
MODEL(SYNAPTICS_SERIAL_TOUCHPAD),
|
||||
MODEL(JUMPING_SEMI_MT),
|
||||
MODEL(APPLE_INTERNAL_KEYBOARD),
|
||||
MODEL(CYBORG_RAT),
|
||||
MODEL(HP_STREAM11_TOUCHPAD),
|
||||
MODEL(LENOVO_T450_TOUCHPAD),
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ enum evdev_device_tags {
|
|||
EVDEV_TAG_TRACKPOINT = (1 << 3),
|
||||
EVDEV_TAG_KEYBOARD = (1 << 4),
|
||||
EVDEV_TAG_LID_SWITCH = (1 << 5),
|
||||
EVDEV_TAG_INTERNAL_KEYBOARD = (1 << 6),
|
||||
EVDEV_TAG_EXTERNAL_KEYBOARD = (1 << 7),
|
||||
};
|
||||
|
||||
enum evdev_middlebutton_state {
|
||||
|
|
@ -112,7 +114,6 @@ enum evdev_device_model {
|
|||
EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9),
|
||||
EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10),
|
||||
EVDEV_MODEL_LENOVO_X220_TOUCHPAD_FW81 = (1 << 12),
|
||||
EVDEV_MODEL_APPLE_INTERNAL_KEYBOARD = (1 << 13),
|
||||
EVDEV_MODEL_CYBORG_RAT = (1 << 14),
|
||||
EVDEV_MODEL_HP_STREAM11_TOUCHPAD = (1 << 16),
|
||||
EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
|
||||
|
|
|
|||
|
|
@ -505,6 +505,56 @@ START_TEST(lid_update_hw_on_key)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(lid_update_hw_on_key_closed_on_init)
|
||||
{
|
||||
struct litest_device *sw = litest_current_device();
|
||||
struct libinput *li;
|
||||
struct litest_device *keyboard;
|
||||
struct libevdev *evdev = sw->evdev;
|
||||
struct input_event ev;
|
||||
|
||||
litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON);
|
||||
|
||||
/* Make sure kernel state is right */
|
||||
libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
|
||||
while (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_SYNC, &ev) >= 0)
|
||||
;
|
||||
ck_assert(libevdev_get_event_value(evdev, EV_SW, SW_LID));
|
||||
|
||||
keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD);
|
||||
|
||||
/* separate context for the right state on init */
|
||||
li = litest_create_context();
|
||||
libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(sw->uinput));
|
||||
libinput_path_add_device(li,
|
||||
libevdev_uinput_get_devnode(keyboard->uinput));
|
||||
|
||||
/* don't expect a switch waiting for us */
|
||||
while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
|
||||
ck_assert_int_ne(libinput_next_event_type(li),
|
||||
LIBINPUT_EVENT_SWITCH_TOGGLE);
|
||||
libinput_event_destroy(libinput_get_event(li));
|
||||
}
|
||||
|
||||
litest_event(keyboard, EV_KEY, KEY_A, 1);
|
||||
litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
|
||||
litest_event(keyboard, EV_KEY, KEY_A, 0);
|
||||
litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
|
||||
/* No switch event, we're still in vanilla (open) state */
|
||||
litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
|
||||
|
||||
/* Make sure kernel state has updated */
|
||||
libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
|
||||
while (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_SYNC, &ev) >= 0)
|
||||
;
|
||||
ck_assert(!libevdev_get_event_value(evdev, EV_SW, SW_LID));
|
||||
|
||||
libinput_unref(li);
|
||||
litest_delete_device(keyboard);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
litest_setup_tests_lid(void)
|
||||
{
|
||||
|
|
@ -525,4 +575,5 @@ litest_setup_tests_lid(void)
|
|||
litest_add_no_device("lid:disable_touchpad", lid_suspend_with_touchpad);
|
||||
|
||||
litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3);
|
||||
litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@ libinput:name:*Lid Switch*:dmi:*:ct10:*
|
|||
libinput:name:*Lid Switch*:dmi:*:ct9:*
|
||||
LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=reliable
|
||||
|
||||
##########################################
|
||||
# Serial keyboards are internal
|
||||
##########################################
|
||||
libinput:keyboard:input:b0011v*
|
||||
LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal
|
||||
|
||||
##########################################
|
||||
# ALPS
|
||||
##########################################
|
||||
|
|
@ -45,7 +51,7 @@ libinput:touchpad:input:b0005v05ACp*
|
|||
LIBINPUT_ATTR_SIZE_HINT=104x75
|
||||
|
||||
libinput:name:*Apple Inc. Apple Internal Keyboard*:dmi:*
|
||||
LIBINPUT_MODEL_APPLE_INTERNAL_KEYBOARD=1
|
||||
LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal
|
||||
|
||||
libinput:mouse:input:b0005v05ACp030D*
|
||||
LIBINPUT_MODEL_APPLE_MAGICMOUSE=1
|
||||
|
|
@ -186,6 +192,10 @@ libinput:mouse:input:b0003v046DpC408*
|
|||
libinput:name:*Lid Switch*:dmi:*svnMicrosoftCorporation:pnSurface3:*
|
||||
LIBINPUT_ATTR_LID_SWITCH_RELIABILITY=write_open
|
||||
|
||||
# Surface 3 Type Cover keyboard
|
||||
libinput:name:*Microsoft Surface Type Cover Keyboard*:dmi:*svnMicrosoftCorporation:pnSurface3:*
|
||||
LIBINPUT_ATTR_KEYBOARD_INTEGRATION=internal
|
||||
|
||||
##########################################
|
||||
# Synaptics
|
||||
##########################################
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ ENV{ID_INPUT_TOUCHPAD}=="1", \
|
|||
ENV{ID_INPUT_MOUSE}=="1", \
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:mouse:"
|
||||
|
||||
# libinput:touchpad:<modalias>
|
||||
ENV{ID_INPUT_KEYBOARD}=="1", \
|
||||
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:keyboard:"
|
||||
|
||||
# libinput:name:<name>:dmi:<dmi string>
|
||||
KERNELS=="input*", \
|
||||
IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'"
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER))
|
|||
UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
|
||||
|
||||
TYPES = {
|
||||
'libinput': ('name', 'touchpad', 'mouse'),
|
||||
'libinput': ('name', 'touchpad', 'mouse', 'keyboard'),
|
||||
}
|
||||
|
||||
@functools.lru_cache()
|
||||
|
|
@ -117,8 +117,13 @@ def property_grammar():
|
|||
Suppress('=') -
|
||||
Group(pressure_range('SETTINGS*')) ]
|
||||
|
||||
kbintegration_tags = Or(('internal', 'external'))
|
||||
kbintegration = [Literal('LIBINPUT_ATTR_KEYBOARD_INTEGRATION')('NAME') -
|
||||
Suppress('=') -
|
||||
kbintegration_tags('VALUE')]
|
||||
|
||||
grammar = Or(model_props + size_props + reliability + tpkbcombo +
|
||||
pressure_prop)
|
||||
pressure_prop + kbintegration)
|
||||
|
||||
return grammar
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue