mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-02-15 06:50:38 +01:00
ei: require the client to confirm capabilities rather than drop them
Our API requires a client to know which capability to pass into the drop_capabilities function. This doesn't work for capabilities newer than the client's version so they do not get disabled. The client will thus receive devices it didn't ask for and doesn't know how to handle. Let's invert the requirement and require the caller to confirm the capabilities it wants - all others are dropped. This is an API break but also requires updates of all clients, the previous simple case of just calling ei_seat_bind() will now result in zero capabilities.
This commit is contained in:
parent
8474d03e03
commit
541dcb415d
7 changed files with 53 additions and 18 deletions
|
|
@ -87,7 +87,7 @@ struct ei_seat {
|
|||
struct list devices_removed; /* removed from seat but client still has a ref */
|
||||
uint32_t id;
|
||||
uint32_t capabilities;
|
||||
uint32_t capabilities_mask;
|
||||
uint32_t capabilities_confirmed;
|
||||
char *name;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ ei_seat_new(struct ei *ei, uint32_t id, const char *name, uint32_t capabilities)
|
|||
seat->name = xstrdup(name);
|
||||
seat->id = id;
|
||||
seat->capabilities = capabilities;
|
||||
seat->capabilities_mask = ~0; /* Masked out by client */
|
||||
seat->capabilities_confirmed = 0;
|
||||
|
||||
list_init(&seat->devices);
|
||||
list_init(&seat->devices_removed);
|
||||
|
|
@ -134,21 +134,20 @@ ei_seat_has_capability(struct ei_seat *seat,
|
|||
case EI_DEVICE_CAP_POINTER_ABSOLUTE:
|
||||
case EI_DEVICE_CAP_KEYBOARD:
|
||||
case EI_DEVICE_CAP_TOUCH:
|
||||
return flag_is_set(seat->capabilities_mask, cap);
|
||||
return flag_is_set(seat->capabilities, cap);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_public_ void
|
||||
ei_seat_drop_capability(struct ei_seat *seat,
|
||||
enum ei_device_capability cap)
|
||||
ei_seat_confirm_capability(struct ei_seat *seat, enum ei_device_capability cap)
|
||||
{
|
||||
if (seat->state != EI_SEAT_STATE_NEW) {
|
||||
log_bug_client(ei_seat_get_context(seat), "Seat is already bound\n");
|
||||
return;
|
||||
}
|
||||
|
||||
flag_clear(seat->capabilities_mask, cap);
|
||||
flag_set(seat->capabilities_confirmed, cap);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
|
|
@ -159,7 +158,7 @@ ei_seat_bind(struct ei_seat *seat)
|
|||
return;
|
||||
}
|
||||
|
||||
ei_send_seat_bind(seat, seat->capabilities & seat->capabilities_mask);
|
||||
ei_send_seat_bind(seat, seat->capabilities & seat->capabilities_confirmed);
|
||||
seat->state = EI_SEAT_STATE_BOUND;
|
||||
}
|
||||
|
||||
|
|
|
|||
30
src/libei.h
30
src/libei.h
|
|
@ -134,7 +134,7 @@ struct ei_region;
|
|||
* device with capabilities unsupported by the client.
|
||||
*
|
||||
* Capabilities are initialized by the EIS implementation but the client may
|
||||
* further reduce the requested capabilities, see ei_seat_drop_capability().
|
||||
* further reduce the requested capabilities, see ei_seat_confirm_capability().
|
||||
* For example, a client may bind to a seat with the pointer and keyboard
|
||||
* capability but only the former is permitted by the EIS implementation.
|
||||
* Keyboard events sent through such a device will be treated as client bug
|
||||
|
|
@ -646,28 +646,40 @@ ei_event_unref(struct ei_event *event);
|
|||
const char *
|
||||
ei_seat_get_name(struct ei_seat *seat);
|
||||
|
||||
/**
|
||||
* Return true if the capabilitiy is available on this seat or false
|
||||
* otherwise. The return value of this function is not affected by
|
||||
* ei_seat_confirm_capability().
|
||||
*/
|
||||
bool
|
||||
ei_seat_has_capability(struct ei_seat *seat,
|
||||
enum ei_device_capability cap);
|
||||
|
||||
/**
|
||||
* Remove a capability from this seat before calling ei_seat_bind().
|
||||
* Devices with only the dropped capability will never be added to this
|
||||
* client, devices with multiple capabilities will not show the dropped
|
||||
* capabilities.
|
||||
* Confirm a capability from this seat before calling ei_seat_bind().
|
||||
*
|
||||
* A client must call this function for every capability on the seat it wants
|
||||
* to receive devices for. Only devices with one or more supported
|
||||
* capabilities will be added to this client.
|
||||
*
|
||||
* Calling this function for a capability that ei_seat_has_capability()
|
||||
* returns false for is a noop and permitted.
|
||||
*
|
||||
* This function has no effect if called after ei_seat_bind().
|
||||
*/
|
||||
void
|
||||
ei_seat_drop_capability(struct ei_seat *seat,
|
||||
enum ei_device_capability cap);
|
||||
ei_seat_confirm_capability(struct ei_seat *seat,
|
||||
enum ei_device_capability cap);
|
||||
|
||||
/**
|
||||
* Bind this client to the given seat for the seat's capabilities.
|
||||
* Bind this client to the given seat for the confirmed seat's capabilities.
|
||||
* This function can only be called once per seat. Once bound, the server will
|
||||
* create devices for the seat's capabillities and send the respective @ref
|
||||
* create devices for the seat's capabilities and send the respective @ref
|
||||
* EI_EVENT_DEVICE_ADDED events.
|
||||
*
|
||||
* A client must call ei_seat_confirm_capability() before calling
|
||||
* ei_seat_bind().
|
||||
*
|
||||
* Devices may be added and removed at any time.
|
||||
*/
|
||||
void
|
||||
|
|
|
|||
|
|
@ -814,6 +814,10 @@ _peck_dispatch_ei(struct peck *peck, int lineno)
|
|||
munit_assert_ptr_null(peck->ei_seat);
|
||||
peck->ei_seat = ei_seat_ref(seat);
|
||||
log_debug(peck, "default seat: %s\n", ei_seat_get_name(peck->ei_seat));
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_TOUCH);
|
||||
ei_seat_bind(seat);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ MUNIT_TEST(test_ei_seat_bind_unbind)
|
|||
with_client(peck) {
|
||||
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
|
||||
seat = ei_seat_ref(ei_event_get_seat(event));
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_TOUCH);
|
||||
ei_seat_bind(seat);
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +105,10 @@ MUNIT_TEST(test_ei_seat_bind_unbind_noref)
|
|||
with_client(peck) {
|
||||
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
|
||||
seat = ei_seat_ref(ei_event_get_seat(event));
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_TOUCH);
|
||||
ei_seat_bind(seat);
|
||||
}
|
||||
|
||||
|
|
@ -149,6 +157,10 @@ MUNIT_TEST(test_ei_seat_bind_unbind_immediately)
|
|||
with_client(peck) {
|
||||
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
|
||||
seat = ei_event_get_seat(event);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_TOUCH);
|
||||
ei_seat_bind(seat);
|
||||
ei_seat_unbind(seat);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,8 +120,12 @@ MUNIT_TEST(eistest_cliend_bind_some_caps)
|
|||
_unref_(ei_event) *event =
|
||||
peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
|
||||
struct ei_seat *seat = ei_event_get_seat(event);
|
||||
ei_seat_drop_capability(seat, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_seat_drop_capability(seat, EI_DEVICE_CAP_TOUCH);
|
||||
munit_assert_true(ei_seat_has_capability(seat, EI_DEVICE_CAP_KEYBOARD));
|
||||
munit_assert_true(ei_seat_has_capability(seat, EI_DEVICE_CAP_POINTER));
|
||||
munit_assert_true(ei_seat_has_capability(seat, EI_DEVICE_CAP_POINTER_ABSOLUTE));
|
||||
munit_assert_true(ei_seat_has_capability(seat, EI_DEVICE_CAP_TOUCH));
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER);
|
||||
ei_seat_confirm_capability(seat, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_seat_bind(seat);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,6 +312,10 @@ int main(int argc, char **argv)
|
|||
}
|
||||
default_seat = ei_seat_ref(ei_event_get_seat(e));
|
||||
colorprint("seat added: %s\n", ei_seat_get_name(default_seat));
|
||||
ei_seat_confirm_capability(default_seat, EI_DEVICE_CAP_POINTER);
|
||||
ei_seat_confirm_capability(default_seat, EI_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
ei_seat_confirm_capability(default_seat, EI_DEVICE_CAP_KEYBOARD);
|
||||
ei_seat_confirm_capability(default_seat, EI_DEVICE_CAP_TOUCH);
|
||||
ei_seat_bind(default_seat);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue