/* * Copyright © 2020 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. */ #pragma once #include #include struct ei; struct ei_device; struct ei_event; struct ei_event_client; struct ei_event_pointer; struct ei_event_keyboard; struct ei_event_touch; enum ei_device_capability { EI_DEVICE_CAP_POINTER = 1, EI_DEVICE_CAP_POINTER_ABSOLUTE, EI_DEVICE_CAP_KEYBOARD, EI_DEVICE_CAP_TOUCH, }; enum ei_keymap_type { EI_KEYMAP_TYPE_NONE = 0, EI_KEYMAP_TYPE_XKB, }; enum ei_keymap_source { /** * The keymap is the one provided by the client. */ EI_KEYMAP_SOURCE_CLIENT = 1, /** * The keymap is provided by the server. */ EI_KEYMAP_SOURCE_SERVER, }; enum ei_event_type { /** * No event ever has this type, this type exists only as potential * return value for ei_next_event_type(). */ EI_EVENT_NONE = 0, /** * The server has approved the connection to this client. */ EI_EVENT_CONNECT, /** * The server has disconnected this client - all resources left to * reference this server are now obsolete. Once this event has been * received, the @ref struct ei and all its associated resources * should be released. */ EI_EVENT_DISCONNECT, /** * The server has added a device for this client. The capabilities * of the device may not match the requested capabilities - it is up * to the client to verify the minimum required capabilities are * indeed set. */ EI_EVENT_DEVICE_ADDED, /** * The server has removed a device belonging to this client. */ EI_EVENT_DEVICE_REMOVED, /** * Any events sent from this device will be discarded until the next * resume. */ EI_EVENT_DEVICE_SUSPENDED, /** * The client may send events. */ EI_EVENT_DEVICE_RESUMED, }; struct ei * ei_new(void *user_data); /** * Set the name for this client. This is a suggestion to the * server only and may not be honored. */ void ei_configure_name(struct ei * ei, const char *name); /** * Set this ei context to use the socket backend. */ int ei_setup_backend_socket(struct ei *ei, const char *socketpath); /** * Initialize the ei context on the given socket */ int ei_setup_backend_fd(struct ei *ei, int fd); struct ei * ei_ref(struct ei *ctx); struct ei * ei_unref(struct ei *ei); void ei_set_user_data(struct ei *ei, void *user_data); void * ei_get_user_data(struct ei *ei); /** * Connect to the libeis server via the org.freedesktop.portal * * @return 0 on success or a negative errno on failure */ int ei_portal_connect(struct ei *ei); /** * Connect to the libeis server on the org.freedesktop.Ei bus name. * * @return 0 on success or a negative errno on failure */ int ei_dbus_connect(struct ei *ei); /** * libei keeps a single file descriptor for all events. Cal * libei_dispatch() if any events become available on this fd. */ int ei_get_fd(struct ei *ei); /** * Main event dispatchment function. Reads events of the file descriptors * and processes them internally. Use libei_get_event() to retrieve the * events. * * Dispatching does not necessarily queue events. This function * should be called immediately once data is available on the file * descriptor returned by libei_get_fd(). */ void ei_dispatch(struct ei *ei); /** * Return the next event from the event queue, removing it from the queue. * * The returned object must be released by the caller with ei_event_unref() */ struct ei_event * ei_get_event(struct ei *ei); /** * Returns the next event in the internal event queue (or NULL) without * removing that event from the queue, i.e. the next call to ei_get_event() * will return that same event. * * This call is useful for checking whether there is an event and/or what * type of event it is. * * Repeated calls to ei_peek_event() return the same event. * * The returned event is refcounted, use ei_event_unref() to drop the * reference. * * A caller must not call ei_get_event() while holding a ref to an event * returned by ei_peek_event(). */ struct ei_event * ei_peek_event(struct ei *ei); /** * Return the type of the next event in the event queue or @ref * EI_EVENT_NONE if none are available. This function does not remove the * event from the queue. */ enum ei_event_type ei_next_event_type(struct ei *ei); /** * Release resources associated with this event. This function always * returns NULL. * * Events can only be unref'd by the caller. They should be considered * transient data and not be held longer than required. */ struct ei_event * ei_event_unref(struct ei_event *event); struct ei_device * ei_device_ref(struct ei_device *device); struct ei_device * ei_device_unref(struct ei_device *device); /** * Create a new device. This device is a proxy representing the server's * device and should be used for initial device configuration. It does not * represent the server-created device until the @ref EI_EVENT_DEVICE_ADDED * for this device has been received. * * Use the configure API (e.g. ei_device_configure_capability()) to set up * the device, then call ei_device_add() to request creation of the device * by the server. * * The returned object must be released by the caller with ei_event_unref() */ struct ei_device * ei_device_new(struct ei *ei); /** * Set the name for this device. This is a suggestion only, the server may * the name and assign a different one (or none). Use ei_device_get_name() * upon receiving @ref EI_EVENT_DEVICE_ADDED to get the server-assigned * name. * * This function has no effect if called after ei_device_add() * * libei may quietly ignore names of unreasonable length. This is not * something a normal caller ever needs to worry about. * * @param name A name suggestion for the device */ void ei_device_configure_name(struct ei_device *device, const char *name); /** * Enable the given capability on this device. This is a suggestion only, * the server may ignore this capability. * Use ei_device_has_capability() upon receiving @ref EI_EVENT_DEVICE_ADDED * to check for the actual capabilities of the device. * * This function has no effect if called after ei_device_add() * * @param cap The capability to enable */ bool ei_device_configure_capability(struct ei_device *device, enum ei_device_capability cap); /** * Set the range of the absolute pointer device in 1/1000th of a logical * pixel. The allowable range for absolute pointer motion is * [0, max) for each axis, i.e. zero inclusive, max exclusive. Coordinates * outside this range may be discarded or clipped silently by the library. * * The values are in 1/1000th of logical pixels, i.e. the value 100 000 * refers to 100 pixels. * * The pointer range is constant. Where the pointer range is no longer * applicable, the client needs to remove the device and create and add a * new device with the updated pointer range. * * The server may use this in mapping heuristics. For example, a pointer * device with a pixel range of 1920x1200 **may** be automatically mapped by * the server to the monitor with this range, or a pointer device with a * ratio of R **may** be mapped to the monitor with the same ratio. This is * not a guarantee, the mapping policy is a private implementation detail * in the server. It is assumed that the client has other communication * channels (e.g. Wayland) to obtain the pointer range it needs to emulate * input on a device and channels to notify the server of desired mappings * (e.g. gsettings). * * It is a client bug to send pointer values outside this range. * It is a client bug to call this function on a device without the @ref * EI_DEVICE_CAP_POINTER_ABSOLUTE capability. * * This function has no effect if called after ei_device_add() * * @param width The maximum (exclusive) x value in 1/1000th of a pixel * @param heigth The maximum (exclusive) y value in 1/1000th of a pixel */ void ei_device_configure_pointer_range(struct ei_device *device, uint32_t width, uint32_t height); /** * Set the range of the touch device in 1/1000th of a logical pixels. This * function is identical to ei_device_configure_pointer_range() but * configures the touch range instead. */ void ei_device_configure_touch_range(struct ei_device *device, uint32_t width, uint32_t height); /** * Set the keymap for this device. The keymap for this device is a suggestion to * the server, the actual keymap used by this device is provided with the * @ref EI_EVENT_DEVICE_ADDED event. It is the responsibility of the client * to handle the situation where a specific keymap is requested but the * server does not allow its use on the device. * * Note that keymap handling for individual input devices is largely * left to private implementation details in the server. For example, * modifier state or group handling may differ between server * implementations. * * The keymap is constant on the device. To change keymaps, disconnect the * device and create a new one. * * This function has no effect if called after ei_device_add() * * @param type the type of the keymap * @param fd a memmap-able file descriptor to the keymap */ void ei_device_configure_keymap(struct ei_device *device, enum ei_keymap_type type, int fd); /** * Request that the device be added to the server. * The server will respond with an @ref EI_EVENT_DEVICE_ADDED or @ref * EI_EVENT_DEVICE_REMOVED event. */ void ei_device_add(struct ei_device *device); /** * Notify the server that the device is no longer required. The server will * reply with a @ref EI_EVENT_DEVICE_REMOVED event once the device has been * removed. * * This does not release any resources associated with this device, use * ei_device_unref() for any references held by the client. */ void ei_device_remove(struct ei_device *device); /** * @return the name of the device (if any) or NULL */ const char * ei_device_get_name(struct ei_device *device); bool ei_device_has_capability(struct ei_device *device, enum ei_device_capability cap); uint32_t ei_device_get_pointer_width(struct ei_device *device); uint32_t ei_device_get_pointer_height(struct ei_device *device); uint32_t ei_device_get_touch_width(struct ei_device *device); uint32_t ei_device_get_touch_height(struct ei_device *device); /** * Return a memmap-able file descriptor pointing to the keymap used by the * device. The keymap is constant for the lifetime of the device and * assigned to this device individually. * * If this function returns -1, this device does not have * an individual keymap assigned. * * FIXME: the current API makes it impossible to know when the keymap has * been consumed so the file stays open forever. */ int ei_device_get_keymap(struct ei_device *device); enum ei_keymap_type ei_device_get_keymap_type(struct ei_device *device); /** * Returns the source for the keymap on this device, if any. This is a * convenience function for the client to check if its keymap was accepted. * * Where ei_device_get_keymap() returns a value other than -1 and this * function returns @ref EI_KEYMAP_SOURCE_CLIENT, the keymap is the one * provided with ei_device_configure_keymap(). * * Where ei_device_get_keymap() returns a value other than -1 and this * function returns @ref EI_KEYMAP_SOURCE_SERVER, the keymap is one created * by the server and **not** the one provided with * ei_device_configure_keymap(). * * Where ei_device_get_keymap() returns -1, the return value of this * function is undefined. */ enum ei_keymap_source ei_device_get_keymap_source(struct ei_device *device); struct ei * ei_device_get_context(struct ei_device *device); /** * Generate a relative motion event on a device with * the @ref EI_DEVICE_CAP_POINTER capability. * * @param x The x movement in 1/1000th of a logical pixel * @param y The y movement in 1/1000th of a logical pixel */ void ei_device_pointer_motion(struct ei_device *device, int32_t x, int32_t y); /** * Generate an absolute motion event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE capability. * * The required conditions are: * - 0 <= x < width * - 0 <= y < height * * @param x The x position in 1/1000th of a logical pixel * @param y The y position in 1/1000th of a logical pixel */ void ei_device_pointer_motion_absolute(struct ei_device *device, uint32_t x, uint32_t y); /** * Generate a button event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE or * @ref EI_DEVICE_CAP_POINTER capability. * * Button codes must match the #defines in linux/input-event-codes.h * * @param button The button code * @param is_press true for button press, false for button release */ void ei_device_pointer_button(struct ei_device *device, uint32_t button, bool is_press); /** * Generate a scroll event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE or * @ref EI_DEVICE_CAP_POINTER capability. * * The server emulates discrete scrolling based on the pixel value, * do not call ei_device_pointer_scroll_discrete() for the * same input event. * * @param x The x scroll distance in 1/1000th of a logical pixel * @param y The y scroll distance in 1/1000th of a logical pixel * * @see ei_device_pointer_scroll_discrete */ void ei_device_pointer_scroll(struct ei_device *device, int32_t x, int32_t y); /** * Generate a discrete scroll event on a device with * the @ref EI_DEVICE_CAP_POINTER_ABSOLUTE or * @ref EI_DEVICE_CAP_POINTER capability. * * A discrete scroll event is based logical scroll units (equivalent to one * mouse wheel click). The value for one scroll unit is 120, a fraction or * multiple thereof represents a fraction or multiple of a wheel click. * * The server emulates pixel-based scrolling based on the discrete value, * do not call ei_device_pointer_scroll() for the * same input event. * * @param x The x scroll distance in fractions or multiples of 120 * @param y The y scroll distance in fractions or multiples of 120 * * @see ei_device_pointer_scroll */ void ei_device_pointer_scroll_discrete(struct ei_device *device, int32_t x, int32_t y); /** * Generate a key event on a device with * the @ref EI_DEVICE_CAP_KEYBOARD capability. * * Keys use the evdev scan codes as defined in * linux/input-event-codes.h * * @param keycode The key code * @param is_press true for key down, false for key up */ void ei_device_keyboard_key(struct ei_device *device, uint32_t keycode, bool is_press); enum ei_event_type ei_event_get_type(struct ei_event *event); /** * Return the device from this event. * * This does not increase the refcount of the device. Use eis_device_ref() * to keep a reference beyond the immediate scope. */ struct ei_device * ei_event_get_device(struct ei_event *event); /** * @return the event time in microseconds */ uint64_t ei_event_pointer_get_time(struct ei_event_pointer *event); /** * @return the event time in microseconds */ uint64_t ei_event_keyboard_get_time(struct ei_event_keyboard *event); /** * @return the event time in microseconds */ uint64_t ei_event_touch_get_time(struct ei_event_touch *event);