mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2025-12-25 04:40:05 +01:00
The original idea here was that we would have an EmulatedInput portal that allows the application to connect directly to the EIS implementation to exchange input events - instead of ping-ponging DBus events through the xdg-desktop-portal as the RemoteDesktop portal requires. This is no longer accurate, there are suggested PRs open to add RemoteDesktop.ConnectToEIS to achieve the same through the existing RemoteDesktop interface [1] and to add a new InputCapture portal to allow for events to be sent to a libei receiver context [2]. The example EmulatedInput portal is thus superfluous and can be removed from here. We could switch the ei_setup_backend_portal() code to use RemoteDesktop or InputCapture, depending on the context type, the utility of this is questionable. Interaction with portals is complex, one needs to implement the Session/Request interfaces correctly and in the case of InputCapture also handle the complex zones/pointer barrier setup. libportal does some of this (or it will, anyway) so it's more useful for an application to use libportal and then just pass the received fd to libei. If there is a future need for this to be handled as part of libei, we can (re)implement this, but for now it's best to just purge all of this. [1] https://github.com/flatpak/xdg-desktop-portal/pull/762 [2] https://github.com/flatpak/xdg-desktop-portal/pull/714
134 lines
4.2 KiB
Text
134 lines
4.2 KiB
Text
# This is pseudocode, illustrating a libeis server implementation
|
|
#
|
|
# This pseudocode assumes to be part of a compositor that can handle
|
|
# input events. It assumes policy decisions as to whether a client may
|
|
# connect are made in the portal or the compositor.
|
|
#
|
|
|
|
function main():
|
|
ctx = eis_new()
|
|
eis_init(ctx)
|
|
|
|
while True:
|
|
poll(eis_get_fd()):
|
|
event = eis_get_event();
|
|
handler = functions[eis_event_get_type(event)]
|
|
handler(event)
|
|
|
|
for client in myclients:
|
|
eis_client_disconnect(client)
|
|
|
|
eis_unref(ctx)
|
|
|
|
|
|
function event_client_connect(event):
|
|
client = eis_event_get_client(event)
|
|
|
|
if do_not_allow_emulated_input:
|
|
eis_client_disconnect(client)
|
|
return
|
|
|
|
# for the portal backend we're assuming that the client has been
|
|
# authenticated by the user, otherwise some authentication needs to
|
|
# be done here
|
|
eis_client_connect(client)
|
|
myclients[client] = eis_client_ref(client)
|
|
|
|
# Send a seats out to the client. Could be the list of seats the
|
|
# server uses anyway, or custom ones.
|
|
seat = eis_client_new_seat(client, "default")
|
|
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_POINTER)
|
|
eis_seat_allow_capability(seat, EIS_DEVICE_CAP_KEYBOARD)
|
|
eis_seat_add(seat)
|
|
|
|
|
|
function event_client_disconnect(event):
|
|
client = eis_event_get_client(event)
|
|
eis_client_unref(client)
|
|
|
|
|
|
function event_device_added(event):
|
|
client = eis_event_get_client(event)
|
|
device = eis_event_get_device(event)
|
|
|
|
if client has too many devices:
|
|
eis_device_disconnect(device)
|
|
return
|
|
|
|
if disallow_touch_input:
|
|
eis_device_disable_capability(EIS_DEVICE_CAP_TOUCH)
|
|
|
|
if eis_device_has_capability(EIS_DEVICE_CAP_POINTER_ABSOLUTE):
|
|
# this is the fixed range give the client. Let's check if there's a
|
|
# monitor with those dimensions and map the device to that monitor
|
|
# That's a server private implementation detail, just used as
|
|
# example here
|
|
w = eis_device_pointer_get_width()
|
|
h = eis_device_pointer_get_height()
|
|
if (w, h) matches an output:
|
|
eis_device_set_user_data(output)
|
|
|
|
if eis_device_has_capability(EIS_DEVICE_CAP_KEYBOARD):
|
|
keymap = eis_device_keyboard_get_keymap()
|
|
# We do not implement per-device keymap in this pseudoserver, notify
|
|
# the client. If we did, here'd be the place to assign the map.
|
|
if keymap != -1:
|
|
eis_device_keyboard_set_keymap(device, -1)
|
|
|
|
eis_device_connect(device)
|
|
# Allow the client to send events
|
|
eis_device_resume(capabilities)
|
|
|
|
|
|
function event_pointer_motion(event):
|
|
x = eis_event_pointer_get_x(event)
|
|
y = eis_event_pointer_get_y(event)
|
|
compositor_handle_pointer_motion(x, y)
|
|
|
|
|
|
function event_pointer_motion_absolute(event):
|
|
x = eis_event_pointer_get_absolute_x(event)
|
|
y = eis_event_pointer_get_absolute_y(event)
|
|
|
|
# the output we map to, see event_device_added
|
|
output = eis_device_get_userdata()
|
|
sx = x/1000
|
|
sy = y/1000
|
|
|
|
compositor_handle_pointer_motion_absolute(output, sx, sy)
|
|
|
|
|
|
function event_pointer_keyboard_key(event):
|
|
device = eis_event_get_device(event)
|
|
|
|
key = eis_event_keyboard_get_key(event)
|
|
press = eis_event_keyboard_get_key_is_press(event)
|
|
|
|
# double escape pauses the device, as an example
|
|
if press and key == KEY_ESC and last_key == KEY_ESC:
|
|
eis_device_pause()
|
|
discard_events = true
|
|
|
|
# We may have paused the client but events can be in mid flight, so
|
|
# we need to process all incoming events regardless. libeis will filter
|
|
# only once the client has received the pause notification.
|
|
update_client_key_state(key, press)
|
|
if not discard_events:
|
|
compositor_handle_key(key, press)
|
|
|
|
|
|
function compositor_vt_switch_callback():
|
|
for client in myclients:
|
|
for device in devices[client]:
|
|
if vt_in:
|
|
eis_device_resume(device)
|
|
else
|
|
eis_device_pause(device)
|
|
|
|
|
|
# Compositor callback if no more emulated input should be handled
|
|
# from a specific client
|
|
function compositor_callback_terminate_EI(condition):
|
|
for client in myclients:
|
|
if client matches condition:
|
|
eis_client_disconnect(client)
|