#include "e_comp_wl_intern.h"
#include "e_comp_wl_input_intern.h"
#include "e_comp_input_intern.h"
+#include "e_input_thread_client_intern.h"
+#include "e_comp_object_intern.h"
+#include "e_pointer_intern.h"
+#include "e_policy_intern.h"
+#include "e_utils_intern.h"
static Eina_List *_ecore_event_handlers = NULL;
+static void
+_e_seat_cb_pointer_unbind(struct wl_resource *resource)
+{
+ E_Comp_Wl_Data *comp_wl;
+ E_Seat *seat;
+ seat = wl_resource_get_user_data(resource);
+ if (!seat) return;
+
+ seat->ptr.resources =
+ eina_list_remove(seat->ptr.resources, resource);
+
+ comp_wl = e_comp_wl_get();
+ wl_signal_emit(&comp_wl->ptr_constraints.pointer_destroy_signal, resource);
+}
+
+static void
+_e_seat_thread_cursor_set(void *data)
+{
+ E_Input_Thread_Request_EClient_Data *ec_data = data;
+ EINA_SAFETY_ON_NULL_RETURN(ec_data);
+
+ ICINF("[input thread|%s] ec(%p), layer_block(%d), is_cursor(%d)\n", __func__, ec_data->ec, ec_data->layer_block, ec_data->is_cursor);
+ e_input_thread_client_layer_block_set(e_input_thread_client_get(ec_data->ec), ec_data->layer_block);
+ e_input_thread_client_is_cursor_set(e_input_thread_client_get(ec_data->ec), ec_data->is_cursor);
+}
+
+static void
+_e_seat_pointer_configure(struct wl_resource *resource,
+ Evas_Coord x, Evas_Coord y,
+ Evas_Coord w, Evas_Coord h)
+{
+ E_Client *ec;
+
+ if (!(ec = e_client_from_surface_resource(resource))) return;
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ e_client_util_resize_without_frame(ec, w, h);
+}
+
+static void
+_e_seat_pointer_map(struct wl_resource *resource)
+{
+ E_Client *ec;
+ E_Pointer *ptr;
+ struct wl_client *wc;
+ E_Comp_Wl_Data *comp_wl;
+
+ if (!(ec = e_client_from_surface_resource(resource))) return;
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ //if cursor ec have external content
+ e_comp_object_content_unset(ec->frame);
+
+ comp_wl = e_comp_wl_get();
+ if (!comp_wl->ptr.ec || !comp_wl->ptr.ec->comp_data) return;
+ struct wl_resource *surface = e_comp_wl_client_surface_get(comp_wl->ptr.ec);
+ if (!surface) return;
+
+ wc = wl_resource_get_client(resource);
+ if (wc != wl_resource_get_client(surface)) return;
+ if (!comp_wl->ptr.ec->pointer_enter_sent) return;
+
+ if ((ptr = e_comp_pointer_get()))
+ e_pointer_view_set(ptr, e_client_view_get(ec), ptr->hot.x, ptr->hot.y);
+}
+
+static void
+_e_seat_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y)
+{
+ E_Client *ec;
+ Eina_Bool got_mouse = EINA_FALSE;
+ struct wl_resource *surface;
+ E_Pointer *comp_pointer = e_comp_pointer_get();
+ E_Seat *seat;
+ seat = wl_resource_get_user_data(resource);
+ if (!seat) return;
+
+ E_Input_Thread_Request_EClient_Data ec_data;
+ memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
+
+ E_CLIENT_FOREACH(ec)
+ {
+ if (e_object_is_del(E_OBJECT(ec))) continue;
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) continue;
+ surface = e_comp_wl_client_surface_get(ec);
+ if (!surface) continue;
+ if (client != wl_resource_get_client(surface)) continue;
+ if ((ec->mouse.in && ec->pointer_enter_sent) ||
+ e_policy_client_is_kvm(ec))
+ {
+ got_mouse = EINA_TRUE;
+ break;
+ }
+ }
+ if (!got_mouse)
+ {
+ ELOGF("COMP", "Cursor Set. got_mouse: false", NULL);
+ return;
+ }
+ if (!surface_resource || e_policy_client_is_waydroid(ec))
+ {
+ E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
+ if (e_policy_client_is_waydroid(ec) && comp_wl->drag)
+ {
+ ELOGF("COMP", "Cursor Set ignored. dragging on Waydroid", ec);
+ return;
+ }
+
+ e_pointer_view_set(comp_pointer, NULL, x, y);
+ ec->has_cursor_unset = EINA_TRUE;
+ ELOGF("COMP", "Cursor Set. has_cursor_unset:TRUE", ec);
+ return;
+ }
+
+ ec->has_cursor_unset = EINA_FALSE;
+
+ ec = e_client_from_surface_resource(surface_resource);
+ if (!ec) return;
+
+ if (!ec->re_manage)
+ {
+ ec->re_manage = 1;
+ ec->ignored = 0;
+
+ ec->lock_focus_out = ec->layer_block = ec->visible = 1;
+ if (!e_config->show_cursor)
+ {
+ ELOGF("COMP", "Cursor Set. show_cursor: false", ec);
+ ec->override = 1;
+ }
+ e_client_icccm_title_set(ec, "Cursor");
+ e_client_window_role_set(ec, "wl_pointer-cursor");
+ e_view_pass_events_set(e_view_client_view_get(e_client_view_get(ec)), 1);
+ /* wl_pointer-cursor surface is always alpha window */
+ ec->argb = EINA_TRUE;
+ ELOGF("COMP", "Cursor Set. argb:%d", ec, ec->argb);
+ e_view_client_alpha_set(e_client_view_get(ec), EINA_TRUE);
+ EC_CHANGED(ec);
+
+ /* Set functions to prevent unwanted handling by shell */
+ ec->comp_data->shell.surface = surface_resource;
+ ec->comp_data->shell.configure = _e_seat_pointer_configure;
+ ec->comp_data->shell.map = _e_seat_pointer_map;
+
+ e_client_layer_set(ec, E_LAYER_CLIENT_CURSOR);
+ ec->is_cursor = EINA_TRUE;
+
+ if (e_input_thread_check_client_cloning_needed())
+ {
+ ec_data.ec = ec;
+ ec_data.layer_block = ec->layer_block;
+ ec_data.is_cursor = ec->is_cursor;
+ INF("[%s] ec(%p), layer_block(%d), is_cursor(%d)\n", __func__, ec, ec->layer_block, ec->is_cursor);
+ e_input_backend_thread_safe_call(_e_seat_thread_cursor_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
+ }
+ }
+
+ /* Set a pointer_object after wl_surface commit
+ * if cursor image is changed,
+ * changed information is sent using attach / damage
+ * So in commit, we can know real current cursor image.
+ */
+#if 0
+ /* ignore cursor changes during resize/move I guess */
+ if (e_client_action_get()) return;
+ e_pointer_view_set(comp_pointer, e_client_view_get(ec), x, y);
+#endif
+ if (comp_pointer)
+ {
+ comp_pointer->hot.x = x;
+ comp_pointer->hot.y = y;
+ if (e_config->show_cursor)
+ ec->visible = EINA_TRUE;
+ }
+}
+
+static void
+_e_seat_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct wl_pointer_interface _e_pointer_interface =
+{
+ _e_seat_pointer_cb_cursor_set,
+ _e_seat_cb_resource_destroy
+};
+
+static const struct wl_keyboard_interface _e_keyboard_interface =
+{
+ _e_seat_cb_resource_destroy
+};
+
+static const struct wl_touch_interface _e_touch_interface =
+{
+ _e_seat_cb_resource_destroy
+};
+
+static void
+_e_seat_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
+{
+ struct wl_resource *res;
+ struct wl_client *ptr_client = NULL;
+ E_Comp_Wl_Client_Data *cdata = NULL;
+ E_Comp_Wl_Data *comp_wl;
+ E_Seat *seat;
+ seat = wl_resource_get_user_data(resource);
+ if (!seat) return;
+
+ comp_wl = e_comp_wl_get();
+
+ /* try to create pointer resource */
+ res = wl_resource_create(client, &wl_pointer_interface,
+ wl_resource_get_version(resource), id);
+ if (!res)
+ {
+ ERR("Could not create pointer on seat %s: %m",
+ seat->name);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ seat->ptr.resources =
+ eina_list_append(seat->ptr.resources, res);
+ wl_resource_set_implementation(res, &_e_pointer_interface,
+ seat,
+ _e_seat_cb_pointer_unbind);
+
+ if ((seat->ptr.num_devices == 1) && comp_wl->ptr.ec && !comp_wl->ptr.ec->pointer_enter_sent && !e_config->use_cursor_timer)
+ {
+ cdata = (E_Comp_Wl_Client_Data*)comp_wl->ptr.ec->comp_data;
+ if (cdata && cdata->wl_surface)
+ ptr_client = wl_resource_get_client(cdata->wl_surface);
+
+ if (ptr_client == client)
+ {
+ Evas_Device *last_ptr = NULL, *dev;
+ Eina_List *list, *l;
+ const char *name, *desc;
+
+ list = (Eina_List *)evas_device_list(evas_object_evas_get(comp_wl->ptr.ec->frame), NULL);
+ EINA_LIST_FOREACH(list, l, dev)
+ {
+ name = evas_device_name_get(dev);
+ desc = evas_device_description_get(dev);
+ if (!name || !desc) continue;
+
+ if ((!e_util_strcmp(name, e_devicemgr->last_device_ptr->name)) &&
+ (!e_util_strcmp(desc, e_devicemgr->last_device_ptr->identifier)) &&
+ (evas_device_class_get(dev) == (Evas_Device_Class)e_devicemgr->last_device_ptr->clas))
+ {
+ last_ptr = dev;
+ break;
+ }
+ }
+ if (last_ptr)
+ e_comp_wl_mouse_in_renew(comp_wl->ptr.ec, 0, wl_fixed_to_int(comp_wl->ptr.x), wl_fixed_to_int(comp_wl->ptr.y), NULL, NULL, NULL, ecore_time_get(), EVAS_EVENT_FLAG_NONE, last_ptr, NULL);
+ }
+ }
+}
+
+static void
+_e_seat_cb_keyboard_unbind(struct wl_resource *resource)
+{
+ INF("[keyboard unbind] resource(%p)\n", resource);
+
+ Eina_List *l, *ll;
+ struct wl_resource *res;
+
+ g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
+ e_comp_input_key->kbd.resources =
+ eina_list_remove(e_comp_input_key->kbd.resources, resource);
+ g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
+
+ g_rec_mutex_lock(&e_comp_input_key->kbd.focused_mutex);
+ EINA_LIST_FOREACH_SAFE(e_comp_input_key->kbd.focused, l, ll, res)
+ if (res == resource)
+ e_comp_input_key->kbd.focused =
+ eina_list_remove_list(e_comp_input_key->kbd.focused, l);
+ g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
+}
+
+static enum wl_iterator_result
+_e_seat_get_resource(struct wl_resource *resource, void *data)
+{
+ Eina_List *l, *ll;
+ struct wl_resource *res;
+
+ g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
+ e_comp_input_key->kbd.resources = eina_list_remove(e_comp_input_key->kbd.resources, resource);
+ g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
+
+ g_rec_mutex_lock(&e_comp_input_key->kbd.focused_mutex);
+ EINA_LIST_FOREACH_SAFE(e_comp_input_key->kbd.focused, l, ll, res)
+ {
+ if (res == resource)
+ e_comp_input_key->kbd.focused = eina_list_remove_list(e_comp_input_key->kbd.focused, l);
+ }
+ g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
+
+ return WL_ITERATOR_CONTINUE;
+}
+
+static void
+_e_seat_cb_wl_client_destroy(struct wl_listener *l, void *data)
+{
+ struct wl_client *client = data;
+
+ wl_client_for_each_resource(client, _e_seat_get_resource, NULL);
+ wl_list_remove(&l->link);
+ E_FREE(l);
+}
+
+static void
+_e_seat_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
+{
+ struct wl_resource *res;
+ struct wl_listener *destroy_listener = NULL;
+ E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
+ E_Client *focused = NULL;
+
+ /* try to create keyboard resource */
+ res = wl_resource_create(client, &wl_keyboard_interface,
+ wl_resource_get_version(resource), id);
+ if (!res)
+ {
+ // ERR("Could not create keyboard on seat %s: %m",
+ // comp_wl->seat.name);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
+ e_comp_input_key->kbd.resources =
+ eina_list_append(e_comp_input_key->kbd.resources, res);
+ g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
+
+ wl_resource_set_implementation(res, &_e_keyboard_interface,
+ comp_wl,
+ _e_seat_cb_keyboard_unbind);
+
+ /* send current repeat_info */
+ if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
+ {
+ wl_keyboard_send_repeat_info(res, e_comp_input_key->kbd.repeat_rate, e_comp_input_key->kbd.repeat_delay);
+ }
+
+ /* send current keymap */
+ TRACE_INPUT_BEGIN(wl_keyboard_send_keymap);
+ e_comp_wl_input_keyboard_keymap_send(res);
+ TRACE_INPUT_END();
+
+ /* if the client owns the focused surface, we need to send an enter */
+ focused = e_client_focused_get();
+ if ((!focused) || (e_object_is_del(E_OBJECT(focused))) ||
+ (!focused->comp_data)) return;
+
+ struct wl_resource *surface = e_comp_wl_client_surface_get(focused);
+ if (!surface) return;
+
+ if (client != wl_resource_get_client(surface)) return;
+ g_rec_mutex_lock(&e_comp_input_key->kbd.focused_mutex);
+ e_comp_input_key->kbd.focused = eina_list_append(e_comp_input_key->kbd.focused, res);
+ g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
+
+ e_comp_wl_input_keyboard_enter_send(surface);
+
+ destroy_listener = E_NEW(struct wl_listener, 1);
+ if (!destroy_listener)
+ {
+ ERR("Failed to allocate memory for wl_client destroy listener !");
+ return;
+ }
+
+ destroy_listener->notify = _e_seat_cb_wl_client_destroy;
+ wl_client_add_destroy_listener(client, destroy_listener);
+}
+
+static void
+_e_seat_cb_touch_unbind(struct wl_resource *resource)
+{
+ E_Seat *seat;
+ seat = wl_resource_get_user_data(resource);
+ if (!seat) return;
+
+ seat->touch.resources =
+ eina_list_remove(seat->touch.resources, resource);
+}
+
+static void
+_e_seat_cb_touch_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id EINA_UNUSED)
+{
+ struct wl_resource *res;
+ E_Seat *seat;
+ seat = wl_resource_get_user_data(resource);
+ if (!seat) return;
+
+ /* try to create pointer resource */
+ res = wl_resource_create(client, &wl_touch_interface,
+ wl_resource_get_version(resource), id);
+ if (!res)
+ {
+ ERR("Could not create touch on seat %s: %m",
+ seat->name);
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ seat->touch.resources =
+ eina_list_append(seat->touch.resources, res);
+
+ wl_resource_set_implementation(res, &_e_touch_interface,
+ seat,
+ _e_seat_cb_touch_unbind);
+}
+
+static const struct wl_seat_interface _e_seat_interface =
+{
+ _e_seat_cb_pointer_get,
+ _e_seat_cb_keyboard_get,
+ _e_seat_cb_touch_get,
+ _e_seat_cb_resource_destroy, //since version 5
+};
+
static Eina_Bool
_e_seat_cb_seat_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
return ECORE_CALLBACK_PASS_ON;
}
+static void
+_e_seat_cb_unbind_seat(struct wl_resource *resource)
+{
+ E_Seat *seat;
+ seat = wl_resource_get_user_data(resource);
+ if (!seat) return;
+
+ INF("Unbind seat: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
+
+ seat->resources =
+ eina_list_remove(seat->resources, resource);
+}
+
+static void
+_e_seat_cb_bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ struct wl_resource *res;
+ E_Seat *seat;
+
+ if (!(seat = data)) return;
+
+ res = wl_resource_create(client, &wl_seat_interface, version, id);
+ if (!res)
+ {
+ ERR("Could not create seat resource: %m");
+ return;
+ }
+ INF("Bind seat: %u (client: %p)", wl_resource_get_id(res), client);
+
+ /* store version of seat interface for reuse in updating capabilities */
+ seat->version = version;
+ seat->resources =
+ eina_list_append(seat->resources, res);
+
+ wl_resource_set_implementation(res, &_e_seat_interface,
+ seat,
+ _e_seat_cb_unbind_seat);
+
+ e_seat_update_seat_caps(seat, client);
+ if (seat->version >= WL_SEAT_NAME_SINCE_VERSION)
+ wl_seat_send_name(res, seat->name);
+}
+
EINTERN void
e_seat_init()
{
_ecore_event_handlers = NULL;
}
+EINTERN E_Seat *
+e_seat_create(const char *seat_name)
+{
+ E_Seat *seat;
+ E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
+ seat = e_seat_find(seat_name);
+ if (seat) return seat;
+
+ if (!(seat = E_NEW(E_Seat, 1))) return EINA_FALSE;
+
+ /* set default seat name */
+ if (!seat_name)
+ seat->name = "default";
+ else
+ seat->name = strdup(seat_name);
+
+ /* create the global resource for input seat */
+ seat->global =
+ wl_global_create(comp_wl->wl.disp, &wl_seat_interface, 7,
+ seat, _e_seat_cb_bind_seat);
+ if (!seat->global)
+ {
+ ERR("Could not create global for seat: %m");
+ return EINA_FALSE;
+ }
+ seat->resources = NULL;
+
+ comp_wl->seats = eina_list_append(comp_wl->seats, seat);
+
+ return seat;
+}
+
+EINTERN void
+e_seat_destroy(E_Seat *seat)
+{
+ E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
+ struct wl_resource *res;
+
+ EINA_LIST_FREE(seat->ptr.resources, res)
+ wl_resource_destroy(res);
+ EINA_LIST_FREE(seat->touch.resources, res)
+ wl_resource_destroy(res);
+ EINA_LIST_FREE(seat->resources, res)
+ wl_resource_destroy(res);
+
+ comp_wl->seats = eina_list_remove(comp_wl->seats, seat);
+ wl_global_destroy(seat->global);
+}
+
EINTERN E_Zone *
e_seat_zone_get(E_Seat *seat)
{
EINA_LIST_FOREACH(seat->touch.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
wl_touch_send_motion(res, timestamp, idx, wl_fixed_from_int(x), wl_fixed_from_int(y));
}
EINA_LIST_FOREACH(s->touch.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
wl_touch_send_motion(res, timestamp, idx, wl_fixed_from_int(x), wl_fixed_from_int(y));
}
EINA_LIST_FOREACH(seat->touch.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
TRACE_INPUT_BEGIN(e_seat_touch_send_downup);
if (pressed)
EINA_LIST_FOREACH(s->touch.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
TRACE_INPUT_BEGIN(e_seat_touch_send_downup);
if (pressed)
EINA_LIST_FOREACH(seat->touch.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
ELOGF("Touch", "Cancel name:%20s", ec, ec ? e_client_util_name_get(ec) : "Unknown");
EINA_LIST_FOREACH(s->touch.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
ELOGF("Touch", "Cancel name:%20s", ec, ec ? e_client_util_name_get(ec) : "Unknown");
EINA_LIST_FOREACH(seat->touch.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
wl_touch_send_frame(res);
}
EINA_LIST_FOREACH(s->touch.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_touch_check(res)) continue;
+ if (!e_seat_touch_check(res)) continue;
wl_touch_send_frame(res);
}
}
return EINA_TRUE;
}
+EINTERN Eina_Bool
+e_seat_touch_check(struct wl_resource *res)
+{
+ return wl_resource_instance_of(res, &wl_touch_interface,
+ &_e_touch_interface);
+}
+
EINTERN void
e_seat_pointer_send_motion(E_Seat *seat, struct wl_client *wc,
int x, int y, uint32_t timestamp)
EINA_LIST_FOREACH(seat->ptr.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_motion(res, timestamp,
wl_fixed_from_int(x),
EINA_LIST_FOREACH(s->ptr.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_motion(res, timestamp,
wl_fixed_from_int(x),
EINA_LIST_FOREACH(seat->ptr.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_enter(res, serial, surface,
wl_fixed_from_int(x), wl_fixed_from_int(y));
EINA_LIST_FOREACH(s->ptr.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_enter(res, serial, surface,
wl_fixed_from_int(x), wl_fixed_from_int(y));
EINA_LIST_FOREACH(seat->ptr.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
if (ec && ec->pointer_enter_sent == EINA_FALSE) continue;
wl_pointer_send_leave(res, serial, surface);
EINA_LIST_FOREACH(s->ptr.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
if (ec && ec->pointer_enter_sent == EINA_FALSE) continue;
wl_pointer_send_leave(res, serial, surface);
EINA_LIST_FOREACH(seat->ptr.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
TRACE_INPUT_BEGIN(e_comp_wl_surface_mouse_button);
ELOGF("Mouse", "Button %s (btn: %d, time: %d)", NULL, (state ? "Down" : "Up"), button, timestamp);
EINA_LIST_FOREACH(s->ptr.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_button(res, serial, timestamp,
button, state);
EINA_LIST_FOREACH(seat->ptr.resources, l, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_axis(res, timestamp, axis, dir);
}
EINA_LIST_FOREACH(s->ptr.resources, ll, res)
{
if (wl_resource_get_client(res) != wc) continue;
- if (!e_comp_wl_input_pointer_check(res)) continue;
+ if (!e_seat_pointer_check(res)) continue;
wl_pointer_send_axis(res, timestamp, axis, dir);
}
return EINA_TRUE;
}
+EINTERN Eina_Bool
+e_seat_pointer_check(struct wl_resource *res)
+{
+ return wl_resource_instance_of(res, &wl_pointer_interface,
+ &_e_pointer_interface);
+}
+
+EINTERN Eina_Bool
+e_seat_keyboard_check(struct wl_resource *res)
+{
+ return wl_resource_instance_of(res, &wl_keyboard_interface,
+ &_e_keyboard_interface);
+}
wl_fixed_t fx,
wl_fixed_t fy);
-static void
-_e_comp_wl_input_pointer_map(struct wl_resource *resource)
-{
- E_Client *ec;
- E_Pointer *ptr;
- struct wl_client *wc;
- E_Comp_Wl_Data *comp_wl;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
-
- //if cursor ec have external content
- e_comp_object_content_unset(ec->frame);
-
- comp_wl = e_comp_wl_get();
- if (!comp_wl->ptr.ec || !comp_wl->ptr.ec->comp_data) return;
- struct wl_resource *surface = e_comp_wl_client_surface_get(comp_wl->ptr.ec);
- if (!surface) return;
-
- wc = wl_resource_get_client(resource);
- if (wc != wl_resource_get_client(surface)) return;
- if (!comp_wl->ptr.ec->pointer_enter_sent) return;
-
- if ((ptr = e_comp_pointer_get()))
- e_pointer_view_set(ptr, e_client_view_get(ec), ptr->hot.x, ptr->hot.y);
-}
-
-static void
-_e_comp_wl_input_pointer_configure(struct wl_resource *resource,
- Evas_Coord x, Evas_Coord y,
- Evas_Coord w, Evas_Coord h)
-{
- E_Client *ec;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
-
- e_client_util_resize_without_frame(ec, w, h);
-}
-
-static void
-_e_comp_wl_input_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
-{
- wl_resource_destroy(resource);
-}
-
-static void
-_e_comp_wl_input_thread_cursor_set(void *data)
-{
- E_Input_Thread_Request_EClient_Data *ec_data = data;
- EINA_SAFETY_ON_NULL_RETURN(ec_data);
-
- ICINF("[input thread|%s] ec(%p), layer_block(%d), is_cursor(%d)\n", __func__, ec_data->ec, ec_data->layer_block, ec_data->is_cursor);
- e_input_thread_client_layer_block_set(e_input_thread_client_get(ec_data->ec), ec_data->layer_block);
- e_input_thread_client_is_cursor_set(e_input_thread_client_get(ec_data->ec), ec_data->is_cursor);
-}
-
-static void
-_e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y)
-{
- E_Client *ec;
- Eina_Bool got_mouse = EINA_FALSE;
- struct wl_resource *surface;
- E_Pointer *comp_pointer = e_comp_pointer_get();
- E_Seat *seat;
- seat = wl_resource_get_user_data(resource);
- if (!seat) return;
-
- E_Input_Thread_Request_EClient_Data ec_data;
- memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
-
- E_CLIENT_FOREACH(ec)
- {
- if (e_object_is_del(E_OBJECT(ec))) continue;
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) continue;
- surface = e_comp_wl_client_surface_get(ec);
- if (!surface) continue;
- if (client != wl_resource_get_client(surface)) continue;
- if ((ec->mouse.in && ec->pointer_enter_sent) ||
- e_policy_client_is_kvm(ec))
- {
- got_mouse = EINA_TRUE;
- break;
- }
- }
- if (!got_mouse)
- {
- ELOGF("COMP", "Cursor Set. got_mouse: false", NULL);
- return;
- }
- if (!surface_resource || e_policy_client_is_waydroid(ec))
- {
- E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
- if (e_policy_client_is_waydroid(ec) && comp_wl->drag)
- {
- ELOGF("COMP", "Cursor Set ignored. dragging on Waydroid", ec);
- return;
- }
-
- e_pointer_view_set(comp_pointer, NULL, x, y);
- ec->has_cursor_unset = EINA_TRUE;
- ELOGF("COMP", "Cursor Set. has_cursor_unset:TRUE", ec);
- return;
- }
-
- ec->has_cursor_unset = EINA_FALSE;
-
- ec = e_client_from_surface_resource(surface_resource);
- if (!ec) return;
-
- if (!ec->re_manage)
- {
- ec->re_manage = 1;
- ec->ignored = 0;
-
- ec->lock_focus_out = ec->layer_block = ec->visible = 1;
- if (!e_config->show_cursor)
- {
- ELOGF("COMP", "Cursor Set. show_cursor: false", ec);
- ec->override = 1;
- }
- e_client_icccm_title_set(ec, "Cursor");
- e_client_window_role_set(ec, "wl_pointer-cursor");
- e_view_pass_events_set(e_view_client_view_get(e_client_view_get(ec)), 1);
- /* wl_pointer-cursor surface is always alpha window */
- ec->argb = EINA_TRUE;
- ELOGF("COMP", "Cursor Set. argb:%d", ec, ec->argb);
- e_view_client_alpha_set(e_client_view_get(ec), EINA_TRUE);
- EC_CHANGED(ec);
-
- /* Set fuctions to prevent unwanted handling by shell */
- ec->comp_data->shell.surface = surface_resource;
- ec->comp_data->shell.configure = _e_comp_wl_input_pointer_configure;
- ec->comp_data->shell.map = _e_comp_wl_input_pointer_map;
-
- e_client_layer_set(ec, E_LAYER_CLIENT_CURSOR);
- ec->is_cursor = EINA_TRUE;
-
- if (e_input_thread_check_client_cloning_needed())
- {
- ec_data.ec = ec;
- ec_data.layer_block = ec->layer_block;
- ec_data.is_cursor = ec->is_cursor;
- INF("[%s] ec(%p), layer_block(%d), is_cursor(%d)\n", __func__, ec, ec->layer_block, ec->is_cursor);
- e_input_backend_thread_safe_call(_e_comp_wl_input_thread_cursor_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
- }
- }
-
- /* Set a pointer_object after wl_surface commit
- * if cursor image is changed,
- * changed information is sent using attach / damage
- * So in commit, we can know real current cursor image.
- */
-#if 0
- /* ignore cursor changes during resize/move I guess */
- if (e_client_action_get()) return;
- e_pointer_view_set(comp_pointer, e_client_view_get(ec), x, y);
-#endif
- if (comp_pointer)
- {
- comp_pointer->hot.x = x;
- comp_pointer->hot.y = y;
- if (e_config->show_cursor)
- ec->visible = EINA_TRUE;
- }
-}
-
-static const struct wl_pointer_interface _e_pointer_interface =
-{
- _e_comp_wl_input_pointer_cb_cursor_set,
- _e_comp_wl_input_cb_resource_destroy
-};
-
-static const struct wl_keyboard_interface _e_keyboard_interface =
-{
- _e_comp_wl_input_cb_resource_destroy
-};
-
-static const struct wl_touch_interface _e_touch_interface =
-{
- _e_comp_wl_input_cb_resource_destroy
-};
-
-static void
-_e_comp_wl_input_cb_pointer_unbind(struct wl_resource *resource)
-{
- E_Comp_Wl_Data *comp_wl;
- E_Seat *seat;
- seat = wl_resource_get_user_data(resource);
- if (!seat) return;
-
- seat->ptr.resources =
- eina_list_remove(seat->ptr.resources, resource);
-
- comp_wl = e_comp_wl_get();
- wl_signal_emit(&comp_wl->ptr_constraints.pointer_destroy_signal, resource);
-}
-
-static void
-_e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
-{
- struct wl_resource *res;
- struct wl_client *ptr_client = NULL;
- E_Comp_Wl_Client_Data *cdata = NULL;
- E_Comp_Wl_Data *comp_wl;
- E_Seat *seat;
- seat = wl_resource_get_user_data(resource);
- if (!seat) return;
-
- comp_wl = e_comp_wl_get();
-
- /* try to create pointer resource */
- res = wl_resource_create(client, &wl_pointer_interface,
- wl_resource_get_version(resource), id);
- if (!res)
- {
- ERR("Could not create pointer on seat %s: %m",
- seat->name);
- wl_client_post_no_memory(client);
- return;
- }
-
- seat->ptr.resources =
- eina_list_append(seat->ptr.resources, res);
- wl_resource_set_implementation(res, &_e_pointer_interface,
- seat,
- _e_comp_wl_input_cb_pointer_unbind);
-
- if ((seat->ptr.num_devices == 1) && comp_wl->ptr.ec && !comp_wl->ptr.ec->pointer_enter_sent && !e_config->use_cursor_timer)
- {
- cdata = (E_Comp_Wl_Client_Data*)comp_wl->ptr.ec->comp_data;
- if (cdata && cdata->wl_surface)
- ptr_client = wl_resource_get_client(cdata->wl_surface);
-
- if (ptr_client == client)
- {
- Evas_Device *last_ptr = NULL, *dev;
- Eina_List *list, *l;
- const char *name, *desc;
-
- list = (Eina_List *)evas_device_list(evas_object_evas_get(comp_wl->ptr.ec->frame), NULL);
- EINA_LIST_FOREACH(list, l, dev)
- {
- name = evas_device_name_get(dev);
- desc = evas_device_description_get(dev);
- if (!name || !desc) continue;
-
- if ((!e_util_strcmp(name, e_devicemgr->last_device_ptr->name)) &&
- (!e_util_strcmp(desc, e_devicemgr->last_device_ptr->identifier)) &&
- (evas_device_class_get(dev) == (Evas_Device_Class)e_devicemgr->last_device_ptr->clas))
- {
- last_ptr = dev;
- break;
- }
- }
- if (last_ptr)
- e_comp_wl_mouse_in_renew(comp_wl->ptr.ec, 0, wl_fixed_to_int(comp_wl->ptr.x), wl_fixed_to_int(comp_wl->ptr.y), NULL, NULL, NULL, ecore_time_get(), EVAS_EVENT_FLAG_NONE, last_ptr, NULL);
- }
- }
-}
-
-static void
-_e_comp_wl_input_cb_keyboard_unbind(struct wl_resource *resource)
-{
- INF("[keyboard unbind] resource(%p)\n", resource);
-
- Eina_List *l, *ll;
- struct wl_resource *res;
-
- g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
- e_comp_input_key->kbd.resources =
- eina_list_remove(e_comp_input_key->kbd.resources, resource);
- g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
-
- g_rec_mutex_lock(&e_comp_input_key->kbd.focused_mutex);
- EINA_LIST_FOREACH_SAFE(e_comp_input_key->kbd.focused, l, ll, res)
- if (res == resource)
- e_comp_input_key->kbd.focused =
- eina_list_remove_list(e_comp_input_key->kbd.focused, l);
- g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
-}
-
void
e_comp_wl_input_keyboard_enter_send(struct wl_resource *surface)
{
g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
}
-static void
-_e_comp_wl_input_keyboard_keymap_send(struct wl_resource *resource)
+EINTERN void
+e_comp_wl_input_keyboard_keymap_send(struct wl_resource *resource)
{
int fd;
int version = wl_resource_get_version(resource);
}
}
-static enum wl_iterator_result
-_e_comp_wl_input_get_resource(struct wl_resource *resource, void *data)
-{
- Eina_List *l, *ll;
- struct wl_resource *res;
-
- g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
- e_comp_input_key->kbd.resources = eina_list_remove(e_comp_input_key->kbd.resources, resource);
- g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
-
- g_rec_mutex_lock(&e_comp_input_key->kbd.focused_mutex);
- EINA_LIST_FOREACH_SAFE(e_comp_input_key->kbd.focused, l, ll, res)
- {
- if (res == resource)
- e_comp_input_key->kbd.focused = eina_list_remove_list(e_comp_input_key->kbd.focused, l);
- }
- g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
-
- return WL_ITERATOR_CONTINUE;
-}
-
-static void
-_e_comp_wl_input_cb_wl_client_destroy(struct wl_listener *l, void *data)
-{
- struct wl_client *client = data;
-
- wl_client_for_each_resource(client, _e_comp_wl_input_get_resource, NULL);
- wl_list_remove(&l->link);
- E_FREE(l);
-}
-
-static void
-_e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
-{
- struct wl_resource *res;
- struct wl_listener *destroy_listener = NULL;
- E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
- E_Client *focused = NULL;
-
- /* try to create keyboard resource */
- res = wl_resource_create(client, &wl_keyboard_interface,
- wl_resource_get_version(resource), id);
- if (!res)
- {
- // ERR("Could not create keyboard on seat %s: %m",
- // comp_wl->seat.name);
- wl_client_post_no_memory(client);
- return;
- }
-
- g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
- e_comp_input_key->kbd.resources =
- eina_list_append(e_comp_input_key->kbd.resources, res);
- g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
-
- wl_resource_set_implementation(res, &_e_keyboard_interface,
- comp_wl,
- _e_comp_wl_input_cb_keyboard_unbind);
-
- /* send current repeat_info */
- if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
- {
- wl_keyboard_send_repeat_info(res, e_comp_input_key->kbd.repeat_rate, e_comp_input_key->kbd.repeat_delay);
- }
-
- /* send current keymap */
- TRACE_INPUT_BEGIN(wl_keyboard_send_keymap);
- _e_comp_wl_input_keyboard_keymap_send(res);
- TRACE_INPUT_END();
-
- /* if the client owns the focused surface, we need to send an enter */
- focused = e_client_focused_get();
- if ((!focused) || (e_object_is_del(E_OBJECT(focused))) ||
- (!focused->comp_data)) return;
-
- struct wl_resource *surface = e_comp_wl_client_surface_get(focused);
- if (!surface) return;
-
- if (client != wl_resource_get_client(surface)) return;
- g_rec_mutex_lock(&e_comp_input_key->kbd.focused_mutex);
- e_comp_input_key->kbd.focused = eina_list_append(e_comp_input_key->kbd.focused, res);
- g_rec_mutex_unlock(&e_comp_input_key->kbd.focused_mutex);
-
- e_comp_wl_input_keyboard_enter_send(surface);
-
- destroy_listener = E_NEW(struct wl_listener, 1);
- if (!destroy_listener)
- {
- KLERR("Failed to allocate memory for wl_client destroy listener !");
- return;
- }
-
- destroy_listener->notify = _e_comp_wl_input_cb_wl_client_destroy;
- wl_client_add_destroy_listener(client, destroy_listener);
-}
-
-static void
-_e_comp_wl_input_cb_touch_unbind(struct wl_resource *resource)
-{
- E_Seat *seat;
- seat = wl_resource_get_user_data(resource);
- if (!seat) return;
-
- seat->touch.resources =
- eina_list_remove(seat->touch.resources, resource);
-}
-
-static void
-_e_comp_wl_input_cb_touch_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id EINA_UNUSED)
-{
- struct wl_resource *res;
- E_Seat *seat;
- seat = wl_resource_get_user_data(resource);
- if (!seat) return;
-
- /* try to create pointer resource */
- res = wl_resource_create(client, &wl_touch_interface,
- wl_resource_get_version(resource), id);
- if (!res)
- {
- ERR("Could not create touch on seat %s: %m",
- seat->name);
- wl_client_post_no_memory(client);
- return;
- }
-
- seat->touch.resources =
- eina_list_append(seat->touch.resources, res);
- wl_resource_set_implementation(res, &_e_touch_interface,
- seat,
- _e_comp_wl_input_cb_touch_unbind);
-}
-
-static const struct wl_seat_interface _e_seat_interface =
-{
- _e_comp_wl_input_cb_pointer_get,
- _e_comp_wl_input_cb_keyboard_get,
- _e_comp_wl_input_cb_touch_get,
- _e_comp_wl_input_cb_resource_destroy, //since version 5
-};
-
-static void
-_e_comp_wl_input_cb_unbind_seat(struct wl_resource *resource)
-{
- E_Seat *seat;
- seat = wl_resource_get_user_data(resource);
- if (!seat) return;
-
- INF("Unbind seat: %u (client: %p)", wl_resource_get_id(resource), wl_resource_get_client(resource));
-
- seat->resources =
- eina_list_remove(seat->resources, resource);
-}
-
-static void
-_e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
- struct wl_resource *res;
- E_Seat *seat;
-
- if (!(seat = data)) return;
-
- res = wl_resource_create(client, &wl_seat_interface, version, id);
- if (!res)
- {
- ERR("Could not create seat resource: %m");
- return;
- }
- INF("Bind seat: %u (client: %p)", wl_resource_get_id(res), client);
-
- /* store version of seat interface for reuse in updating capabilities */
- seat->version = version;
- seat->resources =
- eina_list_append(seat->resources, res);
-
- wl_resource_set_implementation(res, &_e_seat_interface,
- seat,
- _e_comp_wl_input_cb_unbind_seat);
-
- e_seat_update_seat_caps(seat, client);
- if (seat->version >= WL_SEAT_NAME_SINCE_VERSION)
- wl_seat_send_name(res, seat->name);
-}
-
static void
_e_comp_wl_input_cb_relative_pointer_destroy(struct wl_client *client,
struct wl_resource *resource)
TRACE_INPUT_BEGIN(wl_keyboard_send_keymap_update);
g_rec_mutex_lock(&e_comp_input_key->kbd.resources_mutex);
EINA_LIST_FOREACH(e_comp_input_key->kbd.resources, l, res)
- _e_comp_wl_input_keyboard_keymap_send(res);
+ e_comp_wl_input_keyboard_keymap_send(res);
g_rec_mutex_unlock(&e_comp_input_key->kbd.resources_mutex);
TRACE_INPUT_END();
e_comp_input_key->xkb.state = NULL;
}
-static Eina_Bool
-_e_comp_wl_input_seat_init(const char *seat_name)
-{
- E_Seat *seat;
- E_Comp_Wl_Data *comp_wl = e_comp_wl_get();
- seat = e_seat_find(seat_name);
- if (seat) return EINA_FALSE;
-
- if (!(seat = E_NEW(E_Seat, 1))) return EINA_FALSE;
-
- /* set default seat name */
- if (!seat_name)
- seat->name = "default";
- else
- seat->name = strdup(seat_name);
-
- /* create the global resource for input seat */
- seat->global =
- wl_global_create(comp_wl->wl.disp, &wl_seat_interface, 7,
- seat, _e_comp_wl_input_cb_bind_seat);
- if (!seat->global)
- {
- ERR("Could not create global for seat: %m");
- return EINA_FALSE;
- }
- seat->resources = NULL;
-
- comp_wl->seats = eina_list_append(comp_wl->seats, seat);
-
- return EINA_TRUE;
-}
-
static Eina_Bool
_e_comp_wl_input_cb_input_device_add(void *data, int type, void *event)
{
if (e->clas == ECORE_DEVICE_CLASS_SEAT)
{
ERR("Seat added. name: %s identifier: %s, seatname: %s", e->name, e->identifier, e->seatname);
- _e_comp_wl_input_seat_init(e->name);
+ e_seat_create(e->name);
}
end:
if (e_comp_input_key->kbd.repeat_rate < 0)
atomic_store(&e_comp_input_key->kbd.repeat_rate, 25);
- _e_comp_wl_input_seat_init("default");
+ e_seat_create("default");
/* create the global resource for relative pointer */
comp_wl->relative_ptr.global =
E_Seat *seat;
EINA_LIST_FREE(comp_wl->seats, seat)
{
- EINA_LIST_FREE(seat->ptr.resources, res)
- wl_resource_destroy(res);
- EINA_LIST_FREE(seat->touch.resources, res)
- wl_resource_destroy(res);
- EINA_LIST_FREE(seat->resources, res)
- wl_resource_destroy(res);
- wl_global_destroy(seat->global);
+ e_seat_destroy(seat);
}
dont_set_e_input_keymap = EINA_FALSE;
dont_use_xkb_cache = EINA_FALSE;
}
-EINTERN Eina_Bool
-e_comp_wl_input_pointer_check(struct wl_resource *res)
-{
- return wl_resource_instance_of(res, &wl_pointer_interface,
- &_e_pointer_interface);
-}
-
EINTERN Eina_Bool
e_comp_wl_input_relative_pointer_check(struct wl_resource *res)
{
&_e_relative_pointer_interface);
}
-EINTERN Eina_Bool
-e_comp_wl_input_keyboard_check(struct wl_resource *res)
-{
- return wl_resource_instance_of(res, &wl_keyboard_interface,
- &_e_keyboard_interface);
-}
-
EINTERN Eina_Bool
e_comp_wl_input_keyboard_modifiers_serialize(void)
{
e_seat_update_seat_caps(seat, NULL);
}
-EINTERN Eina_Bool
-e_comp_wl_input_touch_check(struct wl_resource *res)
-{
- return wl_resource_instance_of(res, &wl_touch_interface,
- &_e_touch_interface);
-}
-
E_API void
e_comp_wl_input_keyboard_repeat_set(int delay, int rate)
{