1 #define EXECUTIVE_MODE_ENABLED
2 #define E_COMP_WL
3 #include "e.h"
4 #include <sys/mman.h>
5 #ifdef HAVE_WL_DRM
6 #include <Ecore_Drm2.h>
7 #endif
8 #include <Efl_Canvas_Wl.h>
9
10 E_API int E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = -1;
11 static xkb_keycode_t (*_xkb_keymap_key_by_name)(void *, const char *);
12 static void _e_comp_wl_input_context_keymap_set(struct xkb_keymap *keymap, struct xkb_context *context);
13
14 static Eina_Hash *input_gen_modifiers;
15
16 //the following two fields are just set by e_comp_wl_input_keymap_set if it is called before e_comp_wl is valid.
17 //when then later init is called those two fields are used in the keymap of the e_comp_wl struct
18 static struct xkb_context *cached_context;
19 static struct xkb_keymap *cached_keymap;
20 static xkb_layout_index_t choosen_group;
21
22 static void
_e_comp_wl_input_update_seat_caps(void)23 _e_comp_wl_input_update_seat_caps(void)
24 {
25 Eina_List *l;
26 struct wl_resource *res;
27 enum wl_seat_capability caps = 0;
28
29 if (e_comp_wl->ptr.enabled)
30 caps |= WL_SEAT_CAPABILITY_POINTER;
31 if (e_comp_wl->kbd.enabled)
32 caps |= WL_SEAT_CAPABILITY_KEYBOARD;
33 if (e_comp_wl->touch.enabled)
34 caps |= WL_SEAT_CAPABILITY_TOUCH;
35
36 EINA_LIST_FOREACH(e_comp_wl->seat.resources, l, res)
37 wl_seat_send_capabilities(res, caps);
38 }
39
40 static void
_e_comp_wl_input_cb_resource_destroy(struct wl_client * client EINA_UNUSED,struct wl_resource * resource)41 _e_comp_wl_input_cb_resource_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
42 {
43 wl_resource_destroy(resource);
44 }
45
46 static void
_e_comp_wl_input_pointer_cb_cursor_set(struct wl_client * client EINA_UNUSED,struct wl_resource * resource,uint32_t serial EINA_UNUSED,struct wl_resource * surface_resource,int32_t x,int32_t y)47 _e_comp_wl_input_pointer_cb_cursor_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial EINA_UNUSED, struct wl_resource *surface_resource, int32_t x, int32_t y)
48 {
49 E_Client *ec;
50 E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(resource);
51
52 if (!surface_resource)
53 {
54 ptr->cursor_set = 1;
55 ptr->cursor = NULL;
56 ptr->offset.x = x;
57 ptr->offset.y = y;
58 if (ptr->entered)
59 {
60 ecore_evas_cursor_unset(e_comp->ee);
61 evas_object_hide(e_comp->pointer->o_ptr);
62 }
63 return;
64 }
65 ec = wl_resource_get_user_data(surface_resource);
66 /* I think this only happens when we've deleted the resource from
67 * the client del callback - so the client is gone and shouldn't be
68 * setting a cursor, but the surface still exists so stale requests
69 * are being processed... let's BAIL.
70 */
71 if (!ec) return;
72 ptr->cursor_set = 1;
73 ptr->cursor = ec;
74 ptr->offset.x = x;
75 ptr->offset.y = y;
76 if (ec->comp_data->pending.input)
77 eina_tiler_clear(ec->comp_data->pending.input);
78 else
79 {
80 ec->comp_data->pending.input = eina_tiler_new(65535, 65535);
81 eina_tiler_tile_size_set(ec->comp_data->pending.input, 1, 1);
82 }
83 if (!ec->re_manage)
84 {
85 ec->comp_data->cursor = ec->re_manage = 1;
86 ec->ignored = 0;
87 evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO);
88
89 ec->lock_focus_out = ec->layer_block = ec->visible = ec->override = 1;
90 ec->icccm.title = eina_stringshare_add("noshadow");
91 evas_object_pass_events_set(ec->frame, 1);
92 evas_object_show(ec->frame);
93 if (e_comp_object_damage_exists(ec->frame))
94 e_comp_object_render_update_add(ec->frame);
95 ec->comp_data->mapped = 1;
96 e_client_focus_stack_set(eina_list_remove(e_client_focus_stack_get(), ec));
97 EC_CHANGED(ec);
98 }
99
100 if (ptr->entered)
101 e_comp_wl_input_pointer_cursor_update(ptr);
102 }
103
104 static const struct wl_pointer_interface _e_pointer_interface =
105 {
106 _e_comp_wl_input_pointer_cb_cursor_set,
107 _e_comp_wl_input_cb_resource_destroy
108 };
109
110 static const struct wl_keyboard_interface _e_keyboard_interface =
111 {
112 _e_comp_wl_input_cb_resource_destroy
113 };
114
115 static const struct wl_touch_interface _e_touch_interface =
116 {
117 _e_comp_wl_input_cb_resource_destroy
118 };
119
120 static void
_e_comp_wl_input_cb_pointer_unbind(struct wl_resource * resource)121 _e_comp_wl_input_cb_pointer_unbind(struct wl_resource *resource)
122 {
123 E_Comp_Wl_Pointer *ptr = wl_resource_get_user_data(resource);
124
125 if (ptr->cursor_set && ptr->entered)
126 e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
127 e_comp_wl->ptr.resources =
128 eina_list_remove(e_comp_wl->ptr.resources, resource);
129 free(ptr);
130 }
131
132 static void
_e_comp_wl_input_cb_pointer_get(struct wl_client * client,struct wl_resource * resource,uint32_t id)133 _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
134 {
135 struct wl_resource *res;
136 E_Comp_Wl_Pointer *ptr;
137
138 /* try to create pointer resource */
139 res = wl_resource_create(client, &wl_pointer_interface,
140 wl_resource_get_version(resource), id);
141 if (!res)
142 {
143 ERR("Could not create pointer on seat %s",
144 e_comp_wl->seat.name);
145 wl_client_post_no_memory(client);
146 return;
147 }
148 ptr = E_NEW(E_Comp_Wl_Pointer, 1);
149
150 e_comp_wl->ptr.resources =
151 eina_list_append(e_comp_wl->ptr.resources, res);
152 wl_resource_set_implementation(res, &_e_pointer_interface,
153 ptr,
154 _e_comp_wl_input_cb_pointer_unbind);
155 }
156
157 static void
_e_comp_wl_input_cb_keyboard_unbind(struct wl_resource * resource)158 _e_comp_wl_input_cb_keyboard_unbind(struct wl_resource *resource)
159 {
160 Eina_List *l, *ll;
161 struct wl_resource *res;
162
163 e_comp_wl->kbd.resources =
164 eina_list_remove(e_comp_wl->kbd.resources, resource);
165 EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
166 {
167 if (res == resource)
168 {
169 e_comp_wl->kbd.focused =
170 eina_list_remove_list(e_comp_wl->kbd.focused, l);
171 }
172 }
173 }
174
175 void
e_comp_wl_input_keyboard_enter_send(E_Client * ec)176 e_comp_wl_input_keyboard_enter_send(E_Client *ec)
177 {
178 struct wl_resource *res;
179 Eina_List *l;
180 uint32_t serial;
181
182 if (!ec->comp_data->surface) return;
183
184 if (!e_comp_wl->kbd.focused) return;
185
186 e_comp_wl_input_keyboard_modifiers_serialize();
187
188 serial = wl_display_next_serial(e_comp_wl->wl.disp);
189
190 EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
191 {
192 wl_keyboard_send_enter(res, serial, ec->comp_data->surface,
193 &e_comp_wl->kbd.keys);
194 wl_keyboard_send_modifiers(res, serial,
195 e_comp_wl->kbd.mod_depressed,
196 e_comp_wl->kbd.mod_latched,
197 e_comp_wl->kbd.mod_locked,
198 e_comp_wl->kbd.mod_group);
199 }
200 }
201
202 static void
_e_comp_wl_input_cb_keyboard_get(struct wl_client * client,struct wl_resource * resource,uint32_t id)203 _e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
204 {
205 E_Client *focused;
206 struct wl_resource *res;
207
208 /* try to create keyboard resource */
209 res = wl_resource_create(client, &wl_keyboard_interface,
210 wl_resource_get_version(resource), id);
211 if (!res)
212 {
213 ERR("Could not create keyboard on seat %s", e_comp_wl->seat.name);
214 wl_client_post_no_memory(client);
215 return;
216 }
217 wl_resource_set_user_data(res, resource);
218
219 e_comp_wl->kbd.resources =
220 eina_list_append(e_comp_wl->kbd.resources, res);
221 wl_resource_set_implementation(res, &_e_keyboard_interface,
222 e_comp->wl_comp_data,
223 _e_comp_wl_input_cb_keyboard_unbind);
224
225 /* send current repeat_info */
226 if (wl_resource_get_version(res) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
227 wl_keyboard_send_repeat_info(res, e_config->keyboard.repeat_rate, e_config->keyboard.repeat_delay);
228
229 /* send current keymap */
230 e_comp_wl_input_keymap_send(res);
231
232 /* if the client owns the focused surface, we need to send an enter */
233 focused = e_client_focused_get();
234 if (!focused) return;
235
236 if (client != wl_resource_get_client(focused->comp_data->surface)) return;
237 e_comp_wl->kbd.focused = eina_list_append(e_comp_wl->kbd.focused, res);
238
239 e_comp_wl_input_keyboard_enter_send(focused);
240 }
241
242 static void
_e_comp_wl_input_cb_touch_unbind(struct wl_resource * resource)243 _e_comp_wl_input_cb_touch_unbind(struct wl_resource *resource)
244 {
245 e_comp_wl->touch.resources =
246 eina_list_remove(e_comp_wl->touch.resources, resource);
247 }
248
249 static void
_e_comp_wl_input_cb_touch_get(struct wl_client * client EINA_UNUSED,struct wl_resource * resource,uint32_t id EINA_UNUSED)250 _e_comp_wl_input_cb_touch_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id EINA_UNUSED)
251 {
252 struct wl_resource *res;
253
254 /* try to create pointer resource */
255 res = wl_resource_create(client, &wl_touch_interface,
256 wl_resource_get_version(resource), id);
257 if (!res)
258 {
259 ERR("Could not create touch on seat %s",
260 e_comp_wl->seat.name);
261 wl_client_post_no_memory(client);
262 return;
263 }
264
265 e_comp_wl->touch.resources =
266 eina_list_append(e_comp_wl->touch.resources, res);
267 wl_resource_set_implementation(res, &_e_touch_interface,
268 e_comp->wl_comp_data,
269 _e_comp_wl_input_cb_touch_unbind);
270 }
271
272 static void
_e_comp_wl_input_cb_release(struct wl_client * client EINA_UNUSED,struct wl_resource * resource)273 _e_comp_wl_input_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
274 {
275 wl_resource_destroy(resource);
276 }
277
278 static const struct wl_seat_interface _e_seat_interface =
279 {
280 _e_comp_wl_input_cb_pointer_get,
281 _e_comp_wl_input_cb_keyboard_get,
282 _e_comp_wl_input_cb_touch_get,
283 _e_comp_wl_input_cb_release,
284 };
285
286 static void
_e_comp_wl_input_cb_unbind_seat(struct wl_resource * resource)287 _e_comp_wl_input_cb_unbind_seat(struct wl_resource *resource)
288 {
289 e_comp_wl->seat.resources =
290 eina_list_remove(e_comp_wl->seat.resources, resource);
291 }
292
293 static void
_e_comp_wl_input_cb_bind_seat(struct wl_client * client,void * data EINA_UNUSED,uint32_t version,uint32_t id)294 _e_comp_wl_input_cb_bind_seat(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
295 {
296 struct wl_resource *res;
297
298 res = wl_resource_create(client, &wl_seat_interface, version, id);
299 if (!res)
300 {
301 ERR("Could not create seat resource");
302 return;
303 }
304
305 /* store version of seat interface for reuse in updating capabilities */
306 e_comp_wl->seat.version = version;
307 e_comp_wl->seat.resources =
308 eina_list_append(e_comp_wl->seat.resources, res);
309
310 wl_resource_set_implementation(res, &_e_seat_interface,
311 e_comp->wl_comp_data,
312 _e_comp_wl_input_cb_unbind_seat);
313
314 _e_comp_wl_input_update_seat_caps();
315 if (e_comp_wl->seat.version >= WL_SEAT_NAME_SINCE_VERSION)
316 wl_seat_send_name(res, e_comp_wl->seat.name);
317 }
318
319 int
_e_comp_wl_input_keymap_fd_get(void)320 _e_comp_wl_input_keymap_fd_get(void)
321 {
322 int fd = 0, blen = 0, len = 0;
323 const char *path;
324 char tmp[PATH_MAX];
325 long flags;
326 void *mm;
327 Eina_Tmpstr *tmpstr = NULL;
328
329 blen = sizeof(tmp) - 1;
330
331 if (!(path = getenv("XDG_RUNTIME_DIR")))
332 return -1;
333
334 len = strlen(path);
335 if (len < blen)
336 {
337 strcpy(tmp, path);
338 strcat(tmp, "/e-wl-keymap-XXXXXX");
339 }
340 else
341 return -1;
342
343 if ((fd = eina_file_mkstemp(tmp, &tmpstr)) < 0) return -1;
344
345 flags = fcntl(fd, F_GETFD);
346 if (flags < 0)
347 {
348 eina_tmpstr_del(tmpstr);
349 close(fd);
350 return -1;
351 }
352
353 if (fcntl(fd, F_SETFD, (flags | FD_CLOEXEC)) == -1)
354 {
355 eina_tmpstr_del(tmpstr);
356 close(fd);
357 return -1;
358 }
359
360 if (ftruncate(fd, e_comp_wl->xkb.map_size) < 0)
361 {
362 eina_tmpstr_del(tmpstr);
363 close(fd);
364 return -1;
365 }
366
367 unlink(tmpstr);
368 eina_tmpstr_del(tmpstr);
369
370 mm = mmap(NULL, e_comp_wl->xkb.map_size, (PROT_READ | PROT_WRITE),
371 MAP_SHARED, fd, 0);
372 if (mm == MAP_FAILED)
373 {
374 ERR("Failed to mmap keymap area: %m");
375 close(fd);
376 return -1;
377 }
378
379 memcpy(mm, e_comp_wl->xkb.map_string, e_comp_wl->xkb.map_size);
380 munmap(mm, e_comp_wl->xkb.map_size);
381
382 return fd;
383 }
384
385 static void
_e_comp_wl_input_state_update(void)386 _e_comp_wl_input_state_update(void)
387 {
388 xkb_mod_mask_t latched = 0, locked = 0;
389
390 /* unreference any existing keyboard state */
391 if (e_comp_wl->xkb.state)
392 {
393 latched =
394 xkb_state_serialize_mods(e_comp_wl->xkb.state,
395 XKB_STATE_MODS_LATCHED);
396 locked =
397 xkb_state_serialize_mods(e_comp_wl->xkb.state,
398 XKB_STATE_MODS_LOCKED);
399 xkb_state_unref(e_comp_wl->xkb.state);
400 }
401
402 /* create a new xkb state */
403 e_comp_wl->xkb.state = xkb_state_new(e_comp_wl->xkb.keymap);
404
405 xkb_state_update_mask(e_comp_wl->xkb.state, 0,
406 latched, locked, e_comp_wl->kbd.choosen_group,
407 0, 0);
408 }
409
410 void
e_comp_wl_input_keymap_send(struct wl_resource * res)411 e_comp_wl_input_keymap_send(struct wl_resource *res)
412 {
413 int fd;
414
415 fd = _e_comp_wl_input_keymap_fd_get();
416 if (fd == -1)
417 return;
418
419 wl_keyboard_send_keymap(res, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
420 fd, e_comp_wl->xkb.map_size);
421
422 close(fd);
423 }
424
425 static void
nested_keymap_update(void)426 nested_keymap_update(void)
427 {
428 Eina_List *l;
429 Evas_Object *obj;
430
431 EINA_LIST_FOREACH(e_comp_wl->efl_wls, l, obj)
432 efl_canvas_wl_seat_keymap_set(obj, NULL, e_comp_wl->xkb.state, e_comp_wl->xkb.map_string, &e_comp_wl->kbd.keys);
433 }
434
435 static void
_e_comp_wl_input_keymap_update(struct xkb_keymap * keymap)436 _e_comp_wl_input_keymap_update(struct xkb_keymap *keymap)
437 {
438 struct wl_resource *res;
439 Eina_List *l;
440
441 /* unreference any existing keymap */
442 if (e_comp_wl->xkb.keymap)
443 xkb_map_unref(e_comp_wl->xkb.keymap);
444
445 /* free any existing keyboard map string */
446 free(e_comp_wl->xkb.map_string);
447 e_comp_wl->xkb.map_string = NULL;
448
449 /* increment keymap reference */
450 e_comp_wl->xkb.keymap = keymap;
451
452 /* update the state */
453 _e_comp_wl_input_state_update();
454
455 if (!(e_comp_wl->xkb.map_string = xkb_map_get_as_string(keymap)))
456 {
457 ERR("Could not get keymap string");
458 return;
459 }
460
461 e_comp_wl->xkb.map_size = strlen(e_comp_wl->xkb.map_string) + 1;
462
463 /* send updated keymap */
464 EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
465 e_comp_wl_input_keymap_send(res);
466
467 /* update modifiers */
468 e_comp_wl_input_keyboard_modifiers_update();
469 nested_keymap_update();
470 }
471
472 EINTERN Eina_Bool
e_comp_wl_input_init(void)473 e_comp_wl_input_init(void)
474 {
475 /* set default seat name */
476 if (!e_comp_wl->seat.name)
477 e_comp_wl->seat.name = "seat0";
478
479 /* create the global resource for input seat */
480 e_comp_wl->seat.global =
481 wl_global_create(e_comp_wl->wl.disp, &wl_seat_interface, 4,
482 e_comp->wl_comp_data, _e_comp_wl_input_cb_bind_seat);
483 if (!e_comp_wl->seat.global)
484 {
485 ERR("Could not create global for seat");
486 return EINA_FALSE;
487 }
488
489 wl_array_init(&e_comp_wl->kbd.keys);
490
491 E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE = ecore_event_type_new();
492
493 _xkb_keymap_key_by_name = dlsym(NULL, "xkb_keymap_key_by_name");
494
495 if (cached_keymap)
496 _e_comp_wl_input_context_keymap_set(cached_keymap, cached_context);
497 else
498 e_comp_wl_input_keymap_set(NULL, NULL, NULL, NULL, NULL);
499
500 if (choosen_group)
501 e_comp_wl_input_keymap_index_set(choosen_group);
502 else
503 e_comp_wl_input_keymap_index_set(0);
504
505 e_comp_wl_input_keyboard_modifiers_update();
506
507 return EINA_TRUE;
508 }
509
510 EINTERN void
e_comp_wl_input_shutdown(void)511 e_comp_wl_input_shutdown(void)
512 {
513 struct wl_resource *res;
514
515 E_FREE_FUNC(input_gen_modifiers, eina_hash_free);
516
517 /* destroy pointer resources */
518 EINA_LIST_FREE(e_comp_wl->ptr.resources, res)
519 wl_resource_destroy(res);
520
521 /* destroy keyboard resources */
522 EINA_LIST_FREE(e_comp_wl->kbd.resources, res)
523 wl_resource_destroy(res);
524 e_comp_wl->kbd.resources = eina_list_free(e_comp_wl->kbd.resources);
525
526 /* destroy touch resources */
527 EINA_LIST_FREE(e_comp_wl->touch.resources, res)
528 wl_resource_destroy(res);
529
530 /* destroy e_comp_wl->kbd.keys array */
531 wl_array_release(&e_comp_wl->kbd.keys);
532
533 /* free the string copy of the keyboard map */
534 free(e_comp_wl->xkb.map_string);
535
536 /* unreference any existing keyboard state */
537 if (e_comp_wl->xkb.state)
538 xkb_state_unref(e_comp_wl->xkb.state);
539
540 /* unreference any existing keymap */
541 if (e_comp_wl->xkb.keymap)
542 xkb_map_unref(e_comp_wl->xkb.keymap);
543
544 /* unreference any existing context */
545 if (e_comp_wl->xkb.context)
546 xkb_context_unref(e_comp_wl->xkb.context);
547
548 /* destroy the global seat resource */
549 if (e_comp_wl->seat.global)
550 wl_global_destroy(e_comp_wl->seat.global);
551 e_comp_wl->seat.global = NULL;
552 }
553
554 EINTERN void
e_comp_wl_input_pointer_cursor_update(E_Comp_Wl_Pointer * ptr)555 e_comp_wl_input_pointer_cursor_update(E_Comp_Wl_Pointer *ptr)
556 {
557 EINA_SAFETY_ON_TRUE_RETURN(!ptr->entered);
558 if (ptr->cursor_set && (!e_comp_util_mouse_grabbed()))
559 {
560 if (ptr->cursor)
561 e_pointer_object_set(e_comp->pointer, ptr->cursor->frame, ptr->offset.x, ptr->offset.y);
562 else
563 {
564 ecore_evas_cursor_unset(e_comp->ee);
565 evas_object_hide(e_comp->pointer->o_ptr);
566 }
567 }
568 else
569 e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
570 }
571
572 EINTERN Eina_Bool
e_comp_wl_input_pointer_check(struct wl_resource * res)573 e_comp_wl_input_pointer_check(struct wl_resource *res)
574 {
575 return wl_resource_instance_of(res, &wl_pointer_interface,
576 &_e_pointer_interface);
577 }
578
579 EINTERN Eina_Bool
e_comp_wl_input_keyboard_check(struct wl_resource * res)580 e_comp_wl_input_keyboard_check(struct wl_resource *res)
581 {
582 return wl_resource_instance_of(res, &wl_keyboard_interface,
583 &_e_keyboard_interface);
584 }
585
586 EINTERN Eina_Bool
e_comp_wl_input_keyboard_modifiers_serialize(void)587 e_comp_wl_input_keyboard_modifiers_serialize(void)
588 {
589 Eina_Bool changed = EINA_FALSE;
590 xkb_mod_mask_t mod;
591 xkb_layout_index_t grp;
592
593 mod = xkb_state_serialize_mods(e_comp_wl->xkb.state, XKB_STATE_DEPRESSED);
594 changed |= mod != e_comp_wl->kbd.mod_depressed;
595 e_comp_wl->kbd.mod_depressed = mod;
596
597 mod = xkb_state_serialize_mods(e_comp_wl->xkb.state, XKB_STATE_MODS_LATCHED);
598 changed |= mod != e_comp_wl->kbd.mod_latched;
599 e_comp_wl->kbd.mod_latched = mod;
600
601 mod = xkb_state_serialize_mods(e_comp_wl->xkb.state, XKB_STATE_MODS_LOCKED);
602 changed |= mod != e_comp_wl->kbd.mod_locked;
603 e_comp_wl->kbd.mod_locked = mod;
604
605 grp = xkb_state_serialize_layout(e_comp_wl->xkb.state,
606 XKB_STATE_LAYOUT_EFFECTIVE);
607 if (grp != e_comp_wl->kbd.mod_group)
608 {
609 e_config->xkb.cur_group = grp;
610 ecore_event_add(E_EVENT_XKB_CHANGED, NULL, NULL, NULL);
611 }
612 changed |= grp != e_comp_wl->kbd.mod_group;
613 e_comp_wl->kbd.mod_group = grp;
614 return changed;
615 }
616
617 EINTERN void
e_comp_wl_input_keyboard_modifiers_update(void)618 e_comp_wl_input_keyboard_modifiers_update(void)
619 {
620 uint32_t serial;
621 struct wl_resource *res;
622 Eina_List *l;
623
624 if (!e_comp_wl_input_keyboard_modifiers_serialize()) return;
625
626 if ((!e_comp_wl->kbd.focused) || e_comp->input_key_grabs) return;
627
628 serial = wl_display_next_serial(e_comp_wl->wl.disp);
629 EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
630 wl_keyboard_send_modifiers(res, serial,
631 e_comp_wl->kbd.mod_depressed,
632 e_comp_wl->kbd.mod_latched,
633 e_comp_wl->kbd.mod_locked,
634 e_comp_wl->kbd.mod_group);
635 }
636
637 EINTERN void
e_comp_wl_input_keyboard_state_update(uint32_t keycode,Eina_Bool pressed)638 e_comp_wl_input_keyboard_state_update(uint32_t keycode, Eina_Bool pressed)
639 {
640 enum xkb_key_direction dir;
641
642 if (!e_comp_wl->xkb.state) return;
643
644 if (pressed) dir = XKB_KEY_DOWN;
645 else dir = XKB_KEY_UP;
646
647 e_comp_wl->kbd.mod_changed =
648 xkb_state_update_key(e_comp_wl->xkb.state, keycode + 8, dir);
649
650 e_comp_wl_input_keyboard_modifiers_update();
651 }
652
653 E_API void
e_comp_wl_input_pointer_enabled_set(Eina_Bool enabled)654 e_comp_wl_input_pointer_enabled_set(Eina_Bool enabled)
655 {
656 /* check for valid compositor data */
657 if (!e_comp->wl_comp_data)
658 {
659 ERR("No compositor data");
660 return;
661 }
662
663 e_comp_wl->ptr.enabled = !!enabled;
664 _e_comp_wl_input_update_seat_caps();
665 }
666
667 E_API void
e_comp_wl_input_keyboard_enabled_set(Eina_Bool enabled)668 e_comp_wl_input_keyboard_enabled_set(Eina_Bool enabled)
669 {
670 /* check for valid compositor data */
671 if (!e_comp->wl_comp_data)
672 {
673 ERR("No compositor data");
674 return;
675 }
676
677 e_comp_wl->kbd.enabled = !!enabled;
678 _e_comp_wl_input_update_seat_caps();
679 }
680
681 static void
_e_comp_wl_input_context_keymap_set(struct xkb_keymap * keymap,struct xkb_context * context)682 _e_comp_wl_input_context_keymap_set(struct xkb_keymap *keymap, struct xkb_context *context)
683 {
684 if (e_comp_wl)
685 {
686 //we have a initializied and running compositor here
687 if (e_comp_wl->xkb.context)
688 xkb_context_unref(e_comp_wl->xkb.context);
689 e_comp_wl->xkb.context = context;
690
691 /* update compositor keymap */
692 _e_comp_wl_input_keymap_update(keymap);
693 }
694 else
695 {
696 //we dont have a running compositor here, cache the values, init will pick them
697 cached_context = context;
698 cached_keymap = keymap;
699 }
700
701 if (!e_comp->ee) return;
702 //set the values to the drm devices
703 #ifdef HAVE_WL_DRM
704 if (strstr(ecore_evas_engine_name_get(e_comp->ee), "drm"))
705 {
706 Ecore_Drm2_Device *dev;
707
708 dev = ecore_evas_data_get(e_comp->ee, "device");
709 if (dev)
710 ecore_drm2_device_keyboard_info_set(dev, context, keymap,
711 e_comp_wl ? e_comp_wl->kbd.choosen_group : choosen_group);
712 }
713 #endif
714 }
715
716 E_API void
e_comp_wl_input_keymap_index_set(xkb_layout_index_t index)717 e_comp_wl_input_keymap_index_set(xkb_layout_index_t index)
718 {
719 #ifdef HAVE_WL_DRM
720 if (e_comp && e_comp->ee && strstr(ecore_evas_engine_name_get(e_comp->ee), "drm"))
721 {
722 Ecore_Drm2_Device *dev;
723
724 dev = ecore_evas_data_get(e_comp->ee, "device");
725 if (dev)
726 ecore_drm2_device_keyboard_group_set(dev, index);
727 }
728 #endif
729 if (e_comp_wl)
730 {
731 e_comp_wl->kbd.choosen_group = index;
732 _e_comp_wl_input_state_update();
733 e_comp_wl_input_keyboard_modifiers_update();
734 nested_keymap_update();
735 }
736 else
737 choosen_group = index;
738 }
739
740 E_API void
e_comp_wl_input_keymap_set(const char * rules,const char * model,const char * layout,const char * variant,const char * options)741 e_comp_wl_input_keymap_set(const char *rules, const char *model, const char *layout, const char *variant, const char *options)
742 {
743 struct xkb_keymap *keymap;
744 struct xkb_context *context;
745 struct xkb_rule_names names;
746
747 /* DBG("COMP_WL: Keymap Set: %s %s %s", rules, model, layout); */
748
749 /* assemble xkb_rule_names so we can fetch keymap */
750 memset(&names, 0, sizeof(names));
751
752 if (rules) names.rules = rules;
753 else names.rules = "evdev";
754
755 if (model) names.model = model;
756 else names.model = "pc105";
757
758 if (layout) names.layout = layout;
759 else names.layout = "us";
760
761 if (variant) names.variant = variant;
762 else names.variant = NULL;
763
764 if (options) names.options = options;
765 else names.options = NULL;
766
767 /* create a new xkb context */
768 context = xkb_context_new(0);
769
770 /* fetch new keymap based on names */
771 keymap = xkb_map_new_from_names(context, &names, 0);
772
773 if (!keymap)
774 {
775 ERR("Failed to compile keymap");
776 return;
777 }
778
779 _e_comp_wl_input_context_keymap_set(keymap, context);
780 }
781
782 E_API void
e_comp_wl_input_touch_enabled_set(Eina_Bool enabled)783 e_comp_wl_input_touch_enabled_set(Eina_Bool enabled)
784 {
785 /* check for valid compositor data */
786 if (!e_comp->wl_comp_data)
787 {
788 ERR("No compositor data");
789 return;
790 }
791
792 e_comp_wl->touch.enabled = !!enabled;
793 _e_comp_wl_input_update_seat_caps();
794 }
795
796 EINTERN Eina_Bool
e_comp_wl_input_touch_check(struct wl_resource * res)797 e_comp_wl_input_touch_check(struct wl_resource *res)
798 {
799 return wl_resource_instance_of(res, &wl_touch_interface,
800 &_e_touch_interface);
801 }
802
803 EINTERN void
e_comp_wl_input_keyboard_modifers_clear(void)804 e_comp_wl_input_keyboard_modifers_clear(void)
805 {
806 e_comp_wl->kbd.mod_depressed = 0;
807 e_comp_wl->kbd.mod_latched = 0;
808 e_comp_wl->kbd.mod_locked = 0;
809 e_comp_wl->kbd.mod_group = 0;
810
811 e_comp_wl_input_keyboard_modifiers_serialize();
812 }
813
814 static void
_event_generate(const char * key,const char * keyname,int mods,Eina_Bool up)815 _event_generate(const char *key, const char *keyname, int mods, Eina_Bool up)
816 {
817 Ecore_Event_Key *ev;
818 int keycode;
819
820 keycode = _xkb_keymap_key_by_name(e_comp_wl->xkb.keymap, keyname ?: key);
821 if (keycode == -1)
822 {
823 ERR("no keycode found for key '%s'", keyname ?: key);
824 return;
825 }
826 ev = calloc(1, sizeof(Ecore_Event_Key) + (2 * (strlen(key) + 1)));
827
828 ev->keyname = (char *)(ev + 1);
829 ev->key = ev->keyname + strlen(key) + 1;
830
831 strcpy((char *)ev->keyname, key);
832 strcpy((char *)ev->key, key);
833
834 ev->window = e_comp->ee_win;
835 ev->event_window = e_comp->ee_win;
836 ev->timestamp = 0;
837 ev->modifiers = mods;
838 ev->keycode = keycode;
839 ecore_event_add(up ? ECORE_EVENT_KEY_UP : ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
840 }
841
842 static void
_event_generate_mods(int mods,Eina_Bool up)843 _event_generate_mods(int mods, Eina_Bool up)
844 {
845 if (!mods) return;
846 if (mods & ECORE_EVENT_MODIFIER_SHIFT)
847 _event_generate("Shift", "LFSH", mods, up);
848 if (mods & ECORE_EVENT_MODIFIER_CTRL)
849 _event_generate("Control_L", "LCTL", mods, up);
850 if (mods & ECORE_EVENT_MODIFIER_ALT)
851 _event_generate("Alt_L", "LALT", mods, up);
852 if (mods & ECORE_EVENT_MODIFIER_WIN)
853 _event_generate("Super_L", "LWIN", mods, up);
854 if (mods & ECORE_EVENT_MODIFIER_ALTGR)
855 _event_generate("Mode_switch", "ALGR", mods, up);
856 }
857
858 E_API void
e_comp_wl_input_keyboard_event_generate(const char * key,int mods,Eina_Bool up)859 e_comp_wl_input_keyboard_event_generate(const char *key, int mods, Eina_Bool up)
860 {
861 const char *keyname = NULL;
862 /* assumes qwerty layout */
863 /* /usr/share/X11/xkb/keycodes/evdev */
864 static const char *keycodes[] =
865 {
866 ['`'] = "TLDE",
867 ['1'] = "AE01",
868 ['2'] = "AE02",
869 ['3'] = "AE03",
870 ['4'] = "AE04",
871 ['5'] = "AE05",
872 ['6'] = "AE06",
873 ['7'] = "AE07",
874 ['8'] = "AE08",
875 ['9'] = "AE09",
876 ['0'] = "AE10",
877 ['-'] = "AE11",
878 ['='] = "AE12",
879 //''] = "BKSP",
880 ['\t'] = "TAB",
881 ['q'] = "AD01",
882 ['w'] = "AD02",
883 ['e'] = "AD03",
884 ['r'] = "AD04",
885 ['t'] = "AD05",
886 ['y'] = "AD06",
887 ['u'] = "AD07",
888 ['i'] = "AD08",
889 ['o'] = "AD09",
890 ['p'] = "AD10",
891 ['['] = "AD11",
892 [']'] = "AD12",
893 ['\\'] = "BKSL",
894 ['\r'] = "RTRN",
895 //''] = "CAPS",
896 ['a'] = "AC01",
897 ['s'] = "AC02",
898 ['d'] = "AC03",
899 ['f'] = "AC04",
900 ['g'] = "AC05",
901 ['h'] = "AC06",
902 ['j'] = "AC07",
903 ['k'] = "AC08",
904 ['l'] = "AC09",
905 [';'] = "AC10",
906 ['\''] = "AC11",
907 //''] = "LFSH",
908 ['z'] = "AB01",
909 ['x'] = "AB02",
910 ['c'] = "AB03",
911 ['v'] = "AB04",
912 ['b'] = "AB05",
913 ['n'] = "AB06",
914 ['m'] = "AB07",
915 [','] = "AB08",
916 ['.'] = "AB09",
917 ['/'] = "AB10",
918 //''] = "RTSH",
919 [' '] = "SPCE",
920 };
921
922 if (!_xkb_keymap_key_by_name)
923 {
924 ERR("xkbcommon >= 0.6.0 required for keyboard event generation!");
925 return;
926 }
927 EINA_SAFETY_ON_NULL_RETURN(key);
928 EINA_SAFETY_ON_TRUE_RETURN(!key[0]);
929 if (!input_gen_modifiers)
930 {
931 //<RTSH> = 62;
932 //<LALT> = 64;
933 //<LCTL> = 37;
934 //<RCTL> = 105;
935 //<RALT> = 108;
936 //<LWIN> = 133;
937 //<RWIN> = 134;
938 //<COMP> = 135;
939 //alias <MENU> = <COMP>;
940 //<ESC> = 9;
941 static const char *modcodes[] =
942 {
943 "Shift_L",
944 "LFSH",
945
946 "Control_L",
947 "LCTL",
948
949 "Super_L",
950 "LWIN",
951
952 "Alt_L",
953 "LALT",
954
955 "Escape",
956 "ESC",
957
958 "Alt_R",
959 "RALT",
960
961 "Super_R",
962 "RWIN",
963
964 "Menu",
965 "MENU",
966
967 "Control_R",
968 "RCTRL",
969
970 "Mode_switch",
971 "ALGR",
972
973 "Return",
974 "RTRN",
975
976 "Caps_Lock",
977 "CAPS",
978 };
979 unsigned int i;
980
981 input_gen_modifiers = eina_hash_string_superfast_new(NULL);
982 for (i = 0; i < EINA_C_ARRAY_LENGTH(modcodes); i += 2)
983 eina_hash_add(input_gen_modifiers, modcodes[i], modcodes[i + 1]);
984 }
985
986 if (!up)
987 _event_generate_mods(mods, up);
988 keyname = eina_hash_find(input_gen_modifiers, key);
989 if ((!keyname) && (!key[1]))
990 {
991 if (key[0] < (int)EINA_C_ARRAY_LENGTH(keycodes))
992 keyname = keycodes[(unsigned char)key[0]];
993 }
994 _event_generate(key, keyname, mods, up);
995 if (up)
996 _event_generate_mods(mods, up);
997 }
998