2 #include <tizen-extension-server-protocol.h>
4 #include <wayland-tbm-server.h>
6 /* handle include for printing uint64_t */
7 #define __STDC_FORMAT_MACROS
10 #define COMPOSITOR_VERSION 4
12 E_API int E_EVENT_WAYLAND_GLOBAL_ADD = -1;
13 #include "session-recovery-server-protocol.h"
16 # define EGL_HEIGHT 0x3056
19 # define EGL_WIDTH 0x3057
22 /* Resource Data Mapping: (wl_resource_get_user_data)
24 * wl_surface == e_pixmap
25 * wl_region == eina_tiler
26 * wl_subsurface == e_client
30 static void _e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized);
31 static void _e_comp_wl_subsurface_restack(E_Client *ec);
32 static void _e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec);
33 static void _e_comp_wl_subsurface_check_below_bg_rectangle(E_Client *ec);
34 static void _e_comp_wl_subsurface_show(E_Client *ec);
35 static void _e_comp_wl_subsurface_hide(E_Client *ec);
37 static E_Client * _e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep);
40 typedef struct _E_Comp_Wl_Transform_Context
45 } E_Comp_Wl_Transform_Context;
47 typedef struct _E_Comp_Wl_Key_Data
53 static Eina_List *handlers = NULL;
54 static E_Client *cursor_timer_ec = NULL;
55 static Eina_Bool need_send_leave = EINA_TRUE;
56 static Eina_Bool need_send_released = EINA_FALSE;
57 static Eina_Bool need_send_motion = EINA_TRUE;
59 static int _e_comp_wl_hooks_delete = 0;
60 static int _e_comp_wl_hooks_walking = 0;
62 static Eina_Inlist *_e_comp_wl_hooks[] =
64 [E_COMP_WL_HOOK_SHELL_SURFACE_READY] = NULL,
65 [E_COMP_WL_HOOK_SUBSURFACE_CREATE] = NULL,
66 [E_COMP_WL_HOOK_BUFFER_CHANGE] = NULL,
67 [E_COMP_WL_HOOK_CLIENT_REUSE] = NULL,
70 static Eina_List *hooks = NULL;
74 _e_comp_wl_hooks_clean(void)
79 for (x = 0; x < E_COMP_WL_HOOK_LAST; x++)
80 EINA_INLIST_FOREACH_SAFE(_e_comp_wl_hooks[x], l, ch)
82 if (!ch->delete_me) continue;
83 _e_comp_wl_hooks[x] = eina_inlist_remove(_e_comp_wl_hooks[x], EINA_INLIST_GET(ch));
89 _e_comp_wl_hook_call(E_Comp_Wl_Hook_Point hookpoint, E_Client *ec)
93 e_object_ref(E_OBJECT(ec));
94 _e_comp_wl_hooks_walking++;
95 EINA_INLIST_FOREACH(_e_comp_wl_hooks[hookpoint], ch)
97 if (ch->delete_me) continue;
98 ch->func(ch->data, ec);
99 if (e_object_is_del(E_OBJECT(ec)))
102 _e_comp_wl_hooks_walking--;
103 if ((_e_comp_wl_hooks_walking == 0) && (_e_comp_wl_hooks_delete > 0))
104 _e_comp_wl_hooks_clean();
105 e_object_unref(E_OBJECT(ec));
109 _e_comp_wl_configure_send(E_Client *ec, Eina_Bool edges, Eina_Bool send_size)
115 if (e_comp_object_frame_exists(ec->frame))
116 w = ec->client.w, h = ec->client.h;
118 w = ec->w, h = ec->h;
123 ec->comp_data->shell.configure_send(ec->comp_data->shell.surface,
124 edges * e_comp_wl->resize.edges,
129 _e_comp_wl_focus_down_set(E_Client *ec EINA_UNUSED)
135 _e_comp_wl_focus_check(void)
139 if (stopping) return;
140 ec = e_client_focused_get();
141 if ((!ec) || e_pixmap_is_x(ec->pixmap))
142 e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
146 _e_comp_wl_cb_read(void *data EINA_UNUSED, Ecore_Fd_Handler *hdlr EINA_UNUSED)
148 /* dispatch pending wayland events */
149 wl_event_loop_dispatch(e_comp_wl->wl.loop, 0);
151 return ECORE_CALLBACK_RENEW;
155 _e_comp_wl_cb_prepare(void *data EINA_UNUSED, Ecore_Fd_Handler *hdlr EINA_UNUSED)
157 /* flush pending client events */
158 wl_display_flush_clients(e_comp_wl->wl.disp);
161 E_API enum wl_output_transform
162 e_comp_wl_output_buffer_transform_get(E_Client *ec)
164 E_Comp_Wl_Buffer_Viewport *vp;
165 E_Comp_Wl_Buffer *buffer;
166 enum wl_output_transform transform, rotation;
168 if (!ec) return WL_OUTPUT_TRANSFORM_NORMAL;
169 if (e_object_is_del(E_OBJECT(ec))) return WL_OUTPUT_TRANSFORM_NORMAL;
170 if (!ec->comp_data) return WL_OUTPUT_TRANSFORM_NORMAL;
172 vp = &ec->comp_data->scaler.buffer_viewport;
173 if (ec->comp_data->sub.data)
174 return vp->buffer.transform;
176 buffer = ec->comp_data->buffer_ref.buffer;
179 (buffer->type != E_COMP_WL_BUFFER_TYPE_NATIVE && buffer->type != E_COMP_WL_BUFFER_TYPE_TBM))
180 return vp->buffer.transform;
182 rotation = wayland_tbm_server_buffer_get_buffer_transform(NULL, buffer->resource);
184 return vp->buffer.transform;
186 /* ignore the flip value when calculating transform because the screen rotation
187 * functionality doesn't consider the flip output transform currently
189 transform = (4 + (vp->buffer.transform & 0x3) - rotation) & 0x3;
191 DBG("ec(%p) window rotation(%d) buffer_transform(%d) : transform(%d)",
192 ec, rotation, vp->buffer.transform, transform);
198 e_comp_wl_map_size_cal_from_buffer(E_Client *ec)
200 E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
201 E_Comp_Wl_Buffer *buffer;
202 int32_t width, height;
204 buffer = e_pixmap_resource_get(ec->pixmap);
207 ec->comp_data->width_from_buffer = 0;
208 ec->comp_data->height_from_buffer = 0;
212 switch (e_comp_wl_output_buffer_transform_get(ec))
214 case WL_OUTPUT_TRANSFORM_90:
215 case WL_OUTPUT_TRANSFORM_270:
216 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
217 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
218 width = buffer->h / vp->buffer.scale;
219 height = buffer->w / vp->buffer.scale;
222 width = buffer->w / vp->buffer.scale;
223 height = buffer->h / vp->buffer.scale;
227 ec->comp_data->width_from_buffer = width;
228 ec->comp_data->height_from_buffer = height;
232 e_comp_wl_map_size_cal_from_viewport(E_Client *ec)
234 E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
235 int32_t width, height;
237 width = ec->comp_data->width_from_buffer;
238 height = ec->comp_data->height_from_buffer;
240 if (width == 0 && height == 0) return;
242 if (width != 0 && vp->surface.width != -1)
244 ec->comp_data->width_from_viewport = vp->surface.width;
245 ec->comp_data->height_from_viewport = vp->surface.height;
249 if (width != 0 && vp->buffer.src_width != wl_fixed_from_int(-1))
251 int32_t w = wl_fixed_to_int(wl_fixed_from_int(1) - 1 + vp->buffer.src_width);
252 int32_t h = wl_fixed_to_int(wl_fixed_from_int(1) - 1 + vp->buffer.src_height);
253 ec->comp_data->width_from_viewport = w ?: 1;
254 ec->comp_data->height_from_viewport = h ?: 1;
258 ec->comp_data->width_from_viewport = width;
259 ec->comp_data->height_from_viewport = height;
263 e_comp_wl_topmost_parent_get(E_Client *ec)
265 E_Client *parent = NULL;
267 if (!ec->comp_data || !ec->comp_data->sub.data)
270 parent = ec->comp_data->sub.data->parent;
273 if (!parent->comp_data || !parent->comp_data->sub.data)
276 parent = parent->comp_data->sub.data->parent;
283 e_comp_wl_video_subsurface_has(E_Client *ec)
288 if (!ec) return EINA_FALSE;
289 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
290 if (!ec->comp_data) return EINA_FALSE;
292 if (ec->comp_data->video_client)
295 if (ec->comp_data->has_video_client)
298 EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
299 if (e_comp_wl_video_subsurface_has(subc))
302 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
303 if (e_comp_wl_video_subsurface_has(subc))
310 e_comp_wl_normal_subsurface_has(E_Client *ec)
315 if (!ec) return EINA_FALSE;
316 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
317 if (!ec->comp_data) return EINA_FALSE;
319 /* if a leaf client is not video cliet */
320 if (ec->comp_data->sub.data && !ec->comp_data->sub.below_list &&
321 !ec->comp_data->sub.below_list_pending && !ec->comp_data->video_client)
324 EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
325 if (e_comp_wl_normal_subsurface_has(subc))
328 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
329 if (e_comp_wl_normal_subsurface_has(subc))
336 _e_comp_wl_extern_parent_commit(E_Client *ec)
341 if (!ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
343 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
344 _e_comp_wl_extern_parent_commit(subc);
346 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
347 _e_comp_wl_extern_parent_commit(subc);
349 _e_comp_wl_subsurface_parent_commit(ec, EINA_TRUE);
353 e_comp_wl_map_apply(E_Client *ec)
355 E_Comp_Wl_Buffer_Viewport *vp;
356 E_Comp_Wl_Subsurf_Data *sdata;
357 E_Comp_Wl_Client_Data *cdata;
358 int x1, y1, x2, y2, x, y;
361 if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
363 e_comp_object_map_update(ec->frame);
365 vp = &ec->comp_data->scaler.buffer_viewport;
366 if (vp->buffer.src_width == wl_fixed_from_int(-1)) return;
368 cdata = ec->comp_data;
369 sdata = ec->comp_data->sub.data;
372 dx = sdata->position.x;
373 dy = sdata->position.y;
377 dx += sdata->parent->x;
378 dy += sdata->parent->y;
381 if (sdata->remote_surface.offscreen_parent)
383 E_Client *offscreen_parent = sdata->remote_surface.offscreen_parent;
384 Eina_Rectangle *rect;
387 EINA_LIST_FOREACH(offscreen_parent->comp_data->remote_surface.regions, l, rect)
389 /* TODO: If there are one more regions, it means that provider's offscreen
390 * is displayed by one more remote_surfaces. Have to consider it later. At
391 * this time, just consider only one remote_surface.
405 evas_object_geometry_get(ec->frame, &x, &y, NULL, NULL);
406 if (x != dx || y != dy)
407 evas_object_move(ec->frame, dx, dy);
409 if (!cdata->viewport_transform)
411 cdata->viewport_transform = e_util_transform_new();
412 e_client_transform_core_add(ec, cdata->viewport_transform);
415 e_util_transform_viewport_set(cdata->viewport_transform, dx, dy,
416 ec->comp_data->width_from_viewport,
417 ec->comp_data->height_from_viewport);
419 x1 = wl_fixed_to_int(vp->buffer.src_x);
420 y1 = wl_fixed_to_int(vp->buffer.src_y);
421 x2 = wl_fixed_to_int(vp->buffer.src_x + vp->buffer.src_width);
422 y2 = wl_fixed_to_int(vp->buffer.src_y + vp->buffer.src_height);
424 e_util_transform_texcoord_set(cdata->viewport_transform, 0, x1, y1);
425 e_util_transform_texcoord_set(cdata->viewport_transform, 1, x2, y1);
426 e_util_transform_texcoord_set(cdata->viewport_transform, 2, x2, y2);
427 e_util_transform_texcoord_set(cdata->viewport_transform, 3, x1, y2);
429 ELOGF("TRANSFORM", "viewport map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d)",
430 ec->pixmap, ec, ec->x, ec->y, ec->comp_data->width_from_viewport,
431 ec->comp_data->height_from_viewport, x1, y1, x2, y1, x2, y2, x1, y2);
433 e_client_transform_core_update(ec);
437 _e_comp_wl_evas_cb_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
443 if (!(ec = data)) return;
444 if (e_object_is_del(data)) return;
446 if (!ec->override) e_hints_window_visible_set(ec);
448 if ((!ec->override) && (!ec->re_manage) && (!ec->comp_data->reparented) &&
449 (!ec->comp_data->need_reparent))
451 ec->comp_data->need_reparent = EINA_TRUE;
452 ec->visible = EINA_TRUE;
454 if (!e_client_util_ignored_get(ec))
456 ec->take_focus = !starting;
460 if (!ec->comp_data->need_reparent)
462 if ((ec->hidden) || (ec->iconic))
464 evas_object_hide(ec->frame);
465 // e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
467 else if (!ec->internal_elm_win)
468 evas_object_show(ec->frame);
471 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
472 evas_object_show(tmp->frame);
474 topmost = e_comp_wl_topmost_parent_get(ec);
475 if (topmost == ec && (ec->comp_data->sub.list || ec->comp_data->sub.below_list))
476 _e_comp_wl_subsurface_show(ec);
478 if (ec->comp_data->sub.below_obj)
479 evas_object_show(ec->comp_data->sub.below_obj);
483 _e_comp_wl_evas_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
489 if (!(ec = data)) return;
490 if (e_object_is_del(E_OBJECT(ec))) return;
492 /* Uncommonly some clients's final buffer can be skipped if the client
493 * requests unmap of its surface right after wl_surface@commit.
494 * So if this client evas object is hidden state and client is already
495 * unmmapped, we can consider to clear pixmap image here mandatorily.
497 if (!ec->comp_data->mapped)
498 e_pixmap_image_clear(ec->pixmap, 1);
500 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
501 evas_object_hide(tmp->frame);
503 topmost = e_comp_wl_topmost_parent_get(ec);
504 if (topmost == ec && (ec->comp_data->sub.list || ec->comp_data->sub.below_list))
505 _e_comp_wl_subsurface_hide(ec);
507 if (ec->comp_data->sub.below_obj)
508 evas_object_hide(ec->comp_data->sub.below_obj);
512 _e_comp_wl_evas_cb_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
519 if (!(ec = data)) return;
520 if (e_object_is_del(E_OBJECT(ec))) return;
522 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
524 if (!subc->comp_data || !subc->comp_data->sub.data) continue;
525 x = ec->x + subc->comp_data->sub.data->position.x;
526 y = ec->y + subc->comp_data->sub.data->position.y;
527 evas_object_move(subc->frame, x, y);
529 if (subc->comp_data->scaler.viewport)
531 E_Comp_Wl_Client_Data *cdata = subc->comp_data;
532 if (cdata->viewport_transform)
533 e_comp_wl_map_apply(subc);
537 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
539 if (!subc->comp_data || !subc->comp_data->sub.data) continue;
540 x = ec->x + subc->comp_data->sub.data->position.x;
541 y = ec->y + subc->comp_data->sub.data->position.y;
542 evas_object_move(subc->frame, x, y);
544 if (subc->comp_data->scaler.viewport)
546 E_Comp_Wl_Client_Data *cdata = subc->comp_data;
547 if (cdata->viewport_transform)
548 e_comp_wl_map_apply(subc);
552 if (ec->comp_data->sub.below_obj)
553 evas_object_move(ec->comp_data->sub.below_obj, ec->x, ec->y);
557 _e_comp_wl_send_touch_cancel(E_Client *ec)
560 struct wl_resource *res;
561 struct wl_client *wc;
562 E_Comp_Config *comp_conf = NULL;
565 if (e_object_is_del(E_OBJECT(ec))) return;
566 if (!ec->comp_data || !ec->comp_data->surface) return;
567 if ((ec->ignored) && (!ec->remote_surface.provider)) return;
569 wc = wl_resource_get_client(ec->comp_data->surface);
571 comp_conf = e_comp_config_get();
573 EINA_LIST_FOREACH(e_comp->wl_comp_data->touch.resources, l, res)
575 if (wl_resource_get_client(res) != wc) continue;
576 if (!e_comp_wl_input_touch_check(res)) continue;
578 if (comp_conf && comp_conf->input_log_enable)
579 INF("[Server] Touch Cancel (win:0x%08x, name:%20s)\n", e_client_util_win_get(ec), e_client_util_name_get(ec));
581 wl_touch_send_cancel(res);
586 _e_comp_wl_touch_cancel(void)
588 if (!e_comp_wl->ptr.ec)
591 if (!need_send_released)
594 _e_comp_wl_send_touch_cancel(e_comp_wl->ptr.ec);
596 need_send_released = EINA_FALSE;
597 need_send_motion = EINA_FALSE;
601 _e_comp_wl_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
603 E_Client *ec = (E_Client *)data;
605 if ((!ec) || (!ec->comp_data)) return;
606 if (e_object_is_del(E_OBJECT(ec))) return;
607 if (ec->comp_data->sub.restacking) return;
609 if (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
610 _e_comp_wl_touch_cancel();
612 e_comp_wl_subsurface_stack_update(ec);
615 static E_Comp_Wl_Input_Device *
616 _e_comp_wl_device_last_device_get(Ecore_Device_Class dev_class)
620 case ECORE_DEVICE_CLASS_MOUSE:
621 return e_comp_wl->input_device_manager.last_device_ptr;
622 case ECORE_DEVICE_CLASS_KEYBOARD:
623 return e_comp_wl->input_device_manager.last_device_kbd;
624 case ECORE_DEVICE_CLASS_TOUCH:
625 return e_comp_wl->input_device_manager.last_device_touch;
633 _e_comp_wl_device_last_device_set(Ecore_Device_Class dev_class, E_Comp_Wl_Input_Device *device)
637 case ECORE_DEVICE_CLASS_MOUSE:
638 e_comp_wl->input_device_manager.last_device_ptr = device;
640 case ECORE_DEVICE_CLASS_KEYBOARD:
641 e_comp_wl->input_device_manager.last_device_kbd = device;
643 case ECORE_DEVICE_CLASS_TOUCH:
644 e_comp_wl->input_device_manager.last_device_touch = device;
651 static E_Comp_Wl_Input_Device *
652 _e_comp_wl_device_client_last_device_get(E_Client *ec, Ecore_Device_Class dev_class)
656 case ECORE_DEVICE_CLASS_MOUSE:
657 return ec->comp_data->last_device_ptr;
658 case ECORE_DEVICE_CLASS_KEYBOARD:
659 return ec->comp_data->last_device_kbd;
660 case ECORE_DEVICE_CLASS_TOUCH:
661 return ec->comp_data->last_device_touch;
669 _e_comp_wl_device_client_last_device_set(E_Client *ec, Ecore_Device_Class dev_class, E_Comp_Wl_Input_Device *device)
673 case ECORE_DEVICE_CLASS_MOUSE:
674 ec->comp_data->last_device_ptr = device;
676 case ECORE_DEVICE_CLASS_KEYBOARD:
677 ec->comp_data->last_device_kbd = device;
679 case ECORE_DEVICE_CLASS_TOUCH:
680 ec->comp_data->last_device_touch = device;
688 _e_comp_wl_device_send_event_device(E_Client *ec, Evas_Device *dev, uint32_t timestamp)
690 E_Comp_Wl_Input_Device *last_device, *ec_last_device, *input_dev;
691 struct wl_resource *dev_res;
692 const char *dev_name;
693 Ecore_Device_Class dev_class;
694 struct wl_client *wc;
698 EINA_SAFETY_ON_NULL_RETURN(dev);
701 if (ec->cur_mouse_action || e_comp_wl->drag)
703 if (e_object_is_del(E_OBJECT(ec))) return;
704 if ((ec->ignored) && (!ec->remote_surface.provider)) return;
705 if (!ec->comp_data || !ec->comp_data->surface) return;
707 dev_class = (Ecore_Device_Class)evas_device_class_get(dev);
708 dev_name = evas_device_description_get(dev);
709 last_device = _e_comp_wl_device_last_device_get(dev_class);
710 ec_last_device = _e_comp_wl_device_client_last_device_get(ec, dev_class);
712 serial = wl_display_next_serial(e_comp_wl->wl.disp);
713 wc = wl_resource_get_client(ec->comp_data->surface);
714 EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
716 if (!eina_streq(input_dev->identifier, dev_name) || (input_dev->clas != dev_class)) continue;
717 if ((!last_device) || (last_device != input_dev) || (!ec_last_device) || (ec_last_device != input_dev))
719 _e_comp_wl_device_last_device_set(dev_class, input_dev);
720 _e_comp_wl_device_client_last_device_set(ec, dev_class, input_dev);
722 EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
724 if (wl_resource_get_client(dev_res) != wc) continue;
725 tizen_input_device_send_event_device(dev_res, serial, input_dev->identifier, timestamp);
732 _e_comp_wl_device_send_last_event_device(E_Client *ec, Ecore_Device_Class dev_class, uint32_t timestamp)
734 E_Comp_Wl_Input_Device *last_device;
735 struct wl_resource *dev_res;
736 struct wl_client *wc;
740 if (!ec->comp_data || !ec->comp_data->surface) return;
742 last_device = _e_comp_wl_device_last_device_get(dev_class);
743 if (!last_device) return;
745 _e_comp_wl_device_client_last_device_set(ec, dev_class, last_device);
747 serial = wl_display_next_serial(e_comp_wl->wl.disp);
748 wc = wl_resource_get_client(ec->comp_data->surface);
749 EINA_LIST_FOREACH(last_device->resources, l, dev_res)
751 if (wl_resource_get_client(dev_res) != wc) continue;
752 tizen_input_device_send_event_device(dev_res, serial, last_device->identifier, timestamp);
757 _e_comp_wl_send_event_device(struct wl_client *wc, uint32_t timestamp, Ecore_Device *dev, uint32_t serial)
759 E_Comp_Wl_Input_Device *input_dev;
760 struct wl_resource *dev_res;
761 const char *dev_name;
764 EINA_SAFETY_ON_NULL_RETURN(dev);
766 dev_name = ecore_device_identifier_get(dev);
768 EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
770 if (!eina_streq(input_dev->identifier, dev_name)) continue;
771 _e_comp_wl_device_last_device_set(ecore_device_class_get(dev), input_dev);
773 EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
775 if (wl_resource_get_client(dev_res) != wc) continue;
776 tizen_input_device_send_event_device(dev_res, serial, input_dev->identifier, timestamp);
782 _e_comp_wl_cursor_reload(E_Client *ec)
784 struct wl_resource *res;
785 struct wl_client *wc;
790 if (e_comp->pointer->o_ptr && (!evas_object_visible_get(e_comp->pointer->o_ptr)))
791 e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
794 if (e_object_is_del(E_OBJECT(ec))) return;
795 if (!ec->comp_data || !ec->comp_data->surface) return;
797 cx = wl_fixed_to_int(e_comp_wl->ptr.x) - ec->client.x;
798 cy = wl_fixed_to_int(e_comp_wl->ptr.y) - ec->client.y;
800 wc = wl_resource_get_client(ec->comp_data->surface);
801 serial = wl_display_next_serial(e_comp_wl->wl.disp);
802 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
804 if (!e_comp_wl_input_pointer_check(res)) continue;
805 if (wl_resource_get_client(res) != wc) continue;
806 wl_pointer_send_enter(res, serial, ec->comp_data->surface,
807 wl_fixed_from_int(cx), wl_fixed_from_int(cy));
808 ec->pointer_enter_sent = EINA_TRUE;
813 _e_comp_wl_cursor_timer(void *data)
817 e_comp_wl_cursor_hide(ec);
819 return ECORE_CALLBACK_CANCEL;
823 _e_comp_wl_device_send_axis(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, enum tizen_input_device_axis_type axis_type, double value)
825 E_Comp_Wl_Input_Device *input_dev;
826 struct wl_resource *dev_res;
827 struct wl_client *wc;
832 if (e_object_is_del(E_OBJECT(ec))) return;
833 if (!ec->comp_data || !ec->comp_data->surface) return;
835 f_value = wl_fixed_from_double(value);
836 wc = wl_resource_get_client(ec->comp_data->surface);
838 EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
840 if ((strcmp(input_dev->identifier, dev_name)) || (input_dev->clas != (Ecore_Device_Class)dev_class)) continue;
841 EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
843 if (wl_resource_get_client(dev_res) != wc) continue;
844 tizen_input_device_send_axis(dev_res, axis_type, f_value);
850 _e_comp_wl_device_renew_axis(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, unsigned int idx, double radius_x, double radius_y, double pressure, double angle)
852 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_X, radius_x);
853 e_comp_wl->input_device_manager.multi[idx].radius_x = radius_x;
854 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_Y, radius_y);
855 e_comp_wl->input_device_manager.multi[idx].radius_y = radius_y;
856 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_PRESSURE, pressure);
857 e_comp_wl->input_device_manager.multi[idx].pressure = pressure;
858 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_ANGLE, angle);
859 e_comp_wl->input_device_manager.multi[idx].angle = angle;
863 _e_comp_wl_device_handle_axes(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, unsigned int idx, double radius_x, double radius_y, double pressure, double angle)
865 if (idx >= E_COMP_WL_TOUCH_MAX) return;
867 if (e_comp_wl->input_device_manager.multi[idx].radius_x != radius_x)
869 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_X, radius_x);
870 e_comp_wl->input_device_manager.multi[idx].radius_x = radius_x;
872 if (e_comp_wl->input_device_manager.multi[idx].radius_y != radius_y)
874 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_Y, radius_y);
875 e_comp_wl->input_device_manager.multi[idx].radius_y = radius_y;
877 if (e_comp_wl->input_device_manager.multi[idx].pressure != pressure)
879 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_PRESSURE, pressure);
880 e_comp_wl->input_device_manager.multi[idx].pressure = pressure;
882 if (e_comp_wl->input_device_manager.multi[idx].angle != angle)
884 _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_ANGLE, angle);
885 e_comp_wl->input_device_manager.multi[idx].angle = angle;
890 _e_comp_wl_evas_cb_mouse_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
893 Evas_Event_Mouse_In *ev;
894 struct wl_resource *res;
895 struct wl_client *wc;
900 if (!(ec = data)) return;
901 if (e_object_is_del(E_OBJECT(ec))) return;
903 if (!ec->comp_data || !ec->comp_data->surface) return;
905 e_comp_wl->ptr.ec = ec;
908 e_comp_wl_data_device_send_enter(ec);
912 if (e_config->use_cursor_timer)
914 if (e_comp_wl->ptr.hide_tmr)
916 ecore_timer_del(e_comp_wl->ptr.hide_tmr);
917 cursor_timer_ec = ec;
918 e_comp_wl->ptr.hide_tmr = ecore_timer_add(e_config->cursor_timer_interval, _e_comp_wl_cursor_timer, ec);
922 if (e_pointer_is_hidden(e_comp->pointer))
927 if (!eina_list_count(e_comp_wl->ptr.resources)) return;
928 wc = wl_resource_get_client(ec->comp_data->surface);
929 serial = wl_display_next_serial(e_comp_wl->wl.disp);
930 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
932 if (!e_comp_wl_input_pointer_check(res)) continue;
933 if (wl_resource_get_client(res) != wc) continue;
935 _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, ev->timestamp);
937 wl_pointer_send_enter(res, serial, ec->comp_data->surface,
938 wl_fixed_from_int(ev->canvas.x - ec->client.x),
939 wl_fixed_from_int(ev->canvas.y - ec->client.y));
940 ec->pointer_enter_sent = EINA_TRUE;
945 _e_comp_wl_evas_cb_mouse_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
948 Evas_Event_Mouse_Out *ev;
949 struct wl_resource *res;
950 struct wl_client *wc;
953 Eina_Bool inside_check;
957 if (!(ec = data)) return;
958 inside_check = E_INSIDE(ev->canvas.x, ev->canvas.y,
959 ec->client.x, ec->client.y, ec->client.w, ec->client.h);
960 if (ec->cur_mouse_action && inside_check) return;
961 if (e_object_is_del(E_OBJECT(e_comp))) return;
963 /* FIXME? this is a hack to just reset the cursor whenever we mouse out. not sure if accurate */
967 ecore_evas_cursor_get(e_comp->ee, &o, NULL, NULL, NULL);
968 if ((e_comp->pointer->o_ptr != o) && (e_comp->wl_comp_data->ptr.enabled))
970 if ((!e_config->use_cursor_timer) || (!e_pointer_is_hidden(e_comp->pointer)))
971 e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
975 if (e_comp_wl->ptr.ec == ec)
976 e_comp_wl->ptr.ec = NULL;
977 if (e_object_is_del(E_OBJECT(ec))) return;
979 if (!ec->comp_data || !ec->comp_data->surface) return;
983 e_comp_wl_data_device_send_leave(ec);
987 if (e_config->use_cursor_timer && !e_comp_wl->ptr.hide_tmr)
989 if (e_pointer_is_hidden(e_comp->pointer))
993 if (!eina_list_count(e_comp_wl->ptr.resources)) return;
995 wc = wl_resource_get_client(ec->comp_data->surface);
996 serial = wl_display_next_serial(e_comp_wl->wl.disp);
997 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
999 if (!e_comp_wl_input_pointer_check(res)) continue;
1000 if (wl_resource_get_client(res) != wc) continue;
1001 if (ec->pointer_enter_sent == EINA_FALSE) continue;
1003 _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, ev->timestamp);
1005 wl_pointer_send_leave(res, serial, ec->comp_data->surface);
1007 ec->pointer_enter_sent = EINA_FALSE;
1011 _e_comp_wl_send_touch(E_Client *ec, int idx, int canvas_x, int canvas_y, uint32_t timestamp, Eina_Bool pressed)
1014 struct wl_client *wc;
1015 struct wl_resource *res;
1018 E_Comp_Config *comp_conf = NULL;
1021 if (e_object_is_del(E_OBJECT(ec))) return;
1022 if (!ec->comp_data || !ec->comp_data->surface) return;
1024 wc = wl_resource_get_client(ec->comp_data->surface);
1025 serial = wl_display_next_serial(e_comp_wl->wl.disp);
1029 x = wl_fixed_from_int(canvas_x - ec->client.x);
1030 y = wl_fixed_from_int(canvas_y - ec->client.y);
1033 comp_conf = e_comp_config_get();
1035 EINA_LIST_FOREACH(e_comp_wl->touch.resources, l, res)
1037 if (wl_resource_get_client(res) != wc) continue;
1038 if (!e_comp_wl_input_touch_check(res)) continue;
1039 TRACE_INPUT_BEGIN(_e_comp_wl_send_touch);
1042 if (comp_conf && comp_conf->input_log_enable)
1043 INF("[Server] Touch Down (id: %d, time: %d, x:%d, y:%d, win:0x%08x, name:%20s)\n", idx, timestamp, canvas_x - ec->client.x, canvas_y - ec->client.y, e_client_util_win_get(ec), e_client_util_name_get(ec));
1045 wl_touch_send_down(res, serial, timestamp, ec->comp_data->surface, idx, x, y); //id 0 for the 1st finger
1049 if (comp_conf && comp_conf->input_log_enable)
1050 INF("[Server] Touch Up (id: %d, time: %d, x:%d, y:%d, win:0x%08x, name:%20s)\n", idx, timestamp, canvas_x - ec->client.x, canvas_y - ec->client.y, e_client_util_win_get(ec), e_client_util_name_get(ec));
1052 wl_touch_send_up(res, serial, timestamp, idx);
1059 _e_comp_wl_send_touch_move(E_Client *ec, int idx, int canvas_x, int canvas_y, uint32_t timestamp)
1062 struct wl_client *wc;
1063 struct wl_resource *res;
1067 if (e_object_is_del(E_OBJECT(ec))) return;
1068 if (!ec->comp_data || !ec->comp_data->surface) return;
1070 wc = wl_resource_get_client(ec->comp_data->surface);
1072 x = wl_fixed_from_int(canvas_x - ec->client.x);
1073 y = wl_fixed_from_int(canvas_y - ec->client.y);
1075 EINA_LIST_FOREACH(e_comp_wl->touch.resources, l, res)
1077 if (wl_resource_get_client(res) != wc) continue;
1078 if (!e_comp_wl_input_touch_check(res)) continue;
1079 wl_touch_send_motion(res, timestamp, idx, x, y);
1084 _e_comp_wl_send_mouse_move(E_Client *ec, int x, int y, unsigned int timestamp)
1086 struct wl_resource *res;
1087 struct wl_client *wc;
1091 if (e_object_is_del(E_OBJECT(ec))) return;
1092 if (!ec->comp_data || !ec->comp_data->surface) return;
1094 wc = wl_resource_get_client(ec->comp_data->surface);
1095 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
1097 if (!e_comp_wl_input_pointer_check(res)) continue;
1098 if (wl_resource_get_client(res) != wc) continue;
1099 wl_pointer_send_motion(res, timestamp,
1100 wl_fixed_from_int(x - ec->client.x),
1101 wl_fixed_from_int(y - ec->client.y));
1106 _e_comp_wl_cursor_move_timer_control(E_Client *ec)
1108 if (!e_config->use_cursor_timer) return;
1110 if (e_comp_wl->ptr.hide_tmr)
1112 if (cursor_timer_ec == ec)
1114 ecore_timer_interval_set(e_comp_wl->ptr.hide_tmr, e_config->cursor_timer_interval);
1115 ecore_timer_reset(e_comp_wl->ptr.hide_tmr);
1119 ecore_timer_del(e_comp_wl->ptr.hide_tmr);
1120 cursor_timer_ec = ec;
1121 e_comp_wl->ptr.hide_tmr = ecore_timer_add(e_config->cursor_timer_interval, _e_comp_wl_cursor_timer, ec);
1126 cursor_timer_ec = ec;
1127 e_comp_wl->ptr.hide_tmr = ecore_timer_add(e_config->cursor_timer_interval, _e_comp_wl_cursor_timer, ec);
1132 _e_comp_wl_evas_cb_mouse_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1135 Evas_Event_Mouse_Move *ev;
1136 Evas_Device *dev = NULL;
1137 const char *dev_name;
1141 e_comp->wl_comp_data->ptr.x = wl_fixed_from_int(ev->cur.canvas.x);
1142 e_comp->wl_comp_data->ptr.y = wl_fixed_from_int(ev->cur.canvas.y);
1144 if (!(ec = data)) return;
1145 if (ec->cur_mouse_action) return;
1146 if (e_object_is_del(E_OBJECT(ec))) return;
1147 if ((ec->ignored) && (!ec->remote_surface.provider)) return;
1148 if (!ec->comp_data || !ec->comp_data->surface) return;
1150 if ((!need_send_motion) && (!need_send_released) && (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)) return;
1152 if ((!e_comp_wl->drag_client) ||
1153 (!e_client_has_xwindow(e_comp_wl->drag_client)))
1156 dev_name = evas_device_description_get(dev);
1158 if (dev && (evas_device_class_get(dev) == EVAS_DEVICE_CLASS_TOUCH))
1160 if (e_comp_wl->touch.pressed & (1 << 0))
1162 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1164 _e_comp_wl_device_handle_axes(dev_name, evas_device_class_get(dev),
1165 ec, 0, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1166 _e_comp_wl_send_touch_move(ec, 0, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
1168 e_pointer_touch_move(e_comp->pointer, ev->cur.output.x, ev->cur.output.y);
1172 if (e_config->use_cursor_timer)
1174 if (e_pointer_is_hidden(e_comp->pointer))
1175 _e_comp_wl_cursor_reload(ec);
1178 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1179 _e_comp_wl_send_mouse_move(ec, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
1180 e_pointer_mouse_move(e_comp->pointer, ev->cur.output.x, ev->cur.output.y);
1182 _e_comp_wl_cursor_move_timer_control(ec);
1188 _e_comp_wl_evas_handle_mouse_button_to_touch(E_Client *ec, uint32_t timestamp, int canvas_x, int canvas_y, Eina_Bool flag)
1190 if (ec->cur_mouse_action || e_comp_wl->drag) return;
1191 if (e_object_is_del(E_OBJECT(ec))) return;
1192 if (!ec->comp_data || !ec->comp_data->surface) return;
1193 if ((ec->ignored) && (!ec->remote_surface.provider)) return;
1195 e_comp_wl->ptr.button = BTN_LEFT;
1197 _e_comp_wl_send_touch(ec, 0, canvas_x, canvas_y, timestamp, flag);
1201 _e_comp_wl_send_mouse_out(E_Client *ec)
1203 struct wl_resource *res;
1204 struct wl_client *wc;
1209 if (e_object_is_del(E_OBJECT(ec))) return;
1210 if (!ec->comp_data || !ec->comp_data->surface) return;
1212 wc = wl_resource_get_client(ec->comp_data->surface);
1213 serial = wl_display_next_serial(e_comp_wl->wl.disp);
1214 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
1216 if (!e_comp_wl_input_pointer_check(res)) continue;
1217 if (wl_resource_get_client(res) != wc) continue;
1218 wl_pointer_send_leave(res, serial, ec->comp_data->surface);
1223 _e_comp_wl_evas_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1225 E_Client *ec = data;
1226 Evas_Event_Mouse_Down *ev = event;
1227 Evas_Device *dev = NULL;
1228 const char *dev_name;
1232 if (e_object_is_del(E_OBJECT(ec))) return;
1235 dev_name = evas_device_description_get(dev);
1237 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1239 if (dev && (evas_device_class_get(dev) == EVAS_DEVICE_CLASS_TOUCH))
1242 _e_comp_wl_device_renew_axis(dev_name, evas_device_class_get(dev),
1243 ec, 0, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1244 _e_comp_wl_evas_handle_mouse_button_to_touch(ec, ev->timestamp, ev->canvas.x, ev->canvas.y, EINA_TRUE);
1245 e_pointer_touch_move(e_comp->pointer, ev->output.x, ev->output.y);
1246 e_comp_wl->touch.pressed |= (1 << 0);
1250 e_comp_wl_evas_handle_mouse_button(ec, ev->timestamp, ev->button,
1251 WL_POINTER_BUTTON_STATE_PRESSED);
1252 e_pointer_mouse_move(e_comp->pointer, ev->output.x, ev->output.y);
1255 need_send_released = EINA_TRUE;
1257 focused = e_client_focused_get();
1258 if ((focused) && (ec != focused))
1260 if (need_send_leave)
1262 need_send_leave = EINA_FALSE;
1263 _e_comp_wl_device_send_event_device(focused, dev, ev->timestamp);
1264 _e_comp_wl_send_mouse_out(focused);
1266 e_focus_event_mouse_down(ec);
1269 need_send_leave = EINA_TRUE;
1273 _e_comp_wl_evas_cb_mouse_up(void *data, Evas *evas, Evas_Object *obj EINA_UNUSED, void *event)
1275 E_Client *ec = data;
1276 Evas_Event_Mouse_Up *ev = event;
1277 Evas_Device *dev = NULL;
1278 const char *dev_name;
1279 Evas_Event_Flags flags;
1282 if (ec->cur_mouse_action) return;
1283 if (e_object_is_del(E_OBJECT(ec))) return;
1285 if (!need_send_released)
1287 need_send_motion = EINA_TRUE;
1290 flags = evas_event_default_flags_get(evas);
1291 if (flags & EVAS_EVENT_FLAG_ON_HOLD) goto finish;
1294 dev_name = evas_device_description_get(dev);
1296 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1298 if (dev && (evas_device_class_get(dev) == EVAS_DEVICE_CLASS_TOUCH))
1301 _e_comp_wl_device_handle_axes(dev_name, evas_device_class_get(dev),
1302 ec, 0, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1303 _e_comp_wl_evas_handle_mouse_button_to_touch(ec, ev->timestamp, ev->canvas.x, ev->canvas.y, EINA_FALSE);
1304 e_comp_wl->touch.pressed &= ~(1 << 0);
1307 e_comp_wl_evas_handle_mouse_button(ec, ev->timestamp, ev->button,
1308 WL_POINTER_BUTTON_STATE_RELEASED);
1311 need_send_released = EINA_FALSE;
1315 _e_comp_wl_mouse_wheel_send(E_Client *ec, int direction, int z, int timestamp)
1317 struct wl_resource *res;
1318 struct wl_client *wc;
1323 axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
1325 axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
1328 dir = -wl_fixed_from_int(abs(z));
1330 dir = wl_fixed_from_int(z);
1333 if (e_object_is_del(E_OBJECT(ec))) return;
1334 if (!ec->comp_data || !ec->comp_data->surface) return;
1336 wc = wl_resource_get_client(ec->comp_data->surface);
1337 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
1339 if (!e_comp_wl_input_pointer_check(res)) continue;
1340 if (wl_resource_get_client(res) != wc) continue;
1341 wl_pointer_send_axis(res, timestamp, axis, dir);
1346 _e_comp_wl_evas_cb_mouse_wheel(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1349 Evas_Event_Mouse_Wheel *ev;
1352 if (!(ec = data)) return;
1353 if (ec->cur_mouse_action) return;
1354 if (e_object_is_del(E_OBJECT(ec))) return;
1355 if ((ec->ignored) && (!ec->remote_surface.provider)) return;
1357 if (!ec->comp_data || !ec->comp_data->surface) return;
1359 if (!eina_list_count(e_comp_wl->ptr.resources))
1362 _e_comp_wl_device_send_event_device(ec, ev->dev, ev->timestamp);
1364 _e_comp_wl_mouse_wheel_send(ec, ev->direction, ev->z, ev->timestamp);
1368 _e_comp_wl_evas_cb_multi_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1370 E_Client *ec = data;
1371 Evas_Event_Multi_Down *ev = event;
1372 Evas_Device *dev = NULL;
1373 const char *dev_name;
1374 Evas_Device_Class dev_class;
1377 if (e_object_is_del(E_OBJECT(ec))) return;
1378 if (!ec->comp_data || !ec->comp_data->surface) return;
1380 /* Do not deliver emulated single touch events to client */
1381 if (ev->device == 0) return;
1384 if (dev && (dev_name = evas_device_description_get(dev)))
1386 dev_class = evas_device_class_get(dev);
1387 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1388 _e_comp_wl_device_renew_axis(dev_name, dev_class, ec, ev->device, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1391 _e_comp_wl_send_touch(ec, ev->device, ev->canvas.x, ev->canvas.y, ev->timestamp, EINA_TRUE);
1392 e_comp_wl->touch.pressed |= (1 << ev->device);
1396 _e_comp_wl_evas_cb_multi_up(void *data, Evas *evas, Evas_Object *obj EINA_UNUSED, void *event)
1398 E_Client *ec = data;
1399 Evas_Event_Multi_Up *ev = event;
1400 Evas_Device *dev = NULL;
1401 const char *dev_name;
1402 Evas_Device_Class dev_class;
1403 Evas_Event_Flags flags;
1406 if (e_object_is_del(E_OBJECT(ec))) return;
1407 if (!ec->comp_data || !ec->comp_data->surface) return;
1409 /* Do not deliver emulated single touch events to client */
1410 if (ev->device == 0) return;
1412 flags = evas_event_default_flags_get(evas);
1413 if (flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1416 if (dev && (dev_name = evas_device_description_get(dev)))
1418 dev_class = evas_device_class_get(dev);
1419 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1420 _e_comp_wl_device_handle_axes(dev_name, dev_class, ec, ev->device, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1423 _e_comp_wl_send_touch(ec, ev->device, 0, 0, ev->timestamp, EINA_FALSE);
1424 e_comp_wl->touch.pressed &= ~(1 << ev->device);
1428 _e_comp_wl_evas_cb_multi_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1430 E_Client *ec = data;
1431 Evas_Event_Multi_Move *ev = event;
1432 Evas_Device *dev = NULL;
1433 const char *dev_name;
1434 Evas_Device_Class dev_class;
1437 if (e_object_is_del(E_OBJECT(ec))) return;
1438 if (!ec->comp_data || !ec->comp_data->surface) return;
1440 /* Do not deliver emulated single touch events to client */
1441 if (ev->device == 0) return;
1443 if (e_comp_wl->touch.pressed & (1 << ev->device))
1446 if (dev && (dev_name = evas_device_description_get(dev)))
1448 dev_class = evas_device_class_get(dev);
1449 _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1450 _e_comp_wl_device_handle_axes(dev_name, dev_class, ec, ev->device, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1453 _e_comp_wl_send_touch_move(ec, ev->device, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
1458 _e_comp_wl_client_priority_adjust(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_child, Eina_Bool do_child)
1461 char *file, buff[PATH_MAX];
1468 n = (getpriority(PRIO_PROCESS, pid) + adj);
1472 setpriority(PRIO_PROCESS, pid, n);
1475 use_adj = EINA_TRUE;
1477 if (!do_child) return;
1479 files = ecore_file_ls("/proc");
1480 EINA_LIST_FREE(files, file)
1482 if (!isdigit(file[0]))
1485 snprintf(buff, sizeof(buff), "/proc/%s/stat", file);
1486 if ((f = fopen(buff, "r")))
1490 num_read = fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid);
1492 if (num_read == 2 && ppid == pid)
1493 _e_comp_wl_client_priority_adjust(pid2, set,
1495 adj_child, do_child);
1503 _e_comp_wl_client_priority_raise(E_Client *ec)
1505 if (!e_config->priority_control) return;
1506 if (ec->netwm.pid <= 0) return;
1507 if (ec->netwm.pid == getpid()) return;
1508 _e_comp_wl_client_priority_adjust(ec->netwm.pid,
1509 e_config->priority - 1, -1,
1510 EINA_FALSE, EINA_TRUE, EINA_FALSE);
1514 _e_comp_wl_client_priority_normal(E_Client *ec)
1516 if (!e_config->priority_control) return;
1517 if (ec->netwm.pid <= 0) return;
1518 if (ec->netwm.pid == getpid()) return;
1519 _e_comp_wl_client_priority_adjust(ec->netwm.pid, e_config->priority, 1,
1520 EINA_FALSE, EINA_TRUE, EINA_FALSE);
1524 _e_comp_wl_evas_cb_focus_in_timer(E_Client *ec)
1527 E_Comp_Wl_Key_Data *k;
1528 struct wl_resource *res;
1532 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1534 ec->comp_data->on_focus_timer = NULL;
1536 if (!e_comp_wl->kbd.focused) return EINA_FALSE;
1537 serial = wl_display_next_serial(e_comp_wl->wl.disp);
1538 t = ecore_time_unix_get();
1540 EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
1542 wl_array_for_each(k, &e_comp_wl->kbd.keys)
1544 _e_comp_wl_send_event_device(wl_resource_get_client(res), t, k->dev, serial);
1545 wl_keyboard_send_key(res, serial, t,
1546 k->key, WL_KEYBOARD_KEY_STATE_PRESSED);
1552 /* It is called in the following cases:
1553 * When a normal ec->frame has focus.
1554 * Or launching image ec is replaced to the real ec.
1557 e_comp_wl_feed_focus_in(E_Client *ec)
1560 struct wl_resource *res;
1561 struct wl_client *wc;
1565 if (e_object_is_del(E_OBJECT(ec))) return;
1566 if (ec->iconic) return;
1568 /* block spurious focus events */
1569 focused = e_client_focused_get();
1570 if ((focused) && (ec != focused)) return;
1572 /* raise client priority */
1573 _e_comp_wl_client_priority_raise(ec);
1575 wc = wl_resource_get_client(ec->comp_data->surface);
1577 EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
1579 if (wl_resource_get_client(res) == wc)
1581 if (!eina_list_data_find(e_comp_wl->kbd.focused, res))
1582 e_comp_wl->kbd.focused = eina_list_append(e_comp_wl->kbd.focused, res);
1586 if (!e_comp_wl->kbd.focused) return;
1587 e_comp_wl->kbd.focus = ec->comp_data->surface;
1588 e_comp_wl_input_keyboard_enter_send(ec);
1589 e_comp_wl_data_device_keyboard_focus_set();
1590 ec->comp_data->on_focus_timer =
1591 ecore_timer_add(((e_config->xkb.delay_held_key_input_to_focus)/1000.0),
1592 (Ecore_Task_Cb)_e_comp_wl_evas_cb_focus_in_timer, ec);
1593 int rotation = ec->e.state.rot.ang.curr;
1594 if (e_comp->pointer->rotation != rotation)
1595 e_pointer_rotation_set(e_comp->pointer, rotation);
1599 e_comp_wl_subsurface_stack_update(E_Client *ec)
1603 if (!(ec) || !ec->comp_data) return;
1604 if (e_object_is_del(E_OBJECT(ec))) return;
1605 if (ec->comp_data->sub.restacking) return;
1607 /* return if ec isn't both a parent of a subsurface and a subsurface itself */
1608 if (!ec->comp_data->sub.list && !ec->comp_data->sub.below_list && !ec->comp_data->sub.data)
1610 if (ec->comp_data->sub.below_obj)
1611 _e_comp_wl_subsurface_restack_bg_rectangle(ec);
1615 topmost = e_comp_wl_topmost_parent_get(ec);
1617 _e_comp_wl_subsurface_restack(topmost);
1618 _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
1620 //To update client stack list
1621 if ((ec->comp_data->sub.data) &&
1622 (ec->comp_data->sub.data->parent))
1627 parent = ec->comp_data->sub.data->parent;
1629 if ((parent->comp_data->sub.list) &&
1630 (eina_list_data_find(parent->comp_data->sub.list, ec)))
1633 o = evas_object_below_get(ec->frame);
1634 e_comp_object_layer_update(ec->frame, o, NULL);
1636 else if ((parent->comp_data->sub.below_list) &&
1637 (eina_list_data_find(parent->comp_data->sub.below_list, ec)))
1640 o = evas_object_above_get(ec->frame);
1641 e_comp_object_layer_update(ec->frame, NULL, o);
1647 _e_comp_wl_evas_cb_focus_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1650 if (!(ec = data)) return;
1651 e_comp_wl_feed_focus_in(ec);
1655 _e_comp_wl_evas_cb_focus_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1658 struct wl_resource *res;
1660 E_Comp_Wl_Key_Data *k;
1664 if (!(ec = data)) return;
1666 if (!ec->comp_data) return;
1668 E_FREE_FUNC(ec->comp_data->on_focus_timer, ecore_timer_del);
1670 /* lower client priority */
1671 if (!e_object_is_del(data))
1672 _e_comp_wl_client_priority_normal(ec);
1675 /* update keyboard modifier state */
1676 wl_array_for_each(k, &e_comp_wl->kbd.keys)
1677 e_comp_wl_input_keyboard_state_update(k->key, EINA_FALSE);
1679 if (!ec->comp_data->surface) return;
1681 if (!eina_list_count(e_comp_wl->kbd.resources)) return;
1683 /* send keyboard_leave to all keyboard resources */
1684 serial = wl_display_next_serial(e_comp_wl->wl.disp);
1685 t = ecore_time_unix_get();
1687 EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
1689 wl_array_for_each(k, &e_comp_wl->kbd.keys)
1691 _e_comp_wl_send_event_device(wl_resource_get_client(res), t, k->dev, serial);
1692 wl_keyboard_send_key(res, serial, t,
1693 k->key, WL_KEYBOARD_KEY_STATE_RELEASED);
1695 wl_keyboard_send_leave(res, serial, ec->comp_data->surface);
1696 e_comp_wl->kbd.focused =
1697 eina_list_remove_list(e_comp_wl->kbd.focused, l);
1702 _e_comp_wl_evas_cb_resize(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1706 if (!(ec = data)) return;
1708 if ((ec->shading) || (ec->shaded)) return;
1709 if (!ec->comp_data->shell.configure_send) return;
1711 /* TODO: calculate x, y with transfrom object */
1712 if ((e_client_util_resizing_get(ec)) && (!ec->transformed) && (e_comp_wl->resize.edges))
1716 x = ec->mouse.last_down[ec->moveinfo.down.button - 1].w;
1717 y = ec->mouse.last_down[ec->moveinfo.down.button - 1].h;
1718 if (e_comp_object_frame_exists(ec->frame))
1719 e_comp_object_frame_wh_unadjust(ec->frame, x, y, &x, &y);
1721 switch (ec->resize_mode)
1723 case E_POINTER_RESIZE_TL:
1724 case E_POINTER_RESIZE_L:
1725 case E_POINTER_RESIZE_BL:
1726 x += ec->mouse.last_down[ec->moveinfo.down.button - 1].mx -
1727 ec->mouse.current.mx;
1729 case E_POINTER_RESIZE_TR:
1730 case E_POINTER_RESIZE_R:
1731 case E_POINTER_RESIZE_BR:
1732 x += ec->mouse.current.mx - ec->mouse.last_down[ec->moveinfo.down.button - 1].mx;
1737 switch (ec->resize_mode)
1739 case E_POINTER_RESIZE_TL:
1740 case E_POINTER_RESIZE_T:
1741 case E_POINTER_RESIZE_TR:
1742 y += ec->mouse.last_down[ec->moveinfo.down.button - 1].my -
1743 ec->mouse.current.my;
1745 case E_POINTER_RESIZE_BL:
1746 case E_POINTER_RESIZE_B:
1747 case E_POINTER_RESIZE_BR:
1748 y += ec->mouse.current.my - ec->mouse.last_down[ec->moveinfo.down.button - 1].my;
1753 x = E_CLAMP(x, 1, x);
1754 y = E_CLAMP(y, 1, y);
1755 ec->comp_data->shell.configure_send(ec->comp_data->shell.surface,
1756 e_comp_wl->resize.edges,
1759 else if ((!ec->fullscreen) && (!ec->maximized) &&
1760 (!ec->comp_data->maximize_pre))
1761 _e_comp_wl_configure_send(ec, 1, 1);
1763 if (ec->comp_data->sub.below_obj)
1764 evas_object_resize(ec->comp_data->sub.below_obj, ec->w, ec->h);
1768 _e_comp_wl_evas_cb_state_update(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1770 E_Client *ec = data;
1772 if (e_object_is_del(E_OBJECT(ec))) return;
1774 /* check for wayland pixmap */
1776 if (ec->comp_data->shell.configure_send)
1777 _e_comp_wl_configure_send(ec, 0, 0);
1778 ec->comp_data->maximize_pre = 0;
1782 _e_comp_wl_evas_cb_maximize_pre(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1784 E_Client *ec = data;
1786 ec->comp_data->maximize_pre = 1;
1790 _e_comp_wl_evas_cb_delete_request(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1794 if (!(ec = data)) return;
1796 e_comp_ignore_win_del(E_PIXMAP_TYPE_WL, e_pixmap_window_get(ec->pixmap));
1798 e_object_del(E_OBJECT(ec));
1800 _e_comp_wl_focus_check();
1802 /* TODO: Delete request send ??
1803 * NB: No such animal wrt wayland */
1807 _e_comp_wl_evas_cb_kill_request(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1811 if (!(ec = data)) return;
1813 e_comp_ignore_win_del(E_PIXMAP_TYPE_WL, e_pixmap_window_get(ec->pixmap));
1816 if (ec->comp_data->reparented)
1817 e_client_comp_hidden_set(ec, EINA_TRUE);
1820 evas_object_pass_events_set(ec->frame, EINA_TRUE);
1821 if (ec->visible) evas_object_hide(ec->frame);
1822 if (!ec->internal) e_object_del(E_OBJECT(ec));
1824 _e_comp_wl_focus_check();
1828 _e_comp_wl_evas_cb_ping(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1832 if (!(ec = data)) return;
1833 if (!(ec->comp_data)) return;
1834 if (!(ec->comp_data->shell.ping)) return;
1835 if (!(ec->comp_data->shell.surface)) return;
1837 ec->comp_data->shell.ping(ec->comp_data->shell.surface);
1841 _e_comp_wl_evas_cb_color_set(void *data, Evas_Object *obj, void *event EINA_UNUSED)
1846 if (!(ec = data)) return;
1847 evas_object_color_get(obj, NULL, NULL, NULL, &a);
1848 if (ec->netwm.opacity == a) return;
1849 ec->netwm.opacity = a;
1850 ec->netwm.opacity_changed = EINA_TRUE;
1854 _e_comp_wl_buffer_reference_cb_destroy(struct wl_listener *listener, void *data)
1856 E_Comp_Wl_Buffer_Ref *ref;
1858 ref = container_of(listener, E_Comp_Wl_Buffer_Ref, destroy_listener);
1859 if ((E_Comp_Wl_Buffer *)data != ref->buffer) return;
1861 ref->destroy_listener_usable = EINA_FALSE;
1865 _e_comp_wl_buffer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
1867 E_Comp_Wl_Buffer *buffer;
1869 buffer = container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
1871 DBG("Wl Buffer Destroy: b %p owner '%s'(%p)",
1872 buffer, buffer->debug_info.owner_name, buffer->debug_info.owner_ptr);
1874 /* remove debug info */
1875 eina_stringshare_del(buffer->debug_info.owner_name);
1877 wl_signal_emit(&buffer->destroy_signal, buffer);
1879 if (buffer->destroy_listener.notify)
1881 wl_list_remove(&buffer->destroy_listener.link);
1882 buffer->destroy_listener.notify = NULL;
1889 _e_comp_wl_client_evas_init(E_Client *ec)
1891 if (!ec || !ec->comp_data) return;
1892 if (ec->comp_data->evas_init) return;
1894 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_comp_wl_evas_cb_show, ec);
1895 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_comp_wl_evas_cb_hide, ec);
1896 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_comp_wl_evas_cb_move, ec);
1897 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_comp_wl_evas_cb_restack, ec);
1900 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_IN, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_in, ec);
1901 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_OUT, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_out, ec);
1902 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_MOVE, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_move, ec);
1903 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_DOWN, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_down, ec);
1904 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_UP, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_up, ec);
1905 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_WHEEL, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_wheel, ec);
1907 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MULTI_DOWN, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_multi_down, ec);
1908 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MULTI_UP, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_multi_up, ec);
1909 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MULTI_MOVE, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_multi_move, ec);
1911 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_FOCUS_IN, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_focus_in, ec);
1912 evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_FOCUS_OUT, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_focus_out, ec);
1916 evas_object_smart_callback_add(ec->frame, "client_resize", _e_comp_wl_evas_cb_resize, ec);
1917 evas_object_smart_callback_add(ec->frame, "maximize_done", _e_comp_wl_evas_cb_state_update, ec);
1918 evas_object_smart_callback_add(ec->frame, "unmaximize_done", _e_comp_wl_evas_cb_state_update, ec);
1919 evas_object_smart_callback_add(ec->frame, "maximize_pre", _e_comp_wl_evas_cb_maximize_pre, ec);
1920 evas_object_smart_callback_add(ec->frame, "unmaximize_pre", _e_comp_wl_evas_cb_maximize_pre, ec);
1921 evas_object_smart_callback_add(ec->frame, "fullscreen", _e_comp_wl_evas_cb_state_update, ec);
1922 evas_object_smart_callback_add(ec->frame, "unfullscreen", _e_comp_wl_evas_cb_state_update, ec);
1925 /* setup delete/kill callbacks */
1926 evas_object_smart_callback_add(ec->frame, "delete_request", _e_comp_wl_evas_cb_delete_request, ec);
1927 evas_object_smart_callback_add(ec->frame, "kill_request", _e_comp_wl_evas_cb_kill_request, ec);
1929 /* setup ping callback */
1930 evas_object_smart_callback_add(ec->frame, "ping", _e_comp_wl_evas_cb_ping, ec);
1931 evas_object_smart_callback_add(ec->frame, "color_set", _e_comp_wl_evas_cb_color_set, ec);
1933 ec->comp_data->evas_init = EINA_TRUE;
1937 _e_comp_wl_cb_randr_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1941 E_Comp_Screen *e_comp_screen;
1942 unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
1944 if (!e_comp) return ECORE_CALLBACK_RENEW;
1945 if (!e_comp->e_comp_screen) return ECORE_CALLBACK_RENEW;
1946 e_comp_screen = e_comp->e_comp_screen;
1948 EINA_LIST_FOREACH(e_comp_screen->outputs, l, eout)
1950 if (!eout->config.enabled)
1952 e_comp_wl_output_remove(eout->id);
1956 switch (eout->config.rotation)
1959 transform = WL_OUTPUT_TRANSFORM_90;
1962 transform = WL_OUTPUT_TRANSFORM_180;
1965 transform = WL_OUTPUT_TRANSFORM_270;
1969 transform = WL_OUTPUT_TRANSFORM_NORMAL;
1973 if (!e_comp_wl_output_init(eout->id, eout->info.name,
1975 eout->config.geom.x, eout->config.geom.y,
1976 eout->config.geom.w, eout->config.geom.h,
1977 eout->info.size.w, eout->info.size.h,
1978 eout->config.mode.refresh, 0, transform))
1979 ERR("Could not initialize screen %s", eout->info.name);
1982 return ECORE_CALLBACK_RENEW;
1986 _e_comp_wl_cb_comp_object_add(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Comp_Object *ev)
1990 /* try to get the client from the object */
1991 if (!(ec = e_comp_object_client_get(ev->comp_object)))
1992 return ECORE_CALLBACK_RENEW;
1994 /* check for client being deleted */
1995 if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_RENEW;
1997 /* check for wayland pixmap */
1998 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL)
1999 return ECORE_CALLBACK_RENEW;
2001 /* if we have not setup evas callbacks for this client, do it */
2002 if (!ec->comp_data->evas_init) _e_comp_wl_client_evas_init(ec);
2004 return ECORE_CALLBACK_RENEW;
2008 _e_comp_wl_cb_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
2010 e_comp_wl->ptr.x = wl_fixed_from_int(ev->x);
2011 e_comp_wl->ptr.y = wl_fixed_from_int(ev->y);
2012 if (e_comp_wl->selection.target &&
2015 struct wl_resource *res;
2018 res = e_comp_wl_data_find_for_client(wl_resource_get_client(e_comp_wl->selection.target->comp_data->surface));
2019 EINA_SAFETY_ON_NULL_RETURN_VAL(res, ECORE_CALLBACK_RENEW);
2021 x = ev->x - e_comp_wl->selection.target->client.x;
2022 y = ev->y - e_comp_wl->selection.target->client.y;
2024 if (e_comp_wl->drag_client)
2025 evas_object_move(e_comp_wl->drag_client->frame, ev->x, ev->y);
2027 wl_data_device_send_motion(res, ev->timestamp, wl_fixed_from_int(x), wl_fixed_from_int(y));
2030 return ECORE_CALLBACK_RENEW;
2034 _e_comp_wl_cb_mouse_button_cancel(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2036 if (e_comp_wl->ptr.ec)
2037 _e_comp_wl_send_touch_cancel(e_comp_wl->ptr.ec);
2039 return ECORE_CALLBACK_PASS_ON;
2043 _e_comp_wl_cb_zone_display_state_change(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Zone_Display_State_Change *ev EINA_UNUSED)
2045 if (e_comp_wl->ptr.ec && need_send_released)
2047 _e_comp_wl_send_touch_cancel(e_comp_wl->ptr.ec);
2049 need_send_released = EINA_FALSE;
2052 return ECORE_CALLBACK_PASS_ON;
2056 _e_comp_wl_cb_client_rot_change_begin(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Rotation_Change_Begin *ev)
2058 E_Client *ec = ev->ec;
2059 E_Comp_Wl_Buffer_Viewport *vp;
2061 if (!ec) return ECORE_CALLBACK_PASS_ON;
2062 if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
2063 if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
2064 if (ec->comp_data->sub.data) return ECORE_CALLBACK_PASS_ON;
2065 if (ec->e.state.rot.ang.next < 0) return ECORE_CALLBACK_PASS_ON;
2067 vp = &ec->comp_data->scaler.buffer_viewport;
2068 vp->wait_for_transform_change = ((360 + ec->e.state.rot.ang.next - ec->e.state.rot.ang.curr) % 360) / 90;
2070 DBG("ec(%p) wait_for_transform_change(%d)", ec, vp->wait_for_transform_change);
2072 return ECORE_CALLBACK_PASS_ON;
2076 _e_comp_wl_cb_client_rot_change_cancel(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Rotation_Change_Cancel *ev)
2078 E_Client *ec = ev->ec;
2079 E_Comp_Wl_Buffer_Viewport *vp;
2081 if (!ec) return ECORE_CALLBACK_PASS_ON;
2082 if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
2083 if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
2084 if (ec->comp_data->sub.data) return ECORE_CALLBACK_PASS_ON;
2086 vp = &ec->comp_data->scaler.buffer_viewport;
2087 vp->wait_for_transform_change = 0;
2089 DBG("ec(%p) wait_for_transform_change(%d) reset", ec, vp->wait_for_transform_change);
2091 return ECORE_CALLBACK_PASS_ON;
2095 _e_comp_wl_cb_client_rot_change_end(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Rotation_Change_End *ev EINA_UNUSED)
2097 E_Client *focused_ec;
2100 focused_ec = e_client_focused_get();
2101 if (!focused_ec) return ECORE_CALLBACK_PASS_ON;
2103 rotation = focused_ec->e.state.rot.ang.curr;
2104 if (e_comp->pointer->rotation != rotation)
2105 e_pointer_rotation_set(e_comp->pointer, rotation);
2107 return ECORE_CALLBACK_PASS_ON;
2111 _e_comp_wl_subsurface_restack(E_Client *ec)
2113 E_Client *subc, *temp;
2116 if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
2119 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2121 if (!subc || !subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2122 subc->comp_data->sub.restacking = EINA_TRUE;
2123 evas_object_stack_above(subc->frame, temp->frame);
2124 subc->comp_data->sub.restacking = EINA_FALSE;
2129 EINA_LIST_REVERSE_FOREACH(ec->comp_data->sub.below_list, l, subc)
2131 if (!subc || !subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2132 subc->comp_data->sub.restacking = EINA_TRUE;
2133 evas_object_stack_below(subc->frame, temp->frame);
2134 subc->comp_data->sub.restacking = EINA_FALSE;
2138 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2139 _e_comp_wl_subsurface_restack(subc);
2141 EINA_LIST_REVERSE_FOREACH(ec->comp_data->sub.below_list, l, subc)
2142 _e_comp_wl_subsurface_restack(subc);
2146 _e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec)
2148 E_Client *bottom = ec;
2150 if (!ec->comp_data->sub.below_obj)
2155 short layer = evas_object_layer_get(bottom->frame);
2157 if (evas_object_layer_get(ec->comp_data->sub.below_obj) != layer)
2158 evas_object_layer_set(ec->comp_data->sub.below_obj, layer);
2160 evas_object_stack_below(ec->comp_data->sub.below_obj, bottom->frame);
2161 bottom = eina_list_nth(bottom->comp_data->sub.below_list, 0);
2166 _e_comp_wl_subsurface_show(E_Client *ec)
2171 if (!ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
2173 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2175 if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2177 if (e_pixmap_resource_get(subc->pixmap) && !subc->comp_data->mapped)
2179 subc->visible = EINA_TRUE;
2180 evas_object_show(subc->frame);
2181 subc->comp_data->mapped = 1;
2183 _e_comp_wl_subsurface_show(subc);
2186 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
2188 if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2190 if (e_pixmap_resource_get(subc->pixmap) && !subc->comp_data->mapped)
2192 subc->visible = EINA_TRUE;
2193 evas_object_show(subc->frame);
2194 subc->comp_data->mapped = 1;
2196 _e_comp_wl_subsurface_show(subc);
2201 _e_comp_wl_subsurface_hide(E_Client *ec)
2206 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2208 if (!subc->comp_data || !subc->comp_data->sub.data) continue;
2210 if (!subc->comp_data->sub.data->stand_alone)
2212 if (subc->comp_data->mapped)
2214 subc->visible = EINA_FALSE;
2215 evas_object_hide(subc->frame);
2216 subc->comp_data->mapped = 0;
2218 _e_comp_wl_subsurface_hide(subc);
2222 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
2224 if (!subc->comp_data || !subc->comp_data->sub.data) continue;
2226 if (!subc->comp_data->sub.data->stand_alone)
2228 if (subc->comp_data->mapped)
2230 subc->visible = EINA_FALSE;
2231 evas_object_hide(subc->frame);
2232 subc->comp_data->mapped = 0;
2234 _e_comp_wl_subsurface_hide(subc);
2240 _e_comp_wl_subsurface_invisible_parent_get(E_Client *ec)
2242 E_Client *parent = NULL;
2244 if (!ec->comp_data || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data->sub.data)
2247 parent = ec->comp_data->sub.data->parent;
2250 /* in case of topmost */
2251 if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return NULL;
2253 if (!parent->comp_data->sub.data)
2254 return (!evas_object_visible_get(parent->frame)) ? parent : NULL;
2256 if (!evas_object_visible_get(parent->frame)){
2257 if (e_pixmap_resource_get(parent->pixmap))
2260 if (!parent->comp_data->sub.data->parent)
2264 parent = parent->comp_data->sub.data->parent;
2271 _e_comp_wl_subsurface_can_show(E_Client *ec)
2273 E_Comp_Wl_Subsurf_Data *sdata = ec->comp_data->sub.data;
2274 E_Client *invisible_parent;
2277 /* if it's not subsurface */
2281 invisible_parent = _e_comp_wl_subsurface_invisible_parent_get(ec);
2282 topmost = e_comp_wl_topmost_parent_get(ec);
2284 /* if topmost is composited by compositor && if there is a invisible parent */
2285 if (topmost->redirected && invisible_parent)
2292 _e_comp_wl_surface_subsurface_order_commit(E_Client *ec)
2294 E_Client *subc, *epc;
2296 Eina_Bool need_restack = EINA_FALSE;
2298 if (!ec->comp_data) return EINA_FALSE;
2300 if (ec->comp_data->sub.data && (epc = ec->comp_data->sub.data->parent))
2301 if (epc->comp_data->sub.list_changed)
2302 need_restack = _e_comp_wl_surface_subsurface_order_commit(epc);
2304 if (!ec->comp_data->sub.list_changed) return (EINA_FALSE | need_restack);
2305 ec->comp_data->sub.list_changed = EINA_FALSE;
2307 /* TODO: need to check more complicated subsurface tree */
2308 EINA_LIST_FOREACH(ec->comp_data->sub.list_pending, l, subc)
2310 ec->comp_data->sub.list = eina_list_remove(ec->comp_data->sub.list, subc);
2311 ec->comp_data->sub.list = eina_list_append(ec->comp_data->sub.list, subc);
2313 _e_comp_wl_surface_subsurface_order_commit(subc);
2316 EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
2318 ec->comp_data->sub.below_list = eina_list_remove(ec->comp_data->sub.below_list, subc);
2319 ec->comp_data->sub.below_list = eina_list_append(ec->comp_data->sub.below_list, subc);
2321 _e_comp_wl_surface_subsurface_order_commit(subc);
2328 _e_comp_wl_surface_state_size_update(E_Client *ec, E_Comp_Wl_Surface_State *state)
2330 Eina_Rectangle *window;
2332 if (!e_pixmap_size_get(ec->pixmap, &state->bw, &state->bh)) return;
2333 if (e_comp_object_frame_exists(ec->frame)) return;
2334 window = &ec->comp_data->shell.window;
2335 if ((!ec->borderless) && /* FIXME temporarily added this check code
2336 * to prevent updating E_Client's size by frame */
2337 (window->x || window->y || window->w || window->h))
2339 e_comp_object_frame_geometry_set(ec->frame,
2341 (window->x + window->w) - state->bw,
2343 (window->y + window->h) - state->bh);
2346 e_comp_object_frame_geometry_set(ec->frame, 0, 0, 0, 0);
2350 _e_comp_wl_surface_state_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
2352 E_Comp_Wl_Surface_State *state;
2355 container_of(listener, E_Comp_Wl_Surface_State, buffer_destroy_listener);
2356 state->buffer = NULL;
2360 _e_comp_wl_surface_state_init(E_Comp_Wl_Surface_State *state, int w, int h)
2362 state->new_attach = EINA_FALSE;
2363 state->buffer = NULL;
2364 state->buffer_destroy_listener.notify =
2365 _e_comp_wl_surface_state_cb_buffer_destroy;
2366 state->sx = state->sy = 0;
2368 state->input = eina_tiler_new(w, h);
2369 eina_tiler_tile_size_set(state->input, 1, 1);
2371 state->opaque = eina_tiler_new(w, h);
2372 eina_tiler_tile_size_set(state->opaque, 1, 1);
2374 state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
2375 state->buffer_viewport.buffer.scale = 1;
2376 state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
2377 state->buffer_viewport.surface.width = -1;
2378 state->buffer_viewport.changed = 0;
2382 _e_comp_wl_surface_state_finish(E_Comp_Wl_Surface_State *state)
2384 struct wl_resource *cb;
2385 Eina_Rectangle *dmg;
2387 EINA_LIST_FREE(state->frames, cb)
2388 wl_resource_destroy(cb);
2390 EINA_LIST_FREE(state->damages, dmg)
2391 eina_rectangle_free(dmg);
2393 EINA_LIST_FREE(state->buffer_damages, dmg)
2394 eina_rectangle_free(dmg);
2396 if (state->opaque) eina_tiler_free(state->opaque);
2397 state->opaque = NULL;
2399 if (state->input) eina_tiler_free(state->input);
2400 state->input = NULL;
2402 if (state->buffer) wl_list_remove(&state->buffer_destroy_listener.link);
2403 state->buffer = NULL;
2407 _e_comp_wl_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buffer *buffer)
2409 if (state->buffer == buffer) return;
2411 wl_list_remove(&state->buffer_destroy_listener.link);
2412 state->buffer = buffer;
2414 wl_signal_add(&state->buffer->destroy_signal,
2415 &state->buffer_destroy_listener);
2419 _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
2421 Eina_Rectangle *dmg;
2422 Eina_Bool placed = EINA_TRUE;
2425 E_Comp_Wl_Buffer *buffer;
2426 struct wl_resource *cb;
2428 E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
2432 if ((ec->internal) ||
2433 (ec->comp_data->shell.surface && state->new_attach))
2437 e_comp->new_clients++;
2438 e_client_unignore(ec);
2442 if (vp->buffer.transform != state->buffer_viewport.buffer.transform)
2444 int transform_change = (4 + state->buffer_viewport.buffer.transform - vp->buffer.transform) & 0x3;
2446 /* when buffer is transformed, we have to apply the new evas-map */
2447 state->buffer_viewport.changed = EINA_TRUE;
2449 ELOGF("TRANSFORM", "buffer_transform changed: old(%d) new(%d)",
2451 vp->buffer.transform, state->buffer_viewport.buffer.transform);
2453 if (transform_change == vp->wait_for_transform_change)
2454 vp->wait_for_transform_change = 0;
2456 if (e_comp_is_on_overlay(ec)) e_comp_hwc_end(__FUNCTION__);
2459 ec->comp_data->scaler.buffer_viewport = state->buffer_viewport;
2461 if (state->new_attach)
2462 e_comp_wl_surface_attach(ec, state->buffer);
2464 /* emit a apply_viewport signal when the information of viewport and buffer is ready */
2465 wl_signal_emit(&ec->comp_data->apply_viewport_signal,
2466 &ec->comp_data->surface);
2468 _e_comp_wl_surface_state_buffer_set(state, NULL);
2470 if ((state->new_attach) ||
2471 (state->buffer_viewport.changed))
2473 _e_comp_wl_surface_state_size_update(ec, state);
2474 e_comp_wl_map_size_cal_from_viewport(ec);
2476 if (ec->changes.pos)
2478 e_comp_object_frame_xy_unadjust(ec->frame,
2488 if (ec->new_client) placed = ec->placed;
2490 if (!ec->lock_client_size)
2495 ec->client.w = state->bw;
2496 ec->client.h = state->bh;
2498 e_comp_object_frame_wh_adjust(ec->frame,
2499 ec->client.w, ec->client.h,
2502 if ((w != ec->w) || (h != ec->h))
2504 ec->changes.size = 1;
2510 /* map or unmap ec */
2511 if (!e_pixmap_usable_get(ec->pixmap))
2514 if (ec->comp_data->mapped)
2516 if ((ec->comp_data->shell.surface) &&
2517 (ec->comp_data->shell.unmap))
2519 ELOGF("COMP", "Try to unmap. Call shell.unmap.", ec->pixmap, ec);
2520 ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
2522 else if ((ec->internal) ||
2523 (ec->comp_data->sub.data) ||
2524 (ec == e_comp_wl->drag_client))
2526 ELOGF("COMP", "Try to unmap. Hide window. internal:%d, sub:%p, drag:%d",
2527 ec->pixmap, ec, ec->internal, ec->comp_data->sub.data, (ec == e_comp_wl->drag_client));
2528 ec->visible = EINA_FALSE;
2529 evas_object_hide(ec->frame);
2530 ec->comp_data->mapped = 0;
2534 if ((ec->comp_data->sub.below_obj) &&
2535 (evas_object_visible_get(ec->comp_data->sub.below_obj)))
2537 evas_object_hide(ec->comp_data->sub.below_obj);
2543 if (!ec->comp_data->mapped)
2545 if ((ec->comp_data->shell.surface) &&
2546 (ec->comp_data->shell.map))
2548 ELOGF("COMP", "Try to map. Call shell.map.", ec->pixmap, ec);
2549 ec->comp_data->shell.map(ec->comp_data->shell.surface);
2551 else if ((ec->internal) ||
2552 (_e_comp_wl_subsurface_can_show(ec)) ||
2553 (ec == e_comp_wl->drag_client))
2555 ELOGF("COMP", "Try to map. Show window. internal:%d, drag:%d",
2556 ec->pixmap, ec, ec->internal, (ec == e_comp_wl->drag_client));
2557 ec->visible = EINA_TRUE;
2559 evas_object_show(ec->frame);
2560 ec->comp_data->mapped = 1;
2564 if ((ec->comp_data->sub.below_obj) &&
2565 (!evas_object_visible_get(ec->comp_data->sub.below_obj)) &&
2566 (evas_object_visible_get(ec->frame)))
2568 evas_object_show(ec->comp_data->sub.below_obj);
2572 if ((state->new_attach) ||
2573 (state->buffer_viewport.changed))
2575 if ((ec->comp_data->shell.surface) &&
2576 (ec->comp_data->shell.configure))
2578 ec->comp_data->shell.configure(ec->comp_data->shell.surface,
2584 if ((e_comp_wl->drag) &&
2585 (e_comp_wl->drag_client) &&
2586 (e_comp_wl->drag_client == ec))
2588 e_comp_wl->drag->dx -= state->sx;
2589 e_comp_wl->drag->dy -= state->sy;
2591 e_drag_move(e_comp_wl->drag,
2592 e_comp_wl->drag->x + state->sx,
2593 e_comp_wl->drag->y + state->sy);
2595 e_drag_resize(e_comp_wl->drag,
2596 state->bw, state->bh);
2600 e_client_util_move_resize_without_frame(ec, x, y, ec->w, ec->h);
2606 ec->placed = placed;
2607 ec->want_focus |= ec->icccm.accepts_focus && (!ec->override);
2611 if (ec->comp_data->scaler.buffer_viewport.changed)
2612 e_comp_wl_map_apply(ec);
2614 /* resize transform object */
2615 if (ec->transformed)
2616 e_client_transform_update(ec);
2620 state->new_attach = EINA_FALSE;
2622 EINA_LIST_FOREACH_SAFE(ec->comp_data->frames, l, ll, cb)
2624 wl_callback_send_done(cb, ecore_time_unix_get() * 1000);
2625 wl_resource_destroy(cb);
2628 /* insert state frame callbacks into comp_data->frames
2629 * NB: This clears state->frames list */
2630 ec->comp_data->frames = eina_list_merge(ec->comp_data->frames,
2632 state->frames = NULL;
2634 buffer = e_pixmap_resource_get(ec->pixmap);
2636 /* put state damages into surface */
2639 /* FIXME: workaround for bad wayland egl driver which doesn't send damage request */
2640 if (!eina_list_count(state->damages) && !eina_list_count(state->buffer_damages))
2642 if ((ec->comp_data->buffer_ref.buffer) &&
2643 ((ec->comp_data->buffer_ref.buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE) ||
2644 (ec->comp_data->buffer_ref.buffer->type == E_COMP_WL_BUFFER_TYPE_TBM)))
2646 e_comp_object_damage(ec->frame,
2648 ec->comp_data->buffer_ref.buffer->w,
2649 ec->comp_data->buffer_ref.buffer->h);
2654 Eina_List *damages = NULL;
2656 if (eina_list_count(state->buffer_damages))
2658 EINA_LIST_FREE(state->buffer_damages, dmg)
2661 e_comp_wl_rect_convert_inverse(buffer->w, buffer->h,
2662 e_comp_wl_output_buffer_transform_get(ec),
2664 dmg->x, dmg->y, dmg->w, dmg->h,
2665 &dmg->x, &dmg->y, &dmg->w, &dmg->h);
2666 damages = eina_list_append(damages, dmg);
2670 EINA_LIST_FREE(state->damages, dmg)
2671 damages = eina_list_append(damages, dmg);
2673 EINA_LIST_FREE(damages, dmg)
2675 /* not creating damage for ec that shows a underlay video */
2676 if (state->buffer_viewport.changed ||
2677 !e_comp->wl_comp_data->available_hw_accel.underlay ||
2678 !buffer || buffer->type != E_COMP_WL_BUFFER_TYPE_VIDEO)
2679 e_comp_object_damage(ec->frame, dmg->x, dmg->y, dmg->w, dmg->h);
2681 eina_rectangle_free(dmg);
2686 /* put state opaque into surface */
2687 e_pixmap_image_opaque_set(ec->pixmap, 0, 0, 0, 0);
2690 Eina_Rectangle *rect;
2693 itr = eina_tiler_iterator_new(state->opaque);
2694 EINA_ITERATOR_FOREACH(itr, rect)
2698 EINA_RECTANGLE_SET(&r, rect->x, rect->y, rect->w, rect->h);
2699 E_RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h, 0, 0, state->bw, state->bh);
2700 e_pixmap_image_opaque_set(ec->pixmap, r.x, r.y, r.w, r.h);
2704 eina_iterator_free(itr);
2707 /* put state input into surface */
2708 if ((state->input) &&
2709 (!eina_tiler_empty(state->input)))
2711 Eina_Tiler *src, *tmp;
2713 tmp = eina_tiler_new(state->bw, state->bh);
2714 eina_tiler_tile_size_set(tmp, 1, 1);
2715 eina_tiler_rect_add(tmp,
2716 &(Eina_Rectangle){0, 0, state->bw, state->bh});
2717 if ((src = eina_tiler_intersection(state->input, tmp)))
2719 Eina_Rectangle *rect;
2722 e_comp_object_input_objs_del(ec->frame);
2723 itr = eina_tiler_iterator_new(src);
2724 EINA_ITERATOR_FOREACH(itr, rect)
2726 e_comp_object_input_area_set(ec->frame,
2731 eina_iterator_free(itr);
2732 eina_tiler_free(src);
2735 e_comp_object_input_area_set(ec->frame, 0, 0, ec->w, ec->h);
2737 eina_tiler_free(tmp);
2739 /* clear input tiler */
2740 eina_tiler_clear(state->input);
2743 _e_comp_wl_subsurface_check_below_bg_rectangle(ec);
2746 (buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO)) &&
2747 (e_comp->wl_comp_data->available_hw_accel.underlay))
2749 e_pixmap_image_clear(ec->pixmap, 1);
2752 state->buffer_viewport.changed = 0;
2755 ec->exp_iconify.buffer_flush &&
2756 e_policy_visibility_client_is_iconic(ec))
2758 e_pixmap_buffer_clear(ec->pixmap, EINA_FALSE);
2763 _e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2765 DBG("Surface Cb Destroy: %d", wl_resource_get_id(resource));
2766 wl_resource_destroy(resource);
2770 _e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
2773 E_Comp_Wl_Buffer *buffer = NULL;
2775 if (!(ec = wl_resource_get_user_data(resource))) return;
2776 if (e_object_is_del(E_OBJECT(ec))) return;
2778 if (buffer_resource)
2780 if (!(buffer = e_comp_wl_buffer_get(buffer_resource, ec)))
2782 ERR("Could not get buffer from resource");
2783 wl_client_post_no_memory(client);
2788 if (!ec->comp_data->mapped)
2790 if (ec->comp_data->shell.surface &&
2791 !ec->internal && !ec->comp_data->sub.data && !ec->remote_surface.provider)
2793 ELOGF("COMP", "Current unmapped. ATTACH buffer:%p", ec->pixmap, ec, buffer);
2797 _e_comp_wl_surface_state_buffer_set(&ec->comp_data->pending, buffer);
2799 ec->comp_data->pending.sx = sx;
2800 ec->comp_data->pending.sy = sy;
2801 ec->comp_data->pending.new_attach = EINA_TRUE;
2805 _e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
2808 Eina_Rectangle *dmg = NULL;
2810 if (!(ec = wl_resource_get_user_data(resource))) return;
2811 if (e_object_is_del(E_OBJECT(ec))) return;
2813 if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
2815 ec->comp_data->pending.damages =
2816 eina_list_append(ec->comp_data->pending.damages, dmg);
2820 _e_comp_wl_frame_cb_destroy(struct wl_resource *resource)
2824 if (!(ec = wl_resource_get_user_data(resource))) return;
2825 if (e_object_is_del(E_OBJECT(ec)))
2827 if (!e_object_delay_del_ref_get(E_OBJECT(ec)))
2830 if (!ec->comp_data) return;
2832 if (ec->comp_data->frames)
2834 ec->comp_data->frames =
2835 eina_list_remove(ec->comp_data->frames, resource);
2838 if (ec->comp_data->pending.frames)
2840 ec->comp_data->pending.frames =
2841 eina_list_remove(ec->comp_data->pending.frames, resource);
2846 _e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback)
2849 struct wl_resource *res;
2851 if (!(ec = wl_resource_get_user_data(resource))) return;
2852 if (e_object_is_del(E_OBJECT(ec))) return;
2854 /* create frame callback */
2856 wl_resource_create(client, &wl_callback_interface, 1, callback)))
2858 wl_resource_post_no_memory(resource);
2862 wl_resource_set_implementation(res, NULL, ec, _e_comp_wl_frame_cb_destroy);
2864 ec->comp_data->pending.frames =
2865 eina_list_prepend(ec->comp_data->pending.frames, res);
2869 _e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
2873 if (!(ec = wl_resource_get_user_data(resource))) return;
2874 if (e_object_is_del(E_OBJECT(ec))) return;
2876 if (ec->comp_data->pending.opaque)
2877 eina_tiler_clear(ec->comp_data->pending.opaque);
2878 if (region_resource)
2882 if (!(tmp = wl_resource_get_user_data(region_resource)))
2885 eina_tiler_union(ec->comp_data->pending.opaque, tmp);
2887 if (!eina_tiler_empty(ec->comp_data->pending.opaque))
2891 ec->argb = EINA_FALSE;
2893 e_comp_object_alpha_set(ec->frame, EINA_FALSE);
2901 ec->argb = EINA_TRUE;
2903 e_comp_object_alpha_set(ec->frame, EINA_TRUE);
2909 _e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
2913 if (!(ec = wl_resource_get_user_data(resource))) return;
2914 if (e_object_is_del(E_OBJECT(ec))) return;
2916 if (ec->comp_data->pending.input)
2917 eina_tiler_clear(ec->comp_data->pending.input);
2918 if (region_resource)
2922 if (!(tmp = wl_resource_get_user_data(region_resource)))
2925 if (eina_tiler_empty(tmp))
2927 ELOGF("COMP", " |unset input rect", NULL, NULL);
2928 e_comp_object_input_objs_del(ec->frame);
2929 e_comp_object_input_area_set(ec->frame, -1, -1, 1, 1);
2932 eina_tiler_union(ec->comp_data->pending.input, tmp);
2936 eina_tiler_rect_add(ec->comp_data->pending.input,
2937 &(Eina_Rectangle){0, 0, ec->client.w, ec->client.h});
2942 _e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2944 E_Client *ec, *subc;
2947 if (!(ec = wl_resource_get_user_data(resource))) return;
2948 if (e_object_is_del(E_OBJECT(ec))) return;
2950 if (!ec->comp_data->mapped)
2952 if (ec->comp_data->shell.surface &&
2953 !ec->internal && !ec->comp_data->sub.data && !ec->remote_surface.provider)
2955 ELOGF("COMP", "Current unmapped. COMMIT. pixmap_usable:%d", ec->pixmap, ec, e_pixmap_usable_get(ec->pixmap));
2959 if (ec->comp_data->need_commit_extern_parent)
2961 ec->comp_data->need_commit_extern_parent = 0;
2962 _e_comp_wl_extern_parent_commit(ec);
2965 if (e_comp_wl_remote_surface_commit(ec)) return;
2966 if (e_comp_wl_subsurface_commit(ec)) return;
2968 e_comp_wl_surface_commit(ec);
2970 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2973 _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
2976 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
2979 _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
2984 _e_comp_wl_surface_cb_buffer_transform_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t transform)
2988 if (!(ec = wl_resource_get_user_data(resource))) return;
2989 if (e_object_is_del(E_OBJECT(ec))) return;
2991 if (transform < 0 || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270)
2993 wl_resource_post_error(resource,
2994 WL_SURFACE_ERROR_INVALID_TRANSFORM,
2995 "buffer transform must be a valid transform "
2996 "('%d' specified)", transform);
3000 ec->comp_data->pending.buffer_viewport.buffer.transform = transform;
3001 ec->comp_data->pending.buffer_viewport.changed = 1;
3005 _e_comp_wl_surface_cb_buffer_scale_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t scale)
3009 if (!(ec = wl_resource_get_user_data(resource))) return;
3010 if (e_object_is_del(E_OBJECT(ec))) return;
3014 wl_resource_post_error(resource,
3015 WL_SURFACE_ERROR_INVALID_SCALE,
3016 "buffer scale must be at least one "
3017 "('%d' specified)", scale);
3021 ec->comp_data->pending.buffer_viewport.buffer.scale = scale;
3022 ec->comp_data->pending.buffer_viewport.changed = 1;
3026 _e_comp_wl_surface_cb_damage_buffer(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
3029 Eina_Rectangle *dmg = NULL;
3031 if (!(ec = wl_resource_get_user_data(resource))) return;
3032 if (e_object_is_del(E_OBJECT(ec))) return;
3034 if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
3036 ec->comp_data->pending.buffer_damages =
3037 eina_list_append(ec->comp_data->pending.buffer_damages, dmg);
3040 static const struct wl_surface_interface _e_surface_interface =
3042 _e_comp_wl_surface_cb_destroy,
3043 _e_comp_wl_surface_cb_attach,
3044 _e_comp_wl_surface_cb_damage,
3045 _e_comp_wl_surface_cb_frame,
3046 _e_comp_wl_surface_cb_opaque_region_set,
3047 _e_comp_wl_surface_cb_input_region_set,
3048 _e_comp_wl_surface_cb_commit,
3049 _e_comp_wl_surface_cb_buffer_transform_set,
3050 _e_comp_wl_surface_cb_buffer_scale_set,
3051 _e_comp_wl_surface_cb_damage_buffer,
3055 _e_comp_wl_surface_render_stop(E_Client *ec)
3057 /* FIXME: this may be fine after e_pixmap can create textures for wl clients? */
3058 //if ((!ec->internal) && (!e_comp_gl_get()))
3061 /* check if internal animation is running */
3062 if (e_comp_object_is_animating(ec->frame)) return;
3063 /* check if external animation is running */
3064 if (evas_object_data_get(ec->frame, "effect_running")) return;
3066 evas_object_hide(ec->frame);
3070 _e_comp_wl_surface_destroy(struct wl_resource *resource)
3073 struct wl_resource *res;
3076 if (!(ec = wl_resource_get_user_data(resource))) return;
3078 if (ec == e_client_focused_get())
3080 EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
3082 if (wl_resource_get_client(res) ==
3083 wl_resource_get_client(ec->comp_data->surface))
3084 e_comp_wl->kbd.focused =
3085 eina_list_remove_list(e_comp_wl->kbd.focused, l);
3089 ec->comp_data->surface = NULL;
3090 ec->comp_data->wl_surface = NULL;
3091 e_pixmap_win_id_del(ec->pixmap);
3093 _e_comp_wl_surface_render_stop(ec);
3094 e_object_del(E_OBJECT(ec));
3098 _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
3100 struct wl_resource *res;
3101 E_Pixmap *ep = NULL;
3102 E_Client *ec = NULL;
3106 DBG("Compositor Cb Surface Create: %d", id);
3108 TRACE_DS_BEGIN(COMP_WL:SURFACE CREATE CB);
3110 /* try to create an internal surface */
3111 if (!(res = wl_resource_create(client, &wl_surface_interface,
3112 wl_resource_get_version(resource), id)))
3114 ERR("Could not create compositor surface");
3115 wl_client_post_no_memory(client);
3120 DBG("\tCreated Resource: %d", wl_resource_get_id(res));
3122 /* set implementation on resource */
3123 wl_resource_set_implementation(res, &_e_surface_interface, NULL,
3124 _e_comp_wl_surface_destroy);
3126 wl_client_get_credentials(client, &pid, NULL, NULL);
3127 if (pid == getpid())
3129 /* pixmap of internal win was supposed to be created at trap show */
3131 ec = e_pixmap_find_client(E_PIXMAP_TYPE_WL, (uintptr_t)id);
3135 if ((ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)res)))
3137 ERR("There is e_pixmap already, Delete old e_pixmap %p", ep);
3138 e_pixmap_win_id_del(ep);
3145 /* try to create new pixmap */
3146 if (!(ep = e_pixmap_new(E_PIXMAP_TYPE_WL, res)))
3148 ERR("Could not create new pixmap");
3149 wl_resource_destroy(res);
3150 wl_client_post_no_memory(client);
3155 E_Comp_Wl_Client_Data *cdata = e_pixmap_cdata_get(ep);
3157 cdata->wl_surface = res;
3159 DBG("\tUsing Pixmap: %p", ep);
3161 if (!(ec = _e_comp_wl_client_usable_get(pid, ep)))
3163 ec = e_client_new(ep, 0, internal);
3169 ec->netwm.pid = pid;
3171 e_comp->new_clients--;
3173 if ((!ec->client.w) && (ec->client.h))
3174 ec->client.w = ec->client.h = 1;
3175 ec->comp_data->surface = res;
3178 /* set reference to pixmap so we can fetch it later */
3179 DBG("\tUsing Client: %p", ec);
3180 wl_resource_set_user_data(res, ec);
3182 /* emit surface create signal */
3183 wl_signal_emit(&e_comp_wl->signals.surface.create, res);
3189 _e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3191 DBG("Region Destroy: %d", wl_resource_get_id(resource));
3192 wl_resource_destroy(resource);
3196 _e_comp_wl_region_cb_add(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
3200 DBG("Region Add: %d", wl_resource_get_id(resource));
3201 DBG("\tGeom: %d %d %d %d", x, y, w, h);
3203 /* get the tiler from the resource */
3204 if ((tiler = wl_resource_get_user_data(resource)))
3205 eina_tiler_rect_add(tiler, &(Eina_Rectangle){x, y, w, h});
3209 _e_comp_wl_region_cb_subtract(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
3213 DBG("Region Subtract: %d", wl_resource_get_id(resource));
3214 DBG("\tGeom: %d %d %d %d", x, y, w, h);
3216 /* get the tiler from the resource */
3217 if ((tiler = wl_resource_get_user_data(resource)))
3218 eina_tiler_rect_del(tiler, &(Eina_Rectangle){x, y, w, h});
3221 static const struct wl_region_interface _e_region_interface =
3223 _e_comp_wl_region_cb_destroy,
3224 _e_comp_wl_region_cb_add,
3225 _e_comp_wl_region_cb_subtract
3229 _e_comp_wl_compositor_cb_region_destroy(struct wl_resource *resource)
3233 DBG("Compositor Region Destroy: %d", wl_resource_get_id(resource));
3235 /* try to get the tiler from the region resource */
3236 if ((tiler = wl_resource_get_user_data(resource)))
3237 eina_tiler_free(tiler);
3241 _e_comp_wl_compositor_cb_region_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
3244 struct wl_resource *res;
3246 DBG("Region Create: %d", wl_resource_get_id(resource));
3248 /* try to create new tiler */
3249 if (!(tiler = eina_tiler_new(e_comp->w, e_comp->h)))
3251 ERR("Could not create Eina_Tiler");
3252 wl_resource_post_no_memory(resource);
3256 /* set tiler size */
3257 eina_tiler_tile_size_set(tiler, 1, 1);
3259 if (!(res = wl_resource_create(client, &wl_region_interface, 1, id)))
3261 ERR("\tFailed to create region resource");
3262 eina_tiler_free(tiler);
3263 wl_resource_post_no_memory(resource);
3267 wl_resource_set_implementation(res, &_e_region_interface, tiler,
3268 _e_comp_wl_compositor_cb_region_destroy);
3271 static const struct wl_compositor_interface _e_comp_interface =
3273 _e_comp_wl_compositor_cb_surface_create,
3274 _e_comp_wl_compositor_cb_region_create
3278 _e_comp_wl_pname_get(pid_t pid, char *name, int size)
3283 char proc[512], pname[512];
3286 snprintf(proc, 512,"/proc/%d/cmdline", pid);
3288 h = fopen(proc, "r");
3291 len = fread(pname, sizeof(char), 512, h);
3293 pname[len - 1] = '\0';
3295 strncpy(pname, "NO NAME", sizeof(pname));
3299 strncpy(name, pname, size);
3303 _e_comp_wl_pname_print(pid_t pid)
3306 char proc[512], pname[512];
3309 snprintf(proc, 512,"/proc/%d/cmdline", pid);
3311 h = fopen(proc, "r");
3314 len = fread(pname, sizeof(char), 512, h);
3316 pname[len - 1] = '\0';
3318 strncpy(pname, "NO NAME", sizeof(pname));
3322 ELOGF("COMP", " |%s", NULL, NULL, pname);
3327 _e_comp_wl_compositor_cb_unbind(struct wl_resource *res_comp)
3329 struct wl_client *client;
3334 client = wl_resource_get_client(res_comp);
3336 wl_client_get_credentials(client,
3342 "UNBIND |res_comp:0x%08x|client:0x%08x|%d|%d|%d",
3344 (unsigned int)res_comp,
3345 (unsigned int)client,
3349 if ((comp = wl_resource_get_user_data(res_comp)))
3352 E_Comp_Connected_Client_Info *cinfo;
3353 EINA_LIST_FOREACH(comp->connected_clients, l, cinfo)
3355 if (cinfo->pid == pid)
3362 eina_stringshare_del(cinfo->name);
3363 comp->connected_clients = eina_list_remove(comp->connected_clients, cinfo);
3370 _e_comp_wl_compositor_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
3372 struct wl_resource *res;
3378 wl_resource_create(client, &wl_compositor_interface,
3381 ERR("Could not create compositor resource: %m");
3382 wl_client_post_no_memory(client);
3386 wl_resource_set_implementation(res, &_e_comp_interface, e_comp, _e_comp_wl_compositor_cb_unbind);
3388 wl_client_get_credentials(client, &pid, &uid, &gid);
3391 "BIND |res_comp:0x%08x|client:0x%08x|%d|%d|%d",
3394 (unsigned int)client,
3397 _e_comp_wl_pname_print(pid);
3400 _e_comp_wl_pname_get(pid, name, sizeof(name));
3402 E_Comp_Connected_Client_Info *cinfo;
3403 cinfo = E_NEW(E_Comp_Connected_Client_Info, 1);
3406 cinfo->name = eina_stringshare_add(name);
3410 e_comp->connected_clients= eina_list_append(e_comp->connected_clients, cinfo);
3415 _e_comp_wl_subsurface_destroy_sdata(E_Client *ec)
3417 E_Comp_Wl_Subsurf_Data *sdata;
3419 if (!ec || !ec->comp_data || !ec->comp_data->sub.data) return;
3421 sdata = ec->comp_data->sub.data;
3424 /* remove this client from parents sub list */
3425 sdata->parent->comp_data->sub.list =
3426 eina_list_remove(sdata->parent->comp_data->sub.list, ec);
3427 sdata->parent->comp_data->sub.list_pending =
3428 eina_list_remove(sdata->parent->comp_data->sub.list_pending, ec);
3429 sdata->parent->comp_data->sub.below_list =
3430 eina_list_remove(sdata->parent->comp_data->sub.below_list, ec);
3431 sdata->parent->comp_data->sub.below_list_pending =
3432 eina_list_remove(sdata->parent->comp_data->sub.below_list_pending, ec);
3435 _e_comp_wl_surface_state_finish(&sdata->cached);
3436 e_comp_wl_buffer_reference(&sdata->cached_buffer_ref, NULL);
3438 /* the client is getting deleted, which means the pixmap will be getting
3439 * freed. We need to unset the surface user data */
3440 /* wl_resource_set_user_data(ec->comp_data->surface, NULL); */
3444 ec->comp_data->sub.data = NULL;
3448 _e_comp_wl_subsurface_destroy(struct wl_resource *resource)
3450 E_Client *ec = wl_resource_get_user_data(resource);
3452 if (!e_object_unref(E_OBJECT(ec))) return;
3453 if (e_object_is_del(E_OBJECT(ec))) return;
3455 _e_comp_wl_subsurface_destroy_sdata(ec);
3459 _e_comp_wl_subsurface_synchronized_get(E_Comp_Wl_Subsurf_Data *sdata)
3463 if (sdata->synchronized) return EINA_TRUE;
3464 if (!sdata->parent) return EINA_FALSE;
3465 sdata = sdata->parent->comp_data->sub.data;
3472 _e_comp_wl_subsurface_bg_evas_cb_resize(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3476 if (!(ec = data)) return;
3477 if (e_object_is_del(E_OBJECT(ec))) return;
3478 if (!ec->comp_data) return;
3480 if (ec->comp_data->sub.below_obj)
3481 evas_object_resize(ec->comp_data->sub.below_obj, ec->w, ec->h);
3485 _e_comp_wl_subsurface_check_below_bg_rectangle(E_Client *ec)
3489 if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3490 if (ec->comp_data->sub.below_obj) return;
3491 if (ec->comp_data->sub.data)
3493 E_Client *topmost = e_comp_wl_topmost_parent_get(ec);
3494 if (!topmost || e_object_is_del(E_OBJECT(topmost)) || !topmost->comp_data) return;
3495 if (topmost->comp_data->sub.data) return;
3496 if (topmost->comp_data->sub.below_obj) return;
3497 _e_comp_wl_subsurface_check_below_bg_rectangle(topmost);
3501 if (ec->argb) return;
3503 if (ec->comp_data->sub.below_list ||
3504 ec->comp_data->sub.below_list_pending ||
3505 e_comp_wl_video_subsurface_has(ec))
3507 ELOGF("COMP", " |bg_rectangle(%p) created", NULL, ec, ec->comp_data->sub.below_obj);
3509 /* create a bg rectangle if topmost window is 24 depth window */
3510 ec->comp_data->sub.below_obj = evas_object_rectangle_add(e_comp->evas);
3511 EINA_SAFETY_ON_NULL_RETURN(ec->comp_data->sub.below_obj);
3513 layer = evas_object_layer_get(ec->frame);
3514 evas_object_layer_set(ec->comp_data->sub.below_obj, layer);
3515 evas_object_render_op_set(ec->comp_data->sub.below_obj, EVAS_RENDER_COPY);
3517 /* It's more reasonable to use the transparent color instead of black because
3518 * we can show the alpha value of the 24 depth topmost window.
3520 evas_object_color_set(ec->comp_data->sub.below_obj, 0x00, 0x00, 0x00, 0x00);
3521 evas_object_move(ec->comp_data->sub.below_obj, ec->x, ec->y);
3522 evas_object_resize(ec->comp_data->sub.below_obj, ec->w, ec->h);
3523 evas_object_name_set(ec->comp_data->sub.below_obj, "below_bg_rectangle");
3525 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE,
3526 _e_comp_wl_subsurface_bg_evas_cb_resize, ec);
3528 /* set alpha only if SW path */
3529 e_comp_object_alpha_set(ec->frame, EINA_TRUE);
3531 /* force update for changing alpha value. If the native surface has been already
3532 * set before, changing alpha value can't be applied to egl image.
3534 e_comp_object_native_surface_set(ec->frame, EINA_FALSE);
3535 e_pixmap_image_refresh(ec->pixmap);
3536 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
3537 e_comp_object_dirty(ec->frame);
3538 e_comp_object_render(ec->frame);
3540 _e_comp_wl_subsurface_restack(ec);
3541 _e_comp_wl_subsurface_restack_bg_rectangle(ec);
3543 if (evas_object_visible_get(ec->frame))
3544 evas_object_show(ec->comp_data->sub.below_obj);
3549 _e_comp_wl_subsurface_commit_to_cache(E_Client *ec)
3551 E_Comp_Client_Data *cdata;
3552 E_Comp_Wl_Subsurf_Data *sdata;
3553 struct wl_resource *cb;
3556 Eina_Rectangle *rect;
3558 if (!(cdata = ec->comp_data)) return;
3559 if (!(sdata = cdata->sub.data)) return;
3561 DBG("Subsurface Commit to Cache");
3563 /* move pending damage to cached */
3564 EINA_LIST_FOREACH_SAFE(cdata->pending.damages, l, ll, rect)
3565 eina_list_move_list(&sdata->cached.damages, &cdata->pending.damages, l);
3567 EINA_LIST_FOREACH_SAFE(cdata->pending.buffer_damages, l, ll, rect)
3568 eina_list_move_list(&sdata->cached.buffer_damages, &cdata->pending.buffer_damages, l);
3570 if (cdata->pending.new_attach)
3572 sdata->cached.new_attach = EINA_TRUE;
3573 _e_comp_wl_surface_state_buffer_set(&sdata->cached,
3574 cdata->pending.buffer);
3575 e_comp_wl_buffer_reference(&sdata->cached_buffer_ref,
3576 cdata->pending.buffer);
3579 sdata->cached.sx = cdata->pending.sx;
3580 sdata->cached.sy = cdata->pending.sy;
3581 /* sdata->cached.buffer = cdata->pending.buffer; */
3583 /* When subsurface is sync mode, the commit of subsurface can happen before
3584 * a parent surface is committed. In this case, we can't show a attached
3587 //sdata->cached.new_attach = cdata->pending.new_attach;
3589 sdata->cached.buffer_viewport.changed |= cdata->pending.buffer_viewport.changed;
3590 sdata->cached.buffer_viewport.buffer =cdata->pending.buffer_viewport.buffer;
3591 sdata->cached.buffer_viewport.surface = cdata->pending.buffer_viewport.surface;
3593 _e_comp_wl_surface_state_buffer_set(&cdata->pending, NULL);
3594 cdata->pending.sx = 0;
3595 cdata->pending.sy = 0;
3596 cdata->pending.new_attach = EINA_FALSE;
3597 cdata->pending.buffer_viewport.changed = 0;
3599 /* copy cdata->pending.opaque into sdata->cached.opaque */
3600 itr = eina_tiler_iterator_new(cdata->pending.opaque);
3601 EINA_ITERATOR_FOREACH(itr, rect)
3602 eina_tiler_rect_add(sdata->cached.opaque, rect);
3603 eina_iterator_free(itr);
3605 /* repeat for input */
3606 itr = eina_tiler_iterator_new(cdata->pending.input);
3607 EINA_ITERATOR_FOREACH(itr, rect)
3608 eina_tiler_rect_add(sdata->cached.input, rect);
3609 eina_iterator_free(itr);
3611 EINA_LIST_FOREACH_SAFE(cdata->pending.frames, l, ll, cb)
3614 eina_list_move_list(&sdata->cached.frames,
3615 &cdata->pending.frames,
3619 sdata->cached.has_data = EINA_TRUE;
3623 _e_comp_wl_subsurface_commit_from_cache(E_Client *ec)
3625 E_Comp_Client_Data *cdata;
3626 E_Comp_Wl_Subsurf_Data *sdata;
3628 if (!(cdata = ec->comp_data)) return;
3629 if (!(sdata = cdata->sub.data)) return;
3631 DBG("Subsurface Commit from Cache");
3633 _e_comp_wl_surface_state_commit(ec, &sdata->cached);
3635 if (!e_comp_object_damage_exists(ec->frame))
3636 e_pixmap_image_clear(ec->pixmap, 1);
3638 e_comp_wl_buffer_reference(&sdata->cached_buffer_ref, NULL);
3640 if (_e_comp_wl_surface_subsurface_order_commit(ec))
3642 E_Client *topmost = e_comp_wl_topmost_parent_get(ec);
3643 _e_comp_wl_subsurface_restack(topmost);
3644 _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
3649 _e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
3652 E_Comp_Wl_Subsurf_Data *sdata;
3654 if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3655 if (!(sdata = ec->comp_data->sub.data)) return;
3656 if (!(parent = sdata->parent)) return;
3658 if (sdata->position.set)
3660 evas_object_move(ec->frame, parent->x + sdata->position.x,
3661 parent->y + sdata->position.y);
3662 sdata->position.set = EINA_FALSE;
3665 if ((parent_synchronized) || (sdata->synchronized))
3670 if (sdata->cached.has_data)
3671 _e_comp_wl_subsurface_commit_from_cache(ec);
3673 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
3676 _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
3678 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
3681 _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
3687 _e_comp_wl_subsurface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3689 wl_resource_destroy(resource);
3693 _e_comp_wl_subsurface_cb_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y)
3696 E_Comp_Wl_Subsurf_Data *sdata;
3698 DBG("Subsurface Cb Position Set: %d", wl_resource_get_id(resource));
3700 /* try to get the client from resource data */
3701 if (!(ec = wl_resource_get_user_data(resource))) return;
3702 if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3703 if (!(sdata = ec->comp_data->sub.data)) return;
3705 sdata->position.x = x;
3706 sdata->position.y = y;
3707 sdata->position.set = EINA_TRUE;
3711 _e_comp_wl_subsurface_cb_place_above(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
3716 DBG("Subsurface Cb Place Above: %d", wl_resource_get_id(resource));
3718 /* try to get the client from resource data */
3719 if (!(ec = wl_resource_get_user_data(resource))) return;
3720 if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3721 if (!ec->comp_data->sub.data) return;
3723 /* try to get the client from the sibling resource */
3724 if (!(ecs = wl_resource_get_user_data(sibling_resource))) return;
3726 if (!ecs->comp_data->sub.data) return;
3728 if (!(parent = ec->comp_data->sub.data->parent)) return;
3729 if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return;
3731 parent->comp_data->sub.list_pending =
3732 eina_list_remove(parent->comp_data->sub.list_pending, ec);
3734 parent->comp_data->sub.list_pending =
3735 eina_list_append_relative(parent->comp_data->sub.list_pending, ec, ecs);
3737 parent->comp_data->sub.list_changed = EINA_TRUE;
3741 _e_comp_wl_subsurface_cb_place_below(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
3746 DBG("Subsurface Cb Place Below: %d", wl_resource_get_id(resource));
3748 /* try to get the client from resource data */
3749 if (!(ec = wl_resource_get_user_data(resource))) return;
3750 if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3751 if (!ec->comp_data->sub.data) return;
3753 /* try to get the client from the sibling resource */
3754 if (!(ecs = wl_resource_get_user_data(sibling_resource))) return;
3756 if (!ecs->comp_data->sub.data) return;
3758 if (!(parent = ec->comp_data->sub.data->parent)) return;
3759 if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return;
3761 parent->comp_data->sub.list_pending =
3762 eina_list_remove(parent->comp_data->sub.list_pending, ec);
3764 parent->comp_data->sub.list_pending =
3765 eina_list_prepend_relative(parent->comp_data->sub.list_pending, ec, ecs);
3767 parent->comp_data->sub.list_changed = EINA_TRUE;
3771 _e_comp_wl_subsurface_cb_sync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3774 E_Comp_Wl_Subsurf_Data *sdata;
3776 DBG("Subsurface Cb Sync Set: %d", wl_resource_get_id(resource));
3778 /* try to get the client from resource data */
3779 if (!(ec = wl_resource_get_user_data(resource))) return;
3780 if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3781 if (!(sdata = ec->comp_data->sub.data)) return;
3783 sdata->synchronized = EINA_TRUE;
3787 _e_comp_wl_subsurface_cb_desync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3790 E_Comp_Wl_Subsurf_Data *sdata;
3792 DBG("Subsurface Cb Desync Set: %d", wl_resource_get_id(resource));
3794 /* try to get the client from resource data */
3795 if (!(ec = wl_resource_get_user_data(resource))) return;
3796 if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3797 if (!(sdata = ec->comp_data->sub.data)) return;
3799 sdata->synchronized = EINA_FALSE;
3802 static const struct wl_subsurface_interface _e_subsurface_interface =
3804 _e_comp_wl_subsurface_cb_destroy,
3805 _e_comp_wl_subsurface_cb_position_set,
3806 _e_comp_wl_subsurface_cb_place_above,
3807 _e_comp_wl_subsurface_cb_place_below,
3808 _e_comp_wl_subsurface_cb_sync_set,
3809 _e_comp_wl_subsurface_cb_desync_set
3813 e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_resource *surface_resource)
3815 struct wl_client *client;
3816 struct wl_resource *res;
3817 E_Comp_Wl_Subsurf_Data *sdata;
3818 E_Client *offscreen_parent = NULL;
3820 /* try to get the wayland client from the surface resource */
3821 if (!(client = wl_resource_get_client(surface_resource)))
3823 ERR("Could not get client from resource %d",
3824 wl_resource_get_id(surface_resource));
3828 if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
3830 if (!epc || e_object_is_del(E_OBJECT(epc)))
3832 if (ec->comp_data->sub.watcher)
3833 tizen_subsurface_watcher_send_message(ec->comp_data->sub.watcher, TIZEN_SUBSURFACE_WATCHER_MSG_PARENT_ID_INVALID);
3835 /* We have to create a subsurface resource here even though it's error case
3836 * because server will send the fatal error when a client destroy a subsurface object.
3837 * Otherwise, server will kill a client by the fatal error.
3839 if (!(res = wl_resource_create(client, &wl_subsurface_interface, 1, id)))
3841 ERR("Failed to create subsurface resource");
3842 wl_resource_post_no_memory(surface_resource);
3846 wl_resource_set_implementation(res, &_e_subsurface_interface, NULL, NULL);
3848 ERR("tizen_policy failed: invalid parent");
3852 // reparent remote surface provider's subsurfaces
3853 if (epc->comp_data->remote_surface.onscreen_parent)
3855 offscreen_parent = epc;
3856 epc = epc->comp_data->remote_surface.onscreen_parent;
3859 // check parent relationship is a cycle
3861 E_Client *parent = epc;
3867 ERR("Subsurface parent relationship is a cycle : [child win : %x, %s], [parent win : %x, %s]",
3868 e_client_util_win_get(ec), e_client_util_name_get(ec),
3869 e_client_util_win_get(epc), e_client_util_name_get(epc));
3874 if (parent->comp_data->sub.data)
3875 parent = parent->comp_data->sub.data->parent;
3881 /* try to allocate subsurface data */
3882 if (!(sdata = E_NEW(E_Comp_Wl_Subsurf_Data, 1)))
3884 ERR("Could not allocate space for subsurface data");
3888 /* try to create the subsurface resource */
3889 if (!(res = wl_resource_create(client, &wl_subsurface_interface, 1, id)))
3891 ERR("Failed to create subsurface resource");
3892 wl_resource_post_no_memory(surface_resource);
3896 /* set resource implementation */
3897 wl_resource_set_implementation(res, &_e_subsurface_interface, ec,
3898 _e_comp_wl_subsurface_destroy);
3899 e_object_ref(E_OBJECT(ec));
3901 _e_comp_wl_surface_state_init(&sdata->cached, ec->w, ec->h);
3903 /* set subsurface data properties */
3904 sdata->cached_buffer_ref.buffer = NULL;
3905 sdata->resource = res;
3906 sdata->synchronized = EINA_TRUE;
3907 sdata->parent = epc;
3908 sdata->remote_surface.offscreen_parent = offscreen_parent;
3910 /* set subsurface client properties */
3911 ec->borderless = EINA_TRUE;
3912 ec->argb = EINA_TRUE;
3913 ec->lock_border = EINA_TRUE;
3914 ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
3915 ec->netwm.state.skip_taskbar = EINA_TRUE;
3916 ec->netwm.state.skip_pager = EINA_TRUE;
3917 ec->no_shape_cut = EINA_TRUE;
3918 ec->border_size = 0;
3920 ELOGF("COMP", " |subsurface_parent:%p", NULL, ec, epc);
3921 if (offscreen_parent)
3922 ELOGF("COMP", " |offscreen_parent:%p", NULL, ec, offscreen_parent);
3928 short layer = evas_object_layer_get(epc->frame);
3929 evas_object_layer_set(ec->frame, layer);
3934 /* append this client to the parents subsurface list */
3935 epc->comp_data->sub.list =
3936 eina_list_append(epc->comp_data->sub.list, ec);
3937 epc->comp_data->sub.list_changed = EINA_TRUE;
3940 /* TODO: add callbacks ?? */
3943 ec->comp_data->surface = surface_resource;
3944 ec->comp_data->sub.data = sdata;
3946 ec->lock_user_location = 0;
3947 ec->lock_client_location = 0;
3948 ec->lock_user_size = 0;
3949 ec->lock_client_size = 0;
3950 ec->lock_client_stacking = 0;
3951 ec->lock_user_shade = 0;
3952 ec->lock_client_shade = 0;
3953 ec->lock_user_maximize = 0;
3954 ec->lock_client_maximize = 0;
3955 ec->changes.need_maximize = 0;
3956 ec->maximized = E_MAXIMIZE_NONE;
3959 ec->new_client = ec->netwm.ping = EINA_TRUE;
3960 e_comp->new_clients++;
3961 e_client_unignore(ec);
3963 _e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
3973 _e_comp_wl_surface_sub_list_free(Eina_List *sub_list)
3977 EINA_LIST_FREE(sub_list, subc)
3979 if (!subc->comp_data || !subc->comp_data->sub.data) continue;
3981 subc->comp_data->sub.data->parent = NULL;
3983 if (subc->comp_data->sub.watcher)
3984 tizen_subsurface_watcher_send_message(subc->comp_data->sub.watcher, TIZEN_SUBSURFACE_WATCHER_MSG_PARENT_ID_DESTROYED);
3989 _e_comp_wl_subcompositor_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3991 wl_resource_destroy(resource);
3995 _e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
3997 E_Client *ec, *epc = NULL;
3998 static const char where[] = "get_subsurface: wl_subsurface@";
4000 if (!(ec = wl_resource_get_user_data(surface_resource))) return;
4001 if (!(epc = wl_resource_get_user_data(parent_resource))) return;
4005 wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4006 "%s%d: wl_surface@%d cannot be its own parent",
4007 where, id, wl_resource_get_id(surface_resource));
4011 if (e_object_is_del(E_OBJECT(ec))) return;
4012 if (e_object_is_del(E_OBJECT(epc))) return;
4014 /* check if this surface is already a sub-surface */
4015 if ((ec->comp_data) && (ec->comp_data->sub.data))
4017 wl_resource_post_error(resource,
4018 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4019 "%s%d: wl_surface@%d is already a sub-surface",
4020 where, id, wl_resource_get_id(surface_resource));
4024 /* try to create a new subsurface */
4025 if (!e_comp_wl_subsurface_create(ec, epc, id, surface_resource))
4026 ERR("Failed to create subsurface for surface %d",
4027 wl_resource_get_id(surface_resource));
4030 static const struct wl_subcompositor_interface _e_subcomp_interface =
4032 _e_comp_wl_subcompositor_cb_destroy,
4033 _e_comp_wl_subcompositor_cb_subsurface_get
4037 _e_comp_wl_subcompositor_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
4039 struct wl_resource *res;
4042 wl_resource_create(client, &wl_subcompositor_interface,
4045 ERR("Could not create subcompositor resource: %m");
4046 wl_client_post_no_memory(client);
4050 wl_resource_set_implementation(res, &_e_subcomp_interface, e_comp, NULL);
4052 /* TODO: add handlers for client iconify/uniconify */
4056 _e_comp_wl_sr_cb_provide_uuid(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, const char *uuid)
4058 DBG("Provide UUID callback called for UUID: %s", uuid);
4061 static const struct session_recovery_interface _e_session_recovery_interface =
4063 _e_comp_wl_sr_cb_provide_uuid,
4067 _e_comp_wl_session_recovery_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
4069 struct wl_resource *res;
4071 if (!(res = wl_resource_create(client, &session_recovery_interface, 1, id)))
4073 ERR("Could not create session_recovery interface");
4074 wl_client_post_no_memory(client);
4078 /* set implementation on resource */
4079 wl_resource_set_implementation(res, &_e_session_recovery_interface, e_comp, NULL);
4083 _e_comp_wl_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
4087 /* make sure this is a wayland client */
4088 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4090 TRACE_DS_BEGIN(COMP_WL:CLIENT NEW HOOK);
4092 /* get window id from pixmap */
4093 win = e_pixmap_window_get(ec->pixmap);
4095 /* ignore fake root windows */
4096 if ((ec->override) && ((ec->x == -77) && (ec->y == -77)))
4098 e_comp_ignore_win_add(E_PIXMAP_TYPE_WL, win);
4099 e_object_del(E_OBJECT(ec));
4104 if (!(ec->comp_data = E_NEW(E_Comp_Client_Data, 1)))
4106 ERR("Could not allocate new client data structure");
4111 wl_signal_init(&ec->comp_data->destroy_signal);
4112 wl_signal_init(&ec->comp_data->apply_viewport_signal);
4114 _e_comp_wl_surface_state_init(&ec->comp_data->pending, ec->w, ec->h);
4116 /* set initial client properties */
4117 ec->argb = EINA_FALSE;
4118 ec->no_shape_cut = EINA_TRUE;
4119 ec->redirected = ec->ignored = 1;
4120 ec->border_size = 0;
4122 /* NB: could not find a better place to do this, BUT for internal windows,
4123 * we need to set delete_request else the close buttons on the frames do
4124 * basically nothing */
4125 if ((ec->internal) || (ec->internal_elm_win))
4126 ec->icccm.delete_request = EINA_TRUE;
4128 /* set initial client data properties */
4129 ec->comp_data->mapped = EINA_FALSE;
4130 ec->comp_data->first_damage = ec->internal;
4132 ec->comp_data->need_reparent = !ec->internal;
4134 ec->comp_data->scaler.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
4135 ec->comp_data->scaler.buffer_viewport.buffer.scale = 1;
4136 ec->comp_data->scaler.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
4137 ec->comp_data->scaler.buffer_viewport.surface.width = -1;
4139 E_Comp_Client_Data *p_cdata = e_pixmap_cdata_get(ec->pixmap);
4140 EINA_SAFETY_ON_NULL_RETURN(p_cdata);
4141 ec->comp_data->accepts_focus = p_cdata->accepts_focus;
4142 ec->comp_data->conformant = p_cdata->conformant;
4143 ec->comp_data->aux_hint = p_cdata->aux_hint;
4144 ec->comp_data->win_type = p_cdata->win_type;
4145 ec->comp_data->layer = p_cdata->layer;
4146 ec->comp_data->fetch.win_type = p_cdata->fetch.win_type;
4147 ec->comp_data->fetch.layer = p_cdata->fetch.layer;
4148 ec->comp_data->video_client = p_cdata->video_client;
4150 e_pixmap_cdata_set(ec->pixmap, ec->comp_data);
4156 _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
4158 /* Eina_Rectangle *dmg; */
4159 struct wl_resource *cb;
4161 /* make sure this is a wayland client */
4162 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4164 TRACE_DS_BEGIN(COMP_WL:CLIENT DEL CB);
4166 if ((!ec->already_unparented) && (ec->comp_data->reparented))
4167 _e_comp_wl_focus_down_set(ec);
4169 ec->already_unparented = EINA_TRUE;
4170 if (ec->comp_data->reparented)
4172 /* reset pixmap parent window */
4173 e_pixmap_parent_window_set(ec->pixmap, 0);
4176 if (ec->comp_data->sub.data)
4177 _e_comp_wl_subsurface_destroy_sdata(ec);
4179 if (ec->comp_data->sub.below_obj)
4180 evas_object_del(ec->comp_data->sub.below_obj);
4182 /* remove sub list */
4183 /* TODO: if parent is set by onscreen_parent of remote surface? */
4184 _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.list);
4185 ec->comp_data->sub.list = NULL;
4186 _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.list_pending);
4187 ec->comp_data->sub.list_pending = NULL;
4188 _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.below_list);
4189 ec->comp_data->sub.below_list = NULL;
4190 _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.below_list_pending);
4191 ec->comp_data->sub.below_list_pending = NULL;
4193 if (ec->comp_data->sub.watcher)
4194 wl_resource_destroy(ec->comp_data->sub.watcher);
4196 if ((ec->parent) && (ec->parent->modal == ec))
4198 ec->parent->lock_close = EINA_FALSE;
4199 ec->parent->modal = NULL;
4202 wl_signal_emit(&ec->comp_data->destroy_signal, &ec->comp_data->surface);
4204 _e_comp_wl_surface_state_finish(&ec->comp_data->pending);
4206 e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, NULL);
4208 EINA_LIST_FREE(ec->comp_data->frames, cb)
4209 wl_resource_destroy(cb);
4211 EINA_LIST_FREE(ec->comp_data->pending.frames, cb)
4212 wl_resource_destroy(cb);
4214 if (ec->comp_data->surface)
4215 wl_resource_set_user_data(ec->comp_data->surface, NULL);
4217 if (ec->internal_elm_win)
4218 _e_comp_wl_surface_render_stop(ec);
4219 _e_comp_wl_focus_check();
4221 if (ec->comp_data->aux_hint.hints)
4223 E_Comp_Wl_Aux_Hint *hint;
4224 EINA_LIST_FREE(ec->comp_data->aux_hint.hints, hint)
4226 eina_stringshare_del(hint->hint);
4227 eina_stringshare_del(hint->val);
4232 if (cursor_timer_ec == ec)
4234 E_FREE_FUNC(e_comp_wl->ptr.hide_tmr, ecore_timer_del);
4235 cursor_timer_ec = NULL;
4238 if (e_comp_wl->selection.cbhm == ec->comp_data->surface)
4239 e_comp_wl->selection.cbhm = NULL;
4241 if (ec->comp_data->viewport_transform)
4243 e_client_transform_core_remove(ec, ec->comp_data->viewport_transform);
4244 e_util_transform_del(ec->comp_data->viewport_transform);
4245 ec->comp_data->viewport_transform = NULL;
4248 e_pixmap_cdata_set(ec->pixmap, NULL);
4250 E_FREE(ec->comp_data);
4252 _e_comp_wl_focus_check();
4258 _e_comp_wl_client_cb_focus_set(void *data EINA_UNUSED, E_Client *ec)
4260 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4262 /* send configure */
4263 if (ec->comp_data->shell.configure_send)
4265 if (ec->comp_data->shell.surface)
4266 _e_comp_wl_configure_send(ec, 0, 0);
4269 e_comp_wl->kbd.focus = ec->comp_data->surface;
4273 _e_comp_wl_client_cb_focus_unset(void *data EINA_UNUSED, E_Client *ec)
4275 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4277 /* send configure */
4278 if (ec->comp_data->shell.configure_send)
4280 if (ec->comp_data->shell.surface)
4281 _e_comp_wl_configure_send(ec, 0, 0);
4284 _e_comp_wl_focus_check();
4286 if (e_comp_wl->kbd.focus == ec->comp_data->surface)
4287 e_comp_wl->kbd.focus = NULL;
4291 _e_comp_wl_client_cb_resize_begin(void *data EINA_UNUSED, E_Client *ec)
4293 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4294 if (ec->keyboard_resizing) return;
4296 /* do nothing currently */
4301 _e_comp_wl_client_cb_resize_end(void *data EINA_UNUSED, E_Client *ec)
4303 if (e_object_is_del(E_OBJECT(ec))) return;
4304 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4306 e_comp_wl->resize.edges = 0;
4307 e_comp_wl->resize.resource = NULL;
4309 if (ec->pending_resize)
4311 ec->changes.pos = EINA_TRUE;
4312 ec->changes.size = EINA_TRUE;
4316 E_FREE_LIST(ec->pending_resize, free);
4320 _e_comp_wl_client_cb_move_end(void *data EINA_UNUSED, E_Client *ec)
4322 if (e_object_is_del(E_OBJECT(ec))) return;
4323 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4327 _e_comp_wl_client_cb_iconify(void *data EINA_UNUSED, E_Client *ec)
4329 if (e_object_is_del(E_OBJECT(ec))) return;
4330 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4332 /* DON'T iconify subsurface. When iconfied, buffer will be released. */
4333 _e_comp_wl_subsurface_hide(ec);
4337 _e_comp_wl_client_cb_uniconify(void *data EINA_UNUSED, E_Client *ec)
4339 if (e_object_is_del(E_OBJECT(ec))) return;
4340 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4342 _e_comp_wl_subsurface_show(ec);
4346 _e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep)
4348 /* NOTE: this will return usable E_Client for a surface of specified process
4349 * by pid. it doesn't care whatever this surfaces is for but care only what
4350 * is owner process of the surface.
4353 E_Client *ec = NULL, *_ec = NULL;
4356 /* find launchscreen client list */
4357 if (e_comp->launchscrns)
4359 EINA_LIST_FOREACH(e_comp->launchscrns, l, _ec)
4361 if (_ec->netwm.pid == pid)
4369 E_Pixmap *oldep = NULL;
4373 /* do NOT replace with the client having comp data */
4377 e_comp->launchscrns = eina_list_remove(e_comp->launchscrns, ec);
4379 oldep = e_client_pixmap_change(ec, ep);
4382 e_pixmap_win_id_del(oldep);
4383 e_pixmap_free(oldep);
4389 /* to set-up comp data */
4390 _e_comp_wl_client_cb_new(NULL, ec);
4392 if (!ec->comp_data) return NULL;
4393 _e_comp_wl_client_evas_init(ec);
4395 ELOGF("COMP", "Reusable ec. new_pixmap:%p", ec->pixmap, ec, ec->pixmap);
4396 _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_REUSE, ec);
4404 _e_comp_wl_cb_output_unbind(struct wl_resource *resource)
4406 E_Comp_Wl_Output *output;
4408 if (!(output = wl_resource_get_user_data(resource))) return;
4410 output->resources = eina_list_remove(output->resources, resource);
4414 _e_comp_wl_cb_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
4416 E_Comp_Wl_Output *output;
4417 struct wl_resource *resource;
4419 if (!(output = data)) return;
4422 wl_resource_create(client, &wl_output_interface, version, id);
4425 wl_client_post_no_memory(client);
4429 DBG("Bound Output: %s", output->id);
4430 DBG("\tGeom: %d %d %d %d", output->x, output->y, output->w, output->h);
4432 output->resources = eina_list_append(output->resources, resource);
4434 wl_resource_set_implementation(resource, NULL, output,
4435 _e_comp_wl_cb_output_unbind);
4436 wl_resource_set_user_data(resource, output);
4438 wl_output_send_geometry(resource, output->x, output->y,
4439 output->phys_width, output->phys_height,
4440 output->subpixel, output->make ?: "",
4441 output->model ?: "", output->transform);
4443 if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
4444 wl_output_send_scale(resource, output->scale);
4446 /* 3 == preferred + current */
4447 wl_output_send_mode(resource, 3, output->w, output->h, output->refresh);
4449 if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
4450 wl_output_send_done(resource);
4454 _e_comp_wl_gl_init(void *data EINA_UNUSED)
4457 Evas_GL *evasgl = NULL;
4458 Evas_GL_API *glapi = NULL;
4459 Evas_GL_Context *ctx = NULL;
4460 Evas_GL_Surface *sfc = NULL;
4461 Evas_GL_Config *cfg = NULL;
4464 if (!e_comp_gl_get()) return;
4466 /* create dummy evas gl to bind wayland display of enlightenment to egl display */
4467 e_main_ts_begin("\tE_Comp_Wl_GL Init");
4469 /* if wl_drm module doesn't call e_comp_canvas_init yet,
4470 * then we should get evas from ecore_evas.
4473 evas = e_comp->evas;
4475 evas = ecore_evas_get(e_comp->ee);
4477 evasgl = evas_gl_new(evas);
4478 EINA_SAFETY_ON_NULL_GOTO(evasgl, err);
4480 glapi = evas_gl_api_get(evasgl);
4481 EINA_SAFETY_ON_NULL_GOTO(glapi, err);
4482 EINA_SAFETY_ON_NULL_GOTO(glapi->evasglBindWaylandDisplay, err);
4484 cfg = evas_gl_config_new();
4485 EINA_SAFETY_ON_NULL_GOTO(cfg, err);
4487 sfc = evas_gl_surface_create(evasgl, cfg, 1, 1);
4488 EINA_SAFETY_ON_NULL_GOTO(sfc, err);
4490 ctx = evas_gl_context_create(evasgl, NULL);
4491 EINA_SAFETY_ON_NULL_GOTO(ctx, err);
4493 res = evas_gl_make_current(evasgl, sfc, ctx);
4494 EINA_SAFETY_ON_FALSE_GOTO(res, err);
4496 res = glapi->evasglBindWaylandDisplay(evasgl, e_comp_wl->wl.disp);
4497 EINA_SAFETY_ON_FALSE_GOTO(res, err);
4499 evas_gl_config_free(cfg);
4501 e_comp_wl->wl.gl = evasgl;
4502 e_comp_wl->wl.glapi = glapi;
4503 e_comp_wl->wl.glsfc = sfc;
4504 e_comp_wl->wl.glctx = ctx;
4506 /* for native surface */
4509 e_main_ts_end("\tE_Comp_Wl_GL Init Done");
4514 evas_gl_config_free(cfg);
4515 evas_gl_make_current(evasgl, NULL, NULL);
4516 evas_gl_context_destroy(evasgl, ctx);
4517 evas_gl_surface_destroy(evasgl, sfc);
4518 evas_gl_free(evasgl);
4524 _e_comp_wl_gl_popup_cb_close(void *data,
4525 Evas_Object *obj EINA_UNUSED,
4526 void *event_info EINA_UNUSED)
4528 evas_object_del(data);
4532 _e_comp_wl_gl_popup_cb_focus(void *data,
4533 Evas_Object *obj EINA_UNUSED,
4534 void *event_info EINA_UNUSED)
4536 elm_object_focus_set(data, EINA_TRUE);
4541 _e_comp_wl_gl_idle(void *data)
4545 /* show warning window to notify failure of gl init */
4548 Evas_Object *win, *bg, *popup, *btn;
4550 win = elm_win_add(NULL, "compositor warning", ELM_WIN_BASIC);
4551 elm_win_title_set(win, "Compositor Warning");
4552 elm_win_autodel_set(win, EINA_TRUE);
4553 elm_win_borderless_set(win, EINA_TRUE);
4554 elm_win_role_set(win, "notification-low");
4555 elm_win_alpha_set(win, EINA_TRUE);
4557 bg = evas_object_rectangle_add(evas_object_evas_get(win));
4558 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
4559 elm_win_resize_object_add(win, bg);
4560 evas_object_color_set(bg, 125, 125, 125, 125);
4561 evas_object_show(bg);
4563 popup = elm_popup_add(win);
4564 elm_object_text_set(popup,
4565 _( "Your screen does not support OpenGL.<br>"
4566 "Falling back to software engine."));
4567 elm_object_part_text_set(popup, "title,text", "Compositor Warning");
4569 btn = elm_button_add(popup);
4570 elm_object_text_set(btn, "Close");
4571 elm_object_part_content_set(popup, "button1", btn);
4572 evas_object_show(btn);
4574 evas_object_smart_callback_add(win, "focus,in", _e_comp_wl_gl_popup_cb_focus, popup);
4575 evas_object_smart_callback_add(btn, "unpressed", _e_comp_wl_gl_popup_cb_close, win);
4577 evas_object_show(popup);
4578 evas_object_show(win);
4582 return ECORE_CALLBACK_CANCEL;
4586 _e_comp_wl_compositor_create(void)
4588 E_Comp_Wl_Data *cdata;
4593 /* create new compositor data */
4594 if (!(cdata = E_NEW(E_Comp_Wl_Data, 1)))
4596 ERR("Could not create compositor data: %m");
4600 /* set compositor wayland data */
4601 e_comp_wl = e_comp->wl_comp_data = cdata;
4603 /* try to create a wayland display */
4604 if (!(cdata->wl.disp = wl_display_create()))
4606 ERR("Could not create a Wayland display: %m");
4610 /* try to setup wayland socket */
4611 if (!(name = wl_display_add_socket_auto(cdata->wl.disp)))
4613 ERR("Could not create Wayland display socket: %m");
4614 PRCTL("[Winsys] Could not create Wayland display socket: /run/wayland-0");
4618 res = e_comp_socket_init(name);
4619 EINA_SAFETY_ON_FALSE_GOTO(res, sock_err);
4620 PRCTL("[Winsys] change permission and create sym link for %s", name);
4622 /* set wayland display environment variable */
4623 e_env_set("WAYLAND_DISPLAY", name);
4625 /* initialize compositor signals */
4626 wl_signal_init(&cdata->signals.surface.create);
4627 wl_signal_init(&cdata->signals.surface.activate);
4628 wl_signal_init(&cdata->signals.surface.kill);
4630 /* cdata->output.transform = WL_OUTPUT_TRANSFORM_NORMAL; */
4631 /* cdata->output.scale = e_scale; */
4633 /* try to add compositor to wayland globals */
4634 if (!wl_global_create(cdata->wl.disp, &wl_compositor_interface,
4635 COMPOSITOR_VERSION, e_comp,
4636 _e_comp_wl_compositor_cb_bind))
4638 ERR("Could not add compositor to wayland globals: %m");
4639 goto comp_global_err;
4642 /* try to add subcompositor to wayland globals */
4643 if (!wl_global_create(cdata->wl.disp, &wl_subcompositor_interface, 1,
4644 e_comp, _e_comp_wl_subcompositor_cb_bind))
4646 ERR("Could not add subcompositor to wayland globals: %m");
4647 goto comp_global_err;
4650 /* try to add session_recovery to wayland globals */
4651 if (!wl_global_create(cdata->wl.disp, &session_recovery_interface, 1,
4652 e_comp, _e_comp_wl_session_recovery_cb_bind))
4654 ERR("Could not add session_recovery to wayland globals: %m");
4655 goto comp_global_err;
4658 /* initialize shm mechanism */
4659 wl_display_init_shm(cdata->wl.disp);
4661 /* _e_comp_wl_cb_randr_change(NULL, 0, NULL); */
4663 /* try to init data manager */
4664 if (!e_comp_wl_data_manager_init())
4666 ERR("Could not initialize data manager");
4670 /* try to init input */
4671 if (!e_comp_wl_input_init())
4673 ERR("Could not initialize input");
4677 if (e_comp_gl_get())
4678 _e_comp_wl_gl_init(NULL);
4680 /* get the wayland display loop */
4681 cdata->wl.loop = wl_display_get_event_loop(cdata->wl.disp);
4683 /* get the file descriptor of the wayland event loop */
4684 fd = wl_event_loop_get_fd(cdata->wl.loop);
4686 /* create a listener for wayland main loop events */
4688 ecore_main_fd_handler_add(fd, (ECORE_FD_READ | ECORE_FD_ERROR),
4689 _e_comp_wl_cb_read, cdata, NULL, NULL);
4690 ecore_main_fd_handler_prepare_callback_set(cdata->fd_hdlr,
4691 _e_comp_wl_cb_prepare, cdata);
4696 e_comp_wl_data_manager_shutdown();
4699 e_env_unset("WAYLAND_DISPLAY");
4701 wl_display_destroy(cdata->wl.disp);
4708 _e_comp_wl_gl_shutdown(void)
4710 if (!e_comp_wl->wl.gl) return;
4712 e_comp_wl->wl.glapi->evasglUnbindWaylandDisplay(e_comp_wl->wl.gl, e_comp_wl->wl.disp);
4714 evas_gl_make_current(e_comp_wl->wl.gl, NULL, NULL);
4715 evas_gl_context_destroy(e_comp_wl->wl.gl, e_comp_wl->wl.glctx);
4716 evas_gl_surface_destroy(e_comp_wl->wl.gl, e_comp_wl->wl.glsfc);
4717 evas_gl_free(e_comp_wl->wl.gl);
4719 e_comp_wl->wl.glsfc = NULL;
4720 e_comp_wl->wl.glctx = NULL;
4721 e_comp_wl->wl.glapi = NULL;
4722 e_comp_wl->wl.gl = NULL;
4725 /* public functions */
4728 * Creates and initializes a Wayland compositor with ecore.
4729 * Registers callback handlers for keyboard and mouse activity
4730 * and other client events.
4732 * @returns true on success, false if initialization failed.
4735 e_comp_wl_init(void)
4737 TRACE_DS_BEGIN(COMP_WL:INIT);
4739 /* try to create a wayland compositor */
4740 if (!_e_comp_wl_compositor_create())
4742 e_error_message_show(_("Enlightenment cannot create a Wayland Compositor!\n"));
4747 e_comp_wl_shell_init();
4749 #ifdef HAVE_WAYLAND_TBM
4750 e_comp_wl_tbm_init();
4752 e_comp_wl_remote_surface_init();
4756 e_comp_wl_screenshooter_init();
4757 e_comp_wl_video_init();
4758 e_comp_wl_viewport_init();
4760 /* add event handlers to catch E events */
4761 E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREEN_CHANGE, _e_comp_wl_cb_randr_change, NULL);
4762 E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _e_comp_wl_cb_comp_object_add, NULL);
4763 E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE, _e_comp_wl_cb_mouse_move, NULL);
4764 E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_CANCEL, _e_comp_wl_cb_mouse_button_cancel, NULL);
4765 E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DISPLAY_STATE_CHANGE, _e_comp_wl_cb_zone_display_state_change, NULL);
4766 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN, _e_comp_wl_cb_client_rot_change_begin, NULL);
4767 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL, _e_comp_wl_cb_client_rot_change_cancel, NULL);
4768 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_END, _e_comp_wl_cb_client_rot_change_end, NULL);
4770 /* add hooks to catch e_client events */
4771 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_NEW_CLIENT, _e_comp_wl_client_cb_new, NULL);
4772 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_DEL, _e_comp_wl_client_cb_del, NULL);
4773 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_FOCUS_SET, _e_comp_wl_client_cb_focus_set, NULL);
4774 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_FOCUS_UNSET, _e_comp_wl_client_cb_focus_unset, NULL);
4775 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_RESIZE_BEGIN, _e_comp_wl_client_cb_resize_begin, NULL);
4776 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_RESIZE_END, _e_comp_wl_client_cb_resize_end, NULL);
4777 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_MOVE_END, _e_comp_wl_client_cb_move_end, NULL);
4778 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_ICONIFY, _e_comp_wl_client_cb_iconify, NULL);
4779 E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_UNICONIFY, _e_comp_wl_client_cb_uniconify, NULL);
4781 E_EVENT_WAYLAND_GLOBAL_ADD = ecore_event_type_new();
4788 e_comp_wl_deferred_job(void)
4790 ecore_idle_enterer_add(_e_comp_wl_gl_idle, NULL);
4794 * Get the signal that is fired for the creation of a Wayland surface.
4796 * @returns the corresponding Wayland signal
4798 E_API struct wl_signal
4799 e_comp_wl_surface_create_signal_get(void)
4801 return e_comp_wl->signals.surface.create;
4804 /* internal functions */
4806 e_comp_wl_shutdown(void)
4809 E_FREE_LIST(handlers, ecore_event_handler_del);
4810 E_FREE_LIST(hooks, e_client_hook_del);
4811 _e_comp_wl_gl_shutdown();
4813 e_comp_wl_viewport_shutdown();
4814 e_comp_wl_video_shutdown();
4815 e_comp_wl_screenshooter_shutdown();
4817 #ifdef HAVE_WAYLAND_TBM
4818 e_comp_wl_tbm_shutdown();
4820 e_comp_wl_remote_surface_shutdown();
4822 e_pixmap_shutdown();
4824 e_comp_wl_shell_shutdown();
4825 e_comp_wl_input_shutdown();
4829 E_Comp_Wl_Output *output;
4831 if (e_comp_wl->screenshooter.global)
4832 wl_global_destroy(e_comp_wl->screenshooter.global);
4834 EINA_LIST_FREE(e_comp_wl->outputs, output)
4836 if (output->id) eina_stringshare_del(output->id);
4837 if (output->make) eina_stringshare_del(output->make);
4838 if (output->model) eina_stringshare_del(output->model);
4842 /* delete fd handler */
4843 if (e_comp_wl->fd_hdlr) ecore_main_fd_handler_del(e_comp_wl->fd_hdlr);
4845 E_FREE_FUNC(e_comp_wl->ptr.hide_tmr, ecore_timer_del);
4846 cursor_timer_ec = NULL;
4848 /* free allocated data structure */
4854 e_comp_wl_surface_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
4856 e_object_unref(E_OBJECT(ev->ec));
4861 e_comp_wl_surface_attach(E_Client *ec, E_Comp_Wl_Buffer *buffer)
4864 ev = E_NEW(E_Event_Client, 1);
4867 e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, buffer);
4869 /* set usable early because shell module checks this */
4870 e_pixmap_usable_set(ec->pixmap, (buffer != NULL));
4871 e_pixmap_resource_set(ec->pixmap, buffer);
4872 e_pixmap_dirty(ec->pixmap);
4873 e_pixmap_refresh(ec->pixmap);
4875 e_comp_wl_map_size_cal_from_buffer(ec);
4876 _e_comp_wl_surface_state_size_update(ec, &ec->comp_data->pending);
4878 /* wm-policy module uses it */
4879 _e_comp_wl_hook_call(E_COMP_WL_HOOK_BUFFER_CHANGE, ec);
4882 e_object_ref(E_OBJECT(ec));
4883 ecore_event_add(E_EVENT_CLIENT_BUFFER_CHANGE, ev,
4884 (Ecore_End_Cb)e_comp_wl_surface_event_simple_free, NULL);
4888 e_comp_wl_surface_commit(E_Client *ec)
4892 _e_comp_wl_surface_state_commit(ec, &ec->comp_data->pending);
4893 if (!e_comp_object_damage_exists(ec->frame))
4894 e_pixmap_image_clear(ec->pixmap, 1);
4896 ignored = ec->ignored;
4898 if (_e_comp_wl_surface_subsurface_order_commit(ec))
4900 E_Client *topmost = e_comp_wl_topmost_parent_get(ec);
4901 _e_comp_wl_subsurface_restack(topmost);
4902 _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
4905 if (!e_pixmap_usable_get(ec->pixmap))
4907 if (ec->comp_data->mapped)
4909 if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
4911 ELOGF("COMP", "Try to unmap2. Call shell.unmap.", ec->pixmap, ec);
4912 ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
4914 else if (e_client_has_xwindow(ec) || ec->internal || ec->comp_data->sub.data ||
4915 (ec == e_comp_wl->drag_client))
4917 ELOGF("COMP", "Try to unmap2. Hide window. internal:%d, sub:%p, drag:%d",
4918 ec->pixmap, ec, ec->internal, ec->comp_data->sub.data, (ec == e_comp_wl->drag_client));
4919 ec->visible = EINA_FALSE;
4920 evas_object_hide(ec->frame);
4921 ec->comp_data->mapped = 0;
4925 if (ec->comp_data->sub.below_obj && evas_object_visible_get(ec->comp_data->sub.below_obj))
4926 evas_object_hide(ec->comp_data->sub.below_obj);
4930 if (!ec->comp_data->mapped)
4932 if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
4934 ELOGF("COMP", "Try to map2. Call shell.map.", ec->pixmap, ec);
4935 ec->comp_data->shell.map(ec->comp_data->shell.surface);
4937 else if (e_client_has_xwindow(ec) || ec->internal || _e_comp_wl_subsurface_can_show(ec) ||
4938 (ec == e_comp_wl->drag_client))
4940 ELOGF("COMP", "Try to map2. Show window. internal:%d, drag:%d",
4941 ec->pixmap, ec, ec->internal, (ec == e_comp_wl->drag_client));
4942 ec->visible = EINA_TRUE;
4944 evas_object_show(ec->frame);
4945 ec->comp_data->mapped = 1;
4949 if (ec->comp_data->sub.below_obj && !evas_object_visible_get(ec->comp_data->sub.below_obj)
4950 && evas_object_visible_get(ec->frame))
4951 evas_object_show(ec->comp_data->sub.below_obj);
4953 ec->ignored = ignored;
4958 e_comp_wl_subsurface_commit(E_Client *ec)
4960 E_Comp_Wl_Subsurf_Data *sdata;
4962 /* check for valid subcompositor data */
4963 if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
4964 if (!(sdata = ec->comp_data->sub.data)) return EINA_FALSE;
4966 if (_e_comp_wl_subsurface_synchronized_get(sdata))
4967 _e_comp_wl_subsurface_commit_to_cache(ec);
4973 if (sdata->position.set)
4975 E_Client *parent = sdata->parent;
4978 evas_object_move(ec->frame, parent->x + sdata->position.x,
4979 parent->y + sdata->position.y);
4980 sdata->position.set = EINA_FALSE;
4984 if (sdata->cached.has_data)
4986 _e_comp_wl_subsurface_commit_to_cache(ec);
4987 _e_comp_wl_subsurface_commit_from_cache(ec);
4990 e_comp_wl_surface_commit(ec);
4992 EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
4995 _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
4997 EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
5000 _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
5008 e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer)
5010 if ((ref->buffer) && (buffer != ref->buffer))
5012 ref->buffer->busy--;
5013 if (ref->buffer->busy == 0)
5015 if (ref->buffer->resource)
5017 if (!wl_resource_get_client(ref->buffer->resource)) return;
5019 wl_buffer_send_release(ref->buffer->resource);
5020 #ifdef HAVE_WAYLAND_TBM
5021 wayland_tbm_server_increase_buffer_sync_timeline(e_comp_wl->tbm.server,
5022 ref->buffer->resource, 1);
5027 if (ref->buffer->type == E_COMP_WL_BUFFER_TYPE_TBM)
5028 e_comp_wl_tbm_buffer_destroy(ref->buffer);
5032 if (ref->destroy_listener_usable)
5034 wl_list_remove(&ref->destroy_listener.link);
5035 ref->destroy_listener_usable = EINA_FALSE;
5039 if ((buffer) && (buffer != ref->buffer))
5042 wl_signal_add(&buffer->destroy_signal, &ref->destroy_listener);
5043 ref->destroy_listener_usable = EINA_TRUE;
5046 ref->buffer = buffer;
5047 ref->destroy_listener.notify = _e_comp_wl_buffer_reference_cb_destroy;
5051 * Get the buffer for a given resource.
5053 * Retrieves the Wayland SHM buffer for the resource and
5054 * uses it to create a new E_Comp_Wl_Buffer object. This
5055 * buffer will be freed when the resource is destroyed.
5057 * @param resource that owns the desired buffer
5058 * @returns a new E_Comp_Wl_Buffer object
5060 E_API E_Comp_Wl_Buffer *
5061 e_comp_wl_buffer_get(struct wl_resource *resource, E_Client *ec)
5063 E_Comp_Wl_Buffer *buffer = NULL;
5064 struct wl_listener *listener;
5065 struct wl_shm_buffer *shmbuff;
5067 tbm_surface_h tbm_surf;
5070 wl_resource_get_destroy_listener(resource, _e_comp_wl_buffer_cb_destroy);
5072 return container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
5074 if (!(buffer = E_NEW(E_Comp_Wl_Buffer, 1))) return NULL;
5076 shmbuff = wl_shm_buffer_get(resource);
5078 /* TODO: This option is temporarily. It will be removed later. */
5079 /* prefer to use native buffer(wl_buffer) */
5080 if (e_comp->use_native_type_buffer)
5084 buffer->type = E_COMP_WL_BUFFER_TYPE_SHM;
5086 buffer->w = wl_shm_buffer_get_width(shmbuff);
5087 buffer->h = wl_shm_buffer_get_height(shmbuff);
5091 if ((ec) && (ec->comp_data->video_client))
5093 buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
5094 buffer->w = buffer->h = 1;
5096 else if (e_comp->gl)
5098 buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
5100 res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5104 EINA_SAFETY_ON_FALSE_GOTO(res, err);
5106 res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5110 EINA_SAFETY_ON_FALSE_GOTO(res, err);
5114 tbm_surf = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
5118 buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
5119 buffer->w = tbm_surface_get_width(tbm_surf);
5120 buffer->h = tbm_surface_get_height(tbm_surf);
5121 buffer->tbm_surface = tbm_surf;
5124 buffer->shm_buffer = shmbuff;
5128 tbm_surf = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
5132 buffer->type = E_COMP_WL_BUFFER_TYPE_SHM;
5134 buffer->w = wl_shm_buffer_get_width(shmbuff);
5135 buffer->h = wl_shm_buffer_get_height(shmbuff);
5139 tbm_surf = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
5143 if ((ec) && (ec->comp_data->video_client))
5145 buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
5146 buffer->w = buffer->h = 1;
5150 buffer->type = E_COMP_WL_BUFFER_TYPE_TBM;
5151 buffer->w = tbm_surface_get_width(tbm_surf);
5152 buffer->h = tbm_surface_get_height(tbm_surf);
5155 else if (e_comp->gl)
5157 buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
5159 res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5163 EINA_SAFETY_ON_FALSE_GOTO(res, err);
5165 res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5169 EINA_SAFETY_ON_FALSE_GOTO(res, err);
5176 buffer->shm_buffer = shmbuff;
5177 buffer->tbm_surface = tbm_surf;
5180 buffer->resource = resource;
5181 wl_signal_init(&buffer->destroy_signal);
5182 buffer->destroy_listener.notify = _e_comp_wl_buffer_cb_destroy;
5183 wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
5187 buffer->debug_info.owner_ptr = (void *)ec;
5188 buffer->debug_info.owner_name = eina_stringshare_add(ec->icccm.name?:"");
5191 DBG("Wl Buffer Create: b %p owner '%s'(%p)",
5192 buffer, buffer->debug_info.owner_name, buffer->debug_info.owner_ptr);
5197 ERR("Invalid resource:%u", wl_resource_get_id(resource));
5202 static E_Comp_Wl_Output *
5203 _e_comp_wl_output_get(Eina_List *outputs, const char *id)
5206 E_Comp_Wl_Output *output;
5208 EINA_LIST_FOREACH(outputs, l, output)
5210 if (!strcmp(output->id, id))
5218 * Initializes information about one display output.
5220 * Adds or updates the given data about a single display output,
5221 * with an id matching the provided id.
5223 * @param id identification of output to be added or changed
5224 * @param make manufacturer name of the display output
5225 * @param model model name of the display output
5226 * @param x output's top left corner x coordinate
5227 * @param y output's top left corner y coordinate
5228 * @param w output's width in pixels
5229 * @param h output's height in pixels
5230 * @param pw output's physical width in millimeters
5231 * @param ph output's physical height in millimeters
5232 * @param refresh output's refresh rate in mHz
5233 * @param subpixel output's subpixel layout
5234 * @param transform output's rotation and/or mirror transformation
5236 * @returns True if a display output object could be added or updated
5239 e_comp_wl_output_init(const char *id, const char *make, const char *model,
5240 int x, int y, int w, int h, int pw, int ph,
5241 unsigned int refresh, unsigned int subpixel,
5242 unsigned int transform)
5244 E_Comp_Wl_Output *output;
5246 struct wl_resource *resource;
5248 /* retrieve named output; or create it if it doesn't exist */
5249 output = _e_comp_wl_output_get(e_comp_wl->outputs, id);
5252 if (!(output = E_NEW(E_Comp_Wl_Output, 1))) return EINA_FALSE;
5254 if (id) output->id = eina_stringshare_add(id);
5256 output->make = eina_stringshare_add(make);
5258 output->make = eina_stringshare_add("unknown");
5260 output->model = eina_stringshare_add(model);
5262 output->model = eina_stringshare_add("unknown");
5264 e_comp_wl->outputs = eina_list_append(e_comp_wl->outputs, output);
5267 wl_global_create(e_comp_wl->wl.disp, &wl_output_interface,
5268 2, output, _e_comp_wl_cb_output_bind);
5270 output->resources = NULL;
5271 output->scale = e_scale;
5274 /* update the output details */
5279 output->phys_width = pw;
5280 output->phys_height = ph;
5281 output->refresh = refresh;
5282 output->subpixel = subpixel;
5283 output->transform = transform;
5285 if (output->scale <= 0)
5286 output->scale = e_scale;
5288 /* if we have bound resources, send updates */
5289 EINA_LIST_FOREACH(output->resources, l2, resource)
5291 wl_output_send_geometry(resource,
5292 output->x, output->y,
5294 output->phys_height,
5296 output->make ?: "", output->model ?: "",
5299 if (wl_resource_get_version(resource) >= WL_OUTPUT_SCALE_SINCE_VERSION)
5300 wl_output_send_scale(resource, output->scale);
5302 /* 3 == preferred + current */
5303 wl_output_send_mode(resource, 3, output->w, output->h, output->refresh);
5305 if (wl_resource_get_version(resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
5306 wl_output_send_done(resource);
5313 e_comp_wl_output_remove(const char *id)
5315 E_Comp_Wl_Output *output;
5317 output = _e_comp_wl_output_get(e_comp_wl->outputs, id);
5320 e_comp_wl->outputs = eina_list_remove(e_comp_wl->outputs, output);
5322 /* wl_global_destroy(output->global); */
5324 /* eina_stringshare_del(output->id); */
5325 /* eina_stringshare_del(output->make); */
5326 /* eina_stringshare_del(output->model); */
5333 _e_comp_wl_key_send(Ecore_Event_Key *ev, enum wl_keyboard_key_state state, Eina_List *key_list, E_Client *ec)
5335 struct wl_resource *res;
5337 uint32_t serial, keycode;
5338 struct wl_client *wc = NULL;
5339 E_Comp_Config *comp_conf = NULL;
5341 keycode = (ev->keycode - 8);
5343 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5345 comp_conf = e_comp_config_get();
5347 if (ec && ec->comp_data && ec->comp_data->surface)
5348 wc = wl_resource_get_client(ec->comp_data->surface);
5350 EINA_LIST_FOREACH(key_list, l, res)
5352 if (wl_resource_get_client(res) != wc) continue;
5354 TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
5355 _e_comp_wl_send_event_device(ev->data, ev->timestamp, ev->dev, serial);
5357 if (comp_conf && comp_conf->input_log_enable)
5358 INF("[Server] Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
5360 wl_keyboard_send_key(res, serial, ev->timestamp,
5367 e_comp_wl_key_down(Ecore_Event_Key *ev)
5369 E_Client *ec = NULL;
5371 E_Comp_Wl_Key_Data *end, *k;
5373 if ((e_comp->comp_type != E_PIXMAP_TYPE_WL) || (ev->window != e_comp->ee_win))
5378 keycode = (ev->keycode - 8);
5379 if (!(e_comp_wl = e_comp->wl_comp_data))
5384 #ifndef E_RELEASE_BUILD
5385 if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
5386 ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
5387 (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
5388 eina_streq(ev->key, "BackSpace"))
5394 end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.keys.data + (e_comp_wl->kbd.keys.size / sizeof(*k));
5396 for (k = e_comp_wl->kbd.keys.data; k < end; k++)
5398 /* ignore server-generated key repeats */
5399 if (k->key == keycode)
5405 if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
5407 ec = e_client_focused_get();
5408 if (ec && ec->comp_data && ec->comp_data->surface && e_comp_wl->kbd.focused)
5410 _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_PRESSED, e_comp_wl->kbd.focused, ec);
5412 /* A key only sent to clients is added to the list */
5413 e_comp_wl->kbd.keys.size = (const char *)end - (const char *)e_comp_wl->kbd.keys.data;
5414 if (!(k = wl_array_add(&e_comp_wl->kbd.keys, sizeof(*k))))
5416 DBG("wl_array_add: Out of memory\n");
5424 /* update modifier state */
5425 e_comp_wl_input_keyboard_state_update(keycode, EINA_TRUE);
5431 e_comp_wl_key_up(Ecore_Event_Key *ev)
5433 E_Client *ec = NULL;
5434 uint32_t keycode, delivered_key;
5435 E_Comp_Wl_Key_Data *end, *k;
5437 if ((e_comp->comp_type != E_PIXMAP_TYPE_WL) ||
5438 (ev->window != e_comp->ee_win))
5443 keycode = (ev->keycode - 8);
5445 if (!(e_comp_wl = e_comp->wl_comp_data))
5450 end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.keys.data + (e_comp_wl->kbd.keys.size / sizeof(*k));
5451 for (k = e_comp_wl->kbd.keys.data; k < end; k++)
5453 if (k->key == keycode)
5460 e_comp_wl->kbd.keys.size =
5461 (const char *)end - (const char *)e_comp_wl->kbd.keys.data;
5463 /* If a key down event have been sent to clients, send a key up event to client for garantee key event sequence pair. (down/up) */
5464 if ((delivered_key) ||
5465 ((!e_client_action_get()) && (!e_comp->input_key_grabs)))
5467 ec = e_client_focused_get();
5469 if (e_comp_wl->kbd.focused)
5471 _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_RELEASED, e_comp_wl->kbd.focused, ec);
5475 /* update modifier state */
5476 e_comp_wl_input_keyboard_state_update(keycode, EINA_FALSE);
5482 e_comp_wl_key_process(Ecore_Event_Key *ev, int type)
5484 Eina_Bool res = EINA_FALSE;
5486 if (type == ECORE_EVENT_KEY_DOWN)
5488 res = e_comp_wl_key_down(ev);
5490 else if (type == ECORE_EVENT_KEY_UP)
5492 res = e_comp_wl_key_up(ev);
5499 e_comp_wl_evas_handle_mouse_button(E_Client *ec, uint32_t timestamp, uint32_t button_id, uint32_t state)
5502 struct wl_client *wc;
5503 uint32_t serial, btn;
5504 struct wl_resource *res;
5505 E_Comp_Config *comp_conf = NULL;
5507 if (ec->cur_mouse_action || e_comp_wl->drag)
5509 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
5510 if ((ec->ignored) && (!ec->remote_surface.provider)) return EINA_FALSE;
5514 case 1: btn = BTN_LEFT; break;
5515 case 2: btn = BTN_MIDDLE; break;
5516 case 3: btn = BTN_RIGHT; break;
5517 default: btn = button_id; break;
5520 e_comp_wl->ptr.button = btn;
5522 if (!ec->comp_data || !ec->comp_data->surface) return EINA_FALSE;
5524 if (!eina_list_count(e_comp_wl->ptr.resources))
5527 wc = wl_resource_get_client(ec->comp_data->surface);
5528 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5530 comp_conf = e_comp_config_get();
5532 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5534 if (wl_resource_get_client(res) != wc) continue;
5535 if (!e_comp_wl_input_pointer_check(res)) continue;
5536 TRACE_INPUT_BEGIN(e_comp_wl_evas_handle_mouse_button);
5538 if (comp_conf && comp_conf->input_log_enable)
5539 INF("[Server] Mouse Button %s (btn: %d, time: %d)\n", (state ? "Down" : "Up"), btn, timestamp);
5541 wl_pointer_send_button(res, serial, timestamp, btn, state);
5548 e_comp_wl_touch_cancel(void)
5550 _e_comp_wl_touch_cancel();
5553 E_API E_Comp_Wl_Hook *
5554 e_comp_wl_hook_add(E_Comp_Wl_Hook_Point hookpoint, E_Comp_Wl_Hook_Cb func, const void *data)
5558 EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_WL_HOOK_LAST, NULL);
5559 ch = E_NEW(E_Comp_Wl_Hook, 1);
5560 if (!ch) return NULL;
5561 ch->hookpoint = hookpoint;
5563 ch->data = (void*)data;
5564 _e_comp_wl_hooks[hookpoint] = eina_inlist_append(_e_comp_wl_hooks[hookpoint], EINA_INLIST_GET(ch));
5569 e_comp_wl_hook_del(E_Comp_Wl_Hook *ch)
5572 if (_e_comp_wl_hooks_walking == 0)
5574 _e_comp_wl_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_wl_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
5578 _e_comp_wl_hooks_delete++;
5582 e_comp_wl_shell_surface_ready(E_Client *ec)
5586 _e_comp_wl_hook_call(E_COMP_WL_HOOK_SHELL_SURFACE_READY, ec);
5590 e_comp_wl_input_cursor_timer_enable_set(Eina_Bool enabled)
5592 e_config->use_cursor_timer = !!enabled;
5594 if (e_config->use_cursor_timer == EINA_FALSE)
5596 if (e_comp_wl->ptr.hide_tmr)
5598 ecore_timer_del(e_comp_wl->ptr.hide_tmr);
5599 e_comp_wl->ptr.hide_tmr = NULL;
5601 cursor_timer_ec = NULL;
5603 if (e_pointer_is_hidden(e_comp->pointer))
5605 _e_comp_wl_cursor_reload(e_comp_wl->ptr.ec);
5611 e_comp_wl_key_send(E_Client *ec, int keycode, Eina_Bool pressed, Ecore_Device *dev, uint32_t time)
5613 struct wl_resource *res;
5614 struct wl_client *wc;
5616 uint32_t serial, wl_keycode;
5617 enum wl_keyboard_key_state state;
5618 E_Comp_Config *comp_conf = NULL;
5620 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5621 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5622 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5623 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5625 wl_keycode = keycode - 8;
5626 EINA_SAFETY_ON_TRUE_RETURN_VAL(wl_keycode <= 0, EINA_FALSE);
5628 wc = wl_resource_get_client(ec->comp_data->surface);
5629 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5630 if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5631 if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
5632 else state = WL_KEYBOARD_KEY_STATE_RELEASED;
5634 comp_conf = e_comp_config_get();
5636 EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
5638 if (wl_resource_get_client(res) != wc) continue;
5639 if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5640 else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_KEYBOARD, time);
5642 if (comp_conf && comp_conf->input_log_enable)
5643 INF("[Server] Key %s (time: %d)\n", (state ? "Down" : "Up"), time);
5645 wl_keyboard_send_key(res, serial, time,
5653 e_comp_wl_touch_send(E_Client *ec, int idx, int x, int y, Eina_Bool pressed, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, uint32_t time)
5655 struct wl_client *wc;
5657 E_Comp_Wl_Input_Device *device = NULL;
5659 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5660 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5661 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5662 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5664 if (!dev) device = _e_comp_wl_device_last_device_get(ECORE_DEVICE_CLASS_TOUCH);
5666 wc = wl_resource_get_client(ec->comp_data->surface);
5667 if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5668 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5672 _e_comp_wl_send_event_device(wc, time, dev, serial);
5673 _e_comp_wl_device_handle_axes(ecore_device_identifier_get(dev), ECORE_DEVICE_CLASS_TOUCH, ec, idx, radius_x, radius_y, pressure, angle);
5677 _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_TOUCH, time);
5678 _e_comp_wl_device_handle_axes(device->identifier, device->clas, ec, idx, radius_x, radius_y, pressure, angle);
5681 x = x + ec->client.x;
5682 y = y + ec->client.y;
5684 _e_comp_wl_send_touch(ec, idx, x, y, time, pressed);
5690 e_comp_wl_touch_update_send(E_Client *ec, int idx, int x, int y, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, uint32_t time)
5692 E_Comp_Wl_Input_Device *device;
5694 struct wl_client *wc;
5696 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5697 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5698 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5699 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5701 if (!dev) device = _e_comp_wl_device_last_device_get(ECORE_DEVICE_CLASS_TOUCH);
5703 wc = wl_resource_get_client(ec->comp_data->surface);
5704 if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5705 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5709 _e_comp_wl_send_event_device(wc, time, dev, serial);
5710 _e_comp_wl_device_handle_axes(ecore_device_identifier_get(dev), ECORE_DEVICE_CLASS_TOUCH, ec, idx, radius_x, radius_y, pressure, angle);
5714 _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_TOUCH, time);
5715 _e_comp_wl_device_handle_axes(device->identifier, device->clas, ec, idx, radius_x, radius_y, pressure, angle);
5718 x = x + ec->client.x;
5719 y = y + ec->client.y;
5721 _e_comp_wl_send_touch_move(ec, idx, x, y, time);
5727 e_comp_wl_touch_cancel_send(E_Client *ec)
5729 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5730 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5731 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5733 _e_comp_wl_send_touch_cancel(ec);
5739 e_comp_wl_mouse_button_send(E_Client *ec, int buttons, Eina_Bool pressed, Ecore_Device *dev, uint32_t time)
5742 struct wl_client *wc;
5744 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5745 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5746 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5747 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5749 wc = wl_resource_get_client(ec->comp_data->surface);
5750 if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5751 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5753 if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5754 else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5757 e_comp_wl_evas_handle_mouse_button(ec, time, buttons,
5758 WL_POINTER_BUTTON_STATE_PRESSED);
5760 e_comp_wl_evas_handle_mouse_button(ec, time, buttons,
5761 WL_POINTER_BUTTON_STATE_RELEASED);
5767 e_comp_wl_mouse_move_send(E_Client *ec, int x, int y, Ecore_Device *dev, uint32_t time)
5770 struct wl_client *wc;
5772 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5773 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5774 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5775 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5777 wc = wl_resource_get_client(ec->comp_data->surface);
5778 if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5779 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5781 if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5782 else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5784 x = x + ec->client.x;
5785 y = y + ec->client.y;
5787 _e_comp_wl_send_mouse_move(ec, x, y, time);
5793 e_comp_wl_mouse_wheel_send(E_Client *ec, int direction, int z, Ecore_Device *dev, uint32_t time)
5796 struct wl_client *wc;
5798 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5799 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5800 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5801 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5803 wc = wl_resource_get_client(ec->comp_data->surface);
5804 if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5805 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5807 if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5808 else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5810 _e_comp_wl_mouse_wheel_send(ec, direction, z, time);
5816 e_comp_wl_mouse_in_send(E_Client *ec, int x, int y, Ecore_Device *dev, uint32_t time)
5819 struct wl_client *wc;
5820 struct wl_resource *res;
5823 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5824 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5825 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5826 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5827 EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
5829 if (!eina_list_count(e_comp_wl->ptr.resources)) return EINA_FALSE;
5830 wc = wl_resource_get_client(ec->comp_data->surface);
5831 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5832 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5834 if (!e_comp_wl_input_pointer_check(res)) continue;
5835 if (wl_resource_get_client(res) != wc) continue;
5837 if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5838 else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5840 wl_pointer_send_enter(res, serial, ec->comp_data->surface,
5841 wl_fixed_from_int(x),
5842 wl_fixed_from_int(y));
5849 e_comp_wl_mouse_out_send(E_Client *ec, Ecore_Device *dev, uint32_t time)
5852 struct wl_client *wc;
5853 struct wl_resource *res;
5856 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5857 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5858 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5859 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5860 EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
5862 if (!eina_list_count(e_comp_wl->ptr.resources)) return EINA_FALSE;
5863 wc = wl_resource_get_client(ec->comp_data->surface);
5864 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5865 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5867 if (!e_comp_wl_input_pointer_check(res)) continue;
5868 if (wl_resource_get_client(res) != wc) continue;
5870 if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5871 else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5873 wl_pointer_send_leave(res, serial, ec->comp_data->surface);
5880 e_comp_wl_mouse_in_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src)
5882 Evas_Event_Mouse_In ev_in;
5885 if (ec->pointer_enter_sent) return;
5887 ev_in.buttons = buttons;
5895 ev_in.modifiers = modifiers;
5896 ev_in.locks = locks;
5897 ev_in.timestamp = timestamp;
5898 ev_in.event_flags = event_flags;
5901 ev_in.event_src = event_src;
5903 _e_comp_wl_evas_cb_mouse_in((void *)ec, NULL, NULL, &ev_in);
5907 e_comp_wl_mouse_out_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src)
5909 Evas_Event_Mouse_Out ev_out;
5912 if (!ec->pointer_enter_sent) return;
5914 ev_out.buttons = buttons;
5916 ev_out.output.x = x;
5917 ev_out.output.y = y;
5918 ev_out.canvas.x = x;
5919 ev_out.canvas.y = y;
5922 ev_out.modifiers = modifiers;
5923 ev_out.locks = locks;
5924 ev_out.timestamp = timestamp;
5925 ev_out.event_flags = event_flags;
5928 ev_out.event_src = event_src;
5930 _e_comp_wl_evas_cb_mouse_out((void *)ec, NULL, NULL, &ev_out);
5934 e_comp_wl_cursor_hide(E_Client *ec)
5936 struct wl_resource *res;
5937 struct wl_client *wc;
5941 e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
5943 if (e_comp_wl->ptr.hide_tmr)
5945 ecore_timer_del(e_comp_wl->ptr.hide_tmr);
5946 e_comp_wl->ptr.hide_tmr = NULL;
5948 cursor_timer_ec = NULL;
5950 if (!ec) return EINA_FALSE;
5951 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
5953 if (!ec->comp_data || !ec->comp_data->surface) return EINA_FALSE;
5954 wc = wl_resource_get_client(ec->comp_data->surface);
5955 serial = wl_display_next_serial(e_comp_wl->wl.disp);
5956 EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5958 if (!e_comp_wl_input_pointer_check(res)) continue;
5959 if (wl_resource_get_client(res) != wc) continue;
5960 if (ec->pointer_enter_sent == EINA_FALSE) continue;
5961 wl_pointer_send_leave(res, serial, ec->comp_data->surface);
5962 ec->pointer_enter_sent = EINA_FALSE;
5968 /* surface to buffer
5969 * - width : surface width
5970 * - height : surface height
5971 * - transform: buffer transform
5972 * - scale : buffer scale
5974 * - width : screen width
5975 * - height : screen height
5976 * - transform: output transform
5977 * - scale : output scale
5979 static E_Util_Transform_Matrix
5980 _e_comp_wl_buffer_coord_get(int width, int height, int transform, int scale)
5982 E_Util_Transform_Matrix m;
5984 e_util_transform_matrix_load_identity(&m);
5986 if (transform & 0x4)
5988 e_util_transform_matrix_translate(&m, -((double)width / 2), 0, 0);
5989 e_util_transform_matrix_flip_x(&m);
5990 e_util_transform_matrix_translate(&m, (double)width / 2, 0, 0);
5993 switch (transform & 0x3)
5995 case WL_OUTPUT_TRANSFORM_90:
5996 e_util_transform_matrix_translate(&m, -width, 0, 0);
5997 e_util_transform_matrix_rotation_z(&m, 270);
5999 case WL_OUTPUT_TRANSFORM_180:
6000 e_util_transform_matrix_translate(&m, -width, -height, 0);
6001 e_util_transform_matrix_rotation_z(&m, 180);
6003 case WL_OUTPUT_TRANSFORM_270:
6004 e_util_transform_matrix_translate(&m, 0, -height, 0);
6005 e_util_transform_matrix_rotation_z(&m, 90);
6011 e_util_transform_matrix_scale(&m, scale, scale, 1);
6016 /* surface to buffer
6017 * - surface width, surface height, buffer transform, buffer scale
6019 * - screen width, screen height, output transform, output scale
6022 e_comp_wl_pos_convert(int width, int height, int transform, int scale, int sx, int sy, int *bx, int *by)
6024 E_Util_Transform_Matrix m;
6025 E_Util_Transform_Vertex v;
6027 m = _e_comp_wl_buffer_coord_get(width, height, transform, scale);
6029 e_util_transform_vertex_init(&v, sx, sy, 0.0, 1.0);
6030 v = e_util_transform_matrix_multiply_vertex(&m, &v);
6031 e_util_transform_vertex_pos_round_get(&v, bx, by, NULL, NULL);
6035 * - buffer width, buffer height, buffer transform, buffer scale
6038 e_comp_wl_pos_convert_inverse(int width, int height, int transform, int scale, int bx, int by, int *sx, int *sy)
6040 E_Util_Transform_Matrix m;
6041 E_Util_Transform_Vertex v;
6044 if (transform != 0 || scale > 1)
6046 tw = ((transform % 2) ? height : width) / scale;
6047 th = ((transform % 2) ? width : height) / scale;
6055 m = _e_comp_wl_buffer_coord_get(tw, th, transform, scale);
6056 m = e_util_transform_matrix_inverse_get(&m);
6058 e_util_transform_vertex_init(&v, bx, by, 0.0, 1.0);
6059 v = e_util_transform_matrix_multiply_vertex(&m, &v);
6060 e_util_transform_vertex_pos_round_get(&v, sx, sy, NULL, NULL);
6063 /* surface to buffer
6064 * - surface width, surface height, buffer transform, buffer scale
6066 * - screen width, screen height, output transform, output scale
6069 e_comp_wl_rect_convert(int width, int height, int transform, int scale,
6070 int sx, int sy, int sw, int sh, int *bx, int *by, int *bw, int *bh)
6072 E_Util_Transform_Matrix m;
6073 E_Util_Transform_Rect sr = {sx, sy, sw, sh};
6074 E_Util_Transform_Rect_Vertex sv;
6076 m = _e_comp_wl_buffer_coord_get(width, height, transform, scale);
6078 sv = e_util_transform_rect_to_vertices(&sr);
6079 sv = e_util_transform_matrix_multiply_rect_vertex(&m, &sv);
6080 sr = e_util_transform_vertices_to_rect(&sv);
6089 * - buffer width, buffer height, buffer transform, buffer scale
6092 e_comp_wl_rect_convert_inverse(int width, int height, int transform, int scale,
6093 int bx, int by, int bw, int bh, int *sx, int *sy, int *sw, int *sh)
6095 E_Util_Transform_Matrix m;
6096 E_Util_Transform_Rect br = {bx, by, bw, bh};
6097 E_Util_Transform_Rect_Vertex bv;
6100 if (transform != 0 || scale > 1)
6102 tw = ((transform % 2) ? height : width) / scale;
6103 th = ((transform % 2) ? width : height) / scale;
6111 m = _e_comp_wl_buffer_coord_get(tw, th, transform, scale);
6112 m = e_util_transform_matrix_inverse_get(&m);
6114 bv = e_util_transform_rect_to_vertices(&br);
6115 bv = e_util_transform_matrix_multiply_rect_vertex(&m, &bv);
6116 br = e_util_transform_vertices_to_rect(&bv);
6124 E_API E_Comp_Wl_Output*
6125 e_comp_wl_output_find(E_Client *ec)
6128 E_Comp_Wl_Output *output;
6130 if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return NULL;
6132 EINA_LIST_FOREACH(e_comp_wl->outputs, l, output)
6134 if (ec->x < output->x || ec->x >= (output->x + output->w) ||
6135 ec->y < output->y || ec->y >= (output->y + output->h))