libtdm >= "1.0.0" \
glib-2.0 \
gobject-2.0 \
+ libds \
+ libds-tizen-tbm-server \
"
PKG_CHECK_MODULES(E_INFO, [
src/bin/e_device.c \
src/bin/e_input_event.c \
src/bin/e_single_pixel_buffer.c \
-src/bin/e_comp_wl_buffer.c
+src/bin/e_comp_wl_buffer.c \
+src/bin/e_compositor.c
src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=2 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS) $(PIXMAN_CFLAGS) $(POLICY_CFLAGS) $(EGL_CFLAGS)
if HAVE_LIBGOMP
E_API E_Client *
e_client_from_surface_resource(struct wl_resource *surface_resource)
{
- return wl_resource_get_user_data(surface_resource);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(surface_resource, NULL);
+
+ return e_comp_wl_util_client_from_surface_resource(surface_resource);
}
EINTERN void
int pid;
int uid;
int gid;
+ struct wl_listener destroy;
};
EINTERN Eina_Bool e_comp_init(void);
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#define COMPOSITOR_VERSION 4
-
#define E_COM_WL_PREPARE_GAP_LOG_TIME 2000
/* Resource Data Mapping: (wl_resource_get_user_data)
*
*/
+typedef struct _E_Comp_Data E_Comp_Data;
+
+struct _E_Comp_Data
+{
+ E_Comp_Wl_Data base;
+ struct wl_listener client_created;
+};
+
static void _e_comp_wl_move_resize_init(void);
-static E_Client * _e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep);
static Eina_Bool _e_comp_wl_cursor_timer_control(Evas_Callback_Type type, E_Client *ec);
/* local variables */
}
static void
-_e_comp_wl_focus_down_set(E_Client *ec EINA_UNUSED)
-{
- // do nothing
-}
-
-static void
_e_comp_wl_focus_check(void)
{
E_Client *ec;
}
static void
-_e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+_e_comp_wl_surface_render_stop(E_Client *ec)
{
- DBG("Surface Cb Destroy: %d", wl_resource_get_id(resource));
- wl_resource_destroy(resource);
+ /* FIXME: this may be fine after e_pixmap can create textures for wl clients? */
+ //if ((!ec->internal) && (!e_comp_gl_get()))
+ ec->dead = 1;
+
+ /* check if internal animation is running */
+ if (e_comp_object_is_animating(ec->frame)) return;
+ /* check if external animation is running */
+ if (evas_object_data_get(ec->frame, "effect_running")) return;
+
+ evas_object_hide(ec->frame);
}
-static void
-_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)
+EINTERN void
+e_comp_wl_client_surface_finish(E_Client *ec)
{
- E_Client *ec;
- E_Comp_Wl_Buffer *buffer = NULL;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
+ struct wl_resource *res;
+ struct wl_client *surface_client = NULL;
+ Eina_List *l, *ll;
- if (buffer_resource)
+ if (ec == e_client_focused_get())
{
- if (!(buffer = e_comp_wl_buffer_get(buffer_resource, ec)))
- {
- ERR("Could not get buffer from resource");
- wl_client_post_no_memory(client);
- return;
- }
- }
+ struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
+ surface_client = wl_resource_get_client(surface);
- if (!ec->comp_data->mapped)
- {
- if (ec->comp_data->shell.surface &&
- !ec->internal && !e_comp_wl_subsurface_check(ec) && !ec->remote_surface.provider)
+ g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
+ EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
{
- ELOGF("COMP", "Current unmapped. ATTACH buffer:%p", ec, buffer);
- }
- }
+ if (wl_resource_get_client(res) ==
+ surface_client)
+ e_comp_wl->kbd.focused =
+ eina_list_remove_list(e_comp_wl->kbd.focused, l);
- if (!buffer)
- {
- if (ec->comp_data->mapped)
- {
- /* will be unmapped. so run capture */
- e_comp_wl_remote_surface_image_save(ec);
}
+
+ g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
}
- _e_comp_wl_surface_state_buffer_set(&ec->comp_data->pending, buffer);
+ e_comp_wl_client_surface_set(ec, NULL);
- ec->comp_data->pending.sx = sx;
- ec->comp_data->pending.sy = sy;
- ec->comp_data->pending.new_attach = EINA_TRUE;
+ ec->comp_data->wl_surface = NULL;
+ e_pixmap_win_id_del(ec->pixmap);
- e_client_fps_update(ec);
+ _e_comp_wl_surface_render_stop(ec);
+ e_object_del(E_OBJECT(ec));
}
static void
-_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)
+_e_comp_wl_pname_get(pid_t pid, char *name, int size)
{
- E_Client *ec;
- Eina_Rectangle *dmg = NULL;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
-
- if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
+ if (!name) return;
- ec->comp_data->pending.damages =
- eina_list_append(ec->comp_data->pending.damages, dmg);
-}
+ FILE *h;
+ char proc[512], pname[512];
+ size_t len;
-static void
-_e_comp_wl_frame_cb_destroy(struct wl_resource *resource)
-{
- E_Client *ec;
- E_Comp_Wl_Subsurf_Data *sdata;
+ snprintf(proc, 512,"/proc/%d/cmdline", pid);
- if (!(ec = wl_resource_get_user_data(resource))) return;
- if (!ec->comp_data) return;
+ h = fopen(proc, "r");
+ if (!h) return;
- if (ec->comp_data->frames)
- {
- ec->comp_data->frames =
- eina_list_remove(ec->comp_data->frames, resource);
- }
+ len = fread(pname, sizeof(char), 512, h);
+ if (len > 0)
+ pname[len - 1] = '\0';
+ else
+ strncpy(pname, "NO NAME", sizeof(pname));
- if (ec->comp_data->pending.frames)
- {
- ec->comp_data->pending.frames =
- eina_list_remove(ec->comp_data->pending.frames, resource);
- }
+ fclose(h);
- sdata = ec->comp_data->sub.data;
- if ((sdata) && (sdata->cached.frames))
- {
- sdata->cached.frames =
- eina_list_remove(sdata->cached.frames, resource);
- }
+ strncpy(name, pname, size);
}
static void
-_e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback)
+_e_comp_wl_pname_print(pid_t pid)
{
- E_Client *ec;
- struct wl_resource *res;
+ FILE *h;
+ char proc[512], pname[512];
+ size_t len;
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
+ snprintf(proc, 512,"/proc/%d/cmdline", pid);
- /* create frame callback */
- if (!(res =
- wl_resource_create(client, &wl_callback_interface, 1, callback)))
- {
- wl_resource_post_no_memory(resource);
- return;
- }
+ h = fopen(proc, "r");
+ if (!h) return;
+
+ len = fread(pname, sizeof(char), 512, h);
+ if (len > 0)
+ pname[len - 1] = '\0';
+ else
+ strncpy(pname, "NO NAME", sizeof(pname));
- wl_resource_set_implementation(res, NULL, ec, _e_comp_wl_frame_cb_destroy);
+ fclose(h);
- ec->comp_data->pending.frames =
- eina_list_prepend(ec->comp_data->pending.frames, res);
+ ELOGF("COMP", " |%s", NULL, pname);
}
+
static void
-_e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
+_e_comp_wl_connected_client_cb_destroy(struct wl_listener *listener, void *data)
{
- E_Client *ec;
+ struct wl_client *client = data;
+ E_Comp_Connected_Client_Info *cinfo;
+ E_Appinfo *eai;
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
+ cinfo = wl_container_of(listener, cinfo, destroy);
- if (ec->comp_data->pending.opaque)
- eina_tiler_clear(ec->comp_data->pending.opaque);
- if (region_resource)
- {
- Eina_Tiler *tmp;
+ ELOGF("WL_CLIENT", "DESTROY |client:%8p|%d|%d|%d",
+ NULL, client, cinfo->pid, cinfo->uid, cinfo->gid);
- if (!(tmp = wl_resource_get_user_data(region_resource)))
- return;
+ eai = e_appinfo_find_with_pid(cinfo->pid);
+ if (e_appinfo_owner_get(eai) == E_APPINFO_OWNER_SERVER)
+ e_appinfo_del(eai);
- eina_tiler_union(ec->comp_data->pending.opaque, tmp);
+ e_comp->connected_clients = eina_list_remove(e_comp->connected_clients, cinfo);
- if (!eina_tiler_empty(ec->comp_data->pending.opaque))
- {
- if (ec->argb)
- {
- ec->argb = EINA_FALSE;
- ELOGF("COMP", "Set argb:%d", ec, ec->argb);
- EC_CHANGED(ec);
- _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_ALPHA_CHANGE, ec);
- e_comp_object_alpha_set(ec->frame, EINA_FALSE);
- }
- }
- }
- else
- {
- if (!ec->argb)
- {
- ec->argb = EINA_TRUE;
- ELOGF("COMP", "Set argb:%d", ec, ec->argb);
- EC_CHANGED(ec);
- _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_ALPHA_CHANGE, ec);
- e_comp_object_alpha_set(ec->frame, EINA_TRUE);
- }
- }
+ wl_list_remove(&cinfo->destroy.link);
+ eina_stringshare_del(cinfo->name);
+ free(cinfo);
}
static void
-_e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
+_e_comp_wl_connected_client_create(struct wl_client *client, char *name, pid_t pid, uid_t uid, gid_t gid)
{
- E_Client *ec;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
+ E_Comp_Connected_Client_Info *cinfo;
- if (ec->comp_data->pending.input)
- eina_tiler_clear(ec->comp_data->pending.input);
- if (region_resource)
- {
- Eina_Tiler *tmp;
+ cinfo = E_NEW(E_Comp_Connected_Client_Info, 1);
+ EINA_SAFETY_ON_NULL_RETURN(cinfo);
- if (!(tmp = wl_resource_get_user_data(region_resource)))
- return;
+ cinfo->name = eina_stringshare_add(name);
+ cinfo->pid = pid;
+ cinfo->uid = uid;
+ cinfo->gid = gid;
+ cinfo->destroy.notify = _e_comp_wl_connected_client_cb_destroy;
+ wl_client_add_destroy_listener(client, &cinfo->destroy);
+ e_comp->connected_clients = eina_list_append(e_comp->connected_clients, cinfo);
- if (eina_tiler_empty(tmp))
- {
- ELOGF("COMP", " |unset input rect", NULL);
- e_comp_object_input_objs_del(ec->frame);
- e_comp_object_input_area_set(ec->frame, -1, -1, 1, 1);
- }
- else
- eina_tiler_union(ec->comp_data->pending.input, tmp);
- }
- else
- {
- eina_tiler_rect_add(ec->comp_data->pending.input,
- &(Eina_Rectangle){0, 0, ec->client.w, ec->client.h});
- }
+ _e_comp_wl_pid_hook_call(E_COMP_WL_PID_HOOK_CONNECTED_CLIENT_CREATE, pid);
}
static void
-_e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+_e_comp_wl_client_cb_focus_set(void *data EINA_UNUSED, E_Client *ec)
{
- E_Client *ec, *subc;
- Eina_List *l;
- E_Comp_Config *comp_conf = NULL;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
-
- if (!ec->comp_data->first_commit)
- ec->comp_data->first_commit = EINA_TRUE;
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
- if (!ec->comp_data->mapped)
+ /* send configure */
+ if (ec->comp_data->shell.configure_send)
{
- if (ec->comp_data->shell.surface && ec->comp_data->pending.new_attach &&
- !ec->internal && !e_comp_wl_subsurface_check(ec) && !ec->remote_surface.provider)
- {
- ELOGF("COMP", "Current unmapped. COMMIT. pixmap_usable:%d", ec, e_pixmap_usable_get(ec->pixmap));
-
- // no canvas update before client's commit request, begin rendering after 1st commit
- comp_conf = e_comp_config_get();
- if (comp_conf && comp_conf->canvas_render_delay_after_boot && e_comp->canvas_render_delayed)
- {
- ELOGF("COMP", "Begin canvas update for the first time after boot", ec);
- e_comp->canvas_render_delayed = EINA_FALSE;
- }
- }
+ if (ec->comp_data->shell.surface)
+ _e_comp_wl_configure_send(ec, 0, 0);
}
- _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_BEFORE_SURFACE_COMMIT, ec);
-
- if (e_comp_wl_remote_surface_commit(ec)) return;
- if (e_comp_wl_subsurface_commit(ec)) return;
+ e_comp_wl->kbd.focus = ec->comp_data->surface;
+}
- e_comp_wl_surface_commit(ec);
+static void
+_e_comp_wl_client_cb_focus_unset(void *data EINA_UNUSED, E_Client *ec)
+{
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
- EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
+ /* send configure */
+ if (ec->comp_data->shell.configure_send)
{
- if (ec != subc)
- e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
+ if (ec->comp_data->shell.surface)
+ _e_comp_wl_configure_send(ec, 0, 0);
}
- EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
- {
- if (ec != subc)
- e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
- }
+ _e_comp_wl_focus_check();
- _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_SURFACE_COMMIT, ec);
+ if (e_comp_wl->kbd.focus == ec->comp_data->surface)
+ e_comp_wl->kbd.focus = NULL;
}
static void
-_e_comp_wl_surface_cb_buffer_transform_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t transform)
+_e_comp_wl_client_cb_resize_begin(void *data EINA_UNUSED, E_Client *ec)
{
- E_Client *ec;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
-
- if (transform < 0 || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270)
- {
- wl_resource_post_error(resource,
- WL_SURFACE_ERROR_INVALID_TRANSFORM,
- "buffer transform must be a valid transform "
- "('%d' specified)", transform);
- return;
- }
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
+ if (ec->keyboard_resizing) return;
- ec->comp_data->pending.buffer_viewport.buffer.transform = transform;
- ec->comp_data->pending.buffer_viewport.changed = 1;
+ /* do nothing currently */
+ ;
}
static void
-_e_comp_wl_surface_cb_buffer_scale_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t scale)
+_e_comp_wl_client_cb_resize_end(void *data EINA_UNUSED, E_Client *ec)
{
- E_Client *ec;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
if (e_object_is_del(E_OBJECT(ec))) return;
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
+
+ e_comp_wl->resize.edges = 0;
+ e_comp_wl->resize.resource = NULL;
- if (scale < 1)
+ if (ec->pending_resize)
{
- wl_resource_post_error(resource,
- WL_SURFACE_ERROR_INVALID_SCALE,
- "buffer scale must be at least one "
- "('%d' specified)", scale);
- return;
+ ec->changes.pos = EINA_TRUE;
+ ec->changes.size = EINA_TRUE;
+ EC_CHANGED(ec);
}
- ec->comp_data->pending.buffer_viewport.buffer.scale = scale;
- ec->comp_data->pending.buffer_viewport.changed = 1;
+ E_FREE_LIST(ec->pending_resize, free);
}
static void
-_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)
+_e_comp_wl_client_cb_move_end(void *data EINA_UNUSED, E_Client *ec)
{
- E_Client *ec;
- Eina_Rectangle *dmg = NULL;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
if (e_object_is_del(E_OBJECT(ec))) return;
-
- if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
-
- ec->comp_data->pending.buffer_damages =
- eina_list_append(ec->comp_data->pending.buffer_damages, dmg);
-}
-
-static const struct wl_surface_interface _e_surface_interface =
-{
- _e_comp_wl_surface_cb_destroy,
- _e_comp_wl_surface_cb_attach,
- _e_comp_wl_surface_cb_damage,
- _e_comp_wl_surface_cb_frame,
- _e_comp_wl_surface_cb_opaque_region_set,
- _e_comp_wl_surface_cb_input_region_set,
- _e_comp_wl_surface_cb_commit,
- _e_comp_wl_surface_cb_buffer_transform_set,
- _e_comp_wl_surface_cb_buffer_scale_set,
- _e_comp_wl_surface_cb_damage_buffer,
-};
-
-static void
-_e_comp_wl_surface_render_stop(E_Client *ec)
-{
- /* FIXME: this may be fine after e_pixmap can create textures for wl clients? */
- //if ((!ec->internal) && (!e_comp_gl_get()))
- ec->dead = 1;
-
- /* check if internal animation is running */
- if (e_comp_object_is_animating(ec->frame)) return;
- /* check if external animation is running */
- if (evas_object_data_get(ec->frame, "effect_running")) return;
-
- evas_object_hide(ec->frame);
-}
-
-static void
-_e_comp_wl_surface_destroy(struct wl_resource *resource)
-{
- E_Client *ec;
- struct wl_resource *res;
- struct wl_client *surface_client = NULL;
- Eina_List *l, *ll;
-
- if (!(ec = e_client_from_surface_resource(resource))) return;
-
- if (ec == e_client_focused_get())
- {
- struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
- surface_client = wl_resource_get_client(surface);
-
- g_mutex_lock(&e_comp_wl->kbd.focused_mutex);
- EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
- {
- if (wl_resource_get_client(res) ==
- surface_client)
- e_comp_wl->kbd.focused =
- eina_list_remove_list(e_comp_wl->kbd.focused, l);
- }
-
- g_mutex_unlock(&e_comp_wl->kbd.focused_mutex);
- }
-
- e_comp_wl_client_surface_set(ec, NULL);
-
- ec->comp_data->wl_surface = NULL;
- e_pixmap_win_id_del(ec->pixmap);
-
- _e_comp_wl_surface_render_stop(ec);
- e_object_del(E_OBJECT(ec));
-}
-
-static void
-_e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
-{
- struct wl_resource *res;
- E_Pixmap *ep = NULL;
- E_Client *ec = NULL;
- pid_t pid;
- int internal = 0;
-
- DBG("Compositor Cb Surface Create: %d", id);
-
- TRACE_DS_BEGIN(COMP_WL:SURFACE CREATE CB);
-
- /* try to create an internal surface */
- if (!(res = wl_resource_create(client, &wl_surface_interface,
- wl_resource_get_version(resource), id)))
- {
- ERR("Could not create compositor surface");
- wl_client_post_no_memory(client);
- TRACE_DS_END();
- return;
- }
-
- DBG("\tCreated Resource: %d", wl_resource_get_id(res));
-
- /* set implementation on resource */
- wl_resource_set_implementation(res, &_e_surface_interface, NULL,
- _e_comp_wl_surface_destroy);
-
- wl_client_get_credentials(client, &pid, NULL, NULL);
- if (pid == getpid())
- {
- /* pixmap of internal win was supposed to be created at trap show */
- internal = 1;
- ec = e_pixmap_find_client(E_PIXMAP_TYPE_WL, (uintptr_t)id);
- }
- else
- {
- if ((ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)res)))
- {
- ERR("There is e_pixmap already, Delete old e_pixmap %p", ep);
- e_pixmap_win_id_del(ep);
- ep = NULL;
- }
- }
-
- if (!ec)
- {
- /* try to create new pixmap */
- if (!(ep = e_pixmap_new(E_PIXMAP_TYPE_WL, res)))
- {
- ERR("Could not create new pixmap");
- wl_resource_destroy(res);
- wl_client_post_no_memory(client);
- TRACE_DS_END();
- return;
- }
-
- E_Comp_Wl_Client_Data *cdata = e_pixmap_cdata_get(ep);
- if (cdata)
- cdata->wl_surface = res;
-
- DBG("\tUsing Pixmap: %p", ep);
-
- if (!(ec = _e_comp_wl_client_usable_get(pid, ep)))
- {
- ec = e_client_new(ep, 0, internal);
- }
- }
- if (ec)
- {
- if (!ec->netwm.pid)
- ec->netwm.pid = pid;
- if (ec->new_client)
- e_comp->new_clients--;
- ec->new_client = 0;
- if ((!ec->client.w) && (ec->client.h))
- ec->client.w = ec->client.h = 1;
-
- e_comp_wl_client_surface_set(ec, res);
-
- ec->icccm.accepts_focus = 1;
- wl_list_init(&ec->comp_data->pointer_constraints);
- }
-
- /* set reference to pixmap so we can fetch it later */
- DBG("\tUsing Client: %p", ec);
- wl_resource_set_user_data(res, ec);
-
- TRACE_DS_END();
-}
-
-static void
-_e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
-{
- DBG("Region Destroy: %d", wl_resource_get_id(resource));
- wl_resource_destroy(resource);
-}
-
-static void
-_e_comp_wl_region_area_check(struct wl_client *client, Eina_Tiler *tiler, int32_t x, int32_t y, int32_t w, int32_t h)
-{
- Eina_Bool need_set = EINA_FALSE;
- int area_w = 0;
- int area_h = 0;
-
- eina_tiler_area_size_get(tiler, &area_w, &area_h);
- if (x + w > area_w)
- {
- area_w = x + w;
- need_set = EINA_TRUE;
- }
-
- if (y + h > area_h)
- {
- area_h = y + h;
- need_set = EINA_TRUE;
- }
-
- if (need_set)
- {
- INF("change region area. client:%8p(%dx%d)", client, area_w, area_h);
- eina_tiler_area_size_set(tiler, area_w, area_h);
- }
-}
-
-static void
-_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)
-{
- Eina_Tiler *tiler;
-
- DBG("Region Add: %d", wl_resource_get_id(resource));
- DBG("\tGeom: %d %d %d %d", x, y, w, h);
-
- /* get the tiler from the resource */
- if ((tiler = wl_resource_get_user_data(resource)))
- {
- _e_comp_wl_region_area_check(client, tiler, x, y ,w, h);
- eina_tiler_rect_add(tiler, &(Eina_Rectangle){x, y, w, h});
- }
-}
-
-static void
-_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)
-{
- Eina_Tiler *tiler;
-
- DBG("Region Subtract: %d", wl_resource_get_id(resource));
- DBG("\tGeom: %d %d %d %d", x, y, w, h);
-
- /* get the tiler from the resource */
- if ((tiler = wl_resource_get_user_data(resource)))
- eina_tiler_rect_del(tiler, &(Eina_Rectangle){x, y, w, h});
-}
-
-static const struct wl_region_interface _e_region_interface =
-{
- _e_comp_wl_region_cb_destroy,
- _e_comp_wl_region_cb_add,
- _e_comp_wl_region_cb_subtract
-};
-
-static void
-_e_comp_wl_compositor_cb_region_destroy(struct wl_resource *resource)
-{
- Eina_Tiler *tiler;
-
- DBG("Compositor Region Destroy: %d", wl_resource_get_id(resource));
-
- /* try to get the tiler from the region resource */
- if ((tiler = wl_resource_get_user_data(resource)))
- eina_tiler_free(tiler);
-}
-
-static void
-_e_comp_wl_compositor_cb_region_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
-{
- Eina_Tiler *tiler;
- struct wl_resource *res;
-
- DBG("Region Create: %d", wl_resource_get_id(resource));
-
- /* try to create new tiler */
- if (!(tiler = eina_tiler_new(e_comp->w, e_comp->h)))
- {
- ERR("Could not create Eina_Tiler");
- wl_resource_post_no_memory(resource);
- return;
- }
-
- /* set tiler size */
- eina_tiler_tile_size_set(tiler, 1, 1);
-
- if (!(res = wl_resource_create(client, &wl_region_interface, 1, id)))
- {
- ERR("\tFailed to create region resource");
- eina_tiler_free(tiler);
- wl_resource_post_no_memory(resource);
- return;
- }
-
- wl_resource_set_implementation(res, &_e_region_interface, tiler,
- _e_comp_wl_compositor_cb_region_destroy);
-}
-
-static const struct wl_compositor_interface _e_comp_interface =
-{
- _e_comp_wl_compositor_cb_surface_create,
- _e_comp_wl_compositor_cb_region_create
-};
-
-static void
-_e_comp_wl_pname_get(pid_t pid, char *name, int size)
-{
- if (!name) return;
-
- FILE *h;
- char proc[512], pname[512];
- size_t len;
-
- snprintf(proc, 512,"/proc/%d/cmdline", pid);
-
- h = fopen(proc, "r");
- if (!h) return;
-
- len = fread(pname, sizeof(char), 512, h);
- if (len > 0)
- pname[len - 1] = '\0';
- else
- strncpy(pname, "NO NAME", sizeof(pname));
-
- fclose(h);
-
- strncpy(name, pname, size);
-}
-
-static void
-_e_comp_wl_pname_print(pid_t pid)
-{
- FILE *h;
- char proc[512], pname[512];
- size_t len;
-
- snprintf(proc, 512,"/proc/%d/cmdline", pid);
-
- h = fopen(proc, "r");
- if (!h) return;
-
- len = fread(pname, sizeof(char), 512, h);
- if (len > 0)
- pname[len - 1] = '\0';
- else
- strncpy(pname, "NO NAME", sizeof(pname));
-
- fclose(h);
-
- ELOGF("COMP", " |%s", NULL, pname);
-}
-
-
-static void
-_e_comp_wl_compositor_cb_unbind(struct wl_resource *res_comp)
-{
- E_Appinfo *eai = NULL;
- struct wl_client *client;
- pid_t pid = 0;
- uid_t uid = 0;
- gid_t gid = 0;
-
- client = wl_resource_get_client(res_comp);
- if (client)
- wl_client_get_credentials(client,
- &pid,
- &uid,
- &gid);
-
- ELOGF("COMP",
- "UNBIND |res_comp:%8p|client:%8p|%d|%d|%d",
- NULL,
- res_comp,
- client,
- pid, uid, gid);
-
- E_Comp *comp;
- if ((comp = wl_resource_get_user_data(res_comp)))
- {
- Eina_List *l;
- E_Comp_Connected_Client_Info *cinfo;
- EINA_LIST_FOREACH(comp->connected_clients, l, cinfo)
- {
- if (cinfo->pid == pid)
- break;
- cinfo = NULL;
- }
- if (cinfo)
- {
- if (cinfo->name)
- eina_stringshare_del(cinfo->name);
- comp->connected_clients = eina_list_remove(comp->connected_clients, cinfo);
- E_FREE(cinfo);
- }
- }
-
- eai = e_appinfo_find_with_pid(pid);
- if (e_appinfo_owner_get(eai) == E_APPINFO_OWNER_SERVER)
- {
- e_appinfo_del(eai);
- }
-}
-
-static void
-_e_comp_wl_connected_client_create(char *name, pid_t pid, uid_t uid, gid_t gid)
-{
- E_Comp_Connected_Client_Info *cinfo;
-
- cinfo = E_NEW(E_Comp_Connected_Client_Info, 1);
- EINA_SAFETY_ON_NULL_RETURN(cinfo);
-
- cinfo->name = eina_stringshare_add(name);
- cinfo->pid = pid;
- cinfo->uid = uid;
- cinfo->gid = gid;
- e_comp->connected_clients = eina_list_append(e_comp->connected_clients, cinfo);
-
- _e_comp_wl_pid_hook_call(E_COMP_WL_PID_HOOK_CONNECTED_CLIENT_CREATE, pid);
-}
-
-
-static void
-_e_comp_wl_compositor_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
-{
- struct wl_resource *res;
- pid_t pid = 0;
- uid_t uid = 0;
- gid_t gid = 0;
-
- if (!(res =
- wl_resource_create(client, &wl_compositor_interface,
- version, id)))
- {
- ERR("Could not create compositor resource: %m");
- wl_client_post_no_memory(client);
- return;
- }
-
- wl_resource_set_implementation(res, &_e_comp_interface, e_comp, _e_comp_wl_compositor_cb_unbind);
-
- wl_client_get_credentials(client, &pid, &uid, &gid);
-
- ELOGF("COMP",
- "BIND |res_comp:%8p|client:%8p|%d|%d|%d",
- NULL,
- res,
- client,
- pid, uid, gid);
-
- _e_comp_wl_pname_print(pid);
-
- char name[512];
- _e_comp_wl_pname_get(pid, name, sizeof(name));
-
- _e_comp_wl_connected_client_create(name, pid, uid, gid);
-}
-
-static void
-_e_comp_wl_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
-{
- Ecore_Window win;
-
- /* make sure this is a wayland client */
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
-
- TRACE_DS_BEGIN(COMP_WL:CLIENT NEW HOOK);
-
- /* get window id from pixmap */
- win = e_pixmap_window_get(ec->pixmap);
-
- /* ignore fake root windows */
- if ((ec->override) && ((ec->x == -77) && (ec->y == -77)))
- {
- e_comp_ignore_win_add(E_PIXMAP_TYPE_WL, win);
- e_object_del(E_OBJECT(ec));
- TRACE_DS_END();
- return;
- }
-
- if (!(ec->comp_data = E_NEW(E_Comp_Wl_Client_Data, 1)))
- {
- ERR("Could not allocate new client data structure");
- TRACE_DS_END();
- return;
- }
-
- wl_signal_init(&ec->comp_data->destroy_signal);
- wl_signal_init(&ec->comp_data->apply_viewport_signal);
-
- _e_comp_wl_surface_state_init(&ec->comp_data->pending, ec->w, ec->h);
-
- /* set initial client properties */
- ec->argb = EINA_FALSE;
- ELOGF("COMP", "Set argb:%d", ec, ec->argb);
- ec->no_shape_cut = EINA_TRUE;
- ec->redirected = ec->ignored = 1;
- ec->border_size = 0;
-
- /* NB: could not find a better place to do this, BUT for internal windows,
- * we need to set delete_request else the close buttons on the frames do
- * basically nothing */
- if (ec->internal)
- ec->icccm.delete_request = EINA_TRUE;
-
- /* set initial client data properties */
- ec->comp_data->mapped = EINA_FALSE;
- ec->comp_data->first_damage = ec->internal;
-
- ec->comp_data->need_reparent = !ec->internal;
-
- /* set initial value of scaler */
- ec->comp_data->scaler.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
- ec->comp_data->scaler.buffer_viewport.buffer.scale = 1;
- ec->comp_data->scaler.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
- ec->comp_data->scaler.buffer_viewport.surface.width = -1;
-
- e_presentation_time_container_init(&ec->comp_data->presentation_container);
-
- E_Comp_Wl_Client_Data *p_cdata = e_pixmap_cdata_get(ec->pixmap);
- EINA_SAFETY_ON_NULL_GOTO(p_cdata, end);
-
- e_pixmap_cdata_set(ec->pixmap, ec->comp_data);
-
- g_mutex_init(&ec->comp_data->last_device_kbd_mutex);
- g_mutex_init(&ec->comp_data->surface_mutex);
-
-end:
- TRACE_DS_END();
-}
-
-static void
-_e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
-{
- /* Eina_Rectangle *dmg; */
- struct wl_resource *cb;
-
- /* make sure this is a wayland client */
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
-
- TRACE_DS_BEGIN(COMP_WL:CLIENT DEL CB);
-
- g_mutex_clear(&ec->comp_data->last_device_kbd_mutex);
- g_mutex_clear(&ec->comp_data->surface_mutex);
-
- _e_comp_wl_hook_call(E_COMP_WL_HOOK_DEL, ec);
-
- if ((!ec->already_unparented) && (ec->comp_data->reparented))
- _e_comp_wl_focus_down_set(ec);
-
- ec->already_unparented = EINA_TRUE;
- if (ec->comp_data->reparented)
- {
- /* reset pixmap parent window */
- e_pixmap_parent_window_set(ec->pixmap, 0);
- }
-
- if (ec->comp_data->sub.watcher)
- wl_resource_destroy(ec->comp_data->sub.watcher);
-
- wl_signal_emit(&ec->comp_data->destroy_signal, &ec->comp_data->surface);
-
- _e_comp_wl_surface_state_finish(&ec->comp_data->pending);
-
- e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, NULL);
-
- EINA_LIST_FREE(ec->comp_data->frames, cb)
- wl_resource_destroy(cb);
-
- EINA_LIST_FREE(ec->comp_data->pending.frames, cb)
- wl_resource_destroy(cb);
-
- if (ec->comp_data->surface)
- wl_resource_set_user_data(ec->comp_data->surface, NULL);
-
- _e_comp_wl_focus_check();
-
- if (ec->comp_data->aux_hint.hints)
- {
- E_Comp_Wl_Aux_Hint *hint;
- EINA_LIST_FREE(ec->comp_data->aux_hint.hints, hint)
- {
- eina_stringshare_del(hint->hint);
- eina_stringshare_del(hint->val);
- E_FREE(hint);
- }
- }
-
- if (cursor_timer_ec == ec)
- {
- E_FREE_FUNC(e_comp_wl->ptr.hide_tmr, ecore_timer_del);
- cursor_timer_ec = NULL;
- }
-
- if (e_comp_wl->ptr.ec == ec)
- e_comp_wl->ptr.ec = NULL;
-
- if (e_comp_wl->touch.faked_ec == ec)
- e_comp_wl->touch.faked_ec = NULL;
-
- struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
-
- if (e_comp_wl->selection.cbhm == surface)
- e_comp_wl->selection.cbhm = NULL;
-
- if (e_comp_wl->selection.target == ec)
- e_comp_wl->selection.target = NULL;
-
- if (ec->comp_data->viewport_transform)
- {
- e_client_transform_core_remove(ec, ec->comp_data->viewport_transform);
- e_util_transform_del(ec->comp_data->viewport_transform);
- ec->comp_data->viewport_transform = NULL;
- }
-
- e_presentation_time_container_finish(&ec->comp_data->presentation_container);
-
- _e_comp_wl_client_evas_deinit(ec);
-
- e_pixmap_cdata_set(ec->pixmap, NULL);
-
- E_FREE_FUNC(ec->comp_data->on_focus_timer, ecore_timer_del);
-
- E_FREE(ec->comp_data);
-
- _e_comp_wl_focus_check();
-
- TRACE_DS_END();
-}
-
-static void
-_e_comp_wl_client_cb_focus_set(void *data EINA_UNUSED, E_Client *ec)
-{
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
-
- /* send configure */
- if (ec->comp_data->shell.configure_send)
- {
- if (ec->comp_data->shell.surface)
- _e_comp_wl_configure_send(ec, 0, 0);
- }
-
- struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
- e_comp_wl->kbd.focus = surface;
-}
-
-static void
-_e_comp_wl_client_cb_focus_unset(void *data EINA_UNUSED, E_Client *ec)
-{
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
-
- /* send configure */
- if (ec->comp_data->shell.configure_send)
- {
- if (ec->comp_data->shell.surface)
- _e_comp_wl_configure_send(ec, 0, 0);
- }
-
- _e_comp_wl_focus_check();
-
- struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
-
- if (e_comp_wl->kbd.focus == surface)
- e_comp_wl->kbd.focus = NULL;
-}
-
-static void
-_e_comp_wl_client_cb_resize_begin(void *data EINA_UNUSED, E_Client *ec)
-{
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
- if (ec->keyboard_resizing) return;
-
- /* do nothing currently */
- ;
-}
-
-static void
-_e_comp_wl_client_cb_resize_end(void *data EINA_UNUSED, E_Client *ec)
-{
- if (e_object_is_del(E_OBJECT(ec))) return;
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
-
- e_comp_wl->resize.edges = 0;
- e_comp_wl->resize.resource = NULL;
-
- if (ec->pending_resize)
- {
- ec->changes.pos = EINA_TRUE;
- ec->changes.size = EINA_TRUE;
- EC_CHANGED(ec);
- }
-
- E_FREE_LIST(ec->pending_resize, free);
-}
-
-static void
-_e_comp_wl_client_cb_move_end(void *data EINA_UNUSED, E_Client *ec)
-{
- if (e_object_is_del(E_OBJECT(ec))) return;
- if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
-}
-
-static E_Client *
-_e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep)
-{
- /* NOTE: this will return usable E_Client for a surface of specified process
- * by pid. it doesn't care whatever this surfaces is for but care only what
- * is owner process of the surface.
- */
-
- E_Client *ec = NULL, *_ec = NULL;
- Eina_List *l;
-
- /* find launchscreen client list */
- if (e_comp->launchscrns)
- {
- EINA_LIST_FOREACH(e_comp->launchscrns, l, _ec)
- {
- if (_ec->netwm.pid == pid)
- {
- ec = _ec;
- break;
- }
- }
- if (ec)
- {
- E_Pixmap *oldep = NULL;
-
- if (ec->comp_data)
- {
- /* do NOT replace with the client having comp data */
- return NULL;
- }
-
- e_comp->launchscrns = eina_list_remove(e_comp->launchscrns, ec);
-
- oldep = e_client_pixmap_change(ec, ep);
- if (oldep)
- {
- e_pixmap_win_id_del(oldep);
- e_pixmap_free(oldep);
- }
-
- if (ec->internal)
- ec->internal = 0;
-
- /* to set-up comp data */
- _e_comp_wl_client_cb_new(NULL, ec);
- ec->ignored = 0;
- if (!ec->comp_data) return NULL;
- _e_comp_wl_client_evas_init(ec);
-
- ELOGF("COMP", "Reusable ec. new_pixmap:%p", ec, ec->pixmap);
- _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_REUSE, ec);
- }
- }
-
- return ec;
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
}
static void
return ECORE_CALLBACK_CANCEL;
}
+static void
+_e_comp_wl_cb_client_created(struct wl_listener *listener, void *data)
+{
+ struct wl_client *client = data;
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+ char name[512];
+
+ wl_client_get_credentials(client, &pid, &uid, &gid);
+
+ ELOGF("COMP", "WL_CLIENT|client:%8p|%d|%d|%d", NULL, client, pid, uid, gid);
+
+ _e_comp_wl_pname_print(pid);
+ _e_comp_wl_pname_get(pid, name, sizeof(name));
+ _e_comp_wl_connected_client_create(client, name, pid, uid, gid);
+}
+
static Eina_Bool
-_e_comp_wl_compositor_create(void)
+_e_comp_wl_display_create(void)
{
+ E_Comp_Data *comp;
E_Comp_Wl_Data *wl_cdata;
const char *name;
int fd = 0;
Eina_Bool res;
/* create new compositor data */
- if (!(wl_cdata = E_NEW(E_Comp_Wl_Data, 1)))
+ if (!(comp = E_NEW(E_Comp_Data, 1)))
{
- ERR("Could not create compositor data: %m");
- return EINA_FALSE;
+ ERR("Could not create compositor data: %m");
+ return EINA_FALSE;
}
+ wl_cdata = &comp->base;
/* set compositor wayland data */
e_comp_wl = e_comp->wl_comp_data = wl_cdata;
/* wl_cdata->output.transform = WL_OUTPUT_TRANSFORM_NORMAL; */
/* wl_cdata->output.scale = e_scale; */
- /* try to add compositor to wayland globals */
- if (!wl_global_create(wl_cdata->wl.disp, &wl_compositor_interface,
- COMPOSITOR_VERSION, e_comp,
- _e_comp_wl_compositor_cb_bind))
+ if (!e_compositor_init(wl_cdata->wl.disp))
{
- ERR("Could not add compositor to wayland globals: %m");
- goto comp_global_err;
+ ERR("Failed to initialize compositor");
+ goto comp_err;
}
- if (!e_comp_wl_subsurfaces_init(wl_cdata))
+ comp->client_created.notify = _e_comp_wl_cb_client_created;
+ wl_display_add_client_created_listener(comp->base.wl.disp, &comp->client_created);
+
+ if (!e_comp_wl_subsurfaces_init())
{
- ERR("Failed to init subsurfaces");
- goto comp_global_err;
+ ERR("Failed to init_subsurfaces");
+ goto subsurfaces_err;
}
/* initialize shm mechanism */
input_err:
e_comp_wl_data_manager_shutdown();
data_err:
-comp_global_err:
+ e_comp_wl_subsurfaces_shutdown();
+subsurfaces_err:
+ wl_list_remove(&comp->client_created.link);
+comp_err:
e_env_unset("WAYLAND_DISPLAY");
sock_err:
wl_display_destroy(wl_cdata->wl.disp);
disp_err:
- free(wl_cdata);
+ free(comp);
return EINA_FALSE;
}
TRACE_DS_BEGIN(COMP_WL:INIT);
/* try to create a wayland compositor */
- if (!_e_comp_wl_compositor_create())
+ if (!_e_comp_wl_display_create())
{
e_error_message_show(_("Enlightenment cannot create a Wayland Compositor!\n"));
TRACE_DS_END();
E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_END, _e_comp_wl_cb_client_rot_change_end, NULL);
/* add hooks to catch e_client events */
- E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_NEW_CLIENT, _e_comp_wl_client_cb_new, NULL);
- E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_DEL, _e_comp_wl_client_cb_del, NULL);
E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_FOCUS_SET, _e_comp_wl_client_cb_focus_set, NULL);
E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_FOCUS_UNSET, _e_comp_wl_client_cb_focus_unset, NULL);
E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_RESIZE_BEGIN, _e_comp_wl_client_cb_resize_begin, NULL);
EINTERN void
e_comp_wl_shutdown(void)
{
+ E_Comp_Data *comp = (E_Comp_Data *)e_comp_wl;
+
ecore_idle_exiter_del(e_comp_wl->idle_exiter);
e_comp_wl_subsurfaces_shutdown();
e_comp_wl_video_shutdown();
e_comp_wl_screenshooter_shutdown();
-#ifdef HAVE_WAYLAND_TBM
- e_comp_wl_tbm_shutdown();
-#endif
e_comp_wl_remote_surface_shutdown();
e_pixmap_shutdown();
e_comp_wl_shell_shutdown();
e_comp_wl_input_shutdown();
+ wl_list_remove(&comp->client_created.link);
+
+ e_comp_wl = NULL;
+ e_comp->wl_comp_data = NULL;
+ free(comp);
// TODO: yigl
#if 0
E_Comp_Wl_Output *output;
ec->comp_data->surface = surface;
g_mutex_unlock(&ec->comp_data->surface_mutex);
}
+
+EINTERN E_Client *
+e_comp_wl_util_client_from_surface_resource(struct wl_resource *surface_resource)
+{
+ return e_compositor_util_client_from_surface_resource(surface_resource);
+}
+
+EINTERN void
+e_comp_wl_client_surface_pending_buffer_set(E_Client *ec, E_Comp_Wl_Buffer *buffer, int32_t sx, int32_t sy)
+{
+ if (!ec->comp_data->mapped)
+ {
+ if (ec->comp_data->shell.surface &&
+ !ec->internal && !e_comp_wl_subsurface_check(ec) && !ec->remote_surface.provider)
+ {
+ ELOGF("COMP", "Current unmapped. ATTACH buffer:%p", ec, buffer);
+ }
+ }
+
+ if (!buffer)
+ {
+ if (ec->comp_data->mapped)
+ {
+ /* will be unmapped. so run capture */
+ e_comp_wl_remote_surface_image_save(ec);
+ }
+ }
+
+ _e_comp_wl_surface_state_buffer_set(&ec->comp_data->pending, buffer);
+
+ ec->comp_data->pending.sx = sx;
+ ec->comp_data->pending.sy = sy;
+ ec->comp_data->pending.new_attach = EINA_TRUE;
+
+ e_client_fps_update(ec);
+}
+
+EINTERN void
+e_comp_wl_client_surface_pending_opaque_region_set(E_Client *ec, Eina_Tiler *region)
+{
+ if (ec->comp_data->pending.opaque)
+ eina_tiler_clear(ec->comp_data->pending.opaque);
+
+ if (region)
+ {
+ eina_tiler_union(ec->comp_data->pending.opaque, region);
+
+ if (!eina_tiler_empty(ec->comp_data->pending.opaque))
+ {
+ if (ec->argb)
+ {
+ ec->argb = EINA_FALSE;
+ ELOGF("COMP", "Set argb:%d", ec, ec->argb);
+ EC_CHANGED(ec);
+ _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_ALPHA_CHANGE, ec);
+ e_comp_object_alpha_set(ec->frame, EINA_FALSE);
+ }
+ }
+ }
+ else
+ {
+ if (!ec->argb)
+ {
+ ec->argb = EINA_TRUE;
+ ELOGF("COMP", "Set argb:%d", ec, ec->argb);
+ EC_CHANGED(ec);
+ _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_ALPHA_CHANGE, ec);
+ e_comp_object_alpha_set(ec->frame, EINA_TRUE);
+ }
+ }
+}
+
+EINTERN void
+e_comp_wl_client_surface_pending_input_region_set(E_Client *ec, Eina_Tiler *region)
+{
+ if (ec->comp_data->pending.input)
+ eina_tiler_clear(ec->comp_data->pending.input);
+
+ if (region)
+ {
+ if (eina_tiler_empty(region))
+ {
+ ELOGF("COMP", " |unset input rect", NULL);
+ e_comp_object_input_objs_del(ec->frame);
+ e_comp_object_input_area_set(ec->frame, -1, -1, 1, 1);
+ }
+ else
+ eina_tiler_union(ec->comp_data->pending.input, region);
+ }
+ else
+ {
+ eina_tiler_rect_add(ec->comp_data->pending.input,
+ &(Eina_Rectangle){0, 0, ec->client.w, ec->client.h});
+ }
+}
+
+EINTERN void
+e_comp_wl_client_surface_pending_frame_callback_add(E_Client *ec, struct wl_resource *callback_resource)
+{
+ ec->comp_data->pending.frames = eina_list_prepend(ec->comp_data->pending.frames, callback_resource);
+}
+
+EINTERN void
+e_comp_wl_client_surface_frame_callback_remove(E_Client *ec, struct wl_resource *callback_resource)
+{
+ E_Comp_Wl_Subsurf_Data *sdata;
+
+ if (!ec->comp_data)
+ return;
+
+ if (ec->comp_data->frames)
+ {
+ ec->comp_data->frames =
+ eina_list_remove(ec->comp_data->frames, callback_resource);
+ }
+
+ if (ec->comp_data->pending.frames)
+ {
+ ec->comp_data->pending.frames =
+ eina_list_remove(ec->comp_data->pending.frames, callback_resource);
+ }
+
+ sdata = ec->comp_data->sub.data;
+ if ((sdata) && (sdata->cached.frames))
+ {
+ sdata->cached.frames =
+ eina_list_remove(sdata->cached.frames, callback_resource);
+ }
+}
+
+EINTERN void
+e_comp_wl_client_surface_pending_commit(E_Client *ec)
+{
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (e_comp_wl_remote_surface_commit(ec)) return;
+
+ e_comp_wl_surface_commit(ec);
+
+ _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_SURFACE_COMMIT, ec);
+}
+
+static void
+_e_comp_wl_client_subsurface_set(E_Client *ec, E_Comp_Wl_Subsurf_Data *sub)
+{
+ ec->comp_data->surface = ec->comp_data->wl_surface;
+ ec->comp_data->sub.data = sub;
+
+ /* set subsurface client properties */
+ ec->borderless = EINA_TRUE;
+ ec->argb = EINA_TRUE;
+ ELOGF("SUBSURFACE", "Set argb:%d", ec, ec->argb);
+ ec->lock_border = EINA_TRUE;
+ ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
+ ec->netwm.state.skip_taskbar = EINA_TRUE;
+ ec->netwm.state.skip_pager = EINA_TRUE;
+ ec->no_shape_cut = EINA_TRUE;
+ ec->border_size = 0;
+ ec->lock_user_location = 0;
+ ec->lock_client_location = 0;
+ ec->lock_user_size = 0;
+ ec->lock_client_size = 0;
+ ec->lock_client_stacking = 0;
+ ec->lock_user_shade = 0;
+ ec->lock_client_shade = 0;
+ ec->lock_user_maximize = 0;
+ ec->lock_client_maximize = 0;
+ ec->changes.need_maximize = 0;
+ ec->maximized = E_MAXIMIZE_NONE;
+ EC_CHANGED(ec);
+
+ ec->new_client = ec->netwm.ping = EINA_TRUE;
+ e_comp->new_clients++;
+ e_client_unignore(ec);
+
+ /* Delete 'below_obj' if it was created before 'E_Client' becomes subsurface.
+ * It's not for subsurface. */
+ E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
+}
+
+static void
+_e_comp_wl_client_subsurface_parent_set(E_Client *ec, E_Client *parent)
+{
+ E_Comp_Wl_Subsurf_Data *sub = ec->comp_data->sub.data;
+ E_Layer layer;
+
+ ELOGF("COMP", " |subsurface_parent:%p", ec, parent);
+
+ sub->parent = parent;
+
+ if (parent->frame)
+ {
+ layer = e_client_layer_get(parent);
+ if (layer > E_LAYER_BOTTOM)
+ e_client_layer_set(ec, layer);
+ }
+
+ if (parent->comp_data)
+ {
+ /* append this client to the parents subsurface list */
+ parent->comp_data->sub.list_pending =
+ eina_list_append(parent->comp_data->sub.list_pending, ec);
+ parent->comp_data->sub.list_changed = EINA_TRUE;
+ }
+}
+
+EINTERN void
+e_comp_wl_client_subsurface_parent_unset(E_Client *ec)
+{
+ E_Comp_Wl_Subsurf_Data *sub = ec->comp_data->sub.data;
+ E_Client *parent = sub->parent;
+
+ parent->comp_data->sub.list =
+ eina_list_remove(parent->comp_data->sub.list, ec);
+ parent->comp_data->sub.list_pending =
+ eina_list_remove(parent->comp_data->sub.list_pending, ec);
+ parent->comp_data->sub.below_list =
+ eina_list_remove(parent->comp_data->sub.below_list, ec);
+ parent->comp_data->sub.below_list_pending =
+ eina_list_remove(parent->comp_data->sub.below_list_pending, ec);
+
+ sub->parent = NULL;
+}
+
+EINTERN void
+e_comp_wl_client_subsurface_init(E_Client *ec, struct wl_resource *subsurface_resource, E_Comp_Wl_Subsurf_Data *sub, E_Client *parent, E_Client *offscreen_parent)
+{
+ sub->resource = subsurface_resource;
+ sub->cached_buffer_ref.buffer = NULL;
+ sub->synchronized = EINA_TRUE;
+ sub->parent = parent;
+ sub->remote_surface.offscreen_parent = offscreen_parent;
+ if (offscreen_parent)
+ ELOGF("SUBSURFACE", " |offscreen_parent:%p", ec, offscreen_parent);
+
+ _e_comp_wl_surface_state_init(&sub->cached, ec->w, ec->h);
+
+ _e_comp_wl_client_subsurface_set(ec, sub);
+ _e_comp_wl_client_subsurface_parent_set(ec, parent);
+
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
+}
+
+EINTERN void
+e_comp_wl_client_subsurface_finish(E_Client *ec)
+{
+ E_Comp_Wl_Subsurf_Data *sub = ec->comp_data->sub.data;
+
+ if (sub->parent)
+ e_comp_wl_client_subsurface_parent_unset(ec);
+
+ e_comp_wl_surface_state_finish(&sub->cached);
+ e_comp_wl_buffer_reference(&sub->cached_buffer_ref, NULL);
+
+ ec->comp_data->sub.data = NULL;
+}
+
+EINTERN void
+e_comp_wl_client_evas_init(E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ _e_comp_wl_client_evas_init(ec);
+}
+
+EINTERN void
+e_comp_wl_client_evas_deinit(E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ _e_comp_wl_client_evas_deinit(ec);
+}
+
+EINTERN void
+e_comp_wl_focus_check(void)
+{
+ _e_comp_wl_focus_check();
+}
+
+EINTERN Eina_Bool
+e_comp_wl_client_subsurface_cyclic_reference_check(E_Client *ec, E_Client *parent)
+{
+ while (parent)
+ {
+ if (ec == parent)
+ return EINA_TRUE;
+
+ if ((parent->comp_data) && (parent->comp_data->sub.data))
+ parent = parent->comp_data->sub.data->parent;
+ else
+ break;
+ }
+
+ return EINA_FALSE;
+}
EINTERN void e_comp_wl_surface_attach(E_Client *ec, E_Comp_Wl_Buffer *buffer);
EINTERN Eina_Bool e_comp_wl_surface_commit(E_Client *ec);
E_API void e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer);
-EINTERN E_Comp_Wl_Buffer *e_comp_wl_buffer_get(struct wl_resource *resource, E_Client *ec);
EINTERN Eina_Bool e_comp_wl_output_init(const char *id, const char *make, const char *model, int x, int y, int w, int h, int pw, int ph, unsigned int refresh, unsigned int subpixel, unsigned int transform);
EINTERN void e_comp_wl_output_remove(const char *id);
EINTERN void e_comp_wl_client_surface_set(E_Client *ec, struct wl_resource *surface);
EINTERN void e_comp_wl_display_flush();
+
+EINTERN E_Client *e_comp_wl_util_client_from_surface_resource(struct wl_resource *surface_resource);
+
# endif
#endif
#include "e_comp_wl_private.h"
+typedef struct _E_Buffer E_Buffer;
+
+struct _E_Buffer
+{
+ E_Comp_Wl_Buffer base;
+ struct ds_buffer *ds_buffer;
+};
+
static void _e_comp_wl_buffer_ref(E_Comp_Wl_Buffer *buffer);
static void _e_comp_wl_buffer_unref(E_Comp_Wl_Buffer *buffer);
static void _e_comp_wl_buffer_reference_cb_destroy(struct wl_listener *listener, void *data);
-static void _e_comp_wl_buffer_cb_destroy(struct wl_listener *listener, void *data);
-static Eina_Bool _e_comp_wl_buffer_native_type_get(E_Comp_Wl_Buffer *buffer, struct wl_resource *resource, E_Client *ec);
-static Eina_Bool _e_comp_wl_buffer_tbm_type_get(E_Comp_Wl_Buffer *buffer, struct wl_resource *resource, E_Client *ec);
+
+static E_Buffer *_e_buffer_create(struct ds_buffer *ds_buffer, E_Client *ec);
+static E_Buffer *_e_buffer_from_base(E_Comp_Wl_Buffer *base);
+static void _e_buffer_cb_resource_destroy(struct wl_listener *listener, void *data);
E_API void
e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer)
}
/**
- * Get the buffer for a given resource.
+ * Get the buffer for a given ds_buffer.
*
- * Retrieves the Wayland SHM buffer for the resource and
+ * Retrieves the Wayland SHM buffer for the ds_buffer and
* uses it to create a new E_Comp_Wl_Buffer object. This
* buffer will be freed when the resource is destroyed.
*
- * @param resource that owns the desired buffer
+ * @param ds_buffer that owns the desired buffer
* @returns a new E_Comp_Wl_Buffer object
*/
EINTERN E_Comp_Wl_Buffer *
-e_comp_wl_buffer_get(struct wl_resource *resource, E_Client *ec)
+e_comp_wl_buffer_get(struct ds_buffer *ds_buffer, E_Client *ec)
{
- E_Comp_Wl_Buffer *buffer = NULL;
+ E_Buffer *buffer;
struct wl_listener *listener;
- struct wl_shm_buffer *shmbuff;
- E_Single_Pixel_Buffer *single_pixel_buffer;
- Eina_Bool res;
+ struct wl_resource *buffer_resource;
- listener =
- wl_resource_get_destroy_listener(resource, _e_comp_wl_buffer_cb_destroy);
+ buffer_resource = ds_buffer_get_resource(ds_buffer);
+ listener = wl_resource_get_destroy_listener(buffer_resource, _e_buffer_cb_resource_destroy);
if (listener)
{
- buffer = container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
- goto update;
+ buffer = wl_container_of(listener, buffer, base.destroy_listener);
+ goto done;
}
- if (!(buffer = E_NEW(E_Comp_Wl_Buffer, 1))) return NULL;
-
- shmbuff = wl_shm_buffer_get(resource);
- if (shmbuff)
+ buffer = _e_buffer_create(ds_buffer, ec);
+ if (!buffer)
{
- buffer->type = E_COMP_WL_BUFFER_TYPE_SHM;
- buffer->w = wl_shm_buffer_get_width(shmbuff);
- buffer->h = wl_shm_buffer_get_height(shmbuff);
- buffer->format = wl_shm_buffer_get_format(shmbuff);
- buffer->shm_buffer = shmbuff;
+ ERR("Failed to create E_Comp_Wl_Buffer");
+ return NULL;
}
- if (!buffer->type)
- {
- single_pixel_buffer = e_single_pixel_buffer_manager_buffer_get(resource);
- if (single_pixel_buffer)
- {
- buffer->type = E_COMP_WL_BUFFER_TYPE_SINGLE_PIXEL;
- buffer->w = 1;
- buffer->h = 1;
- buffer->format = WL_SHM_FORMAT_ARGB8888;
- buffer->single_pixel_buffer = single_pixel_buffer;
- }
- }
+done:
+ if (buffer->base.tbm_surface)
+ buffer->base.transform = wayland_tbm_server_buffer_get_buffer_transform(NULL, buffer->base.resource);
- if (!buffer->type)
- {
- /* TODO: This option is temporarily. It will be removed later. */
- /* prefer to use native buffer(wl_buffer) */
- if (e_comp->use_native_type_buffer)
- {
- if (e_comp->gl)
- {
- res = _e_comp_wl_buffer_native_type_get(buffer, resource, ec);
- EINA_SAFETY_ON_FALSE_GOTO(res, err);
- }
- else
- {
- res = _e_comp_wl_buffer_tbm_type_get(buffer, resource, ec);
- EINA_SAFETY_ON_FALSE_GOTO(res, err);
- }
- }
- else
- {
- res = _e_comp_wl_buffer_tbm_type_get(buffer, resource, ec);
- if (!res && e_comp->gl)
- res = _e_comp_wl_buffer_native_type_get(buffer,resource, ec);
-
- EINA_SAFETY_ON_FALSE_GOTO(res, err);
- }
- }
+ return &buffer->base;
+}
- buffer->resource = resource;
- wl_signal_init(&buffer->destroy_signal);
- buffer->destroy_listener.notify = _e_comp_wl_buffer_cb_destroy;
- wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
+static void
+_e_comp_wl_buffer_ref(E_Comp_Wl_Buffer *base)
+{
+ E_Buffer *buffer;
- if (ec)
+ base->busy++;
+ if (base->busy == 1)
{
- buffer->debug_info.owner_ptr = (void *)ec;
- buffer->debug_info.owner_name = eina_stringshare_add(ec->icccm.name?:"");
+ buffer = _e_buffer_from_base(base);
+ if (buffer)
+ ds_buffer_lock(buffer->ds_buffer);
}
-
- DBG("Wl Buffer Create: b %p owner '%s'(%p)",
- buffer, buffer->debug_info.owner_name, buffer->debug_info.owner_ptr);
-
-update:
- if (buffer->tbm_surface)
- buffer->transform = wayland_tbm_server_buffer_get_buffer_transform(NULL, resource);
-
- return buffer;
-
-err:
- ERR("Invalid resource:%u", wl_resource_get_id(resource));
- E_FREE(buffer);
- return NULL;
}
static void
-_e_comp_wl_buffer_ref(E_Comp_Wl_Buffer *buffer)
+_e_comp_wl_buffer_unref(E_Comp_Wl_Buffer *base)
{
- buffer->busy++;
-}
+ E_Buffer *buffer;
-static void
-_e_comp_wl_buffer_unref(E_Comp_Wl_Buffer *buffer)
-{
- buffer->busy--;
- if (buffer->busy != 0)
+ base->busy--;
+ if (base->busy != 0)
return;
- if (buffer->buffer_release)
+ if (base->buffer_release)
{
- e_explicit_sync_buffer_release_destroy(buffer->buffer_release);
- buffer->buffer_release = NULL;
+ e_explicit_sync_buffer_release_destroy(base->buffer_release);
+ base->buffer_release = NULL;
}
- if (buffer->resource)
+ if (base->resource)
{
- if (!wl_resource_get_client(buffer->resource)) return;
+ buffer = _e_buffer_from_base(base);
+ if (buffer)
+ ds_buffer_unlock(buffer->ds_buffer);
+ else
+ wl_buffer_send_release(base->resource);
- wl_buffer_send_release(buffer->resource);
#ifdef HAVE_WAYLAND_TBM
wayland_tbm_server_increase_buffer_sync_timeline(e_comp_wl->tbm.server,
- buffer->resource, 1);
+ base->resource, 1);
#endif
}
else
{
- if (buffer->type == E_COMP_WL_BUFFER_TYPE_TBM)
- e_comp_wl_tbm_buffer_destroy(buffer);
+ if (base->type == E_COMP_WL_BUFFER_TYPE_TBM)
+ e_comp_wl_tbm_buffer_destroy(base);
}
}
_e_comp_wl_buffer_reference_cb_destroy(struct wl_listener *listener, void *data)
{
E_Comp_Wl_Buffer_Ref *ref;
+ E_Buffer *buffer;
ref = container_of(listener, E_Comp_Wl_Buffer_Ref, destroy_listener);
- wl_list_remove(&ref->destroy_listener.link);
- ref->buffer = NULL;
-}
-
-static void
-_e_comp_wl_buffer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
-{
- E_Comp_Wl_Buffer *buffer;
-
- buffer = container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
-
- DBG("Wl Buffer Destroy: b %p owner '%s'(%p)",
- buffer, buffer->debug_info.owner_name, buffer->debug_info.owner_ptr);
-
- /* remove debug info */
- eina_stringshare_del(buffer->debug_info.owner_name);
-
- if (buffer->tbm_surface) tbm_surface_internal_unref(buffer->tbm_surface);
-
- if (buffer->buffer_release)
- e_explicit_sync_buffer_release_destroy(buffer->buffer_release);
- wl_signal_emit(&buffer->destroy_signal, buffer);
-
- if (buffer->destroy_listener.notify)
+ if (--ref->buffer->busy == 0)
{
- wl_list_remove(&buffer->destroy_listener.link);
- buffer->destroy_listener.notify = NULL;
+ buffer = _e_buffer_from_base(ref->buffer);
+ if (buffer)
+ ds_buffer_unlock(buffer->ds_buffer);
}
- free(buffer);
+ wl_list_remove(&ref->destroy_listener.link);
+ ref->buffer = NULL;
}
static Eina_Bool
-_e_comp_wl_buffer_native_type_get(E_Comp_Wl_Buffer *buffer, struct wl_resource *resource,
+_e_comp_wl_buffer_native_type_get(E_Comp_Wl_Buffer *base, struct wl_resource *resource,
E_Client *ec)
{
Eina_Bool res;
- if (!buffer || !resource || !ec) return EINA_FALSE;
+ if (!base || !resource || !ec) return EINA_FALSE;
- buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
+ base->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
res = e_comp_wl->evas_gl->glapi->evasglQueryWaylandBuffer(e_comp_wl->evas_gl->gl,
resource,
EVAS_GL_WIDTH,
- &buffer->w);
+ &base->w);
EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EINA_FALSE);
res = e_comp_wl->evas_gl->glapi->evasglQueryWaylandBuffer(e_comp_wl->evas_gl->gl,
resource,
EVAS_GL_HEIGHT,
- &buffer->h);
+ &base->h);
EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EINA_FALSE);
res = e_comp_wl->evas_gl->glapi->evasglQueryWaylandBuffer(e_comp_wl->evas_gl->gl,
resource,
EVAS_GL_TEXTURE_FORMAT,
- &buffer->format);
+ &base->format);
EINA_SAFETY_ON_FALSE_RETURN_VAL(res, EINA_FALSE);
return EINA_TRUE;
}
static Eina_Bool
-_e_comp_wl_buffer_tbm_type_get(E_Comp_Wl_Buffer *buffer, struct wl_resource *resource,
+_e_comp_wl_buffer_tbm_type_get(E_Comp_Wl_Buffer *base, struct wl_resource *resource,
E_Client *ec)
{
tbm_surface_h tsurface;
struct gbm_bo *gbo;
- if (!buffer || !resource || !ec) return EINA_FALSE;
+ if (!base || !resource || !ec) return EINA_FALSE;
tsurface = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
if (tsurface)
if ((ec) && (ec->comp_data->video_client))
{
- buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
- buffer->w = buffer->h = 1;
- buffer->format = 0;
+ base->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
+ base->w = base->h = 1;
+ base->format = 0;
}
else if ((ec) && (e_client_video_hw_composition_check(ec)))
{
- buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
- buffer->w = tbm_surface_get_width(tsurface);
- buffer->h = tbm_surface_get_height(tsurface);
- buffer->format = tbm_surface_get_format(tsurface);
+ base->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
+ base->w = tbm_surface_get_width(tsurface);
+ base->h = tbm_surface_get_height(tsurface);
+ base->format = tbm_surface_get_format(tsurface);
}
else
{
- buffer->type = E_COMP_WL_BUFFER_TYPE_TBM;
- buffer->w = tbm_surface_get_width(tsurface);
- buffer->h = tbm_surface_get_height(tsurface);
- buffer->format = tbm_surface_get_format(tsurface);
+ base->type = E_COMP_WL_BUFFER_TYPE_TBM;
+ base->w = tbm_surface_get_width(tsurface);
+ base->h = tbm_surface_get_height(tsurface);
+ base->format = tbm_surface_get_format(tsurface);
}
- buffer->tbm_surface = tsurface;
+ base->tbm_surface = tsurface;
return EINA_TRUE;
}
+static Eina_Bool
+_e_comp_wl_buffer_init(E_Comp_Wl_Buffer *base, struct wl_resource *resource, E_Client *ec)
+{
+ struct wl_shm_buffer *shmbuff;
+ E_Single_Pixel_Buffer *single_pixel_buffer;
+ Eina_Bool res;
+
+ shmbuff = wl_shm_buffer_get(resource);
+ if (shmbuff)
+ {
+ base->type = E_COMP_WL_BUFFER_TYPE_SHM;
+ base->w = wl_shm_buffer_get_width(shmbuff);
+ base->h = wl_shm_buffer_get_height(shmbuff);
+ base->format = wl_shm_buffer_get_format(shmbuff);
+ base->shm_buffer = shmbuff;
+ }
+
+ if (!base->type)
+ {
+ single_pixel_buffer = e_single_pixel_buffer_manager_buffer_get(resource);
+ if (single_pixel_buffer)
+ {
+ base->type = E_COMP_WL_BUFFER_TYPE_SINGLE_PIXEL;
+ base->w = 1;
+ base->h = 1;
+ base->format = WL_SHM_FORMAT_ARGB8888;
+ base->single_pixel_buffer = single_pixel_buffer;
+ }
+ }
+
+ if (!base->type)
+ {
+ /* TODO: This option is temporarily. It will be removed later. */
+ /* prefer to use native base(wl_buffer) */
+ if (e_comp->use_native_type_buffer)
+ {
+ if (e_comp->gl)
+ {
+ res = _e_comp_wl_buffer_native_type_get(base, resource, ec);
+ EINA_SAFETY_ON_FALSE_GOTO(res, err);
+ }
+ else
+ {
+ res = _e_comp_wl_buffer_tbm_type_get(base, resource, ec);
+ EINA_SAFETY_ON_FALSE_GOTO(res, err);
+ }
+ }
+ else
+ {
+ res = _e_comp_wl_buffer_tbm_type_get(base, resource, ec);
+ if (!res && e_comp->gl)
+ res = _e_comp_wl_buffer_native_type_get(base,resource, ec);
+
+ EINA_SAFETY_ON_FALSE_GOTO(res, err);
+ }
+ }
+
+ base->resource = resource;
+ wl_signal_init(&base->destroy_signal);
+
+ if (ec)
+ {
+ base->debug_info.owner_ptr = (void *)ec;
+ base->debug_info.owner_name = eina_stringshare_add(ec->icccm.name?:"");
+ }
+
+ DBG("Wl Buffer Create: b %p owner '%s'(%p)",
+ base, base->debug_info.owner_name, base->debug_info.owner_ptr);
+
+ return EINA_TRUE;
+
+err:
+ ERR("Invalid resource:%u", wl_resource_get_id(resource));
+ return EINA_FALSE;
+}
+
+static void
+_e_comp_wl_buffer_finish(E_Comp_Wl_Buffer *base)
+{
+ DBG("Wl Buffer Destroy: b %p owner '%s'(%p)",
+ base, base->debug_info.owner_name, base->debug_info.owner_ptr);
+
+ /* remove debug info */
+ eina_stringshare_del(base->debug_info.owner_name);
+
+ if (base->tbm_surface) tbm_surface_internal_unref(base->tbm_surface);
+
+ if (base->buffer_release)
+ e_explicit_sync_buffer_release_destroy(base->buffer_release);
+
+ wl_signal_emit(&base->destroy_signal, base);
+}
+
+static E_Buffer *
+_e_buffer_create(struct ds_buffer *ds_buffer, E_Client *ec)
+{
+ E_Buffer *buffer;
+ struct wl_resource *buffer_resource;
+
+ buffer = E_NEW(E_Buffer, 1);
+ if (!buffer)
+ return NULL;
+
+ buffer->ds_buffer = ds_buffer;
+
+ buffer_resource = ds_buffer_get_resource(ds_buffer);
+ if (!_e_comp_wl_buffer_init(&buffer->base, buffer_resource, ec))
+ {
+ free(buffer);
+ return NULL;
+ }
+
+ buffer->base.destroy_listener.notify = _e_buffer_cb_resource_destroy;
+ wl_resource_add_destroy_listener(buffer_resource, &buffer->base.destroy_listener);
+
+ return buffer;
+}
+
+static E_Buffer *
+_e_buffer_from_base(E_Comp_Wl_Buffer *base)
+{
+ if (base->destroy_listener.notify == _e_buffer_cb_resource_destroy)
+ return (E_Buffer *)base;
+ return NULL;
+}
+
+static void
+_e_buffer_cb_resource_destroy(struct wl_listener *listener, void *data)
+{
+ E_Buffer *buffer;
+
+ buffer = wl_container_of(listener, buffer, base.destroy_listener);
+
+ _e_comp_wl_buffer_finish(&buffer->base);
+ wl_list_remove(&buffer->base.destroy_listener.link);
+ free(buffer);
+}
#ifndef E_COMP_WL_BUFFER_H
#define E_COMP_WL_BUFFER_H
-EINTERN E_Comp_Wl_Buffer *e_comp_wl_buffer_get(struct wl_resource *resource, E_Client *ec);
+#include <libds/types/ds_buffer.h>
+
+EINTERN E_Comp_Wl_Buffer *e_comp_wl_buffer_get(struct ds_buffer *ds_buffer, E_Client *ec);
#endif
#include "e.h"
#include "e_comp_wl_buffer.h"
+#include "e_compositor.h"
struct _E_Comp_Wl_Evas_Gl
{
Evas_GL_API *glapi;
};
+EINTERN void e_comp_wl_focus_check(void);
+
+EINTERN void e_comp_wl_client_evas_init(E_Client *ec);
+EINTERN void e_comp_wl_client_evas_deinit(E_Client *ec);
+
+EINTERN void e_comp_wl_client_surface_init(E_Client *ec);
+EINTERN void e_comp_wl_client_surface_finish(E_Client *ec);
+EINTERN void e_comp_wl_client_surface_pending_buffer_set(E_Client *ec, E_Comp_Wl_Buffer *buffer, int32_t sx, int32_t sy);
+EINTERN void e_comp_wl_client_surface_pending_opaque_region_set(E_Client *ec, Eina_Tiler *region);
+EINTERN void e_comp_wl_client_surface_pending_input_region_set(E_Client *ec, Eina_Tiler *region);
+EINTERN void e_comp_wl_client_surface_pending_frame_callback_add(E_Client *ec, struct wl_resource *callback_resource);
+EINTERN void e_comp_wl_client_surface_frame_callback_remove(E_Client *ec, struct wl_resource *callback_resource);
+EINTERN void e_comp_wl_client_surface_pending_commit(E_Client *ec);
+
+EINTERN void e_comp_wl_client_subsurface_init(E_Client *ec, struct wl_resource *subsurface_resource, E_Comp_Wl_Subsurf_Data *sub, E_Client *parent, E_Client *offscreen_parent);
+EINTERN void e_comp_wl_client_subsurface_finish(E_Client *ec);
+EINTERN void e_comp_wl_client_subsurface_parent_unset(E_Client *ec);
+EINTERN Eina_Bool e_comp_wl_client_subsurface_cyclic_reference_check(E_Client *ec, E_Client *parent);
+EINTERN void e_comp_wl_client_subsurface_commit_to_cache(E_Client *ec);
+EINTERN void e_comp_wl_client_subsurface_commit_from_cache(E_Client *ec);
+
#endif
#include <tizen-extension-server-protocol.h>
-typedef struct _E_Subsurface E_Subsurface;
-
-struct _E_Subsurface
-{
- /* NOTE
- * DO NOT move 'base' from first field.
- * The address of it is assigned to ec->comp_data->sub.data and be used
- * to access not only E_Comp_Wl_Subsurf_Data, but also E_Subsurface. */
- E_Comp_Wl_Subsurf_Data base;
-
- E_Client *ec;
-
- struct
- {
- E_Comp_Wl_Hook *ec_del;
- E_Comp_Wl_Hook *parent_del;
- } comp_hook;
-};
-
-static struct wl_global *global = NULL;
static Eina_List *hooks = NULL;
static Eina_List *handlers = NULL;
-static const char *e_comp_wl_subsurface_role_name = "wl_subsurface";
-
static E_Comp_Wl_Subsurf_Data *_e_comp_wl_subsurface_data_get(E_Client *ec);
-static Eina_Bool _e_comp_wl_subsurface_circular_reference_check(E_Client *ec, E_Client *parent);
-static void _e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized);
-static Eina_Bool _e_comp_wl_subsurface_synchronized_get(E_Comp_Wl_Subsurf_Data *sdata);
-static void _e_comp_wl_subsurface_synchronized_commit(E_Client *ec);
-static void _e_comp_wl_subsurface_remove_from_parent(E_Client *parent, E_Client *subc);
-static void _e_comp_wl_subsurface_child_remove(E_Comp_Wl_Client_Data *parent_cdata, E_Client *child);
-static void _e_comp_wl_subsurface_place_above(E_Client *parent, E_Client *subc, E_Client *above);
-static void _e_comp_wl_subsurface_place_below(E_Client *parent, E_Client *subc, E_Client *below);
+static void _e_comp_wl_subsurface_commit_to_cache(E_Client *ec);
+static void _e_comp_wl_subsurface_commit_from_cache(E_Client *ec);
static void _e_comp_wl_subsurface_stack_update(E_Client *ec);
static void _e_comp_wl_subsurface_below_obj_destroy(E_Client *ec);
-static E_Subsurface *_e_comp_wl_subsurface_create(struct wl_resource *resource, E_Client *ec, E_Client *epc, E_Client *offscreen_parent);
-static void _e_comp_wl_subsurface_destroy(E_Subsurface *sub);
-static void _e_comp_wl_subsurface_ec_link(E_Subsurface *sub, E_Client *ec);
-static void _e_comp_wl_subsurface_parent_link(E_Subsurface *sub, E_Client *parent);
-static void _e_comp_wl_subsurface_parent_unlink(E_Subsurface *sub);
+EINTERN void
+e_comp_wl_client_subsurface_commit_to_cache(E_Client *ec)
+{
+ _e_comp_wl_subsurface_commit_to_cache(ec);
+}
+
+EINTERN void
+e_comp_wl_client_subsurface_commit_from_cache(E_Client *ec)
+{
+ _e_comp_wl_subsurface_commit_from_cache(ec);
+}
static void
_e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec)
l);
}
- e_presentation_time_container_feedback_discard(&sdata->cached.presentation_container);
- e_presentation_time_container_feedback_merge(&sdata->cached.presentation_container,
- &cdata->pending.presentation_container);
-
- e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_COMMIT_TO_CACHE, ec);
-
sdata->cached.has_data = EINA_TRUE;
}
}
static void
-_e_comp_wl_subsurface_synchronized_commit(E_Client *ec)
-{
- E_Comp_Wl_Subsurf_Data *sdata;
- E_Client *subc;
- Eina_List *l;
-
- sdata = _e_comp_wl_subsurface_data_get(ec);
- EINA_SAFETY_ON_NULL_RETURN(sdata);
-
- if (sdata->cached.has_data)
- _e_comp_wl_subsurface_commit_from_cache(ec);
-
- e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_SYNCHRONIZED_COMMIT, ec);
-
- EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
- {
- if (ec != subc)
- _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
- }
- EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
- {
- if (ec != subc)
- _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
- }
-}
-
-static void
-_e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
-{
- E_Client *parent;
- E_Comp_Wl_Subsurf_Data *sdata;
-
- if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
-
- sdata = _e_comp_wl_subsurface_data_get(ec);
- EINA_SAFETY_ON_NULL_RETURN(sdata);
-
- if (!(parent = sdata->parent)) return;
-
- if (sdata->position.set)
- {
- evas_object_move(ec->frame, parent->x + sdata->position.x,
- parent->y + sdata->position.y);
- sdata->position.set = EINA_FALSE;
- }
-
- if ((parent_synchronized) || (sdata->synchronized))
- _e_comp_wl_subsurface_synchronized_commit(ec);
-}
-
-static void
-_e_comp_wl_subsurface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
-{
- wl_resource_destroy(resource);
-}
-
-static void
-_e_comp_wl_subsurface_cb_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y)
-{
- E_Subsurface *sub;
-
- DBG("Subsurface Cb Position Set: %d", wl_resource_get_id(resource));
-
- sub = wl_resource_get_user_data(resource);
- if (!sub)
- return;
-
- sub->base.position.x = x;
- sub->base.position.y = y;
- sub->base.position.set = EINA_TRUE;
-}
-
-static Eina_Bool
-_subsurface_sibling_check(E_Client *ec1, E_Client *ec2)
-{
- E_Client *parent, *sibling;
- Eina_List *l;
-
- parent = ec1->comp_data->sub.data->parent;
-
- if (parent == ec2)
- return EINA_TRUE;
-
- EINA_LIST_FOREACH(parent->comp_data->sub.list_pending, l, sibling)
- {
- if ((sibling != ec1) && (sibling == ec2))
- return EINA_TRUE;
- }
-
- EINA_LIST_FOREACH(parent->comp_data->sub.below_list_pending, l, sibling)
- {
- if ((sibling != ec1) && (sibling == ec2))
- return EINA_TRUE;
- }
-
- return EINA_FALSE;
-}
-
-static void
-_e_comp_wl_subsurface_cb_place_above(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
-{
- E_Subsurface *sub;
- E_Client *ecs;
- E_Client *parent;
-
- DBG("Subsurface Cb Place Above: %d", wl_resource_get_id(resource));
-
- sub = wl_resource_get_user_data(resource);
- if (!sub)
- return;
-
- if (!(parent = sub->base.parent)) return;
- if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return;
-
- /* try to get the client from the sibling resource */
- if (!(ecs = e_client_from_surface_resource(sibling_resource))) return;
-
- if (!_subsurface_sibling_check(sub->ec, ecs))
- {
- struct wl_resource *surface = e_comp_wl_client_surface_get(ecs);
- wl_resource_post_error(sub->base.resource,
- WL_SUBSURFACE_ERROR_BAD_SURFACE,
- "%s: wl_surface@%d is not a parent or sibling",
- "place_above", wl_resource_get_id(surface));
- return;
- }
-
- _e_comp_wl_subsurface_place_above(parent, sub->ec, ecs);
-}
-
-static void
-_e_comp_wl_subsurface_cb_place_below(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
-{
- E_Subsurface *sub;
- E_Client *ecs;
- E_Client *parent;
-
- DBG("Subsurface Cb Place Below: %d", wl_resource_get_id(resource));
-
- sub = wl_resource_get_user_data(resource);
- if (!sub)
- return;
-
- if (!(parent = sub->base.parent)) return;
- if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return;
-
- /* try to get the client from the sibling resource */
- if (!(ecs = e_client_from_surface_resource(sibling_resource))) return;
-
- if (!_subsurface_sibling_check(sub->ec, ecs))
- {
- struct wl_resource *surface = e_comp_wl_client_surface_get(ecs);
- wl_resource_post_error(sub->base.resource,
- WL_SUBSURFACE_ERROR_BAD_SURFACE,
- "%s: wl_surface@%d is not a parent or sibling",
- "place_below", wl_resource_get_id(surface));
- return;
- }
-
- _e_comp_wl_subsurface_place_below(parent, sub->ec, ecs);
-}
-
-static void
-_e_comp_wl_subsurface_cb_sync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
-{
- E_Subsurface *sub;
-
- DBG("Subsurface Cb Sync Set: %d", wl_resource_get_id(resource));
-
- sub = wl_resource_get_user_data(resource);
- if (!sub)
- return;
-
- sub->base.synchronized = EINA_TRUE;
-}
-
-static void
-_e_comp_wl_subsurface_cb_desync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
-{
- E_Subsurface *sub;
-
- DBG("Subsurface Cb Desync Set: %d", wl_resource_get_id(resource));
-
- sub = wl_resource_get_user_data(resource);
- if (!sub)
- return;
-
- if (sub->base.synchronized)
- {
- sub->base.synchronized = EINA_FALSE;
-
- if (!_e_comp_wl_subsurface_synchronized_get(&sub->base))
- _e_comp_wl_subsurface_synchronized_commit(sub->ec);
- }
-}
-
-static const struct wl_subsurface_interface _e_subsurface_interface =
-{
- _e_comp_wl_subsurface_cb_destroy,
- _e_comp_wl_subsurface_cb_position_set,
- _e_comp_wl_subsurface_cb_place_above,
- _e_comp_wl_subsurface_cb_place_below,
- _e_comp_wl_subsurface_cb_sync_set,
- _e_comp_wl_subsurface_cb_desync_set
-};
-
-static void
-_e_comp_wl_subcompositor_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
-{
- wl_resource_destroy(resource);
-}
-
-static void
-_e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface)
-{
- Eina_Bool res;
-
- res = e_comp_wl_subsurface_add(client, resource, id,
- surface, parent_surface);
- if (!res)
- {
- ERR("Failed to add subsurface for surface %d",
- wl_resource_get_id(surface));
- }
-}
-
-static const struct wl_subcompositor_interface _e_subcomp_interface =
-{
- _e_comp_wl_subcompositor_cb_destroy,
- _e_comp_wl_subcompositor_cb_subsurface_get
-};
-
-static void
-_e_comp_wl_subcompositor_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
-{
- struct wl_resource *res;
-
- res = wl_resource_create(client, &wl_subcompositor_interface, version, id);
- if (!res)
- {
- ERR("Could not create subcompositor resource: %m");
- wl_client_post_no_memory(client);
- return;
- }
-
- wl_resource_set_implementation(res, &_e_subcomp_interface, NULL, NULL);
-
- /* TODO: add handlers for client iconify/uniconify */
-}
-
-static void
_e_comp_wl_subsurface_cb_ec_iconify(void *data EINA_UNUSED, E_Client *ec)
{
if (e_object_is_del(E_OBJECT(ec))) return;
}
static void
-_e_comp_wl_subsurface_cb_resource_destroy(struct wl_resource *resource)
-{
- E_Subsurface *sub;
-
- sub = wl_resource_get_user_data(resource);
- if (!sub)
- return;
-
- _e_comp_wl_subsurface_destroy(sub);
-}
-
-static Eina_Bool
-_e_comp_wl_subsurface_synchronized_get(E_Comp_Wl_Subsurf_Data *sdata)
-{
- while (sdata)
- {
- if (sdata->synchronized) return EINA_TRUE;
- if (!sdata->parent) return EINA_FALSE;
-
- if (!sdata->parent->comp_data) return EINA_FALSE;
- if (e_object_is_del(E_OBJECT(sdata->parent))) return EINA_FALSE;
-
- sdata = _e_comp_wl_subsurface_data_get(sdata->parent);
- }
-
- return EINA_FALSE;
-}
-
-static Eina_Bool
-_e_comp_wl_subsurface_circular_reference_check(E_Client *ec, E_Client *parent)
-{
- while (parent)
- {
- if (ec == parent)
- return EINA_TRUE;
-
- if ((parent->comp_data) && (parent->comp_data->sub.data))
- parent = parent->comp_data->sub.data->parent;
- else
- break;
- }
-
- return EINA_FALSE;
-}
-
-static void
_e_comp_wl_subsurface_cb_comp_object_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec, *above, *below;
}
EINTERN Eina_Bool
-e_comp_wl_subsurfaces_init(E_Comp_Wl_Data *wl_comp)
+e_comp_wl_subsurfaces_init(void)
{
- EINA_SAFETY_ON_NULL_RETURN_VAL(wl_comp, EINA_FALSE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(wl_comp->wl.disp, EINA_FALSE);
-
- global = wl_global_create(wl_comp->wl.disp,
- &wl_subcompositor_interface,
- 1, NULL,
- _e_comp_wl_subcompositor_cb_bind);
- if (!global)
- {
- ERR("Could not add subcompositor to wayland globals: %m");
- return EINA_FALSE;
- }
-
E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_ICONIFY, _e_comp_wl_subsurface_cb_ec_iconify, NULL);
E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_UNICONIFY, _e_comp_wl_subsurface_cb_ec_uniconify, NULL);
EINTERN void
e_comp_wl_subsurfaces_shutdown(void)
{
- E_FREE_FUNC(global, wl_global_destroy);
E_FREE_LIST(hooks, e_client_hook_del);
E_FREE_LIST(handlers, ecore_event_handler_del);
}
EINTERN Eina_Bool
-e_comp_wl_subsurface_add(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface)
-{
- E_Subsurface *sub;
- E_Client *ec, *epc;
- E_Client *offscreen_parent = NULL;
- struct wl_resource *subsurf_res;
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(client, EINA_FALSE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(resource, EINA_FALSE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
- EINA_SAFETY_ON_NULL_RETURN_VAL(parent_surface, EINA_FALSE);
-
- ec = e_client_from_surface_resource(surface);
- epc = e_client_from_surface_resource(parent_surface);
-
- if (ec == epc)
- {
- wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "%d: wl_surface@%d cannot be its own parent",
- id, wl_resource_get_id(surface));
- return EINA_FALSE;
- }
-
- if (e_comp_wl_subsurface_check(ec))
- {
- wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "%d: wl_surface@%d is already a sub-surface",
- id, wl_resource_get_id(surface));
- return EINA_FALSE;
- }
-
- // reparent remote surface provider's subsurfaces
- if ((epc->comp_data) &&
- (epc->comp_data->remote_surface.onscreen_parent))
- {
- offscreen_parent = epc;
- epc = epc->comp_data->remote_surface.onscreen_parent;
- }
-
- if (_e_comp_wl_subsurface_circular_reference_check(ec, epc))
- {
- ERR("Subsurface parent relationship is a cycle : "
- "[child win : %zx, %s], [parent win : %zx, %s]",
- e_client_util_win_get(ec), e_client_util_name_get(ec),
- e_client_util_win_get(epc), e_client_util_name_get(epc));
- wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
- "%d: wl_surface@%d is an ancestor of parent",
- id, wl_resource_get_id(surface));
- return EINA_FALSE;
- }
-
- if (!e_comp_wl_surface_role_set(ec, e_comp_wl_subsurface_role_name,
- resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE))
- {
- return EINA_FALSE;
- }
-
- subsurf_res = wl_resource_create(client, &wl_subsurface_interface, 1, id);
- if (!subsurf_res)
- {
- wl_resource_post_no_memory(resource);
- return EINA_FALSE;
- }
-
- sub = _e_comp_wl_subsurface_create(subsurf_res, ec, epc, offscreen_parent);
- if (!sub)
- {
- wl_resource_destroy(subsurf_res);
- wl_resource_post_no_memory(resource);
- return EINA_FALSE;
- }
-
- wl_resource_set_implementation(subsurf_res, &_e_subsurface_interface, sub,
- _e_comp_wl_subsurface_cb_resource_destroy);
-
- ELOGF("SUBSURFACE", "Create with parent(%p)", ec, epc);
-
- return EINA_TRUE;
-}
-
-EINTERN void
-e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
-{
- EINA_SAFETY_ON_NULL_RETURN(ec);
-
- _e_comp_wl_subsurface_parent_commit(ec, parent_synchronized);
-}
-
-EINTERN Eina_Bool
e_comp_wl_subsurface_order_commit(E_Client *ec)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
}
EINTERN Eina_Bool
-e_comp_wl_subsurface_commit(E_Client *ec)
-{
- E_Comp_Wl_Subsurf_Data *sdata;
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-
- /* check for valid subcompositor data */
- if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
-
- sdata = _e_comp_wl_subsurface_data_get(ec);
- if (!sdata) return EINA_FALSE;
-
- if (_e_comp_wl_subsurface_synchronized_get(sdata))
- _e_comp_wl_subsurface_commit_to_cache(ec);
- else
- {
- E_Client *subc;
- Eina_List *l;
-
- if (sdata->position.set)
- {
- E_Client *parent = sdata->parent;
- if (parent)
- {
- evas_object_move(ec->frame, parent->x + sdata->position.x,
- parent->y + sdata->position.y);
- sdata->position.set = EINA_FALSE;
- }
- }
-
- if (sdata->cached.has_data)
- {
- _e_comp_wl_subsurface_commit_to_cache(ec);
- _e_comp_wl_subsurface_commit_from_cache(ec);
- }
- else
- e_comp_wl_surface_commit(ec);
-
- EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
- {
- if (ec != subc)
- _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
- }
- EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
- {
- if (ec != subc)
- _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
- }
- }
-
- return EINA_TRUE;
-}
-
-EINTERN Eina_Bool
e_comp_wl_subsurface_can_show(E_Client *ec)
{
E_Comp_Wl_Subsurf_Data *sdata;
return ec->comp_data->sub.data ? ec->comp_data->sub.data->parent : NULL;
}
-EINTERN void
-e_comp_wl_subsurface_resource_stand_alone_mode_set(struct wl_resource *subsurface_resource)
-{
- E_Subsurface *sub;
-
- EINA_SAFETY_ON_FALSE_RETURN(wl_resource_instance_of(subsurface_resource,
- &wl_subsurface_interface,
- &_e_subsurface_interface));
-
- sub = wl_resource_get_user_data(subsurface_resource);
- EINA_SAFETY_ON_NULL_RETURN(sub);
-
- ELOGF("SUBSURFACE", "SUBSURF|STAND_ALONE", sub->ec);
- sub->base.stand_alone = EINA_TRUE;
-}
-
EINTERN Eina_Bool
e_comp_wl_subsurface_stand_alone_mode_get(E_Client *ec)
{
ec->comp_data->sub.data->stand_alone : EINA_FALSE;
}
-EINTERN void
-e_comp_wl_subsurface_resource_place_below_parent(struct wl_resource *subsurface_resource)
-{
- E_Subsurface *sub;
- E_Comp_Wl_Client_Data *epc_cdata;
-
- EINA_SAFETY_ON_FALSE_RETURN(wl_resource_instance_of(subsurface_resource,
- &wl_subsurface_interface,
- &_e_subsurface_interface));
-
- sub = wl_resource_get_user_data(subsurface_resource);
- EINA_SAFETY_ON_NULL_RETURN(sub);
-
- EINA_SAFETY_ON_NULL_RETURN(sub->base.parent);
- epc_cdata = e_client_cdata_get(sub->base.parent);
- EINA_SAFETY_ON_NULL_RETURN(epc_cdata);
-
- ELOGF("SUBSURFACE", "SUBSURF|BELOW_PARENT", sub->ec);
- epc_cdata->sub.list = eina_list_remove(epc_cdata->sub.list, sub->ec);
- epc_cdata->sub.list_pending = eina_list_remove(epc_cdata->sub.list_pending, sub->ec);
- epc_cdata->sub.below_list = eina_list_remove(epc_cdata->sub.below_list, sub->ec);
- epc_cdata->sub.below_list_pending = eina_list_remove(epc_cdata->sub.below_list_pending, sub->ec);
-
- epc_cdata->sub.below_list_pending = eina_list_append(epc_cdata->sub.below_list_pending, sub->ec);
- epc_cdata->sub.below_list = eina_list_append(epc_cdata->sub.below_list, sub->ec);
- epc_cdata->sub.list_changed = EINA_TRUE;
-}
-
EINTERN Eina_Bool
e_comp_wl_subsurface_position_get(E_Client *ec, int *x, int *y)
{
return EINA_TRUE;
}
-static void
-_e_comp_wl_subsurface_remove_from_parent(E_Client *parent, E_Client *subc)
-{
- parent->comp_data->sub.list =
- eina_list_remove(parent->comp_data->sub.list, subc);
- parent->comp_data->sub.list_pending =
- eina_list_remove(parent->comp_data->sub.list_pending, subc);
- parent->comp_data->sub.below_list =
- eina_list_remove(parent->comp_data->sub.below_list, subc);
- parent->comp_data->sub.below_list_pending =
- eina_list_remove(parent->comp_data->sub.below_list_pending, subc);
-}
-
static E_Comp_Wl_Subsurf_Data *
_e_comp_wl_subsurface_data_get(E_Client *ec)
{
}
static void
-_e_comp_wl_subsurface_child_remove(E_Comp_Wl_Client_Data *parent_cdata, E_Client *child)
-{
- if (parent_cdata->sub.list_pending)
- {
- parent_cdata->sub.list_pending =
- eina_list_remove(parent_cdata->sub.list_pending, child);
- }
- if (parent_cdata->sub.below_list_pending)
- {
- parent_cdata->sub.below_list_pending =
- eina_list_remove(parent_cdata->sub.below_list_pending, child);
- }
-}
-
-static void
-_e_comp_wl_subsurface_place_above(E_Client *parent, E_Client *subc, E_Client *above)
-{
- E_Comp_Wl_Client_Data *pc;
-
- pc = parent->comp_data;
-
- _e_comp_wl_subsurface_child_remove(pc, subc);
-
- if (parent == above)
- {
- pc->sub.list_pending = eina_list_prepend(pc->sub.list_pending, subc);
- }
- else if (eina_list_data_find(pc->sub.list_pending, above))
- {
- pc->sub.list_pending =
- eina_list_append_relative(pc->sub.list_pending, subc, above);
- }
- else
- {
- pc->sub.below_list_pending =
- eina_list_append_relative(pc->sub.below_list_pending, subc, above);
- }
-
- pc->sub.list_changed = EINA_TRUE;
-}
-
-static void
-_e_comp_wl_subsurface_place_below(E_Client *parent, E_Client *subc, E_Client *below)
-{
- E_Comp_Wl_Client_Data *pc;
-
- pc = parent->comp_data;
-
- _e_comp_wl_subsurface_child_remove(pc, subc);
-
- if (parent == below)
- {
- pc->sub.below_list_pending =
- eina_list_append(pc->sub.below_list_pending, subc);
- }
- else if (eina_list_data_find(pc->sub.list_pending, below))
- {
- pc->sub.list_pending =
- eina_list_prepend_relative(pc->sub.list_pending, subc, below);
- }
- else
- {
- pc->sub.below_list_pending =
- eina_list_prepend_relative(pc->sub.below_list_pending, subc, below);
- }
-
- pc->sub.list_changed = EINA_TRUE;
-}
-
-static void
_e_comp_wl_subsurface_stack_update(E_Client *ec)
{
E_Client *topmost;
}
}
}
-
-static E_Subsurface *
-_e_comp_wl_subsurface_create(struct wl_resource *resource, E_Client *ec, E_Client *epc, E_Client *offscreen_parent)
-{
- E_Subsurface *sub;
-
- sub = E_NEW(E_Subsurface, 1);
- if (!sub)
- return NULL;
-
- sub->base.resource = resource;
- sub->base.cached_buffer_ref.buffer = NULL;
- sub->base.synchronized = EINA_TRUE;
- sub->base.remote_surface.offscreen_parent = offscreen_parent;
- if (offscreen_parent)
- ELOGF("SUBSURFACE", " |offscreen_parent:%p", ec, offscreen_parent);
-
- _e_comp_wl_subsurface_ec_link(sub, ec);
- _e_comp_wl_subsurface_parent_link(sub, epc);
-
- e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
-
- return sub;
-}
-
-static void
-_e_comp_wl_subsurface_destroy(E_Subsurface *sub)
-{
- sub->ec->comp_data->sub.data = NULL;
-
- if (sub->base.parent)
- _e_comp_wl_subsurface_parent_unlink(sub);
-
- E_FREE_FUNC(sub->comp_hook.ec_del, e_comp_wl_hook_del);
-
- e_comp_wl_surface_state_finish(&sub->base.cached);
- e_comp_wl_buffer_reference(&sub->base.cached_buffer_ref, NULL);
- free(sub);
-}
-
-static void
-_e_comp_wl_subsurface_cb_comp_data_del(void *data, E_Client *ec)
-{
- E_Subsurface *sub;
-
- sub = data;
- if (sub->ec != ec)
- return;
-
- ELOGF("SUBSURFACE", "The comp_data of E_Client is deleted", ec);
-
- wl_resource_set_user_data(sub->base.resource, NULL);
-
- _e_comp_wl_subsurface_destroy(sub);
-}
-
-static void
-_e_comp_wl_subsurface_ec_link(E_Subsurface *sub, E_Client *ec)
-{
- sub->ec = ec;
- sub->comp_hook.ec_del =
- e_comp_wl_hook_add(E_COMP_WL_HOOK_DEL,
- _e_comp_wl_subsurface_cb_comp_data_del,
- sub);
-
- e_comp_wl_client_surface_set(ec, ec->comp_data->wl_surface);
-
- ec->comp_data->sub.data = &sub->base;
-
- e_comp_wl_surface_state_init(&sub->base.cached, ec->w, ec->h);
-
- /* set subsurface client properties */
- ec->borderless = EINA_TRUE;
- ec->argb = EINA_TRUE;
- ELOGF("COMP", "Set argb:%d", ec, ec->argb);
- ec->lock_border = EINA_TRUE;
- ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
- ec->netwm.state.skip_taskbar = EINA_TRUE;
- ec->netwm.state.skip_pager = EINA_TRUE;
- ec->no_shape_cut = EINA_TRUE;
- ec->border_size = 0;
-
- /* TODO: add callbacks ?? */
-
- ec->lock_user_location = 0;
- ec->lock_client_location = 0;
- ec->lock_user_size = 0;
- ec->lock_client_size = 0;
- ec->lock_client_stacking = 0;
- ec->lock_user_shade = 0;
- ec->lock_client_shade = 0;
- ec->lock_user_maximize = 0;
- ec->lock_client_maximize = 0;
- ec->changes.need_maximize = 0;
- ec->maximized = E_MAXIMIZE_NONE;
- EC_CHANGED(ec);
-
- ec->new_client = ec->netwm.ping = EINA_TRUE;
- e_comp->new_clients++;
- e_client_unignore(ec);
-
- /* Delete 'below_obj' if it was created before 'E_Client' becomes subsurface.
- * It's not for subsurface. */
- E_FREE_FUNC(ec->comp_data->sub.below_obj, evas_object_del);
-}
-
-static void
-_e_comp_wl_subsurface_cb_parent_comp_data_del(void *data, E_Client *ec)
-{
- E_Subsurface *sub;
-
- sub = data;
- if (sub->base.parent != ec)
- return;
-
- ELOGF("SUBSURFACE", "The comp_data of parent(%p) is deleted",
- sub->ec, sub->base.parent);
-
- if ((sub->ec) &&
- (sub->ec->comp_data->sub.watcher))
- tizen_subsurface_watcher_send_message(sub->ec->comp_data->sub.watcher,
- TIZEN_SUBSURFACE_WATCHER_MSG_PARENT_ID_DESTROYED);
-
- _e_comp_wl_subsurface_parent_unlink(sub);
-}
-
-static void
-_e_comp_wl_subsurface_parent_link(E_Subsurface *sub, E_Client *parent)
-{
- E_Layer layer;
-
- ELOGF("COMP", " |subsurface_parent:%p", sub->ec, parent);
-
- /* set subsurface data properties */
- sub->base.parent = parent;
- sub->comp_hook.parent_del =
- e_comp_wl_hook_add(E_COMP_WL_HOOK_DEL,
- _e_comp_wl_subsurface_cb_parent_comp_data_del,
- sub);
-
- if (parent->frame)
- {
- layer = e_client_layer_get(parent);
- if (layer > E_LAYER_BOTTOM)
- e_client_layer_set(sub->ec, layer);
- }
-
- if (parent->comp_data)
- {
- /* append this client to the parents subsurface list */
- parent->comp_data->sub.list_pending =
- eina_list_append(parent->comp_data->sub.list_pending, sub->ec);
- parent->comp_data->sub.list_changed = EINA_TRUE;
- }
-}
-
-static void
-_e_comp_wl_subsurface_parent_unlink(E_Subsurface *sub)
-{
- _e_comp_wl_subsurface_remove_from_parent(sub->base.parent, sub->ec);
- E_FREE_FUNC(sub->comp_hook.parent_del, e_comp_wl_hook_del);
- sub->base.parent = NULL;
-}
EINTERN void e_comp_wl_subsurface_resource_stand_alone_mode_set(struct wl_resource *subsurface_resource);
EINTERN void e_comp_wl_subsurface_resource_place_below_parent(struct wl_resource *subsurface_resource);
-EINTERN Eina_Bool e_comp_wl_subsurfaces_init(E_Comp_Wl_Data *wl_comp);
+EINTERN Eina_Bool e_comp_wl_subsurfaces_init(void);
EINTERN void e_comp_wl_subsurfaces_shutdown(void);
-EINTERN Eina_Bool e_comp_wl_subsurface_add(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, struct wl_resource *parent_surface);
-EINTERN void e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized);
+EINTERN Eina_Bool e_comp_wl_subsurface_add(struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource);
EINTERN Eina_Bool e_comp_wl_subsurface_order_commit(E_Client *ec);
EINTERN Eina_Bool e_comp_wl_subsurface_commit(E_Client *ec);
EINTERN Eina_Bool e_comp_wl_subsurface_can_show(E_Client *ec);
#include <tbm_bufmgr.h>
#include <tbm_surface_internal.h>
#include <gbm.h>
+#include <libds-tizen/types/tbm_server.h>
+#include <libds-tizen/tbm_server.h>
static uint64_t e_comp_wl_tbm_gbm_bo_key;
#define E_COMP_WL_TBM_GBM_BO_KEY (unsigned long)(&e_comp_wl_tbm_gbm_bo_key)
return 0;
}
-static int
-_e_comp_wl_tbm_bind_wl_display(struct wayland_tbm_server *tbm_server, struct wl_display *display)
-{
- tbm_bufmgr bufmgr = NULL;
-
- bufmgr = wayland_tbm_server_get_bufmgr(tbm_server);
- EINA_SAFETY_ON_FALSE_RETURN_VAL(bufmgr, EINA_FALSE);
-
- if (!tbm_bufmgr_bind_native_display(bufmgr, (void *)display))
- {
- e_error_message_show(_("Enlightenment cannot bind native Display TBM!\n"));
- return EINA_FALSE;
- }
-
- return EINA_TRUE;
-}
-
E_API Eina_Bool
e_comp_wl_tbm_module_func_set(const char *module_name, E_Comp_Wl_Tbm_Funcs *fn)
{
return NULL;
}
+static void
+_e_comp_wl_tbm_cb_display_destroy(struct wl_listener *listener, void *data)
+{
+ e_comp->wl_comp_data->tbm.server = NULL;
+}
+
EINTERN Eina_Bool
e_comp_wl_tbm_init(void)
{
- struct wayland_tbm_server *tbm_server = NULL;
+ static struct wl_listener display_destroy;
+ struct ds_tbm_server *ds_tbm_server;
if (!e_comp)
{
if (e_comp->wl_comp_data->tbm.server)
return EINA_TRUE;
- tbm_server = wayland_tbm_server_init(e_comp->wl_comp_data->wl.disp, NULL, -1, 0);
- if (!tbm_server)
+ ds_tbm_server = ds_tbm_server_create(e_comp->wl_comp_data->wl.disp);
+ if (!ds_tbm_server)
{
- e_error_message_show(_("Enlightenment cannot initialize a Wayland TBM!\n"));
+ e_error_message_show(_("Enlightenment cannot initialize ds_tbm_server!\n"));
return EINA_FALSE;
}
- e_comp->wl_comp_data->tbm.server = (void *)tbm_server;
-
- _e_comp_wl_tbm_bind_wl_display(tbm_server, e_comp->wl_comp_data->wl.disp);
+ e_comp->wl_comp_data->tbm.server = (void *)ds_tbm_server->wl_tbm;
+ display_destroy.notify = _e_comp_wl_tbm_cb_display_destroy;
+ ds_tbm_server_add_destroy_listener(ds_tbm_server, &display_destroy);
if (e_comp_socket_init("tbm-drm-auth"))
PRCTL("[Winsys] change permission and create sym link for %s", "tbm-drm-auth");
}
EINTERN void
-e_comp_wl_tbm_shutdown(void)
-{
- if (!e_comp)
- return;
-
- if (!e_comp->wl_comp_data)
- return;
-
- if (!e_comp->wl_comp_data->tbm.server)
- return;
-
- wayland_tbm_server_deinit((struct wayland_tbm_server *)e_comp->wl_comp_data->tbm.server);
-
- e_comp->wl_comp_data->tbm.server = NULL;
-}
-
-EINTERN void
e_comp_wl_tbm_buffer_destroy(E_Comp_Wl_Buffer *buffer)
{
if (!buffer) return;
};
EINTERN Eina_Bool e_comp_wl_tbm_init(void);
-EINTERN void e_comp_wl_tbm_shutdown(void);
EINTERN E_Comp_Wl_Buffer *e_comp_wl_tbm_buffer_get(tbm_surface_h tsurface);
EINTERN void e_comp_wl_tbm_buffer_destroy(E_Comp_Wl_Buffer *buffer);
--- /dev/null
+#include "e.h"
+#include "e_comp_wl_private.h"
+
+// for tizen_subsurface_watcher_send_message()
+#include <tizen-extension-server-protocol.h>
+
+#include <libds/compositor.h>
+#include <libds/subcompositor.h>
+#include <libds/types/ds_surface.h>
+#include <libds/types/ds_subsurface.h>
+
+typedef struct _E_Compositor E_Compositor;
+typedef struct _E_Surface E_Surface;
+typedef struct _E_Subsurface E_Subsurface;
+typedef struct _E_Frame_Callback E_Frame_Callback;
+
+struct _E_Compositor
+{
+ struct ds_compositor *ds_compositor;
+ struct ds_subcompositor *ds_subcompositor;
+
+ E_Client_Hook *new_client_hook;
+
+ struct wl_listener new_surface;
+ struct wl_listener display_destroy;
+};
+
+struct _E_Surface
+{
+ E_Comp_Wl_Client_Data base;
+
+ E_Client *ec;
+ struct ds_surface *ds_surface;
+
+ E_Client_Hook *client_del_hook;
+
+ struct wl_listener destroy;
+ struct wl_listener commit;
+ struct wl_listener new_subsurface;
+};
+
+struct _E_Subsurface
+{
+ E_Comp_Wl_Subsurf_Data base;
+
+ E_Surface *surface;
+ struct ds_subsurface *ds_subsurface;
+
+ struct wl_listener destroy;
+ struct wl_listener surface_destroy;
+ struct wl_listener parent_surface_destroy;
+ struct wl_listener cached;
+ struct wl_listener request_move;
+};
+
+struct _E_Frame_Callback
+{
+ E_Client *ec;
+ struct wl_listener destroy;
+};
+
+static void _e_compositor_cb_display_destroy(struct wl_listener *listener, void *data);
+static void _e_compositor_cb_new_surface(struct wl_listener *listener, void *data);
+static void _e_compositor_cb_new_client(void *data EINA_UNUSED, E_Client *ec);
+
+static E_Surface *_e_surface_create(E_Client *ec);
+static E_Surface *_e_surface_from_ds_surface(struct ds_surface *ds_surface);
+static E_Surface *_e_surface_from_comp_data(E_Comp_Wl_Client_Data *comp_data);
+static void _e_surface_destroy(E_Surface *surface);
+static void _e_surface_ds_surface_set(E_Surface *surface, struct ds_surface *ds_surface);
+static void _e_surface_cb_client_del(void *data, E_Client *ec);
+static void _e_surface_cb_destroy(struct wl_listener *listener, void *data);
+static void _e_surface_cb_commit(struct wl_listener *listener, void *data);
+static void _e_surface_cb_new_subsurface(struct wl_listener *listener, void *data);
+
+static E_Subsurface *_e_subsurface_create(struct ds_subsurface *ds_subsurface, E_Surface *parent_surface);
+static E_Subsurface *_e_subsurface_from_surface(E_Surface *surface);
+static E_Subsurface *_e_subsurface_from_resource(struct wl_resource *resource);
+static E_Subsurface *_e_subsurface_from_ds_subsurface(struct ds_subsurface *ds_subsurface);
+static void _e_subsurface_destroy(E_Subsurface *sub);
+static void _e_subsurface_commit(E_Subsurface *sub);
+static void _e_subsurface_place_below_parent(E_Subsurface *sub);
+static void _e_subsurface_cb_destroy(struct wl_listener *listener, void *data);
+static void _e_subsurface_cb_cached(struct wl_listener *listener, void *data);
+static void _e_subsurface_cb_request_move(struct wl_listener *listener, void *data);
+static void _e_subsurface_cb_surface_destroy(struct wl_listener *listener, void *data);
+static void _e_subsurface_cb_parent_surface_destroy(struct wl_listener *listener, void *data);
+
+static const char *e_comp_wl_subsurface_role_name = "ds_subsurface";
+static E_Compositor *_compositor;
+
+EINTERN Eina_Bool
+e_compositor_init(struct wl_display *display)
+{
+ E_Compositor *comp;
+
+ if (_compositor)
+ return EINA_TRUE;
+
+ comp = E_NEW(E_Compositor, 1);
+ if (!comp)
+ return EINA_FALSE;
+
+ comp->ds_compositor = ds_compositor_create(display);
+ if (!comp->ds_compositor)
+ {
+ ELOGF("COMPOSITOR", "Could not create ds_compositor", NULL);
+ free(comp);
+ return EINA_FALSE;
+ }
+
+ comp->ds_subcompositor = ds_subcompositor_create(display);
+ if (!comp->ds_subcompositor)
+ {
+ ELOGF("COMPOSITOR", "Could not create ds_subcompositor", NULL);
+ free(comp);
+ return EINA_FALSE;
+ }
+
+ comp->new_surface.notify = _e_compositor_cb_new_surface;
+ ds_compositor_add_new_surface_listener(comp->ds_compositor,
+ &comp->new_surface);
+
+ comp->new_client_hook = e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT,
+ _e_compositor_cb_new_client,
+ NULL);
+
+ comp->display_destroy.notify = _e_compositor_cb_display_destroy;
+ wl_display_add_destroy_listener(display, &comp->display_destroy);
+
+ _compositor = comp;
+
+ return EINA_TRUE;
+}
+
+EINTERN E_Client *
+e_compositor_util_client_from_surface_resource(struct wl_resource *surface_resource)
+{
+ E_Surface *surface;
+ struct ds_surface *ds_surface;
+
+ ds_surface = ds_surface_from_resource(surface_resource);
+ if (!ds_surface)
+ return NULL;
+
+ surface = _e_surface_from_ds_surface(ds_surface);
+ if (!surface)
+ return NULL;
+
+ return surface->ec;
+}
+
+EINTERN Eina_Bool
+e_comp_wl_subsurface_add(struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
+{
+ return !!ds_subsurface_create(resource,
+ ds_surface_from_resource(surface_resource),
+ ds_surface_from_resource(parent_resource),
+ id);
+}
+
+EINTERN void
+e_comp_wl_subsurface_resource_stand_alone_mode_set(struct wl_resource *subsurface_resource)
+{
+ E_Subsurface *sub;
+
+ sub = _e_subsurface_from_resource(subsurface_resource);
+ EINA_SAFETY_ON_NULL_RETURN(sub);
+
+ ELOGF("SUBSURFACE", "SUBSURF|STAND_ALONE", sub->surface->ec);
+
+ sub->base.stand_alone = EINA_TRUE;
+}
+
+EINTERN void
+e_comp_wl_subsurface_resource_place_below_parent(struct wl_resource *subsurface_resource)
+{
+ E_Subsurface *sub;
+ E_Comp_Wl_Client_Data *epc_cdata;
+
+ sub = _e_subsurface_from_resource(subsurface_resource);
+ EINA_SAFETY_ON_NULL_RETURN(sub);
+
+ EINA_SAFETY_ON_NULL_RETURN(sub->base.parent);
+ epc_cdata = e_client_cdata_get(sub->base.parent);
+ EINA_SAFETY_ON_NULL_RETURN(epc_cdata);
+
+ ELOGF("SUBSURFACE", "SUBSURF|BELOW_PARENT", sub->surface->ec);
+
+ _e_subsurface_place_below_parent(sub);
+
+ epc_cdata->sub.list = eina_list_remove(epc_cdata->sub.list, sub->surface->ec);
+ epc_cdata->sub.list_pending = eina_list_remove(epc_cdata->sub.list_pending, sub->surface->ec);
+ epc_cdata->sub.below_list = eina_list_remove(epc_cdata->sub.below_list, sub->surface->ec);
+ epc_cdata->sub.below_list_pending = eina_list_remove(epc_cdata->sub.below_list_pending, sub->surface->ec);
+
+ epc_cdata->sub.below_list_pending = eina_list_append(epc_cdata->sub.below_list_pending, sub->surface->ec);
+ epc_cdata->sub.below_list = eina_list_append(epc_cdata->sub.below_list, sub->surface->ec);
+ epc_cdata->sub.list_changed = EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_comp_wl_subsurface_commit(E_Client *ec)
+{
+ E_Surface *surface;
+ E_Subsurface *sub;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
+
+ surface = _e_surface_from_comp_data(ec->comp_data);
+ sub = _e_subsurface_from_surface(surface);
+ if (!sub)
+ return EINA_FALSE;
+
+ _e_subsurface_commit(sub);
+
+ return EINA_TRUE;
+}
+
+static void
+_e_compositor_cb_display_destroy(struct wl_listener *listener EINA_UNUSED, void *data EINA_UNUSED)
+{
+ wl_list_remove(&_compositor->display_destroy.link);
+ wl_list_remove(&_compositor->new_surface.link);
+ e_client_hook_del(_compositor->new_client_hook);
+ E_FREE(_compositor);
+}
+
+static E_Client *
+_e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep)
+{
+ /* NOTE: this will return usable E_Client for a surface of specified process
+ * by pid. it doesn't care whatever this surfaces is for but care only what
+ * is owner process of the surface.
+ */
+
+ E_Client *ec = NULL, *_ec = NULL;
+ Eina_List *l;
+
+ /* find launchscreen client list */
+ if (e_comp->launchscrns)
+ {
+ EINA_LIST_FOREACH(e_comp->launchscrns, l, _ec)
+ {
+ if (_ec->netwm.pid == pid)
+ {
+ ec = _ec;
+ break;
+ }
+ }
+ if (ec)
+ {
+ E_Pixmap *oldep = NULL;
+
+ if (ec->comp_data)
+ {
+ /* do NOT replace with the client having comp data */
+ return NULL;
+ }
+
+ e_comp->launchscrns = eina_list_remove(e_comp->launchscrns, ec);
+
+ oldep = e_client_pixmap_change(ec, ep);
+ if (oldep)
+ {
+ e_pixmap_win_id_del(oldep);
+ e_pixmap_free(oldep);
+ }
+
+ if (ec->internal)
+ ec->internal = 0;
+
+ /* to set-up comp data */
+ _e_compositor_cb_new_client(NULL, ec);
+ ec->ignored = 0;
+ if (!ec->comp_data) return NULL;
+ e_comp_wl_client_evas_init(ec);
+
+ ELOGF("COMP", "Reusable ec. new_pixmap:%p", ec, ec->pixmap);
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_REUSE, ec);
+ }
+ }
+
+ return ec;
+}
+
+static void
+_e_compositor_cb_new_surface(struct wl_listener *listener, void *data)
+{
+ struct ds_surface *ds_surface = data;
+ E_Client *ec = NULL;
+ E_Pixmap *ep;
+ struct wl_resource *surface_resource;
+ pid_t pid;
+ int internal = 0;
+
+ DBG("New ds_surface %p", ds_surface);
+
+ TRACE_DS_BEGIN(COMP_WL:NEW SURFACE CB);
+
+ surface_resource = ds_surface_get_wl_resource(ds_surface);
+ wl_client_get_credentials(wl_resource_get_client(surface_resource), &pid, NULL, NULL);
+ if (pid == getpid())
+ {
+ internal = 1;
+ ec = e_pixmap_find_client(E_PIXMAP_TYPE_WL, (uintptr_t)wl_resource_get_id(surface_resource));
+ }
+ else if ((ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)surface_resource)))
+ {
+ ERR("There is e_pixmap already, Delete old e_pixmap %p", ep);
+ e_pixmap_win_id_del(ep);
+ }
+
+ if (!ec)
+ {
+ /* try to create new pixmap */
+ if (!(ep = e_pixmap_new(E_PIXMAP_TYPE_WL, surface_resource)))
+ {
+ ERR("Could not create new pixmap");
+ TRACE_DS_END();
+ return;
+ }
+
+ E_Comp_Wl_Client_Data *cdata = e_pixmap_cdata_get(ep);
+ if (cdata)
+ cdata->wl_surface = surface_resource;
+
+ DBG("\tUsing Pixmap: %p", ep);
+
+ if (!(ec = _e_comp_wl_client_usable_get(pid, ep)))
+ {
+ ec = e_client_new(ep, 0, internal);
+ }
+ }
+ if (ec)
+ {
+ if (!ec->netwm.pid)
+ ec->netwm.pid = pid;
+ if (ec->new_client)
+ e_comp->new_clients--;
+ ec->new_client = 0;
+ if ((!ec->client.w) && (ec->client.h))
+ ec->client.w = ec->client.h = 1;
+ ec->comp_data->surface = surface_resource;
+ ec->icccm.accepts_focus = 1;
+
+ _e_surface_ds_surface_set(_e_surface_from_comp_data(ec->comp_data),
+ ds_surface);
+ }
+
+ DBG("\tUsing Client: %p", ec);
+
+ TRACE_DS_END();
+}
+
+static void
+_e_compositor_cb_new_client(void *data EINA_UNUSED, E_Client *ec)
+{
+ E_Surface *surface;
+ Ecore_Window win;
+
+ /* make sure this is a wayland client */
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
+
+ TRACE_DS_BEGIN(COMP_WL:CLIENT NEW HOOK);
+
+ /* get window id from pixmap */
+ win = e_pixmap_window_get(ec->pixmap);
+
+ /* ignore fake root windows */
+ if ((ec->override) && ((ec->x == -77) && (ec->y == -77)))
+ {
+ e_comp_ignore_win_add(E_PIXMAP_TYPE_WL, win);
+ e_object_del(E_OBJECT(ec));
+ TRACE_DS_END();
+ return;
+ }
+
+ surface = _e_surface_create(ec);
+ if (!surface)
+ {
+ ERR("Could not create E_Surface");
+ TRACE_DS_END();
+ return;
+ }
+
+ ec->comp_data = &surface->base;
+
+ /* set initial client properties */
+ ec->argb = EINA_FALSE;
+ ELOGF("COMP", "Set argb:%d", ec, ec->argb);
+ ec->no_shape_cut = EINA_TRUE;
+ ec->redirected = ec->ignored = 1;
+ ec->border_size = 0;
+
+ /* NB: could not find a better place to do this, BUT for internal windows,
+ * we need to set delete_request else the close buttons on the frames do
+ * basically nothing */
+ if (ec->internal)
+ ec->icccm.delete_request = EINA_TRUE;
+
+ E_Comp_Wl_Client_Data *p_cdata = e_pixmap_cdata_get(ec->pixmap);
+ EINA_SAFETY_ON_NULL_GOTO(p_cdata, end);
+
+ e_pixmap_cdata_set(ec->pixmap, &surface->base);
+
+ g_mutex_init(&ec->comp_data->last_device_kbd_mutex);
+ g_mutex_init(&ec->comp_data->surface_mutex);
+
+end:
+ TRACE_DS_END();
+}
+
+static E_Surface *
+_e_surface_create(E_Client *ec)
+{
+ E_Surface *surface;
+
+ surface = E_NEW(E_Surface, 1);
+ if (!surface)
+ return NULL;
+
+ e_object_ref(E_OBJECT(ec));
+ surface->ec = ec;
+
+ wl_signal_init(&surface->base.destroy_signal);
+ wl_signal_init(&surface->base.apply_viewport_signal);
+
+ e_comp_wl_surface_state_init(&surface->base.pending, ec->w, ec->h);
+
+ /* set initial client data properties */
+ surface->base.mapped = EINA_FALSE;
+ surface->base.first_damage = ec->internal;
+ surface->base.need_reparent = !ec->internal;
+
+ /* set initial value of scaler */
+ surface->base.scaler.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ surface->base.scaler.buffer_viewport.buffer.scale = 1;
+ surface->base.scaler.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
+ surface->base.scaler.buffer_viewport.surface.width = -1;
+
+ e_presentation_time_container_init(&surface->base.presentation_container);
+
+ surface->client_del_hook = e_client_hook_add(E_CLIENT_HOOK_DEL,
+ _e_surface_cb_client_del,
+ surface);
+
+ return surface;
+}
+
+static void
+_e_surface_destroy(E_Surface *surface)
+{
+ struct wl_resource *cb;
+
+ if (surface->base.reparented)
+ {
+ /* reset pixmap parent window */
+ e_pixmap_parent_window_set(surface->ec->pixmap, 0);
+ }
+
+ if (surface->base.sub.watcher)
+ wl_resource_destroy(surface->base.sub.watcher);
+
+ wl_signal_emit(&surface->base.destroy_signal, &surface->base.surface);
+
+ e_comp_wl_surface_state_finish(&surface->base.pending);
+
+ e_comp_wl_buffer_reference(&surface->base.buffer_ref, NULL);
+
+ EINA_LIST_FREE(surface->base.frames, cb)
+ wl_resource_destroy(cb);
+
+ EINA_LIST_FREE(surface->base.pending.frames, cb)
+ wl_resource_destroy(cb);
+
+ if (surface->base.aux_hint.hints)
+ {
+ E_Comp_Wl_Aux_Hint *hint;
+ EINA_LIST_FREE(surface->base.aux_hint.hints, hint)
+ {
+ eina_stringshare_del(hint->hint);
+ eina_stringshare_del(hint->val);
+ E_FREE(hint);
+ }
+ }
+
+ if (e_comp_wl->selection.cbhm == surface->base.surface)
+ e_comp_wl->selection.cbhm = NULL;
+
+ if (surface->base.viewport_transform)
+ {
+ e_client_transform_core_remove(surface->ec, surface->base.viewport_transform);
+ e_util_transform_del(surface->base.viewport_transform);
+ surface->base.viewport_transform = NULL;
+ }
+
+ e_presentation_time_container_finish(&surface->base.presentation_container);
+
+ E_FREE_FUNC(surface->base.on_focus_timer, ecore_timer_del);
+
+ e_client_hook_del(surface->client_del_hook);
+
+ surface->ec->comp_data = NULL;
+ e_object_unref(E_OBJECT(surface->ec));
+ free(surface);
+}
+
+static void
+_e_surface_ds_surface_set(E_Surface *surface, struct ds_surface *ds_surface)
+{
+ surface->ds_surface = ds_surface;
+
+ surface->destroy.notify = _e_surface_cb_destroy;
+ ds_surface_add_destroy_listener(ds_surface, &surface->destroy);
+
+ surface->commit.notify = _e_surface_cb_commit;
+ ds_surface_add_commit_listener(ds_surface, &surface->commit);
+
+ surface->new_subsurface.notify = _e_surface_cb_new_subsurface;
+ ds_surface_add_new_subsurface_listener(ds_surface, &surface->new_subsurface);
+}
+
+static E_Surface *
+_e_surface_from_ds_surface(struct ds_surface *ds_surface)
+{
+ E_Surface *surface = NULL;
+ struct wl_listener *listener;
+
+ listener = wl_signal_get(&ds_surface->events.destroy,
+ _e_surface_cb_destroy);
+ if (listener)
+ surface = wl_container_of(listener, surface, destroy);
+
+ return surface;
+}
+
+static E_Surface *
+_e_surface_from_comp_data(E_Comp_Wl_Client_Data *comp_data)
+{
+ E_Surface *surface;
+ return wl_container_of(comp_data, surface, base);
+}
+
+static E_Surface *
+_e_surface_root_surface_get(E_Surface *surface)
+{
+ E_Surface *iter = surface;
+ E_Subsurface *sub;
+
+ while ((sub = _e_subsurface_from_surface(iter)))
+ iter = _e_surface_from_ds_surface(sub->ds_subsurface->parent);
+
+ return iter;
+}
+
+static void
+_e_surface_pending_buffer_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ E_Client *ec = surface->ec;
+ E_Comp_Wl_Buffer *buffer = NULL;
+
+ if (ds_surface->buffer)
+ buffer = e_comp_wl_buffer_get(ds_surface->buffer, ec);
+
+ e_comp_wl_client_surface_pending_buffer_set(ec, buffer,
+ ds_surface->current.dx,
+ ds_surface->current.dy);
+}
+
+static void
+_e_surface_pending_surface_damage_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ pixman_box32_t *rects;
+ int32_t x, y, w, h;
+ int nrects, i;
+ Eina_Rectangle *dmg;
+
+ rects = pixman_region32_rectangles(&ds_surface->current.surface_damage, &nrects);
+ for (i = 0; i < nrects; i++)
+ {
+ x = rects[i].x1;
+ y = rects[i].y1;
+ w = rects[i].x2 - x;
+ h = rects[i].y2 - y;
+
+ dmg = eina_rectangle_new(x, y, w, h);
+ if (dmg)
+ {
+ surface->base.pending.damages =
+ eina_list_append(surface->base.pending.damages, dmg);
+ }
+ }
+}
+
+static void
+_e_surface_pending_buffer_damage_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ pixman_box32_t *rects;
+ int32_t x, y, w, h;
+ int nrects, i;
+ Eina_Rectangle *dmg;
+
+ rects = pixman_region32_rectangles(&ds_surface->current.buffer_damage, &nrects);
+ for (i = 0; i < nrects; i++)
+ {
+ x = rects[i].x1;
+ y = rects[i].y1;
+ w = rects[i].x2 - x;
+ h = rects[i].y2 - y;
+
+ dmg = eina_rectangle_new(x, y, w, h);
+ if (dmg)
+ {
+ surface->base.pending.buffer_damages =
+ eina_list_append(surface->base.pending.buffer_damages, dmg);
+ }
+ }
+}
+
+static void
+_region_area_check(Eina_Tiler *tiler, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+ Eina_Bool need_set = EINA_FALSE;
+ int area_w = 0;
+ int area_h = 0;
+
+ eina_tiler_area_size_get(tiler, &area_w, &area_h);
+ if (x + w > area_w)
+ {
+ area_w = x + w;
+ need_set = EINA_TRUE;
+ }
+
+ if (y + h > area_h)
+ {
+ area_h = y + h;
+ need_set = EINA_TRUE;
+ }
+
+ if (need_set)
+ {
+ INF("change region area. (%dx%d)", area_w, area_h);
+ eina_tiler_area_size_set(tiler, area_w, area_h);
+ }
+}
+
+static Eina_Tiler *
+_tiler_new_from_pixman_region(pixman_region32_t *pixman_region)
+{
+ Eina_Tiler *tiler;
+ pixman_box32_t *rects;
+ int32_t x, y, w, h;
+ int nrects, i;
+
+ tiler = eina_tiler_new(e_comp->w, e_comp->h);
+ if (!tiler)
+ return NULL;
+
+ eina_tiler_tile_size_set(tiler, 1, 1);
+
+ rects = pixman_region32_rectangles(pixman_region, &nrects);
+ for (i = 0; i < nrects; i++)
+ {
+ x = rects[i].x1;
+ y = rects[i].y1;
+ w = rects[i].x2 - x;
+ h = rects[i].y2 - y;
+ _region_area_check(tiler, x, y, w, h);
+ eina_tiler_rect_add(tiler, &(Eina_Rectangle){x, y, w, h});
+ }
+
+ return tiler;
+}
+
+static void
+_e_surface_pending_opaque_region_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ E_Client *ec = surface->ec;
+ Eina_Tiler *region;
+
+ if (pixman_region32_not_empty(&ds_surface->current.opaque))
+ {
+ region = _tiler_new_from_pixman_region(&ds_surface->current.opaque);
+ if (!region)
+ return;
+
+ e_comp_wl_client_surface_pending_opaque_region_set(ec, region);
+
+ eina_tiler_free(region);
+ }
+ else
+ {
+ e_comp_wl_client_surface_pending_opaque_region_set(ec, NULL);
+ }
+}
+
+static void
+_e_surface_pending_input_region_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ E_Client *ec = surface->ec;
+ Eina_Tiler *region;
+
+ if (pixman_region32_not_empty(&ds_surface->current.input))
+ {
+ region = _tiler_new_from_pixman_region(&ds_surface->current.input);
+ if (!region)
+ return;
+
+ e_comp_wl_client_surface_pending_input_region_set(ec, region);
+
+ eina_tiler_free(region);
+ }
+ else
+ {
+ e_comp_wl_client_surface_pending_input_region_set(ec, NULL);
+ }
+}
+
+static void
+_e_surface_pending_buffer_transform_update(E_Surface *surface)
+{
+ int32_t transform = surface->ds_surface->current.transform;
+
+ surface->base.pending.buffer_viewport.buffer.transform = transform;
+ surface->base.pending.buffer_viewport.changed = 1;
+}
+
+static void
+_e_surface_pending_buffer_scale_update(E_Surface *surface)
+{
+ int32_t scale = surface->ds_surface->current.scale;
+
+ surface->base.pending.buffer_viewport.buffer.scale = scale;
+ surface->base.pending.buffer_viewport.changed = 1;
+}
+
+static void
+_frame_callback_cb_destroy(struct wl_listener *listener, void *data)
+{
+ struct wl_resource *resource = data;
+ E_Frame_Callback *frame_callback;
+
+ frame_callback = wl_container_of(listener, frame_callback, destroy);
+ e_comp_wl_client_surface_frame_callback_remove(frame_callback->ec, resource);
+ e_object_unref(E_OBJECT(frame_callback->ec));
+ free(frame_callback);
+}
+
+static void
+_e_surface_pending_frame_callback_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ E_Client *ec = surface->ec;
+ E_Frame_Callback *frame_callback;
+ struct wl_resource *resource;
+
+ wl_resource_for_each(resource, &ds_surface->current.frame_callback_list)
+ {
+ frame_callback = E_NEW(E_Frame_Callback, 1);
+ if (!frame_callback)
+ continue;
+
+ e_object_ref(E_OBJECT(ec));
+ frame_callback->ec = ec;
+
+ frame_callback->destroy.notify = _frame_callback_cb_destroy;
+ wl_resource_add_destroy_listener(resource, &frame_callback->destroy);
+
+ e_comp_wl_client_surface_pending_frame_callback_add(ec, resource);
+ }
+
+ wl_list_init(&ds_surface->current.frame_callback_list);
+}
+
+static void
+_e_surface_pending_viewport_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ struct ds_surface_state *state = &ds_surface->current;
+ E_Comp_Wl_Buffer_Viewport *vp = &surface->base.pending.buffer_viewport;
+
+ if (state->viewport.has_src)
+ {
+ vp->buffer.src_x = wl_fixed_from_double(state->viewport.src.x);
+ vp->buffer.src_y = wl_fixed_from_double(state->viewport.src.y);
+ vp->buffer.src_width = wl_fixed_from_double(state->viewport.src.width);
+ vp->buffer.src_height = wl_fixed_from_double(state->viewport.src.height);
+ vp->changed = EINA_TRUE;
+ }
+ else
+ {
+ vp->buffer.src_width = wl_fixed_from_int(-1);
+ vp->changed = EINA_TRUE;
+ }
+
+ if (state->viewport.has_dst)
+ {
+ vp->surface.width = state->viewport.dst_width;
+ vp->surface.height = state->viewport.dst_height;
+ vp->changed = EINA_TRUE;
+ }
+ else
+ {
+ vp->surface.width = -1;
+ vp->changed = EINA_TRUE;
+ }
+}
+
+static void
+_e_surface_pending_subsurface_order_update(E_Surface *surface)
+{
+ struct ds_surface *ds_surface = surface->ds_surface;
+ struct ds_subsurface *ds_subsurface;
+ E_Subsurface *sub;
+ Eina_Bool reordered = EINA_FALSE;
+
+ E_FREE_FUNC(surface->base.sub.list_pending, eina_list_free);
+ E_FREE_FUNC(surface->base.sub.below_list_pending, eina_list_free);
+
+ wl_list_for_each(ds_subsurface,
+ &ds_surface->pending.subsurfaces_above,
+ pending.link)
+ {
+ sub = _e_subsurface_from_ds_subsurface(ds_subsurface);
+ surface->base.sub.list_pending =
+ eina_list_append(surface->base.sub.list_pending, sub->surface->ec);
+
+ reordered |= ds_subsurface->reordered;
+
+ _e_surface_pending_subsurface_order_update(sub->surface);
+ }
+
+ wl_list_for_each(ds_subsurface,
+ &ds_surface->pending.subsurfaces_below,
+ pending.link)
+ {
+ sub = _e_subsurface_from_ds_subsurface(ds_subsurface);
+ surface->base.sub.below_list_pending =
+ eina_list_append(surface->base.sub.below_list_pending, sub->surface->ec);
+
+ reordered |= ds_subsurface->reordered;
+
+ _e_surface_pending_subsurface_order_update(sub->surface);
+ }
+
+ surface->base.sub.list_changed |= reordered;
+}
+
+static void
+_e_surface_pending_update(E_Surface *surface)
+{
+ E_Surface *root_surface;
+ struct ds_surface *ds_surface = surface->ds_surface;
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_BUFFER)
+ _e_surface_pending_buffer_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_SURFACE_DAMAGE)
+ _e_surface_pending_surface_damage_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_BUFFER_DAMAGE)
+ _e_surface_pending_buffer_damage_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_OPAQUE_REGION)
+ _e_surface_pending_opaque_region_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_INPUT_REGION)
+ _e_surface_pending_input_region_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_TRANSFORM)
+ _e_surface_pending_buffer_transform_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_SCALE)
+ _e_surface_pending_buffer_scale_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_FRAME_CALLBACK_LIST)
+ _e_surface_pending_frame_callback_update(surface);
+
+ if (ds_surface->current.committed & DS_SURFACE_STATE_VIEWPORT)
+ _e_surface_pending_viewport_update(surface);
+
+ // FIXME
+ // It's not supposed to update subsurface order for entire surface tree.
+ // This is for backward compatibility
+ root_surface = _e_surface_root_surface_get(surface);
+ _e_surface_pending_subsurface_order_update(root_surface);
+}
+
+static void
+_e_surface_commit_pre(E_Surface *surface)
+{
+ E_Client *ec = surface->ec;
+ E_Comp_Config *comp_conf = NULL;
+
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (!surface->base.first_commit)
+ surface->base.first_commit = EINA_TRUE;
+
+ if (!surface->base.mapped)
+ {
+ if (surface->base.shell.surface && surface->base.pending.new_attach &&
+ !ec->internal && !e_comp_wl_subsurface_check(ec) && !ec->remote_surface.provider)
+ {
+ ELOGF("COMP", "Current unmapped. COMMIT. pixmap_usable:%d", ec, e_pixmap_usable_get(ec->pixmap));
+
+ // no canvas update before client's commit request, begin rendering after 1st commit
+ comp_conf = e_comp_config_get();
+ if (comp_conf && comp_conf->canvas_render_delay_after_boot && e_comp->canvas_render_delayed)
+ {
+ ELOGF("COMP", "Begin canvas update for the first time after boot", ec);
+ e_comp->canvas_render_delayed = EINA_FALSE;
+ }
+ }
+ }
+
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_BEFORE_SURFACE_COMMIT, ec);
+}
+
+static void
+_e_surface_commit(E_Surface *surface)
+{
+ e_comp_wl_client_surface_pending_commit(surface->ec);
+}
+
+static void
+_e_surface_cb_client_del(void *data, E_Client *ec)
+{
+ E_Surface *surface = data;
+
+ if (surface->ec != ec)
+ return;
+
+ /* make sure this is a wayland client */
+ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
+
+ TRACE_DS_BEGIN(COMP_WL:CLIENT DEL CB);
+
+ g_mutex_clear(&ec->comp_data->last_device_kbd_mutex);
+ g_mutex_clear(&ec->comp_data->surface_mutex);
+
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_DEL, ec);
+
+ ec->already_unparented = EINA_TRUE;
+
+ e_comp_wl_client_evas_deinit(ec);
+
+ e_pixmap_cdata_set(ec->pixmap, NULL);
+
+ _e_surface_destroy(surface);
+
+ TRACE_DS_END();
+}
+
+static void
+_e_surface_cb_destroy(struct wl_listener *listener, void *data)
+{
+ E_Surface *surface;
+
+ surface = wl_container_of(listener, surface, destroy);
+
+ wl_list_remove(&surface->destroy.link);
+ wl_list_remove(&surface->commit.link);
+ wl_list_remove(&surface->new_subsurface.link);
+ surface->ds_surface = NULL;
+
+ e_comp_wl_client_surface_finish(surface->ec);
+}
+
+static void
+_e_surface_cb_commit(struct wl_listener *listener, void *data)
+{
+ E_Surface *surface;
+ E_Subsurface *sub;
+
+ surface = wl_container_of(listener, surface, commit);
+
+ _e_surface_pending_update(surface);
+ _e_surface_commit_pre(surface);
+
+ if (e_comp_wl_remote_surface_commit(surface->ec)) return;
+
+ sub = _e_subsurface_from_surface(surface);
+ if (sub)
+ _e_subsurface_commit(sub);
+ else
+ _e_surface_commit(surface);
+}
+
+static void
+_e_surface_cb_new_subsurface(struct wl_listener *listener, void *data)
+{
+ struct ds_subsurface *ds_subsurface = data;
+ E_Surface *surface;
+
+ surface = wl_container_of(listener, surface, new_subsurface);
+
+ if (!_e_subsurface_create(ds_subsurface, surface))
+ {
+ ELOGF("COMPOSITOR", "Could not create E_Subsurface", surface->ec);
+ return;
+ }
+}
+
+static E_Subsurface *
+_e_subsurface_create(struct ds_subsurface *ds_subsurface, E_Surface *parent_surface)
+{
+ E_Subsurface *sub;
+ E_Surface *surface;
+ E_Client *offscreen_parent = NULL, *epc = parent_surface->ec;
+
+ sub = E_NEW(E_Subsurface, 1);
+ if (!sub)
+ return NULL;
+
+ surface = _e_surface_from_ds_surface(ds_subsurface->surface);
+
+ if (parent_surface->base.remote_surface.onscreen_parent)
+ {
+ offscreen_parent = epc;
+ epc = parent_surface->base.remote_surface.onscreen_parent;
+ }
+
+ if (e_comp_wl_client_subsurface_cyclic_reference_check(surface->ec, epc))
+ {
+ ERR("Subsurface parent relationship is a cycle : "
+ "[child win : %zx, %s], [parent win : %zx, %s]",
+ e_client_util_win_get(surface->ec),
+ e_client_util_name_get(surface->ec),
+ e_client_util_win_get(epc),
+ e_client_util_name_get(epc));
+ free(sub);
+ return NULL;
+ }
+
+ if (!e_comp_wl_surface_role_set(surface->ec, e_comp_wl_subsurface_role_name,
+ NULL, 0))
+ {
+ free(sub);
+ return NULL;
+ }
+
+ sub->ds_subsurface = ds_subsurface;
+ sub->destroy.notify = _e_subsurface_cb_destroy;
+ wl_signal_add(&ds_subsurface->events.destroy, &sub->destroy);
+
+ sub->cached.notify = _e_subsurface_cb_cached;
+ wl_signal_add(&ds_subsurface->events.cached, &sub->cached);
+
+ sub->request_move.notify = _e_subsurface_cb_request_move;
+ wl_signal_add(&ds_subsurface->events.request_move, &sub->request_move);
+
+ sub->surface = surface;
+ sub->surface_destroy.notify = _e_subsurface_cb_surface_destroy;
+ wl_signal_add(&surface->base.destroy_signal, &sub->surface_destroy);
+
+ sub->parent_surface_destroy.notify = _e_subsurface_cb_parent_surface_destroy;
+ wl_signal_add(&parent_surface->base.destroy_signal, &sub->parent_surface_destroy);
+
+ e_comp_wl_client_subsurface_init(surface->ec,
+ ds_subsurface->resource,
+ &sub->base,
+ epc,
+ offscreen_parent);
+
+ ELOGF("SUBSURFACE", "Create: parent(%p)", surface->ec, epc);
+
+ return sub;
+}
+
+static void
+_e_subsurface_destroy(E_Subsurface *sub)
+{
+ ELOGF("SUBSURFACE", "Destroy", sub->surface->ec);
+ e_comp_wl_client_subsurface_finish(sub->surface->ec);
+ wl_list_remove(&sub->parent_surface_destroy.link);
+ wl_list_remove(&sub->cached.link);
+ wl_list_remove(&sub->surface_destroy.link);
+ wl_list_remove(&sub->destroy.link);
+ free(sub);
+}
+
+static E_Subsurface *
+_e_subsurface_from_ds_subsurface(struct ds_subsurface *ds_subsurface)
+{
+ struct wl_listener *listener;
+ E_Subsurface *sub = NULL;
+
+ listener = wl_signal_get(&ds_subsurface->events.destroy,
+ _e_subsurface_cb_destroy);
+ if (listener)
+ sub = wl_container_of(listener, sub, destroy);
+
+ return sub;
+}
+
+static E_Subsurface *
+_e_subsurface_from_surface(E_Surface *surface)
+{
+ if (!ds_surface_is_subsurface(surface->ds_surface))
+ return NULL;
+
+ return _e_subsurface_from_ds_subsurface(
+ ds_subsurface_from_surface(surface->ds_surface));
+}
+
+static E_Subsurface *
+_e_subsurface_from_resource(struct wl_resource *resource)
+{
+ return _e_subsurface_from_ds_subsurface(
+ ds_subsurface_from_resource(resource));
+}
+
+static Eina_Bool
+_e_subsurface_synchronized_check(E_Subsurface *sub)
+{
+ struct ds_subsurface *ds_subsurface = sub->ds_subsurface;
+
+ do
+ {
+ if (ds_subsurface->synchronized)
+ return EINA_TRUE;
+ }
+ while ((ds_subsurface = ds_subsurface_from_surface(ds_subsurface->parent)));
+
+ return EINA_FALSE;
+}
+
+static void
+_e_subsurface_commit(E_Subsurface *sub)
+{
+ if (sub->base.cached.has_data)
+ {
+ e_comp_wl_client_subsurface_commit_to_cache(sub->surface->ec);
+ e_comp_wl_client_subsurface_commit_from_cache(sub->surface->ec);
+ }
+ else
+ {
+ e_comp_wl_surface_commit(sub->surface->ec);
+ }
+
+ if (_e_subsurface_synchronized_check(sub))
+ {
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_SYNCHRONIZED_COMMIT,
+ sub->surface->ec);
+ }
+}
+
+static void
+_e_subsurface_position_update(E_Subsurface *sub)
+{
+ E_Client *ec = sub->surface->ec;
+ int x, y;
+
+ x = sub->base.parent->x + sub->base.position.x;
+ y = sub->base.parent->y + sub->base.position.y;
+ evas_object_move(ec->frame, x, y);
+}
+
+static void
+_e_subsurface_place_below_parent(E_Subsurface *sub)
+{
+ struct ds_subsurface *ds_subsurface = sub->ds_subsurface;
+
+ wl_list_remove(&ds_subsurface->pending.link);
+ wl_list_insert(ds_subsurface->parent->pending.subsurfaces_below.prev,
+ &ds_subsurface->pending.link);
+
+ // FIXME
+ wl_list_remove(&ds_subsurface->current.link);
+ wl_list_insert(ds_subsurface->parent->current.subsurfaces_below.prev,
+ &ds_subsurface->current.link);
+
+ ds_subsurface->reordered = true;
+}
+
+static void
+_e_subsurface_cb_destroy(struct wl_listener *listener, void *data)
+{
+ E_Subsurface *sub;
+
+ sub = wl_container_of(listener, sub, destroy);
+ _e_subsurface_destroy(sub);
+}
+
+static void
+_e_subsurface_cb_cached(struct wl_listener *listener, void *data)
+{
+ E_Subsurface *sub;
+
+ sub = wl_container_of(listener, sub, cached);
+
+ e_presentation_time_container_feedback_discard(&sub->base.cached.presentation_container);
+ e_presentation_time_container_feedback_merge(&sub->base.cached.presentation_container,
+ &sub->surface->base.pending.presentation_container);
+
+ sub->base.cached.has_data = EINA_TRUE;
+
+ e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_COMMIT_TO_CACHE, sub->surface->ec);
+}
+
+static void
+_e_subsurface_cb_request_move(struct wl_listener *listener, void *data)
+{
+ E_Subsurface *sub;
+ struct ds_subsurface *ds_subsurface;
+
+ sub = wl_container_of(listener, sub, request_move);
+ ds_subsurface = sub->ds_subsurface;
+
+ if ((sub->base.position.x == ds_subsurface->current.x) &&
+ (sub->base.position.y == ds_subsurface->current.y))
+ return;
+
+ sub->base.position.x = ds_subsurface->current.x;
+ sub->base.position.y = ds_subsurface->current.y;
+
+ _e_subsurface_position_update(sub);
+}
+
+static void
+_e_subsurface_cb_surface_destroy(struct wl_listener *listener, void *data)
+{
+ E_Subsurface *sub;
+
+ sub = wl_container_of(listener, sub, surface_destroy);
+ _e_subsurface_destroy(sub);
+}
+
+static void
+_e_subsurface_cb_parent_surface_destroy(struct wl_listener *listener, void *data)
+{
+ E_Subsurface *sub;
+ E_Client *ec;
+
+ sub = wl_container_of(listener, sub, parent_surface_destroy);
+ e_comp_wl_client_subsurface_parent_unset(sub->surface->ec);
+
+ ec = sub->surface->ec;
+ if (ec->comp_data->sub.watcher)
+ {
+ tizen_subsurface_watcher_send_message(ec->comp_data->sub.watcher,
+ TIZEN_SUBSURFACE_WATCHER_MSG_PARENT_ID_DESTROYED);
+ }
+}
+
--- /dev/null
+#ifndef E_COMPOSITOR_H
+#define E_COMPOSITOR_H
+
+EINTERN Eina_Bool e_compositor_init(struct wl_display *display);
+EINTERN E_Client *e_compositor_util_client_from_surface_resource(struct wl_resource *surface_resource);
+
+#endif
return;
}
- res = e_comp_wl_subsurface_add(client, resource, id, surface,
+ res = e_comp_wl_subsurface_add(resource, id, surface,
epc->comp_data->wl_surface);
if (!res)
{
E_Comp_Wl_Client_Data *cdata;
if (!(ec = wl_resource_get_user_data(resource))) return;
- if (e_object_is_del(E_OBJECT(ec))) return;
cdata = e_client_cdata_get(ec);
if (!cdata) return;