#define XDG_SERVER_VERSION 5
typedef struct _E_Xdg_Shell E_Xdg_Shell;
-typedef struct _E_Xdg_Pos E_Xdg_Pos;
struct _E_Xdg_Shell
{
struct wl_client *wc;
struct wl_resource *res; /* xdg_shell resource */
Eina_List *ping_ecs; /* list of all ec which are waiting for pong response */
- Eina_List *positioners; /* list of E_Xdg_Pos */
};
-struct _E_Xdg_Pos
+static Eina_Hash *xdg_sh_hash = NULL;
+
+EINTERN Eina_Bool
+e_shell_e_client_shell_assignable_check(E_Client *ec)
{
- E_Xdg_Shell *sh;
- struct wl_resource *res; /* xdg_positioner_v6 resources */
-};
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-static Eina_Hash *xdg_sh_hash = NULL;
+ if (e_object_is_del(E_OBJECT(ec)))
+ {
+ ELOGF("SHELL", "ERR: Could not assign shell: being deleted by compositor",
+ ec->pixmap, ec);
+ return EINA_FALSE;
+ }
+ else if (!ec->comp_data)
+ {
+ ELOGF("SHELL", "ERR: Could not assign shell: No E_Comp_Client_Data",
+ ec->pixmap, ec);
+ return EINA_FALSE;
+ }
+ else if (ec->comp_data->shell.surface)
+ {
+ ELOGF("SHELL", "ERR: Could not assign shell: Already assigned",
+ ec->pixmap, ec);
+ return EINA_FALSE;
+ }
-static void
-_e_shell_surface_parent_set(E_Client *ec, struct wl_resource *parent_resource)
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_shell_e_client_shsurface_assign(E_Client *ec,
+ struct wl_resource *shsurface,
+ E_Shell_Surface_Api *api)
+{
+ E_Comp_Client_Data *cdata;
+
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+ EINA_SAFETY_ON_NULL_RETURN(shsurface);
+
+ cdata = ec->comp_data;
+ if (!cdata)
+ {
+ ELOGF("SHELL", "ERR: E_Client must have E_Comp_Client_Data",
+ ec->pixmap, ec);
+ return;
+ }
+
+ cdata->shell.surface = shsurface;
+ if (api)
+ {
+ cdata->shell.configure_send = api->configure_send;
+ cdata->shell.configure = api->configure;
+ cdata->shell.ping = api->ping;
+ cdata->shell.map = api->map;
+ cdata->shell.unmap = api->unmap;
+ }
+
+ ec->netwm.ping = 1;
+ e_object_ref(E_OBJECT(ec));
+}
+
+EINTERN void
+e_shell_e_client_shsurface_api_set(E_Client *ec, E_Shell_Surface_Api *api)
+{
+ E_Comp_Client_Data *cdata;
+
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+ EINA_SAFETY_ON_NULL_RETURN(api);
+
+ cdata = ec->comp_data;
+ if (!cdata)
+ {
+ ELOGF("SHELL", "ERR: E_Client must have E_Comp_Client_Data",
+ ec->pixmap, ec);
+ return;
+ }
+
+ cdata->shell.configure_send = api->configure_send;
+ cdata->shell.configure = api->configure;
+ cdata->shell.ping = api->ping;
+ cdata->shell.map = api->map;
+ cdata->shell.unmap = api->unmap;
+}
+
+EINTERN void
+e_shell_e_client_toplevel_set(E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ ELOGF("SHELL", "Set toplevel", ec->pixmap, ec);
+
+ /* set toplevel client properties */
+ ec->icccm.accepts_focus = 1;
+ if (!ec->internal)
+ ec->borderless = 1;
+ ec->lock_border = EINA_TRUE;
+ if ((!ec->internal) || (!ec->borderless))
+ ec->border.changed = ec->changes.border = !ec->borderless;
+ if (ec->netwm.type == E_WINDOW_TYPE_UNKNOWN)
+ ec->netwm.type = E_WINDOW_TYPE_NORMAL;
+ ec->comp_data->set_win_type = EINA_TRUE;
+}
+
+EINTERN void
+e_shell_e_client_popup_set(E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ ELOGF("SHELL", "Set popup", ec->pixmap, ec);
+
+ EC_CHANGED(ec);
+ ec->new_client = ec->override = 1;
+ e_client_unignore(ec);
+ e_comp->new_clients++;
+ if (!ec->internal)
+ ec->borderless = !ec->internal_elm_win;
+ ec->lock_border = EINA_TRUE;
+ if (!ec->internal)
+ ec->border.changed = ec->changes.border = !ec->borderless;
+ ec->changes.icon = !!ec->icccm.class;
+ ec->netwm.type = E_WINDOW_TYPE_POPUP_MENU;
+ ec->comp_data->set_win_type = EINA_TRUE;
+ evas_object_layer_set(ec->frame, E_LAYER_CLIENT_POPUP);
+}
+
+EINTERN void
+e_shell_e_client_pong(E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ ELOGF("SHELL", "Pong", ec->pixmap, ec);
+
+ ec->ping_ok = EINA_TRUE;
+ ec->hung = EINA_FALSE;
+}
+
+EINTERN void
+e_shell_e_client_parent_set(E_Client *ec, struct wl_resource *parent_resource)
{
E_Client *pc;
Ecore_Window pwin = 0;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
if (!parent_resource)
{
ec->icccm.fetch.transient_for = EINA_FALSE;
ec->icccm.transient_for = pwin;
}
+EINTERN Eina_Bool
+e_shell_e_client_name_title_set(E_Client *ec, const char *name, const char *title)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ if (name)
+ eina_stringshare_replace(&ec->icccm.name, name);
+
+ if (title)
+ {
+ eina_stringshare_replace(&ec->icccm.title, title);
+ if (ec->frame)
+ e_comp_object_frame_title_set(ec->frame, title);
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_shell_e_client_app_id_set(E_Client *ec, const char *app_id)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ /* set class */
+ eina_stringshare_replace(&ec->icccm.class, app_id);
+ ec->changes.icon = !!ec->icccm.class;
+ EC_CHANGED(ec);
+
+ return EINA_TRUE;
+}
+
static void
-_e_shell_surface_mouse_down_helper(E_Client *ec, E_Binding_Event_Mouse_Button *ev, Eina_Bool move, int resize_edges)
+_e_shell_e_client_mouse_down_helper(E_Client *ec, E_Binding_Event_Mouse_Button *ev, Eina_Bool move, int resize_edges)
{
E_Pointer_Mode resize_mode = E_POINTER_RESIZE_NONE;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
if (move)
{
/* tell E to start moving the client */
e_focus_event_mouse_down(ec);
}
-static void
-_e_shell_surface_destroy(struct wl_resource *resource)
+EINTERN Eina_Bool
+e_shell_e_client_interactive_move(E_Client *ec,
+ /* TODO Multi seat is not yet supported */
+ struct wl_resource *seat EINA_UNUSED)
{
- E_Client *ec = NULL;
+ E_Binding_Event_Mouse_Button ev;
- /* get the client for this resource */
- if ((ec = wl_resource_get_user_data(resource)))
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ if ((ec->maximized) || (ec->fullscreen))
+ return EINA_FALSE;
+
+ TRACE_DS_BEGIN(SHELL:SURFACE MOVE REQUEST CB);
+
+ switch (e_comp_wl->ptr.button)
{
- if (e_policy_visibility_client_grab_cancel(ec))
- {
- ELOGF("POL_VIS", "CLIENT VIS ON(temp).", ec->pixmap, ec);
- ec->visibility.obscured = E_VISIBILITY_UNOBSCURED;
- ec->visibility.changed = 1;
- }
+ case BTN_LEFT: ev.button = 1; break;
+ case BTN_MIDDLE: ev.button = 2; break;
+ case BTN_RIGHT: ev.button = 3; break;
+ default: ev.button = e_comp_wl->ptr.button; break;
+ }
+
+ e_comp_object_frame_xy_unadjust(ec->frame,
+ wl_fixed_to_int(e_comp_wl->ptr.x),
+ wl_fixed_to_int(e_comp_wl->ptr.y),
+ &ev.canvas.x,
+ &ev.canvas.y);
+
+ _e_shell_e_client_mouse_down_helper(ec, &ev, EINA_TRUE, 0);
+
+ TRACE_DS_END();
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_shell_e_client_interactive_resize(E_Client *ec,
+ struct wl_resource *resource,
+ /* TODO Multi seat is not yet supported */
+ struct wl_resource *seat EINA_UNUSED,
+ uint32_t edges)
+{
+ E_Binding_Event_Mouse_Button ev;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+
+ if ((edges == 0) || (edges > 15) ||
+ ((edges & 3) == 3) || ((edges & 12) == 12))
+ return EINA_FALSE;
+
+ if ((ec->maximized) || (ec->fullscreen))
+ return EINA_FALSE;
+
+ TRACE_DS_BEGIN(SHELL:SURFACE RESIZE REQUEST CB);
+
+ e_comp_wl->resize.resource = resource;
+ e_comp_wl->resize.edges = edges;
+ e_comp_wl->ptr.grab_x = e_comp_wl->ptr.x - wl_fixed_from_int(ec->client.x);
+ e_comp_wl->ptr.grab_y = e_comp_wl->ptr.y - wl_fixed_from_int(ec->client.y);
+
+ switch (e_comp_wl->ptr.button)
+ {
+ case BTN_LEFT: ev.button = 1; break;
+ case BTN_MIDDLE: ev.button = 2; break;
+ case BTN_RIGHT: ev.button = 3; break;
+ default: ev.button = e_comp_wl->ptr.button; break;
+ }
+
+ e_comp_object_frame_xy_unadjust(ec->frame,
+ wl_fixed_to_int(e_comp_wl->ptr.x),
+ wl_fixed_to_int(e_comp_wl->ptr.y),
+ &ev.canvas.x,
+ &ev.canvas.y);
+
+ _e_shell_e_client_mouse_down_helper(ec, &ev, EINA_FALSE, edges);
- if ((e_object_unref(E_OBJECT(ec))) &&
- (!e_object_is_del(E_OBJECT(ec))))
+ TRACE_DS_END();
+
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_shell_e_client_destroy(E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ if (e_policy_visibility_client_grab_cancel(ec))
+ {
+ ELOGF("POL_VIS", "CLIENT VIS ON(temp).", ec->pixmap, ec);
+ ec->visibility.obscured = E_VISIBILITY_UNOBSCURED;
+ ec->visibility.changed = 1;
+ }
+
+ if ((e_object_unref(E_OBJECT(ec))) &&
+ (!e_object_is_del(E_OBJECT(ec))))
+ {
+ if (ec->comp_data->mapped)
{
- if (ec->comp_data->mapped)
- {
- if ((ec->comp_data->shell.surface) &&
- (ec->comp_data->shell.unmap))
- {
- ELOGF("SHELL", "Call shell.unmap by destory surface", ec->pixmap, ec);
- ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
- }
- }
- if (ec->parent)
+ if ((ec->comp_data->shell.surface) &&
+ (ec->comp_data->shell.unmap))
{
- ec->parent->transients =
- eina_list_remove(ec->parent->transients, ec);
- if (ec->parent->modal == ec) ec->parent->modal = NULL;
- ec->parent = NULL;
+ ELOGF("SHELL", "Call shell.unmap by destory surface", ec->pixmap, ec);
+ ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
}
- /* wl_resource_destroy(ec->comp_data->shell.surface); */
}
- if (ec->comp_data)
- ec->comp_data->shell.surface = NULL;
-
- ELOGF("SHELL", "Destroy shell surface", ec->pixmap, ec);
+ if (ec->parent)
+ {
+ ec->parent->transients =
+ eina_list_remove(ec->parent->transients, ec);
+ if (ec->parent->modal == ec) ec->parent->modal = NULL;
+ ec->parent = NULL;
+ }
+ /* wl_resource_destroy(ec->comp_data->shell.surface); */
}
+ if (ec->comp_data)
+ ec->comp_data->shell.surface = NULL;
+
+ ELOGF("SHELL", "Destroy shell surface", ec->pixmap, ec);
+
e_policy_client_unmap(ec);
}
+static void
+_e_shell_surface_destroy(struct wl_resource *resource)
+{
+ E_Client *ec = NULL;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ return;
+
+ e_shell_e_client_destroy(ec);
+}
+
static void
_e_shell_surface_cb_destroy(struct wl_resource *resource)
{
E_Client *ec;
if ((ec = wl_resource_get_user_data(resource)))
- {
- ec->ping_ok = EINA_TRUE;
- ec->hung = EINA_FALSE;
- }
+ e_shell_e_client_pong(ec);
}
static void
-_e_shell_surface_cb_move(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource EINA_UNUSED, uint32_t serial EINA_UNUSED)
+_e_shell_surface_cb_move(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial EINA_UNUSED)
{
E_Client *ec;
- E_Binding_Event_Mouse_Button ev;
/* get the client for this resource */
if (!(ec = wl_resource_get_user_data(resource)))
return;
}
- if ((ec->maximized) || (ec->fullscreen)) return;
-
- switch (e_comp_wl->ptr.button)
- {
- case BTN_LEFT: ev.button = 1; break;
- case BTN_MIDDLE: ev.button = 2; break;
- case BTN_RIGHT: ev.button = 3; break;
- default: ev.button = e_comp_wl->ptr.button; break;
- }
-
- e_comp_object_frame_xy_unadjust(ec->frame,
- wl_fixed_to_int(e_comp_wl->ptr.x),
- wl_fixed_to_int(e_comp_wl->ptr.y),
- &ev.canvas.x, &ev.canvas.y);
-
- _e_shell_surface_mouse_down_helper(ec, &ev, EINA_TRUE, 0);
+ e_shell_e_client_interactive_move(ec, seat_resource);
}
static void
-_e_shell_surface_cb_resize(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource EINA_UNUSED, uint32_t serial EINA_UNUSED, uint32_t edges)
+_e_shell_surface_cb_resize(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial EINA_UNUSED, uint32_t edges)
{
E_Client *ec;
- E_Binding_Event_Mouse_Button ev;
/* get the client for this resource */
if (!(ec = wl_resource_get_user_data(resource)))
return;
}
- if ((edges == 0) || (edges > 15) ||
- ((edges & 3) == 3) || ((edges & 12) == 12)) return;
-
- if ((ec->maximized) || (ec->fullscreen)) return;
-
- e_comp_wl->resize.resource = resource;
- e_comp_wl->resize.edges = edges;
- e_comp_wl->ptr.grab_x = e_comp_wl->ptr.x - wl_fixed_from_int(ec->client.x);
- e_comp_wl->ptr.grab_y = e_comp_wl->ptr.y - wl_fixed_from_int(ec->client.y);
-
- switch (e_comp_wl->ptr.button)
- {
- case BTN_LEFT: ev.button = 1; break;
- case BTN_MIDDLE: ev.button = 2; break;
- case BTN_RIGHT: ev.button = 3; break;
- default: ev.button = e_comp_wl->ptr.button; break;
- }
-
- e_comp_object_frame_xy_unadjust(ec->frame,
- wl_fixed_to_int(e_comp_wl->ptr.x),
- wl_fixed_to_int(e_comp_wl->ptr.y),
- &ev.canvas.x, &ev.canvas.y);
-
- _e_shell_surface_mouse_down_helper(ec, &ev, EINA_FALSE, edges);
+ e_shell_e_client_interactive_resize(ec, resource, seat_resource, edges);
}
static void
}
/* set toplevel client properties */
- ec->icccm.accepts_focus = 1;
- if (!ec->internal)
- ec->borderless = !ec->internal;
+ e_shell_e_client_toplevel_set(ec);
- ec->lock_border = EINA_TRUE;
- if (!ec->internal)
- ec->border.changed = ec->changes.border = !ec->borderless;
- ec->netwm.type = E_WINDOW_TYPE_NORMAL;
- ec->comp_data->set_win_type = EINA_TRUE;
if ((!ec->lock_user_maximize) && (ec->maximized))
e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
if ((!ec->lock_user_fullscreen) && (ec->fullscreen))
}
/* set this client as a transient for parent */
- _e_shell_surface_parent_set(ec, parent_resource);
+ e_shell_e_client_parent_set(ec, parent_resource);
EC_CHANGED(ec);
}
ec->layer = E_LAYER_CLIENT_POPUP;
/* set this client as a transient for parent */
- _e_shell_surface_parent_set(ec, parent_resource);
+ e_shell_e_client_parent_set(ec, parent_resource);
EC_CHANGED(ec);
}
}
/* set title */
- eina_stringshare_replace(&ec->icccm.title, title);
- if (ec->frame) e_comp_object_frame_title_set(ec->frame, title);
+ e_shell_e_client_name_title_set(ec, NULL, title);
}
static void
_e_shell_cb_shell_surface_get(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t id, struct wl_resource *surface_resource)
{
E_Client *ec;
- E_Comp_Client_Data *cdata;
+ struct wl_resource *shsurf_resource;
+ E_Shell_Surface_Api api = {
+ .configure_send = _e_shell_surface_configure_send,
+ .configure = _e_shell_surface_configure,
+ .ping = _e_shell_surface_ping,
+ .map = _e_shell_surface_map,
+ .unmap = _e_shell_surface_unmap,
+ };
/* get the pixmap from this surface so we can find the client */
if (!(ec = wl_resource_get_user_data(surface_resource)))
"No Pixmap Set On Surface");
return;
}
- ec->netwm.ping = 1;
- /* get the client data */
- if (!(cdata = ec->comp_data))
- {
- wl_resource_post_error(surface_resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Data For Client");
- return;
- }
- /* check for existing shell surface */
- if (cdata->shell.surface)
+ if (!e_shell_e_client_shell_assignable_check(ec))
{
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Client already has shell surface");
+ "Could not assign shell surface to wl_surface");
return;
}
- /* try to create a shell surface */
- if (!(cdata->shell.surface =
- wl_resource_create(client, &wl_shell_surface_interface, 1, id)))
+ shsurf_resource = wl_resource_create(client, &wl_shell_surface_interface, 1, id);
+ if (!shsurf_resource)
{
- wl_resource_post_no_memory(surface_resource);
+ wl_client_post_no_memory(client);
return;
}
- ELOGF("SHELL", "Create shell surface", ec->pixmap, ec);
- wl_resource_set_implementation(cdata->shell.surface,
+ wl_resource_set_implementation(shsurf_resource,
&_e_shell_surface_interface,
ec,
_e_shell_surface_cb_destroy);
- e_object_ref(E_OBJECT(ec));
-
- cdata->shell.configure_send = _e_shell_surface_configure_send;
- cdata->shell.configure = _e_shell_surface_configure;
- cdata->shell.ping = _e_shell_surface_ping;
- cdata->shell.map = _e_shell_surface_map;
- cdata->shell.unmap = _e_shell_surface_unmap;
+ ELOGF("SHELL", "Create shell surface", ec->pixmap, ec);
+ e_shell_e_client_shsurface_assign(ec, shsurf_resource, &api);
e_comp_wl_shell_surface_ready(ec);
}
}
/* set this client as a transient for parent */
- _e_shell_surface_parent_set(ec, parent_resource);
+ e_shell_e_client_parent_set(ec, parent_resource);
EC_CHANGED(ec);
}
}
/* set title */
- eina_stringshare_replace(&ec->icccm.title, title);
- eina_stringshare_replace(&ec->icccm.name, title);
- if (ec->frame) e_comp_object_frame_title_set(ec->frame, title);
+ e_shell_e_client_name_title_set(ec, title, title);
}
static void
/* use the wl_client to get the pid * and set it in the netwm props */
wl_client_get_credentials(client, &ec->netwm.pid, NULL, NULL);
- /* set class */
- eina_stringshare_replace(&ec->icccm.class, id);
- /* eina_stringshare_replace(&ec->netwm.name, id); */
- ec->changes.icon = !!ec->icccm.class;
- EC_CHANGED(ec);
+ e_shell_e_client_app_id_set(ec, id);
}
static void
}
static void
-_e_xdg_shell_surface_cb_move(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource EINA_UNUSED, uint32_t serial EINA_UNUSED)
+_e_xdg_shell_surface_cb_move(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial EINA_UNUSED)
{
E_Client *ec;
- E_Binding_Event_Mouse_Button ev;
/* get the client for this resource */
if (!(ec = wl_resource_get_user_data(resource)))
return;
}
- if ((ec->maximized) || (ec->fullscreen)) return;
-
- TRACE_DS_BEGIN(SHELL:SURFACE MOVE REQUEST CB);
-
- switch (e_comp_wl->ptr.button)
- {
- case BTN_LEFT: ev.button = 1; break;
- case BTN_MIDDLE: ev.button = 2; break;
- case BTN_RIGHT: ev.button = 3; break;
- default: ev.button = e_comp_wl->ptr.button; break;
- }
-
- e_comp_object_frame_xy_unadjust(ec->frame,
- wl_fixed_to_int(e_comp_wl->ptr.x),
- wl_fixed_to_int(e_comp_wl->ptr.y),
- &ev.canvas.x,
- &ev.canvas.y);
-
- _e_shell_surface_mouse_down_helper(ec, &ev, EINA_TRUE, 0);
-
- TRACE_DS_END();
-}
+ e_shell_e_client_interactive_move(ec, seat_resource);
+}
static void
-_e_xdg_shell_surface_cb_resize(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource EINA_UNUSED, uint32_t serial EINA_UNUSED, uint32_t edges)
+_e_xdg_shell_surface_cb_resize(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial EINA_UNUSED, uint32_t edges)
{
E_Client *ec;
- E_Binding_Event_Mouse_Button ev;
/* get the client for this resource */
if (!(ec = wl_resource_get_user_data(resource)))
return;
}
- if ((edges == 0) ||
- (edges > 15) ||
- ((edges & 3) == 3) ||
- ((edges & 12) == 12))
- return;
-
- if ((ec->maximized) || (ec->fullscreen)) return;
-
- TRACE_DS_BEGIN(SHELL:SURFACE RESIZE REQUEST CB);
-
- e_comp_wl->resize.resource = resource;
- e_comp_wl->resize.edges = edges;
- e_comp_wl->ptr.grab_x = e_comp_wl->ptr.x - wl_fixed_from_int(ec->client.x);
- e_comp_wl->ptr.grab_y = e_comp_wl->ptr.y - wl_fixed_from_int(ec->client.y);
-
- switch (e_comp_wl->ptr.button)
- {
- case BTN_LEFT: ev.button = 1; break;
- case BTN_MIDDLE: ev.button = 2; break;
- case BTN_RIGHT: ev.button = 3; break;
- default: ev.button = e_comp_wl->ptr.button; break;
- }
-
- e_comp_object_frame_xy_unadjust(ec->frame,
- wl_fixed_to_int(e_comp_wl->ptr.x),
- wl_fixed_to_int(e_comp_wl->ptr.y),
- &ev.canvas.x,
- &ev.canvas.y);
-
- _e_shell_surface_mouse_down_helper(ec, &ev, EINA_FALSE, edges);
-
- TRACE_DS_END();
+ e_shell_e_client_interactive_resize(ec, resource, seat_resource, edges);
}
static void
return ECORE_CALLBACK_CANCEL;
}
-static void
-_e_xdg_shell_surface_map(struct wl_resource *resource)
+EINTERN void
+e_shell_e_client_map(E_Client *ec)
{
- E_Client *ec;
+ int pw = 0;
+ int ph = 0;
+ int cw;
+ int ch;
- if (!resource) return;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
- TRACE_DS_BEGIN(SHELL:MAP);
+ if ((ec->comp_data->mapped) || (!e_pixmap_usable_get(ec->pixmap)))
+ return;
- /* get the client for this resource */
- if (!(ec = wl_resource_get_user_data(resource)))
+ cw = ec->w;
+ ch = ec->h;
+
+ e_pixmap_size_get(ec->pixmap, &pw, &ph);
+ evas_object_geometry_get(ec->frame, NULL, NULL, &cw, &ch);
+ if (cw == 0 && ch == 0)
{
- wl_resource_post_error(resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- TRACE_DS_END();
- return;
+ cw = ec->w;
+ ch = ec->h;
}
- if ((!ec->comp_data->mapped) && (e_pixmap_usable_get(ec->pixmap)))
+ if (pw != cw || ph != ch)
{
- int pw = 0;
- int ph = 0;
- int cw = ec->w;
- int ch = ec->h;
- e_pixmap_size_get(ec->pixmap, &pw, &ph);
- evas_object_geometry_get(ec->frame, NULL, NULL, &cw, &ch);
- if (cw == 0 && ch == 0)
+ if ((ec->changes.need_maximize) ||
+ ((ec->maximized & E_MAXIMIZE_BOTH) == E_MAXIMIZE_BOTH))
{
- cw = ec->w;
- ch = ec->h;
- }
+ // skip. because the pixmap's size doesnot same to ec's size
+ ELOGF("SHELL",
+ "Deny Map |win:0x%08x|ec_size:%d,%d|get_size:%d,%d|pix_size:%d,%d",
+ ec->pixmap, ec,
+ (unsigned int)e_client_util_win_get(ec),
+ ec->w, ec->h, cw, ch, pw, ph);
- if (pw != cw || ph != ch)
- {
- if ((ec->changes.need_maximize) ||
- ((ec->maximized & E_MAXIMIZE_BOTH) == E_MAXIMIZE_BOTH))
- {
- // skip. because the pixmap's size doesnot same to ec's size
- ELOGF("SHELL",
- "Deny Map |win:0x%08x|ec_size:%d,%d|get_size:%d,%d|pix_size:%d,%d",
- ec->pixmap, ec,
- (unsigned int)e_client_util_win_get(ec),
- ec->w, ec->h, cw, ch, pw, ph);
-
- if (!ec->map_timer)
- ec->map_timer = ecore_timer_add(3.0, _e_xdg_shell_surface_map_cb_timer, ec);
-
- TRACE_DS_END();
- return;
- }
- }
- E_FREE_FUNC(ec->map_timer, ecore_timer_del);
+ if (!ec->map_timer)
+ ec->map_timer = ecore_timer_add(3.0, _e_xdg_shell_surface_map_cb_timer, ec);
- ELOGF("SHELL",
- "Map window |win:0x%08x|ec_size:%d,%d|pid:%d|title:%s, name:%s",
- ec->pixmap, ec,
- (unsigned int)e_client_util_win_get(ec),
- ec->w, ec->h, ec->netwm.pid, ec->icccm.title, ec->netwm.name);
+ TRACE_DS_END();
+ return;
+ }
+ }
+ E_FREE_FUNC(ec->map_timer, ecore_timer_del);
- ELOGF("SHELL",
- "spash:%d, first_mapped:%d, iconic:%d(client:%d), raise:%d, lower:%d, ignore:%d, override:%d, input_only:%d",
- ec->pixmap, ec,
- ec->use_splash, ec->first_mapped, ec->iconic, ec->exp_iconify.by_client,
- ec->post_raise, ec->post_lower, ec->ignored, ec->override, ec->input_only);
+ ELOGF("SHELL",
+ "Map window |win:0x%08x|ec_size:%d,%d|pid:%d|title:%s, name:%s",
+ ec->pixmap, ec,
+ (unsigned int)e_client_util_win_get(ec),
+ ec->w, ec->h, ec->netwm.pid, ec->icccm.title, ec->netwm.name);
- _e_shell_client_map_common_pre(ec);
- _e_shell_client_map_common_post(ec);
- }
+ ELOGF("SHELL",
+ "spash:%d, first_mapped:%d, iconic:%d(client:%d), raise:%d, lower:%d, ignore:%d, override:%d, input_only:%d",
+ ec->pixmap, ec,
+ ec->use_splash, ec->first_mapped, ec->iconic, ec->exp_iconify.by_client,
+ ec->post_raise, ec->post_lower, ec->ignored, ec->override, ec->input_only);
- TRACE_DS_END();
+ _e_shell_client_map_common_pre(ec);
+ _e_shell_client_map_common_post(ec);
}
static void
-_e_xdg_shell_surface_unmap(struct wl_resource *resource)
+_e_xdg_shell_surface_map(struct wl_resource *resource)
{
E_Client *ec;
if (!resource) return;
- TRACE_DS_BEGIN(SHELL:UNMAP);
+ TRACE_DS_BEGIN(SHELL:MAP);
/* get the client for this resource */
if (!(ec = wl_resource_get_user_data(resource)))
return;
}
+ e_shell_e_client_map(ec);
+
+ TRACE_DS_END();
+}
+
+EINTERN void
+e_shell_e_client_unmap(E_Client *ec)
+{
+
E_FREE_FUNC(ec->map_timer, ecore_timer_del);
if (ec->comp_data->mapped)
(unsigned int)e_client_util_win_get(ec),
ec->w, ec->h);
}
-
- TRACE_DS_END();
}
static void
-_e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t id, struct wl_resource *surface_resource)
+_e_xdg_shell_surface_unmap(struct wl_resource *resource)
{
E_Client *ec;
- E_Comp_Client_Data *cdata;
- /* get the pixmap from this surface so we can find the client */
- if (!(ec = wl_resource_get_user_data(surface_resource)))
+ if (!resource) return;
+
+ TRACE_DS_BEGIN(SHELL:UNMAP);
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
{
- wl_resource_post_error(surface_resource,
+ wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Pixmap Set On Surface");
+ "No Client For Shell Surface");
+ TRACE_DS_END();
return;
}
- ec->netwm.ping = 1;
+ e_shell_e_client_unmap(ec);
+
+ TRACE_DS_END();
+}
+
+static void
+_e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t id, struct wl_resource *surface_resource)
+{
+ E_Client *ec;
+ struct wl_resource *shsurf_resource;
+ E_Shell_Surface_Api api = {
+ .configure_send = _e_xdg_shell_surface_configure_send,
+ .configure = _e_xdg_shell_surface_configure,
+ .ping = _e_xdg_shell_surface_ping,
+ .map = _e_xdg_shell_surface_map,
+ .unmap = _e_xdg_shell_surface_unmap,
+ };
- /* get the client data */
- if (!(cdata = ec->comp_data))
+ /* get the pixmap from this surface so we can find the client */
+ if (!(ec = wl_resource_get_user_data(surface_resource)))
{
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Data For Client");
+ "No Pixmap Set On Surface");
return;
}
- /* check for existing shell surface */
- if (cdata->shell.surface)
+ if (!e_shell_e_client_shell_assignable_check(ec))
{
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Client already has XDG shell surface");
+ "Could not assign shell surface to wl_surface");
return;
}
/* try to create a shell surface */
- if (!(cdata->shell.surface =
- wl_resource_create(client, &xdg_surface_interface, 1, id)))
+ shsurf_resource = wl_resource_create(client, &xdg_surface_interface, 1, id);
+ if (!shsurf_resource)
{
ERR("Could not create xdg shell surface");
wl_resource_post_no_memory(surface_resource);
}
ELOGF("SHELL", "Create xdg shell surface", ec->pixmap, ec);
- wl_resource_set_implementation(cdata->shell.surface,
+ wl_resource_set_implementation(shsurf_resource,
&_e_xdg_surface_interface,
ec,
_e_shell_surface_cb_destroy);
- e_object_ref(E_OBJECT(ec));
-
- cdata->shell.configure_send = _e_xdg_shell_surface_configure_send;
- cdata->shell.configure = _e_xdg_shell_surface_configure;
- cdata->shell.ping = _e_xdg_shell_surface_ping;
- cdata->shell.map = _e_xdg_shell_surface_map;
- cdata->shell.unmap = _e_xdg_shell_surface_unmap;
-
- /* set toplevel client properties */
- ec->icccm.accepts_focus = 1;
- if (!ec->internal)
- ec->borderless = 1;
- ec->lock_border = EINA_TRUE;
- if ((!ec->internal) || (!ec->borderless))
- ec->border.changed = ec->changes.border = !ec->borderless;
- if (ec->netwm.type == E_WINDOW_TYPE_UNKNOWN)
- ec->netwm.type = E_WINDOW_TYPE_NORMAL;
- ec->comp_data->set_win_type = EINA_TRUE;
+ e_shell_e_client_shsurface_assign(ec, shsurf_resource, &api);
+ e_shell_e_client_toplevel_set(ec);
e_comp_wl_shell_surface_ready(ec);
}
{
E_Client *ec;
E_Comp_Client_Data *cdata;
+ struct wl_resource *shsurf_resource;
+ E_Shell_Surface_Api api = {
+ .configure_send = _e_xdg_shell_surface_configure_send,
+ .configure = _e_xdg_shell_surface_configure,
+ .ping = _e_xdg_shell_surface_ping,
+ .map = _e_xdg_shell_surface_map,
+ .unmap = _e_xdg_shell_surface_unmap,
+ };
/* get the pixmap from this surface so we can find the client */
if (!(ec = wl_resource_get_user_data(surface_resource)))
return;
}
- /* get the client data */
- if (!(cdata = ec->comp_data))
- {
- wl_resource_post_error(surface_resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Data For Client");
- return;
- }
-
- /* check for existing shell surface */
- if (cdata->shell.surface)
+ if (!e_shell_e_client_shell_assignable_check(ec))
{
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Client already has shell popup surface");
+ "Could not assign shell surface to wl_surface");
return;
}
}
/* try to create a shell surface */
- if (!(cdata->shell.surface =
- wl_resource_create(client, &xdg_popup_interface, 1, id)))
+ shsurf_resource = wl_resource_create(client, &xdg_popup_interface, 1, id);
+ if (!shsurf_resource)
{
ERR("Could not create xdg shell surface");
wl_resource_post_no_memory(surface_resource);
}
ELOGF("SHELL", "Create xdg shell popup surface", ec->pixmap, ec);
- wl_resource_set_implementation(cdata->shell.surface,
+ wl_resource_set_implementation(shsurf_resource,
&_e_xdg_popup_interface,
ec,
NULL);
- e_object_ref(E_OBJECT(ec));
-
- cdata->shell.configure_send = _e_xdg_shell_surface_configure_send;
- cdata->shell.configure = _e_xdg_shell_surface_configure;
- cdata->shell.ping = _e_xdg_shell_surface_ping;
- cdata->shell.map = _e_xdg_shell_surface_map;
- cdata->shell.unmap = _e_xdg_shell_surface_unmap;
-
- EC_CHANGED(ec);
- ec->new_client = ec->override = 1;
- e_client_unignore(ec);
- e_comp->new_clients++;
- if (!ec->internal)
- ec->borderless = !ec->internal_elm_win;
- ec->lock_border = EINA_TRUE;
- if (!ec->internal)
- ec->border.changed = ec->changes.border = !ec->borderless;
- ec->changes.icon = !!ec->icccm.class;
- ec->netwm.type = E_WINDOW_TYPE_POPUP_MENU;
- ec->comp_data->set_win_type = EINA_TRUE;
- evas_object_layer_set(ec->frame, E_LAYER_CLIENT_POPUP);
+ e_shell_e_client_shsurface_assign(ec, shsurf_resource, &api);
+ e_shell_e_client_popup_set(ec);
/* set this client as a transient for parent */
- _e_shell_surface_parent_set(ec, parent_resource);
+ e_shell_e_client_parent_set(ec, parent_resource);
+ cdata = ec->comp_data;
if (ec->parent)
{
cdata->popup.x = E_CLAMP(x, 0, ec->parent->client.w);
EINA_SAFETY_ON_FALSE_RETURN(esh->res == resource);
EINA_LIST_FREE(esh->ping_ecs, ec)
- {
- if (e_object_is_del(E_OBJECT(ec))) continue;
-
- ec->ping_ok = EINA_TRUE;
- ec->hung = EINA_FALSE;
- }
+ e_shell_e_client_pong(ec);
}
static void
_e_xdg_shell_cb_unbind(struct wl_resource *resource)
{
E_Xdg_Shell *esh;
- E_Xdg_Pos *epos;
E_Client *ec;
struct wl_client *client;
- Eina_List *l, *ll;
client = wl_resource_get_client(resource);
EINA_SAFETY_ON_NULL_RETURN(client);
EINA_SAFETY_ON_NULL_RETURN(esh);
EINA_LIST_FREE(esh->ping_ecs, ec)
- {
- if (e_object_is_del(E_OBJECT(ec))) continue;
- ec->ping_ok = EINA_TRUE;
- ec->hung = EINA_FALSE;
- }
-
- EINA_LIST_FOREACH_SAFE(esh->positioners, l, ll, epos)
- {
- E_FREE(epos);
- }
+ e_shell_e_client_pong(ec);
eina_hash_del_by_key(xdg_sh_hash, &client);
wl_client_post_no_memory(client);
}
-////////////////////////////////////////////////////////////////////////////////
static void
-_e_xdg_surf_v6_configure_send(struct wl_resource *res_xdg_surf_v6,
- uint32_t edges,
- int32_t width,
- int32_t height)
+_e_tz_surf_cb_tz_res_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface)
{
+ struct wl_resource *res;
E_Client *ec;
- E_Comp_Client_Data *cdata;
- struct wl_array states;
- uint32_t serial;
- struct wl_resource *resource;
-
- EINA_SAFETY_ON_NULL_RETURN(res_xdg_surf_v6);
+ uint32_t res_id;
- ec = wl_resource_get_user_data(res_xdg_surf_v6);
- if (!ec)
+ /* get the pixmap from this surface so we can find the client */
+ if (!(ec = wl_resource_get_user_data(surface)))
{
- wl_resource_post_error(res_xdg_surf_v6,
+ wl_resource_post_error(surface,
WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
+ "No Pixmap Set On Surface");
return;
}
- cdata = ec->comp_data;
- EINA_SAFETY_ON_NULL_RETURN(cdata);
- EINA_SAFETY_ON_NULL_RETURN(cdata->sh_v6.res_role);
-
- resource = cdata->sh_v6.res_role;
-
- wl_array_init(&states);
-
- if (ec->fullscreen)
- {
- _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN);
+ /* find the window id for this pixmap */
+ res_id = e_pixmap_res_id_get(ec->pixmap);
- // send fullscreen size
- if ((width == 0) && (height == 0))
- {
- width = ec->client.w && ec->client.h? ec->client.w : ec->w;
- height = ec->client.w && ec->client.h? ec->client.h : ec->h;
- }
- }
- else if (ec->maximized)
+ /* try to create a tizen_gid */
+ if (!(res = wl_resource_create(client,
+ &tizen_resource_interface,
+ wl_resource_get_version(resource),
+ id)))
{
- _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED);
-
- // send maximized size
- if ((width == 0) && (height == 0))
- {
- width = ec->client.w && ec->client.h? ec->client.w : ec->w;
- height = ec->client.w && ec->client.h? ec->client.h : ec->h;
- }
+ wl_resource_post_no_memory(resource);
+ return;
}
- if (edges != 0)
- _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_RESIZING);
-
- if (ec->focused)
- _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED);
-
- zxdg_toplevel_v6_send_configure(cdata->sh_v6.res_role, width, height, &states);
- serial = wl_display_next_serial(e_comp_wl->wl.disp);
- zxdg_surface_v6_send_configure(res_xdg_surf_v6, serial);
-
- wl_array_release(&states);
+ wl_resource_set_implementation(res,
+ &_e_tz_res_interface,
+ ec,
+ NULL);
- ELOGF("SH", "SEND configure v6 %dx%d", ec->pixmap, ec, width, height);
+ tizen_resource_send_resource_id(res, res_id);
}
static void
-_e_xdg_sh_v6_ping(struct wl_resource *res_xdg_surf_v6)
+_e_tz_surf_cb_destroy(struct wl_client *client, struct wl_resource *resource)
{
- E_Client *ec;
- uint32_t serial;
- struct wl_client *client;
- E_Xdg_Shell *esh;
+ wl_resource_destroy(resource);
+}
- if (!res_xdg_surf_v6) return;
+static const struct tizen_surface_interface _e_tz_surf_interface =
+{
+ _e_tz_surf_cb_tz_res_get,
+ _e_tz_surf_cb_destroy
+};
- ec = wl_resource_get_user_data(res_xdg_surf_v6);
- if (!ec)
+static void
+_e_tz_surf_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ struct wl_resource *res;
+
+ if (!(res = wl_resource_create(client,
+ &tizen_surface_interface,
+ version,
+ id)))
{
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- client = wl_resource_get_client(res_xdg_surf_v6);
-
- esh = eina_hash_find(xdg_sh_hash, &client);
- EINA_SAFETY_ON_NULL_RETURN(esh);
- EINA_SAFETY_ON_NULL_RETURN(esh->res);
-
- if (!eina_list_data_find(esh->ping_ecs, ec))
- esh->ping_ecs = eina_list_append(esh->ping_ecs, ec);
-
- serial = wl_display_next_serial(e_comp_wl->wl.disp);
- zxdg_shell_v6_send_ping(esh->res, serial);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-static void
-_e_xdg_toplv_v6_cb_res_destroy(struct wl_resource *res_xdg_toplv_v6)
-{
- _e_shell_surface_destroy(res_xdg_toplv_v6);
-}
-
-static void
-_e_xdg_toplv_v6_cb_destroy(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6)
-{
- wl_resource_destroy(res_xdg_toplv_v6);
-}
-
-static void
-_e_xdg_toplv_v6_cb_parent_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- struct wl_resource *res_xdg_toplv_v6_parent)
-{
- E_Client *ec, *pc;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if (res_xdg_toplv_v6_parent)
- {
- pc = wl_resource_get_user_data(res_xdg_toplv_v6_parent);
- if (!pc)
- {
- ERR("Could not get parent resource clinet");
- return;
- }
- if (!pc->comp_data) return;
- res_xdg_toplv_v6_parent = pc->comp_data->surface;
- }
-
- /* set this client as a transient for parent */
- _e_shell_surface_parent_set(ec, res_xdg_toplv_v6_parent);
-}
-
-static void
-_e_xdg_toplv_v6_cb_title_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- const char *title)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- eina_stringshare_replace(&ec->icccm.title, title);
- eina_stringshare_replace(&ec->icccm.name, title);
- if (ec->frame) e_comp_object_frame_title_set(ec->frame, title);
-}
-
-static void
-_e_xdg_toplv_v6_cb_app_id_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- const char *app_id)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- /* use the wl_client to get the pid * and set it in the netwm props */
- wl_client_get_credentials(client, &ec->netwm.pid, NULL, NULL);
-
- /* set class */
- eina_stringshare_replace(&ec->icccm.class, app_id);
- ec->changes.icon = !!ec->icccm.class;
- EC_CHANGED(ec);
-}
-
-static void
-_e_xdg_toplv_v6_cb_win_menu_show(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- struct wl_resource *res_seat,
- uint32_t serial,
- int32_t x,
- int32_t y)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- /* TODO no op */
-}
-
-static void
-_e_xdg_toplv_v6_cb_move(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- struct wl_resource *res_seat,
- uint32_t serial)
-{
- E_Client *ec;
- E_Binding_Event_Mouse_Button ev;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if ((ec->maximized) || (ec->fullscreen)) return;
-
- TRACE_DS_BEGIN(SHELL:SURFACE MOVE REQUEST CB);
-
- switch (e_comp_wl->ptr.button)
- {
- case BTN_LEFT: ev.button = 1; break;
- case BTN_MIDDLE: ev.button = 2; break;
- case BTN_RIGHT: ev.button = 3; break;
- default: ev.button = e_comp_wl->ptr.button; break;
- }
-
- e_comp_object_frame_xy_unadjust(ec->frame,
- wl_fixed_to_int(e_comp_wl->ptr.x),
- wl_fixed_to_int(e_comp_wl->ptr.y),
- &ev.canvas.x,
- &ev.canvas.y);
-
- _e_shell_surface_mouse_down_helper(ec, &ev, EINA_TRUE, 0);
-
- TRACE_DS_END();
-}
-
-static void
-_e_xdg_toplv_v6_cb_resize(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- struct wl_resource *res_seat,
- uint32_t serial,
- uint32_t edges)
-{
- E_Client *ec;
- E_Binding_Event_Mouse_Button ev;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if ((edges == 0) ||
- (edges > 15) ||
- ((edges & 3) == 3) ||
- ((edges & 12) == 12))
- return;
-
- if ((ec->maximized) || (ec->fullscreen)) return;
-
- TRACE_DS_BEGIN(SHELL:SURFACE RESIZE REQUEST CB);
-
- e_comp_wl->resize.resource = res_xdg_toplv_v6;
- e_comp_wl->resize.edges = edges;
- e_comp_wl->ptr.grab_x = e_comp_wl->ptr.x - wl_fixed_from_int(ec->client.x);
- e_comp_wl->ptr.grab_y = e_comp_wl->ptr.y - wl_fixed_from_int(ec->client.y);
-
- switch (e_comp_wl->ptr.button)
- {
- case BTN_LEFT: ev.button = 1; break;
- case BTN_MIDDLE: ev.button = 2; break;
- case BTN_RIGHT: ev.button = 3; break;
- default: ev.button = e_comp_wl->ptr.button; break;
- }
-
- e_comp_object_frame_xy_unadjust(ec->frame,
- wl_fixed_to_int(e_comp_wl->ptr.x),
- wl_fixed_to_int(e_comp_wl->ptr.y),
- &ev.canvas.x,
- &ev.canvas.y);
-
- _e_shell_surface_mouse_down_helper(ec, &ev, EINA_FALSE, edges);
-
- TRACE_DS_END();
-}
-
-static void
-_e_xdg_toplv_v6_cb_max_size_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- int32_t w,
- int32_t h)
-{
- /* TODO no op */
-}
-
-static void
-_e_xdg_toplv_v6_cb_min_size_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- int32_t w,
- int32_t h)
-{
- /* TODO no op */
-}
-
-static void
-_e_xdg_toplv_v6_cb_maximized_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if (!ec->lock_user_maximize)
- {
- e_client_maximize(ec,
- ((e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_BOTH));
- }
-}
-
-static void
-_e_xdg_toplv_v6_cb_maximized_unset(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
-
- _e_xdg_shell_surface_configure_send(res_xdg_toplv_v6,
- 0,
- ec->w,
- ec->h); // TODO
-}
-
-static void
-_e_xdg_toplv_v6_cb_fullscreen_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6,
- struct wl_resource *res_output)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if (!ec->lock_user_fullscreen)
- e_client_fullscreen(ec, e_config->fullscreen_policy);
-}
-
-static void
-_e_xdg_toplv_v6_cb_fullscreen_unset(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if (!ec->lock_user_fullscreen)
- e_client_unfullscreen(ec);
-}
-
-static void
-_e_xdg_toplv_v6_cb_minimized_set(struct wl_client *client,
- struct wl_resource *res_xdg_toplv_v6)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_toplv_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_toplv_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
-
- if (!ec->lock_client_iconify)
- e_client_iconify(ec);
-}
-
-static const struct zxdg_toplevel_v6_interface _e_xdg_toplv_v6_interface =
-{
- _e_xdg_toplv_v6_cb_destroy,
- _e_xdg_toplv_v6_cb_parent_set,
- _e_xdg_toplv_v6_cb_title_set,
- _e_xdg_toplv_v6_cb_app_id_set,
- _e_xdg_toplv_v6_cb_win_menu_show,
- _e_xdg_toplv_v6_cb_move,
- _e_xdg_toplv_v6_cb_resize,
- _e_xdg_toplv_v6_cb_max_size_set,
- _e_xdg_toplv_v6_cb_min_size_set,
- _e_xdg_toplv_v6_cb_maximized_set,
- _e_xdg_toplv_v6_cb_maximized_unset,
- _e_xdg_toplv_v6_cb_fullscreen_set,
- _e_xdg_toplv_v6_cb_fullscreen_unset,
- _e_xdg_toplv_v6_cb_minimized_set
-};
-
-////////////////////////////////////////////////////////////////////////////////
-static void
-_e_xdg_popup_v6_cb_res_destroy(struct wl_resource *res_xdg_popup_v6)
-{
- _e_shell_surface_destroy(res_xdg_popup_v6);
-}
-
-static void
-_e_xdg_popup_v6_cb_destroy(struct wl_client *client,
- struct wl_resource *res_xdg_popup_v6)
-{
- wl_resource_destroy(res_xdg_popup_v6);
-}
-
-static void
-_e_xdg_popup_v6_cb_grab(struct wl_client *client,
- struct wl_resource *res_xdg_popup_v6,
- struct wl_resource *res_seat,
- uint32_t serial)
-{
- /* TODO no op */
-}
-
-static const struct zxdg_popup_v6_interface _e_xdg_popup_v6_interface =
-{
- _e_xdg_popup_v6_cb_destroy,
- _e_xdg_popup_v6_cb_grab
-};
-
-////////////////////////////////////////////////////////////////////////////////
-static void
-_e_xdg_pos_v6_cb_res_destroy(struct wl_resource *res_xdg_pos_v6)
-{
- E_Xdg_Shell *esh = NULL;
- E_Xdg_Pos *epos = NULL;
-
- epos = wl_resource_get_user_data(res_xdg_pos_v6);
- EINA_SAFETY_ON_NULL_RETURN(epos);
-
- esh = epos->sh;
- esh->positioners = eina_list_remove(esh->positioners, epos);
-
- E_FREE(epos);
-}
-
-static void
-_e_xdg_pos_v6_cb_destroy(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6)
-{
- wl_resource_destroy(res_xdg_pos_v6);
-}
-
-static void
-_e_xdg_pos_v6_cb_size_set(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6,
- int32_t w,
- int32_t h)
-{
- /* TODO: no op */
-}
-
-static void
-_e_xdg_pos_v6_cb_anchor_rect_set(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6,
- int32_t x,
- int32_t y,
- int32_t w,
- int32_t h)
-{
- /* TODO: no op */
-}
-
-static void
-_e_xdg_pos_v6_cb_anchor_set(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6,
- uint32_t anchor)
-{
- /* TODO: no op */
-}
-
-static void
-_e_xdg_pos_v6_cb_gravity_set(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6,
- uint32_t gravity)
-{
- /* TODO: no op */
-}
-
-static void
-_e_xdg_pos_v6_cb_constraint_adjustment_set(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6,
- uint32_t constraint_adjustment)
-{
- /* TODO: no op */
-}
-
-static void
-_e_xdg_pos_v6_cb_offset_set(struct wl_client *client,
- struct wl_resource *res_xdg_pos_v6,
- int32_t x,
- int32_t y)
-{
- /* TODO: no op */
-}
-
-static const struct zxdg_positioner_v6_interface _e_xdg_pos_v6_interface =
-{
- _e_xdg_pos_v6_cb_destroy,
- _e_xdg_pos_v6_cb_size_set,
- _e_xdg_pos_v6_cb_anchor_rect_set,
- _e_xdg_pos_v6_cb_anchor_set,
- _e_xdg_pos_v6_cb_gravity_set,
- _e_xdg_pos_v6_cb_constraint_adjustment_set,
- _e_xdg_pos_v6_cb_offset_set
-};
-
-////////////////////////////////////////////////////////////////////////////////
-static void
-_e_xdg_surf_v6_cb_destroy(struct wl_client *client,
- struct wl_resource *res_xdg_surf_v6)
-{
- wl_resource_destroy(res_xdg_surf_v6);
-}
-
-static void
-_e_xdg_surf_v6_cb_toplevel_get(struct wl_client *client,
- struct wl_resource *res_xdg_surf_v6,
- uint32_t id)
-{
- E_Client *ec;
- E_Comp_Client_Data *cdata;
-
- ec = wl_resource_get_user_data(res_xdg_surf_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Pixmap Set On Surface");
- return;
- }
-
- cdata = ec->comp_data;
- if (!cdata)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Data For Client");
- return;
- }
-
- if (cdata->sh_v6.res_role)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Client already has shell toplevel resource");
- return;
- }
-
- cdata->sh_v6.res_role = wl_resource_create(client,
- &zxdg_toplevel_v6_interface,
- 1,
- id);
- if (!cdata->sh_v6.res_role)
- {
- ERR("Could not create xdg toplevel resource");
- wl_resource_post_no_memory(res_xdg_surf_v6);
- return;
- }
-
- wl_resource_set_implementation(cdata->sh_v6.res_role,
- &_e_xdg_toplv_v6_interface,
- ec,
- _e_xdg_toplv_v6_cb_res_destroy); // TODO
-
- e_object_ref(E_OBJECT(ec));
-
- cdata->sh_v6.role = E_COMP_WL_SH_SURF_ROLE_TOPLV;
-
- cdata->shell.configure_send = _e_xdg_surf_v6_configure_send;
- cdata->shell.configure = _e_xdg_shell_surface_configure;
- cdata->shell.ping = _e_xdg_sh_v6_ping;
- cdata->shell.map = _e_xdg_shell_surface_map;
- cdata->shell.unmap = _e_xdg_shell_surface_unmap;
-
- /* set toplevel client properties */
- ec->icccm.accepts_focus = 1;
- if (!ec->internal)
- ec->borderless = 1;
- ec->lock_border = EINA_TRUE;
- if ((!ec->internal) || (!ec->borderless))
- ec->border.changed = ec->changes.border = !ec->borderless;
- if (ec->netwm.type == E_WINDOW_TYPE_UNKNOWN)
- ec->netwm.type = E_WINDOW_TYPE_NORMAL;
- ec->comp_data->set_win_type = EINA_TRUE;
-
- e_comp_wl_shell_surface_ready(ec);
-}
-
-static void
-_e_xdg_surf_v6_cb_popup_get(struct wl_client *client,
- struct wl_resource *res_xdg_surf_v6,
- uint32_t id,
- struct wl_resource *res_xdg_surf_v6_parent,
- struct wl_resource *res_xdg_pos_v6)
-{
- E_Client *ec;
- E_Comp_Client_Data *cdata;
-
- ec = wl_resource_get_user_data(res_xdg_surf_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Pixmap Set On Surface");
- return;
- }
-
- cdata = ec->comp_data;
- if (!cdata)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Data For Client");
- return;
- }
-
- if (cdata->sh_v6.res_role)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Client already has shell popup resource");
- return;
- }
-
- if (!res_xdg_surf_v6_parent)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Popup requires a parent shell surface");
- return;
- }
-
- cdata->sh_v6.res_role = wl_resource_create(client,
- &zxdg_popup_v6_interface,
- 1,
- id);
- if (!cdata->sh_v6.res_role)
- {
- ERR("Could not create xdg popup resource");
- wl_resource_post_no_memory(res_xdg_surf_v6);
- return;
- }
-
- wl_resource_set_implementation(cdata->sh_v6.res_role,
- &_e_xdg_popup_v6_interface,
- ec,
- _e_xdg_popup_v6_cb_res_destroy); // TODO
-
- e_object_ref(E_OBJECT(ec));
-
- cdata->sh_v6.role = E_COMP_WL_SH_SURF_ROLE_POPUP;
-
- cdata->shell.configure_send = _e_xdg_surf_v6_configure_send;
- cdata->shell.configure = _e_xdg_shell_surface_configure;
- cdata->shell.ping = _e_xdg_sh_v6_ping;
- cdata->shell.map = _e_xdg_shell_surface_map;
- cdata->shell.unmap = _e_xdg_shell_surface_unmap;
-
- EC_CHANGED(ec);
- ec->new_client = ec->override = 1;
- e_client_unignore(ec);
- e_comp->new_clients++;
- if (!ec->internal)
- ec->borderless = !ec->internal_elm_win;
- ec->lock_border = EINA_TRUE;
- if (!ec->internal)
- ec->border.changed = ec->changes.border = !ec->borderless;
- ec->changes.icon = !!ec->icccm.class;
- ec->netwm.type = E_WINDOW_TYPE_POPUP_MENU;
- ec->comp_data->set_win_type = EINA_TRUE;
- evas_object_layer_set(ec->frame, E_LAYER_CLIENT_POPUP);
-
- /* set this client as a transient for parent */
- _e_shell_surface_parent_set(ec, res_xdg_surf_v6_parent);
-}
-
-static void
-_e_xdg_surf_v6_cb_win_geom_set(struct wl_client *client,
- struct wl_resource *res_xdg_surf_v6,
- int32_t x,
- int32_t y,
- int32_t w,
- int32_t h)
-{
- E_Client *ec;
-
- ec = wl_resource_get_user_data(res_xdg_surf_v6);
- if (!ec)
- {
- wl_resource_post_error(res_xdg_surf_v6,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Client For Shell Surface");
- return;
- }
- EINA_RECTANGLE_SET(&ec->comp_data->shell.window, x, y, w, h);
-}
-
-static void
-_e_xdg_surf_v6_cb_configure_ack(struct wl_client *client,
- struct wl_resource *res_xdg_surf_v6,
- uint32_t serial)
-{
- /* TODO no op */
-}
-
-static const struct zxdg_surface_v6_interface _e_xdg_surf_v6_interface =
-{
- _e_xdg_surf_v6_cb_destroy,
- _e_xdg_surf_v6_cb_toplevel_get,
- _e_xdg_surf_v6_cb_popup_get,
- _e_xdg_surf_v6_cb_win_geom_set,
- _e_xdg_surf_v6_cb_configure_ack
-};
-
-////////////////////////////////////////////////////////////////////////////////
-static void
-_e_xdg_sh_v6_cb_destroy(struct wl_client *client,
- struct wl_resource *res_xdg_sh_v6)
-{
- wl_resource_destroy(res_xdg_sh_v6);
-}
-
-static void
-_e_xdg_sh_v6_cb_pos_create(struct wl_client *client,
- struct wl_resource *res_xdg_sh_v6,
- uint32_t id)
-{
- E_Xdg_Shell *esh = NULL;
- E_Xdg_Pos *epos = NULL;
- struct wl_resource *res_xdg_pos_v6 = NULL;
-
- esh = eina_hash_find(xdg_sh_hash, &client);
- EINA_SAFETY_ON_NULL_GOTO(esh, err);
- EINA_SAFETY_ON_NULL_GOTO(esh->res, err);
- EINA_SAFETY_ON_FALSE_GOTO(esh->res == res_xdg_sh_v6, err);
-
- epos = E_NEW(E_Xdg_Pos, 1);
- EINA_SAFETY_ON_NULL_GOTO(epos, err);
-
- res_xdg_pos_v6 = wl_resource_create(client,
- &zxdg_positioner_v6_interface,
- 1,
- id);
- EINA_SAFETY_ON_NULL_GOTO(res_xdg_pos_v6, err);
-
- wl_resource_set_implementation(res_xdg_pos_v6,
- &_e_xdg_pos_v6_interface,
- epos,
- _e_xdg_pos_v6_cb_res_destroy);
-
- epos->sh = esh;
- epos->res = res_xdg_pos_v6;
-
- esh->positioners = eina_list_append(esh->positioners, epos);
-
- return;
-
-err:
- if (epos) E_FREE(epos);
- wl_resource_post_no_memory(res_xdg_sh_v6);
-}
-
-static void
-_e_xdg_sh_v6_cb_surf_get(struct wl_client *client,
- struct wl_resource *res_xdg_sh_v6 EINA_UNUSED,
- uint32_t id,
- struct wl_resource *res_surf)
-{
- E_Client *ec = NULL;
- E_Comp_Client_Data *cdata = NULL;
-
- ec = wl_resource_get_user_data(res_surf);
- if (!ec)
- {
- wl_resource_post_error(res_surf,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Pixmap Set On Surface");
- return;
- }
-
- cdata = ec->comp_data;
- if (!cdata)
- {
- wl_resource_post_error(res_surf,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Data For Client");
- return;
- }
-
- if (cdata->shell.surface)
- {
- wl_resource_post_error(res_surf,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "Client already has XDG shell surface");
- return;
- }
-
- cdata->shell.surface = wl_resource_create(client,
- &zxdg_surface_v6_interface,
- 1,
- id);
- if (!cdata->shell.surface)
- {
- ERR("Could not create xdg shell surface");
- wl_resource_post_no_memory(res_surf);
- return;
- }
-
- wl_resource_set_implementation(cdata->shell.surface,
- &_e_xdg_surf_v6_interface,
- ec,
- _e_shell_surface_cb_destroy);
-
- e_object_ref(E_OBJECT(ec));
-
- ec->netwm.ping = 1;
-}
-
-static const struct zxdg_shell_v6_interface _e_xdg_sh_v6_interface =
-{
- _e_xdg_sh_v6_cb_destroy,
- _e_xdg_sh_v6_cb_pos_create,
- _e_xdg_sh_v6_cb_surf_get,
- _e_xdg_shell_cb_pong /* use v5 pong handler */
-};
-
-////////////////////////////////////////////////////////////////////////////////
-static void
-_e_xdg_sh_v6_cb_bind(struct wl_client *client,
- void *data,
- uint32_t version,
- uint32_t id)
-{
- E_Xdg_Shell *esh;
- struct wl_resource *res_xdg_sh_v6;
-
- res_xdg_sh_v6 = wl_resource_create(client,
- &zxdg_shell_v6_interface,
- version,
- id);
- EINA_SAFETY_ON_NULL_GOTO(res_xdg_sh_v6, err);
-
- esh = E_NEW(E_Xdg_Shell, 1);
- EINA_SAFETY_ON_NULL_GOTO(esh, err);
-
- esh->wc = client;
- esh->res = res_xdg_sh_v6;
- eina_hash_add(xdg_sh_hash, &client, esh);
-
- wl_resource_set_implementation(res_xdg_sh_v6,
- &_e_xdg_sh_v6_interface,
- e_comp->wl_comp_data,
- _e_xdg_shell_cb_unbind);
- return;
-
-err:
- wl_client_post_no_memory(client);
-}
-
-static void
-_e_tz_surf_cb_tz_res_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface)
-{
- struct wl_resource *res;
- E_Client *ec;
- uint32_t res_id;
-
- /* get the pixmap from this surface so we can find the client */
- if (!(ec = wl_resource_get_user_data(surface)))
- {
- wl_resource_post_error(surface,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "No Pixmap Set On Surface");
- return;
- }
-
- /* find the window id for this pixmap */
- res_id = e_pixmap_res_id_get(ec->pixmap);
-
- /* try to create a tizen_gid */
- if (!(res = wl_resource_create(client,
- &tizen_resource_interface,
- wl_resource_get_version(resource),
- id)))
- {
- wl_resource_post_no_memory(resource);
- return;
- }
-
- wl_resource_set_implementation(res,
- &_e_tz_res_interface,
- ec,
- NULL);
-
- tizen_resource_send_resource_id(res, res_id);
-}
-
-static void
-_e_tz_surf_cb_destroy(struct wl_client *client, struct wl_resource *resource)
-{
- wl_resource_destroy(resource);
-}
-
-static const struct tizen_surface_interface _e_tz_surf_interface =
-{
- _e_tz_surf_cb_tz_res_get,
- _e_tz_surf_cb_destroy
-};
-
-static void
-_e_tz_surf_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
-{
- struct wl_resource *res;
-
- if (!(res = wl_resource_create(client,
- &tizen_surface_interface,
- version,
- id)))
- {
- ERR("Could not create tizen_surface resource: %m");
- wl_client_post_no_memory(client);
+ ERR("Could not create tizen_surface resource: %m");
+ wl_client_post_no_memory(client);
return;
}
return;
}
- if (!wl_global_create(e_comp_wl->wl.disp,
- &zxdg_shell_v6_interface,
- 1,
- e_comp->wl_comp_data,
- _e_xdg_sh_v6_cb_bind))
+ if (!e_xdg_shell_v6_init())
{
- ERR("Could not create xdg_shell global: %m");
+ ERR("Could not init xdg_shell_v6");
return;
}
--- /dev/null
+#include "e.h"
+#include <xdg-shell-unstable-v6-server-protocol.h>
+
+#ifdef LOG
+#undef LOG
+#endif
+#ifdef ERR
+#undef ERR
+#endif
+
+#define LOG(f, p, e, x...) ELOGF("XDG6 <LOG>", f, p, e, ##x)
+#define ERR(f, p, e, x...) ELOGF("XDG6 <ERR>", f, p, e, ##x)
+
+#define e_xdg_surface_role_biggest_struct E_Xdg_Toplevel
+
+typedef enum _E_Xdg_Surface_Role E_Xdg_Surface_Role;
+typedef struct _E_Xdg_Size E_Xdg_Size;
+typedef struct _E_Xdg_Shell E_Xdg_Shell;
+typedef struct _E_Xdg_Surface E_Xdg_Surface;
+typedef struct _E_Xdg_Toplevel E_Xdg_Toplevel;
+typedef struct _E_Xdg_Popup E_Xdg_Popup;
+typedef struct _E_Xdg_Positioner E_Xdg_Positioner;
+typedef struct _E_Xdg_Toplevel_State E_Xdg_Toplevel_State;
+typedef struct _E_Xdg_Surface_Configure E_Xdg_Surface_Configure;
+
+enum _E_Xdg_Surface_Role
+{
+ E_XDG_SURFACE_ROLE_NONE,
+ E_XDG_SURFACE_ROLE_TOPLEVEL,
+ E_XDG_SURFACE_ROLE_POPUP,
+};
+
+struct _E_Xdg_Size
+{
+ int w, h;
+};
+
+struct _E_Xdg_Shell
+{
+ struct wl_client *wclient;
+ struct wl_resource *resource; /* xdg_shell resource */
+ Eina_List *surfaces; /* list of all E_Xdg_Surface belonging to shell */
+ Eina_List *positioners; /* list of E_Xdg_Positioner */
+ uint32_t ping_serial;
+};
+
+struct _E_Xdg_Toplevel_State
+{
+ Eina_Bool maximized;
+ Eina_Bool fullscreen;
+ Eina_Bool resizing;
+ Eina_Bool activated;
+};
+
+struct _E_Xdg_Surface
+{
+ struct wl_resource *resource; /* wl_resource for Zxdg_Surface_V6 */
+ E_Client *ec; /* E_Client corresponding Xdg_Surface */
+ E_Xdg_Shell *shell; /* Xdg_Shell created Xdg_Surface */
+ Eina_List *configure_list; /* list of data being appended whenever configure send and remove by ack_configure */
+
+ Ecore_Idle_Enterer *configure_idle; /* Idle_Enterer for sending configure */
+ Ecore_Event_Handler *commit_handler; /* Handler raised when wl_buffer is committed. */
+
+ E_Xdg_Surface_Role role;
+ Eina_Rectangle configured_geometry; /* configured geometry by compositor */
+ Eina_Rectangle window_geometry; /* window geometry set by client */
+
+ Eina_Bool configured :1;
+ Eina_Bool has_window_geometry: 1;
+ Eina_Bool wait_next_commit;
+};
+
+struct _E_Xdg_Toplevel
+{
+ E_Xdg_Surface base;
+ struct wl_resource *resource;
+
+ struct
+ {
+ E_Xdg_Toplevel_State state;
+ E_Xdg_Size size;
+ uint32_t edges;
+ } pending;
+ struct
+ {
+ E_Xdg_Toplevel_State state;
+ E_Xdg_Size size;
+ E_Xdg_Size min_size, max_size;
+ } next;
+ struct
+ {
+ E_Xdg_Toplevel_State state;
+ E_Xdg_Size min_size, max_size;
+ } current;
+};
+
+struct _E_Xdg_Popup
+{
+ E_Xdg_Surface base;
+
+ struct wl_resource *resource;
+ E_Xdg_Surface *parent;
+
+ Eina_Rectangle geometry;
+ Eina_Bool committed;
+};
+
+struct _E_Xdg_Surface_Configure
+{
+ uint32_t serial;
+ E_Xdg_Toplevel_State state;
+ E_Xdg_Size size;
+};
+
+struct _E_Xdg_Positioner
+{
+ E_Xdg_Shell *shell;
+ struct wl_resource *resource; /* xdg_positioner_v6 resources */
+ E_Xdg_Size size;
+ Eina_Rectangle anchor_rect;
+ enum zxdg_positioner_v6_anchor anchor;
+ enum zxdg_positioner_v6_gravity gravity;
+ enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment;
+ struct
+ {
+ int x, y;
+ } offset;
+};
+
+static struct wl_global *global_resource = NULL;
+
+static void _e_xdg_shell_surface_add(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf);
+static void _e_xdg_shell_surface_remove(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf);
+static void _e_xdg_shell_ping(E_Xdg_Shell *shell);
+static Eina_Bool _e_xdg_surface_cb_configure_send(void *data);
+static Eina_Rectangle _e_xdg_positioner_geometry_get(E_Xdg_Positioner *p);
+
+/**********************************************************
+ * Implementation for Utility
+ **********************************************************/
+static Eina_Bool
+_e_client_shsurface_assignable_check(E_Client *ec)
+{
+ if (!e_shell_e_client_shell_assignable_check(ec))
+ {
+ ERR("Could not assign shell", ec->pixmap, ec);
+ wl_resource_post_error(ec->comp_data->surface,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Could not assign shell surface to wl_surface");
+ return EINA_FALSE;
+ }
+
+ if (e_pixmap_usable_get(ec->pixmap))
+ {
+ wl_resource_post_error(ec->comp_data->surface,
+ ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
+ "buffer attached/committed before configure");
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_client_xdg_shell_v6_assigned_check(E_Client *ec)
+{
+ return !!ec->comp_data->sh_v6.res_role;
+}
+
+static void
+_e_client_xdg_shell_v6_assign(E_Client *ec,
+ struct wl_resource *resource,
+ E_Comp_Wl_Sh_Surf_Role role)
+{
+ ec->comp_data->sh_v6.res_role = resource;
+ ec->comp_data->sh_v6.role = role;
+}
+
+static void
+_validate_size(struct wl_resource *resource, int32_t value)
+{
+ if (value <= 0)
+ wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, "Invalid size passed");
+}
+/* End of utility */
+
+/**********************************************************
+ * Implementation for Xdg_popup
+ **********************************************************/
+static void
+_e_xdg_popup_positioner_apply(E_Xdg_Popup *popup, E_Xdg_Positioner *pos)
+{
+ popup->geometry = _e_xdg_positioner_geometry_get(pos);
+
+ /* TODO apply geometry to popup */
+
+}
+
+static void
+_e_xdg_popup_parent_set(E_Xdg_Popup *popup, E_Xdg_Surface *parent)
+{
+ popup->parent = parent;
+ /* set this client as a transient for parent */
+ e_shell_e_client_parent_set(popup->base.ec, parent->ec->comp_data->surface);
+}
+
+static void
+_e_xdg_popup_set(E_Xdg_Popup *popup, struct wl_resource *resource)
+{
+ popup->resource = resource;
+ _e_client_xdg_shell_v6_assign(popup->base.ec, resource, E_COMP_WL_SH_SURF_ROLE_POPUP);
+ e_shell_e_client_popup_set(popup->base.ec);
+}
+
+static void
+_e_xdg_popup_committed(E_Xdg_Popup *popup)
+{
+ if (!popup->committed)
+ {
+ if (!popup->base.configure_idle)
+ {
+ popup->base.configure_idle =
+ ecore_idle_enterer_add(_e_xdg_surface_cb_configure_send, popup);
+ }
+ }
+
+ popup->committed = EINA_TRUE;
+
+ /* TODO: Weston does update the position of popup here */
+}
+
+static void
+_e_xdg_popup_configure_send(E_Xdg_Popup *popup)
+{
+ zxdg_popup_v6_send_configure(popup->resource,
+ popup->geometry.x,
+ popup->geometry.y,
+ popup->geometry.w,
+ popup->geometry.h);
+}
+
+static void
+_e_xdg_popup_cb_resource_destroy(struct wl_resource *resource)
+{
+ /* Nothing to do here */
+}
+
+static void
+_e_xdg_popup_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_popup_cb_grab(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *res_seat,
+ uint32_t serial)
+{
+ /* TODO no op */
+}
+
+static const struct zxdg_popup_v6_interface _e_xdg_popup_interface =
+{
+ _e_xdg_popup_cb_destroy,
+ _e_xdg_popup_cb_grab
+};
+
+/* End of Xdg_Popup */
+
+/**********************************************************
+ * Implementation for Xdg_toplevel
+ ***********************************************************/
+static void
+_e_xdg_toplevel_set(E_Xdg_Toplevel *toplevel, struct wl_resource *resource)
+{
+ toplevel->resource = resource;
+ _e_client_xdg_shell_v6_assign(toplevel->base.ec, resource, E_COMP_WL_SH_SURF_ROLE_TOPLV);
+ e_shell_e_client_toplevel_set(toplevel->base.ec);
+ e_comp_wl_shell_surface_ready(toplevel->base.ec);
+}
+
+static void
+_e_xdg_toplevel_committed(E_Xdg_Toplevel *toplevel)
+{
+ E_Client *ec;
+ int pw, ph;
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("E_Xdg_Toplevel must have E_Client", NULL, NULL);
+ return;
+ }
+
+ if (!ec->comp_data)
+ {
+ ERR("E_Client must have E_Comp_Client_Data", ec->pixmap, ec);
+ return;
+ }
+
+ if (!e_pixmap_usable_get(ec->pixmap))
+ {
+ ERR("E_Pixmap should be valid here", ec->pixmap, ec);
+ return;
+ }
+
+ e_pixmap_size_get(ec->pixmap, &pw, &ph);
+
+ if ((toplevel->next.state.maximized || toplevel->next.state.fullscreen) &&
+ (toplevel->next.size.w != ec->comp_data->shell.window.w ||
+ toplevel->next.size.h != ec->comp_data->shell.window.h))
+ {
+ ERR("Xdg_surface buffer does not match the configured state\nmaximized: "
+ "%d fullscreen: %d expected size (%d %d) window size (%d %d)",
+ ec->pixmap, ec,
+ toplevel->next.state.maximized,
+ toplevel->next.state.fullscreen,
+ toplevel->next.size.w, toplevel->next.size.h,
+ ec->comp_data->shell.window.w, ec->comp_data->shell.window.h);
+ /* TODO Disable this part for now, but need to consider enabling it later.
+ * To enable this part, we first need to ensure that do not send configure
+ * with argument of size as 0, and make client ensure that set
+ * window geometry correctly so that match its commit buffer size, if
+ * its state is maximize or fullscreen.
+ */
+ /*
+ wl_resource_post_error(toplevel->base.shell->resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+ "xdg_surface buffer does not match the configured state");
+ return;
+ */
+ }
+ toplevel->current.state = toplevel->next.state;
+ toplevel->current.min_size = toplevel->next.min_size;
+ toplevel->current.max_size = toplevel->next.max_size;
+
+ /* Now we can adjust size of its composite object corresponding client */
+}
+
+static void
+_e_xdg_toplevel_configure_ack(E_Xdg_Toplevel *toplevel,
+ E_Xdg_Surface_Configure *configure)
+{
+ LOG("Ack configure TOPLEVEL size (%d %d) "
+ "state (f %d m %d r %d a %d)",
+ toplevel->base.ec->pixmap, toplevel->base.ec,
+ configure->size.w, configure->size.h,
+ configure->state.fullscreen, configure->state.maximized,
+ configure->state.resizing, configure->state.activated);
+
+ toplevel->next.state = configure->state;
+ toplevel->next.size = configure->size;
+ toplevel->base.wait_next_commit = EINA_TRUE;
+}
+
+static void
+_e_xdg_toplevel_configure_send(E_Xdg_Toplevel *toplevel,
+ E_Xdg_Surface_Configure *configure)
+{
+ uint32_t *s;
+ struct wl_array states;
+
+ configure->state = toplevel->pending.state;
+ configure->size = toplevel->pending.size;
+
+ wl_array_init(&states);
+ if (toplevel->pending.state.maximized)
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
+ }
+ if (toplevel->pending.state.fullscreen)
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
+ }
+ if (toplevel->pending.state.resizing)
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
+ }
+ if (toplevel->pending.state.activated)
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
+ }
+
+ LOG("Send configure: Topevel size (%d %d) "
+ "state (f %d m %d r %d a %d)",
+ toplevel->base.ec->pixmap, toplevel->base.ec,
+ toplevel->pending.size.w, toplevel->pending.size.h,
+ toplevel->pending.state.fullscreen, toplevel->pending.state.maximized,
+ toplevel->pending.state.resizing, toplevel->pending.state.activated);
+
+ zxdg_toplevel_v6_send_configure(toplevel->resource,
+ toplevel->pending.size.w,
+ toplevel->pending.size.h,
+ &states);
+
+ wl_array_release(&states);
+}
+
+static void
+_e_xdg_toplevel_configure_pending_set(E_Xdg_Toplevel *toplevel,
+ uint32_t edges,
+ int32_t width,
+ int32_t height)
+{
+ E_Client *ec, *focused;
+
+ ec = toplevel->base.ec;
+
+ toplevel->pending.state.fullscreen = ec->fullscreen;
+ toplevel->pending.state.maximized = !!ec->maximized;
+ toplevel->pending.state.resizing = !!edges;
+ toplevel->pending.edges = edges;
+ toplevel->pending.size.w = width;
+ toplevel->pending.size.h = height;
+
+ if ((toplevel->pending.state.maximized) ||
+ (toplevel->pending.state.fullscreen))
+ {
+ /* NOTE
+ * DO NOT configure maximized or fullscreen surface to (0x0) size.
+ * If the width or height arguments are zero, it means the client should
+ * decide its own window dimension. See xdg-shell-v6.xml
+ */
+ LOG("FORCELY STAY current size (%d %d) of E_Client, requested size "
+ "is (%d %d), the state (maximize %d, fullscreen %d)",
+ ec->pixmap, ec, ec->w, ec->h, width, height,
+ toplevel->pending.state.maximized,
+ toplevel->pending.state.fullscreen);
+ toplevel->pending.size.w = ec->w;
+ toplevel->pending.size.h = ec->h;
+ }
+
+ focused = e_client_focused_get();
+ toplevel->pending.state.activated = (ec == focused);
+
+ LOG("Set pending state: edges %d size (%d %d) "
+ "state (f %d m %d r %d a %d)",
+ ec->pixmap, ec,
+ toplevel->pending.edges,
+ toplevel->pending.size.w, toplevel->pending.size.h,
+ toplevel->pending.state.fullscreen, toplevel->pending.state.maximized,
+ toplevel->pending.state.resizing, toplevel->pending.state.activated);
+}
+
+static Eina_Bool
+_e_xdg_toplevel_pending_state_compare(E_Xdg_Toplevel *toplevel)
+{
+ E_Xdg_Surface_Configure *configure;
+ int pw, ph;
+ int cw, ch;
+
+ struct {
+ E_Xdg_Toplevel_State state;
+ E_Xdg_Size size;
+ } configured;
+
+ /* must send configure at least once */
+ if (!toplevel->base.configured)
+ return EINA_FALSE;
+
+ if (!toplevel->base.configure_list)
+ {
+ /* if configure_list is empty, last configure is actually the current
+ * state */
+ e_pixmap_size_get(toplevel->base.ec->pixmap, &pw, &ph);
+ e_client_geometry_get(toplevel->base.ec, NULL, NULL, &cw, &ch);
+
+ if ((pw != cw) || (ph != ch))
+ {
+ ERR("The size of buffer is different with expected "
+ "client size. So, here, let it compare with buffer size.",
+ toplevel->base.ec->pixmap, toplevel->base.ec);
+ }
+
+ configured.state = toplevel->current.state;
+ configured.size.w = pw;
+ configured.size.h = ph;
+ }
+ else
+ {
+ configure = eina_list_last_data_get(toplevel->base.configure_list);
+ configured.state = configure->state;
+ configured.size = configure->size;
+ }
+
+ if (toplevel->pending.state.activated != configured.state.activated)
+ return EINA_FALSE;
+ if (toplevel->pending.state.fullscreen != configured.state.fullscreen)
+ return EINA_FALSE;
+ if (toplevel->pending.state.maximized != configured.state.maximized)
+ return EINA_FALSE;
+ if (toplevel->pending.state.resizing != configured.state.resizing)
+ return EINA_FALSE;
+
+ if ((toplevel->pending.size.w == configured.size.w) &&
+ (toplevel->pending.size.h == configured.size.h))
+ return EINA_TRUE;
+
+ if ((toplevel->pending.size.w == 0) &&
+ (toplevel->pending.size.h == 0))
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+static void
+_e_xdg_toplevel_cb_resource_destroy(struct wl_resource *resource)
+{
+ /* Nothing to do here */
+}
+
+static void
+_e_xdg_toplevel_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_toplevel_cb_parent_set(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *res_parent)
+{
+ E_Xdg_Toplevel *toplevel, *parent;
+ E_Client *pc;
+ struct wl_resource *parent_wsurface = NULL;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ if (res_parent)
+ {
+ parent = wl_resource_get_user_data(res_parent);
+ if (!parent)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(res_parent,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+
+ return;
+ }
+
+ pc = parent->base.ec;
+ if (!pc)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(res_parent,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ if (!pc->comp_data) return;
+
+ parent_wsurface = pc->comp_data->surface;
+ }
+
+ /* set this client as a transient for parent */
+ e_shell_e_client_parent_set(toplevel->base.ec, parent_wsurface);
+}
+
+static void
+_e_xdg_toplevel_cb_title_set(struct wl_client *client,
+ struct wl_resource *resource,
+ const char *title)
+{
+ E_Xdg_Toplevel *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ e_shell_e_client_name_title_set(toplevel->base.ec, title, title);
+}
+
+static void
+_e_xdg_toplevel_cb_app_id_set(struct wl_client *client,
+ struct wl_resource *resource,
+ const char *app_id)
+{
+ E_Xdg_Toplevel *toplevel;
+ E_Client *ec;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ /* use the wl_client to get the pid * and set it in the netwm props */
+ wl_client_get_credentials(client, &ec->netwm.pid, NULL, NULL);
+
+ e_shell_e_client_app_id_set(ec, app_id);
+}
+
+static void
+_e_xdg_toplevel_cb_win_menu_show(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *res_seat,
+ uint32_t serial,
+ int32_t x,
+ int32_t y)
+{
+ /* TODO no op */
+}
+
+static void
+_e_xdg_toplevel_cb_move(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *res_seat,
+ uint32_t serial)
+{
+ E_Xdg_Toplevel *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ if (!e_shell_e_client_interactive_move(toplevel->base.ec, res_seat))
+ {
+ ERR("Failed to move this Toplevel", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Can't move this surface");
+ return;
+ }
+}
+
+static void
+_e_xdg_toplevel_cb_resize(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *res_seat,
+ uint32_t serial,
+ uint32_t edges)
+{
+ E_Xdg_Toplevel *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ if (!e_shell_e_client_interactive_resize(toplevel->base.ec, resource, res_seat, edges))
+ {
+ ERR("Failed to resize this Toplevel", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Can't resize this surface");
+ return;
+ }
+}
+
+static void
+_e_xdg_toplevel_cb_max_size_set(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t w,
+ int32_t h)
+{
+ E_Xdg_Toplevel *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No data in wl_resource");
+ return;
+ }
+
+ toplevel->next.max_size.w = w;
+ toplevel->next.max_size.h = h;
+}
+
+static void
+_e_xdg_toplevel_cb_min_size_set(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t w,
+ int32_t h)
+{
+ E_Xdg_Toplevel *toplevel;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No data in wl_resource");
+ return;
+ }
+
+ toplevel->next.min_size.w = w;
+ toplevel->next.min_size.h = h;
+}
+
+static void
+_e_xdg_toplevel_cb_maximized_set(struct wl_client *client, struct wl_resource *resource)
+{
+ E_Xdg_Toplevel *toplevel;
+ E_Client *ec;
+ E_Maximize max;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ if (!ec->lock_user_maximize)
+ {
+ max = (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_BOTH;
+ e_client_maximize(ec, max);
+ }
+}
+
+static void
+_e_xdg_toplevel_cb_maximized_unset(struct wl_client *client, struct wl_resource *resource)
+{
+ E_Xdg_Toplevel *toplevel;
+ E_Client *ec;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ /* it's doubtful */
+ e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
+}
+
+static void
+_e_xdg_toplevel_cb_fullscreen_set(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *res_output)
+{
+ E_Xdg_Toplevel *toplevel;
+ E_Client *ec;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ if (!ec->lock_user_fullscreen)
+ e_client_fullscreen(ec, e_config->fullscreen_policy);
+}
+
+static void
+_e_xdg_toplevel_cb_fullscreen_unset(struct wl_client *client, struct wl_resource *resource)
+{
+ E_Xdg_Toplevel *toplevel;
+ E_Client *ec;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ if (!ec->lock_user_fullscreen)
+ e_client_unfullscreen(ec);
+}
+
+static void
+_e_xdg_toplevel_cb_minimized_set(struct wl_client *client, struct wl_resource *resource)
+{
+ E_Xdg_Toplevel *toplevel;
+ E_Client *ec;
+
+ toplevel = wl_resource_get_user_data(resource);
+ if (!toplevel)
+ {
+ ERR("No E_Xdg_Toplevel data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Toplevel data in wl_resource");
+ return;
+ }
+
+ ec = toplevel->base.ec;
+ if (!ec)
+ {
+ ERR("Toplevel must have E_Client", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Client data in wl_resource");
+ return;
+ }
+
+ if (!ec->lock_client_iconify)
+ e_client_iconify(ec);
+}
+
+static const struct zxdg_toplevel_v6_interface _e_xdg_toplevel_interface =
+{
+ _e_xdg_toplevel_cb_destroy,
+ _e_xdg_toplevel_cb_parent_set,
+ _e_xdg_toplevel_cb_title_set,
+ _e_xdg_toplevel_cb_app_id_set,
+ _e_xdg_toplevel_cb_win_menu_show,
+ _e_xdg_toplevel_cb_move,
+ _e_xdg_toplevel_cb_resize,
+ _e_xdg_toplevel_cb_max_size_set,
+ _e_xdg_toplevel_cb_min_size_set,
+ _e_xdg_toplevel_cb_maximized_set,
+ _e_xdg_toplevel_cb_maximized_unset,
+ _e_xdg_toplevel_cb_fullscreen_set,
+ _e_xdg_toplevel_cb_fullscreen_unset,
+ _e_xdg_toplevel_cb_minimized_set
+};
+
+/* End of Xdg_toplevel */
+
+/**********************************************************
+ * Implementation for Xdg_Positioner
+ **********************************************************/
+static Eina_Rectangle
+_e_xdg_positioner_geometry_get(E_Xdg_Positioner *p)
+{
+ Eina_Rectangle geometry = {
+ .x = p->offset.x,
+ .y = p->offset.y,
+ .w = p->size.w,
+ .h = p->size.h,
+ };
+
+ if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP)
+ geometry.y += p->anchor_rect.y;
+ else if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)
+ geometry.y += p->anchor_rect.y + p->anchor_rect.h;
+ else
+ geometry.y += p->anchor_rect.y + p->anchor_rect.h / 2;
+
+ if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT)
+ geometry.x += p->anchor_rect.x;
+ else if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT)
+ geometry.x += p->anchor_rect.x + p->anchor_rect.w;
+ else
+ geometry.x += p->anchor_rect.x + p->anchor_rect.w / 2;
+
+ if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP)
+ geometry.y -= geometry.h;
+ else if (!(p->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM))
+ geometry.y = geometry.h / 2;
+
+ if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT)
+ geometry.x -= geometry.w;
+ else if (!(p->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))
+ geometry.x = geometry.w / 2;
+
+ if (p->constraint_adjustment == ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE)
+ return geometry;
+
+ /* TODO: According to weston, add compositor policy configuration and the
+ * code here
+ */
+
+ return geometry;
+}
+
+static Eina_Bool
+_e_xdg_positioner_validation_check(E_Xdg_Positioner *p)
+{
+ return ((p->size.w != 0) && (p->anchor_rect.w != 0));
+}
+
+static void
+_e_xdg_positioner_cb_resource_destroy(struct wl_resource *resource)
+{
+ E_Xdg_Positioner *p;
+
+ p = wl_resource_get_user_data(resource);
+ EINA_SAFETY_ON_NULL_RETURN(p);
+
+ if (!p->shell)
+ goto finish;
+
+ p->shell->positioners = eina_list_remove(p->shell->positioners, p);
+
+finish:
+ free(p);
+}
+
+static void
+_e_xdg_positioner_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_positioner_cb_size_set(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t w, int32_t h)
+{
+ E_Xdg_Positioner *p;
+
+ _validate_size(resource, w);
+ _validate_size(resource, h);
+
+ p = wl_resource_get_user_data(resource);
+ p->size.w = w;
+ p->size.h = h;
+}
+
+static void
+_e_xdg_positioner_cb_anchor_rect_set(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t x, int32_t y, int32_t w, int32_t h)
+{
+ E_Xdg_Positioner *p;
+
+ _validate_size(resource, w);
+ _validate_size(resource, h);
+
+ p = wl_resource_get_user_data(resource);
+ EINA_RECTANGLE_SET(&p->anchor_rect, x, y, w, h);
+}
+
+static void
+_e_xdg_positioner_cb_anchor_set(struct wl_client *client,
+ struct wl_resource *resource,
+ enum zxdg_positioner_v6_anchor anchor)
+{
+ E_Xdg_Positioner *p;
+
+ if ((anchor & (ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) ==
+ (ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_BOTTOM))
+ {
+ wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "Invalid anchor values passed");
+ }
+ else if ((anchor & (ZXDG_POSITIONER_V6_ANCHOR_LEFT | ZXDG_POSITIONER_V6_ANCHOR_RIGHT)) ==
+ (ZXDG_POSITIONER_V6_ANCHOR_LEFT | ZXDG_POSITIONER_V6_ANCHOR_RIGHT))
+ {
+ wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "Invalid anchor values passed");
+ }
+ else
+ {
+ p = wl_resource_get_user_data(resource);
+ p->anchor = anchor;
+ }
+}
+
+static void
+_e_xdg_positioner_cb_gravity_set(struct wl_client *client,
+ struct wl_resource *resource,
+ enum zxdg_positioner_v6_gravity gravity)
+{
+ E_Xdg_Positioner *p;
+
+ if ((gravity & (ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) ==
+ (ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_BOTTOM))
+ {
+ wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "Invalid gravity values passed");
+ }
+ else if ((gravity & (ZXDG_POSITIONER_V6_GRAVITY_LEFT | ZXDG_POSITIONER_V6_GRAVITY_RIGHT)) ==
+ (ZXDG_POSITIONER_V6_GRAVITY_LEFT | ZXDG_POSITIONER_V6_GRAVITY_RIGHT))
+ {
+ wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+ "Invalid gravity values passed");
+ }
+ else
+ {
+ p = wl_resource_get_user_data(resource);
+ p->gravity = gravity;
+ }
+}
+
+static void
+_e_xdg_positioner_cb_constraint_adjustment_set(struct wl_client *client,
+ struct wl_resource *resource,
+ enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
+{
+ E_Xdg_Positioner *p;
+
+ p = wl_resource_get_user_data(resource);
+ p->constraint_adjustment = constraint_adjustment;
+}
+
+static void
+_e_xdg_positioner_cb_offset_set(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t x, int32_t y)
+{
+ E_Xdg_Positioner *p;
+
+ p = wl_resource_get_user_data(resource);
+ p->offset.x = x;
+ p->offset.y = y;
+}
+
+static const struct zxdg_positioner_v6_interface _e_xdg_positioner_interface =
+{
+ _e_xdg_positioner_cb_destroy,
+ _e_xdg_positioner_cb_size_set,
+ _e_xdg_positioner_cb_anchor_rect_set,
+ _e_xdg_positioner_cb_anchor_set,
+ _e_xdg_positioner_cb_gravity_set,
+ _e_xdg_positioner_cb_constraint_adjustment_set,
+ _e_xdg_positioner_cb_offset_set,
+};
+
+/* End of Xdg_positioner */
+
+/**********************************************************
+ * Implementation for Xdg_Surface
+ **********************************************************/
+static const char *
+_e_xdg_surface_util_role_string_get(E_Xdg_Surface *exsurf)
+{
+ switch (exsurf->role)
+ {
+ case E_XDG_SURFACE_ROLE_TOPLEVEL:
+ return "TOPLEVEL";
+ case E_XDG_SURFACE_ROLE_POPUP:
+ return "POPUP";
+ default:
+ case E_XDG_SURFACE_ROLE_NONE:
+ return "NONE";
+ }
+}
+
+static Eina_Bool
+_e_xdg_surface_cb_configure_send(void *data)
+{
+ E_Xdg_Surface *exsurf;
+ E_Xdg_Surface_Configure *configure;
+
+ exsurf = data;
+
+ EINA_SAFETY_ON_NULL_GOTO(exsurf, end);
+ EINA_SAFETY_ON_NULL_GOTO(exsurf->ec, end);
+ EINA_SAFETY_ON_NULL_GOTO(exsurf->ec->comp_data, end);
+
+ if (e_object_is_del(E_OBJECT(exsurf->ec)))
+ goto end;
+
+ /* Make configure */
+ configure = E_NEW(E_Xdg_Surface_Configure, 1);
+ if (!configure)
+ {
+ ERR("Failed to allocate memory: E_Xdg_Surface_Configure", NULL, NULL);
+ goto end;
+ }
+
+ exsurf->configure_list = eina_list_append(exsurf->configure_list, configure);
+ configure->serial = wl_display_next_serial(e_comp_wl->wl.disp);
+
+ switch (exsurf->role)
+ {
+ case E_XDG_SURFACE_ROLE_NONE:
+ ERR("Cannot reach here", NULL, NULL);
+ break;
+ case E_XDG_SURFACE_ROLE_POPUP:
+ _e_xdg_popup_configure_send((E_Xdg_Popup *)exsurf);
+ break;
+ case E_XDG_SURFACE_ROLE_TOPLEVEL:
+ _e_xdg_toplevel_configure_send((E_Xdg_Toplevel *)exsurf, configure);
+ break;
+ }
+
+ zxdg_surface_v6_send_configure(exsurf->resource, configure->serial);
+
+ LOG("Send configure: %s serial %d", exsurf->ec->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf), configure->serial);
+
+end:
+ exsurf->configure_idle = NULL;
+ return ECORE_CALLBACK_DONE;
+}
+
+static void
+_e_xdg_surface_configure_send(struct wl_resource *resource,
+ uint32_t edges,
+ int32_t width,
+ int32_t height)
+{
+ E_Xdg_Surface *exsurf;
+ Eina_Bool pending_same = EINA_FALSE;
+
+ EINA_SAFETY_ON_NULL_RETURN(resource);
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ ERR("Invalid wl_resource", NULL, NULL);
+ return;
+ }
+
+ LOG("Scheduling task to send configure %s edges %d w %d h %d",
+ exsurf->ex->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf), edges, width, height);
+
+ switch (exsurf->role)
+ {
+ case E_XDG_SURFACE_ROLE_NONE:
+ default:
+ ERR("Cannot reach here", exsurf->ec->pixmap, exsurf->ec);
+ break;
+ case E_XDG_SURFACE_ROLE_TOPLEVEL:
+ _e_xdg_toplevel_configure_pending_set((E_Xdg_Toplevel *)exsurf,
+ edges, width, height);
+
+ pending_same = _e_xdg_toplevel_pending_state_compare((E_Xdg_Toplevel *)exsurf);
+ if (pending_same)
+ {
+ LOG("\tSKIP Configuring state is same with current state",
+ exsurf->ec->pixmap, exsurf->ec);
+ }
+ break;
+ case E_XDG_SURFACE_ROLE_POPUP:
+ break;
+ }
+
+ if (exsurf->configure_idle)
+ {
+ if (!pending_same)
+ return;
+
+ LOG("\tRemove configure idler", exsurf->ec->pixmap, exsurf->ec);
+
+ E_FREE_FUNC(exsurf->configure_idle, ecore_idle_enterer_del);
+ }
+ else
+ {
+ if (pending_same)
+ return;
+
+ exsurf->configure_idle =
+ ecore_idle_enterer_add(_e_xdg_surface_cb_configure_send, exsurf);
+
+ LOG("\tAdd configure idler %p",
+ exsurf->ec->pixmap, exsurf->ec, exsurf->configure_idle);
+ }
+}
+
+static void
+_e_xdg_surface_configure(struct wl_resource *resource,
+ Evas_Coord x, Evas_Coord y,
+ Evas_Coord w, Evas_Coord h)
+{
+ E_Xdg_Surface *exsurf;
+
+ EINA_SAFETY_ON_NULL_RETURN(resource);
+
+ /* get the client for this resource */
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ ERR("No E_Xdg_Surface data in wl_resource", NULL, NULL);
+ return;
+ }
+
+ if ((exsurf->configured_geometry.x == x) &&
+ (exsurf->configured_geometry.y == y) &&
+ (exsurf->configured_geometry.w == w) &&
+ (exsurf->configured_geometry.h == h))
+ {
+ LOG("Configure (SKIP) Trying to resize it the same size "
+ "with previous %s (%d %d %d %d)",
+ exsurf->ec->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf),
+ x, y, w, h);
+
+ return;
+ }
+
+ EINA_RECTANGLE_SET(&exsurf->configured_geometry, x, y, w, h);
+
+ LOG("Configure %s geometry (%d %d %d %d)",
+ exsurf->ec->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf), x, y, w, h);
+
+ e_client_util_move_resize_without_frame(exsurf->ec, x, y, w, h);
+}
+
+static void
+_e_xdg_surface_ping(struct wl_resource *resource)
+{
+ E_Xdg_Surface *exsurf;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ ERR("No E_Xdg_Surface data in wl_resource", NULL, NULL);
+ return;
+ }
+
+ if (e_object_is_del(E_OBJECT(exsurf->ec)))
+ return;
+
+ _e_xdg_shell_ping(exsurf->shell);
+}
+
+static void
+_e_xdg_surface_map(struct wl_resource *resource)
+{
+ E_Xdg_Surface *exsurf;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ ERR("No E_Xdg_Surface in wl_resource", NULL, NULL);
+ return;
+ }
+
+ e_shell_e_client_map(exsurf->ec);
+}
+
+static void
+_e_xdg_surface_unmap(struct wl_resource *resource)
+{
+ E_Xdg_Surface *exsurf;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ ERR("No E_Xdg_Surface in wl_resource", NULL, NULL);
+ return;
+ }
+
+ e_shell_e_client_unmap(exsurf->ec);
+}
+
+static Eina_Bool
+_e_xdg_surface_role_assign(E_Xdg_Surface *exsurf,
+ struct wl_resource *resource,
+ E_Xdg_Surface_Role role)
+{
+ E_Shell_Surface_Api api = {
+ .configure_send = _e_xdg_surface_configure_send,
+ .configure = _e_xdg_surface_configure,
+ .ping = _e_xdg_surface_ping,
+ .map = _e_xdg_surface_map,
+ .unmap = _e_xdg_surface_unmap,
+ };
+
+ if (_e_client_xdg_shell_v6_assigned_check(exsurf->ec))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Client already has shell resource");
+ return EINA_FALSE;
+ }
+
+ exsurf->role = role;
+
+ e_shell_e_client_shsurface_api_set(exsurf->ec, &api);
+
+ switch (role)
+ {
+ case E_XDG_SURFACE_ROLE_NONE:
+ default:
+ ERR("Cannot reach here", exsurf->ec->pixmap, exsurf->ec);
+ return EINA_FALSE;
+
+ case E_XDG_SURFACE_ROLE_TOPLEVEL:
+ _e_xdg_toplevel_set((E_Xdg_Toplevel *)exsurf, resource);
+ break;
+
+ case E_XDG_SURFACE_ROLE_POPUP:
+ _e_xdg_popup_set((E_Xdg_Popup *)exsurf, resource);
+ break;
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_e_xdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_surface_cb_toplevel_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
+{
+ E_Xdg_Surface *exsurf;
+ struct wl_resource *toplevel_resource;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Surface data in wl_resource");
+ return;
+ }
+
+ toplevel_resource = wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id);
+ if (!toplevel_resource)
+ {
+ ERR("Could not create xdg toplevel resource", NULL, NULL);
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_resource_set_implementation(toplevel_resource,
+ &_e_xdg_toplevel_interface,
+ exsurf,
+ _e_xdg_toplevel_cb_resource_destroy);
+
+ if (!_e_xdg_surface_role_assign(exsurf, toplevel_resource, E_XDG_SURFACE_ROLE_TOPLEVEL))
+ {
+ ERR("Failed to assign TOPLEVEL role", exsurf->ec->pixmap, exsurf->ec);
+ wl_resource_destroy(toplevel_resource);
+ return;
+ }
+}
+
+static void
+_e_xdg_surface_cb_popup_get(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *res_parent,
+ struct wl_resource *res_pos)
+{
+ struct wl_resource *popup_resource;
+ E_Xdg_Surface *exsurf, *parent;
+ E_Xdg_Positioner *p;
+
+ if (!res_parent)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Popup requires a parent shell surface");
+ return;
+ }
+
+ parent = wl_resource_get_user_data(res_parent);
+ if (!parent)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "xdg_popup must have parent");
+ return;
+ }
+
+ p = wl_resource_get_user_data(res_pos);
+ if (!p)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "invalid positioner");
+ return;
+ }
+
+ if (!_e_xdg_positioner_validation_check(p))
+ {
+ wl_resource_post_error(resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
+ "invalid positioner");
+ return;
+ }
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Popup data in wl_resource");
+ return;
+ }
+
+ popup_resource = wl_resource_create(client, &zxdg_popup_v6_interface, 1, id);
+ if (!popup_resource)
+ {
+ ERR("Could not create xdg popup resource", NULL, NULL);
+ wl_resource_post_no_memory(resource);
+ }
+
+ wl_resource_set_implementation(popup_resource,
+ &_e_xdg_popup_interface,
+ exsurf,
+ _e_xdg_popup_cb_resource_destroy);
+
+
+ if (!_e_xdg_surface_role_assign(exsurf, popup_resource, E_XDG_SURFACE_ROLE_POPUP))
+ {
+ ERR("Failed to assign role to surface", exsurf->ec->pixmap, exsurf->ec);
+ wl_resource_destroy(popup_resource);
+ return;
+ }
+
+ _e_xdg_popup_parent_set((E_Xdg_Popup *)exsurf, parent);
+ _e_xdg_popup_positioner_apply((E_Xdg_Popup *)exsurf, p);
+}
+
+static void
+_e_xdg_surface_cb_win_geometry_set(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t x,
+ int32_t y,
+ int32_t w,
+ int32_t h)
+{
+ E_Xdg_Surface *exsurf;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Surface data in wl_resource");
+ return;
+ }
+
+ LOG("Set window geometry: geometry(%d %d %d %d)",
+ exsurf->ec->pixmap, exsurf->ec, x, y, w, h);
+
+ exsurf->has_window_geometry = EINA_TRUE;
+ EINA_RECTANGLE_SET(&exsurf->window_geometry, x, y, w, h);
+
+ exsurf->wait_next_commit = EINA_TRUE;
+}
+
+static void
+_e_xdg_surface_cb_configure_ack(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
+{
+ E_Xdg_Surface *exsurf;
+ E_Xdg_Surface_Configure *configure;
+ Eina_List *l, *ll;
+ Eina_Bool found = EINA_FALSE;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Surface data in wl_surface");
+ return;
+ }
+
+ LOG("Ack configure", exsurf->ec->pixmap, exsurf->ec);
+
+ if ((exsurf->role != E_XDG_SURFACE_ROLE_TOPLEVEL) &&
+ (exsurf->role != E_XDG_SURFACE_ROLE_POPUP))
+ {
+ wl_resource_post_error(resource,
+ ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+ "xdg_surface must have a role");
+ return;
+ }
+
+ EINA_LIST_FOREACH_SAFE(exsurf->configure_list, l, ll, configure)
+ {
+ if (configure->serial < serial)
+ {
+ exsurf->configure_list =
+ eina_list_remove_list(exsurf->configure_list, l);
+ free(configure);
+ }
+ else if (configure->serial == serial)
+ {
+ exsurf->configure_list =
+ eina_list_remove_list(exsurf->configure_list, l);
+ found = EINA_TRUE;
+ break;
+ }
+ else
+ break;
+ }
+
+ LOG("Ack configure %s first %d serial %d found %d",
+ exsurf->ec->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf),
+ !exsurf->configured,
+ serial, found);
+
+ if (!found)
+ {
+ wl_resource_post_error(exsurf->shell->resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+ "Wrong configure serial: %u", serial);
+ return;
+ }
+
+ exsurf->configured = EINA_TRUE;
+
+ switch (exsurf->role)
+ {
+ case E_XDG_SURFACE_ROLE_NONE:
+ ERR("Cannot reach here", exsurf->ec->pixmap, exsurf->ec);
+ break;
+ case E_XDG_SURFACE_ROLE_TOPLEVEL:
+ _e_xdg_toplevel_configure_ack((E_Xdg_Toplevel *)exsurf, configure);
+ break;
+ case E_XDG_SURFACE_ROLE_POPUP:
+ break;
+ }
+
+ E_FREE_FUNC(configure, free);
+}
+
+static const struct zxdg_surface_v6_interface _e_xdg_surface_interface =
+{
+ _e_xdg_surface_cb_destroy,
+ _e_xdg_surface_cb_toplevel_get,
+ _e_xdg_surface_cb_popup_get,
+ _e_xdg_surface_cb_win_geometry_set,
+ _e_xdg_surface_cb_configure_ack
+};
+
+static Eina_Bool
+_e_xdg_surface_cb_commit(void *data, int type, void *event)
+{
+ E_Xdg_Surface *exsurf;
+ E_Event_Client *ev;
+
+ exsurf = (E_Xdg_Surface *)data;
+ ev = (E_Event_Client *)event;
+
+ if (exsurf->ec != ev->ec)
+ goto end;
+
+ if (!exsurf->wait_next_commit)
+ goto end;
+
+ LOG("Wl_Surface Commit, Update Xdg_Surface state %s",
+ exsurf->ec->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf));
+
+ exsurf->wait_next_commit = EINA_FALSE;
+
+ if (exsurf->has_window_geometry)
+ {
+ exsurf->has_window_geometry = EINA_FALSE;
+ EINA_RECTANGLE_SET(&exsurf->ec->comp_data->shell.window,
+ exsurf->window_geometry.x,
+ exsurf->window_geometry.y,
+ exsurf->window_geometry.w,
+ exsurf->window_geometry.h);
+ }
+
+ switch (exsurf->role)
+ {
+ case E_XDG_SURFACE_ROLE_NONE:
+ wl_resource_post_error(exsurf->resource,
+ ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+ "xdg_surface must have a role");
+ break;
+ case E_XDG_SURFACE_ROLE_TOPLEVEL:
+ _e_xdg_toplevel_committed((E_Xdg_Toplevel *)exsurf);
+ break;
+ case E_XDG_SURFACE_ROLE_POPUP:
+ _e_xdg_popup_committed((E_Xdg_Popup *)exsurf);
+ break;
+ }
+
+end:
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_e_xdg_surface_destroy(E_Xdg_Surface *exsurf)
+{
+ _e_xdg_shell_surface_remove(exsurf->shell, exsurf);
+
+ if (exsurf->configure_list)
+ eina_list_free(exsurf->configure_list);
+ if (exsurf->configure_idle)
+ ecore_idle_enterer_del(exsurf->configure_idle);
+ if (exsurf->commit_handler)
+ ecore_event_handler_del(exsurf->commit_handler);
+
+ free(exsurf);
+}
+
+static void
+_e_xdg_surface_cb_resource_destroy(struct wl_resource *resource)
+{
+ E_Xdg_Surface *exsurf;
+
+ exsurf = wl_resource_get_user_data(resource);
+ if (!exsurf)
+ {
+ ERR("No E_Xdg_Surface data in wl_resource", NULL, NULL);
+ return;
+
+ }
+
+ LOG("Destroy resource of Xdg_Surface %s",
+ exsurf->ec->pixmap, exsurf->ec,
+ _e_xdg_surface_util_role_string_get(exsurf));
+
+ e_shell_e_client_destroy(exsurf->ec);
+ _e_xdg_surface_destroy(exsurf);
+
+}
+
+static E_Xdg_Surface *
+_e_xdg_surface_create(E_Xdg_Shell *shell,
+ struct wl_resource *wsurface,
+ uint32_t id)
+{
+ E_Xdg_Surface *exsurf;
+ E_Client *ec;
+
+ ec = wl_resource_get_user_data(wsurface);
+ if (!ec)
+ {
+ ERR("No E_Client data in wl_resource", NULL, NULL);
+ wl_resource_post_error(wsurface,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No data in wl_resource");
+ return NULL;
+ }
+
+ LOG("Create Xdg_Surface", ec->pixmap, ec);
+
+ if (!_e_client_shsurface_assignable_check(ec))
+ {
+ ERR("Cannot get xdg_surface with this wl_surface", ec->pixmap, ec);
+ return NULL;
+ }
+
+ exsurf = (E_Xdg_Surface *)calloc(1, sizeof(e_xdg_surface_role_biggest_struct));
+ if (!exsurf)
+ {
+ wl_client_post_no_memory(shell->wclient);
+ return NULL;
+ }
+
+ exsurf->resource = wl_resource_create(shell->wclient,
+ &zxdg_surface_v6_interface,
+ 1,
+ id);
+ if (!exsurf->resource)
+ {
+ ERR("Could not create wl_resource for xdg surface", ec->pixmap, ec);
+ wl_client_post_no_memory(shell->wclient);
+ free(exsurf);
+ return NULL;
+ }
+
+ wl_resource_set_implementation(exsurf->resource,
+ &_e_xdg_surface_interface,
+ exsurf,
+ _e_xdg_surface_cb_resource_destroy);
+
+ e_shell_e_client_shsurface_assign(ec, exsurf->resource, NULL);
+
+ exsurf->shell = shell;
+ exsurf->ec = ec;
+ exsurf->configured = EINA_FALSE;
+ exsurf->commit_handler =
+ ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
+ _e_xdg_surface_cb_commit,
+ exsurf);
+
+ _e_xdg_shell_surface_add(shell, exsurf);
+
+ return exsurf;
+}
+/* End of Xdg_surface */
+
+/**********************************************************
+ * Implementation for Xdg_Shell
+ **********************************************************/
+static void
+_e_xdg_shell_surface_add(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf)
+{
+ if (!shell) return;
+ shell->surfaces = eina_list_append(shell->surfaces, exsurf);
+}
+
+static void
+_e_xdg_shell_surface_remove(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf)
+{
+ if (!shell) return;
+ shell->surfaces = eina_list_remove(shell->surfaces, exsurf);
+}
+
+static void
+_e_xdg_shell_ping(E_Xdg_Shell *shell)
+{
+ EINA_SAFETY_ON_NULL_RETURN(shell);
+
+ if (shell->ping_serial != 0)
+ return;
+
+ shell->ping_serial = wl_display_next_serial(e_comp_wl->wl.disp);
+ zxdg_shell_v6_send_ping(shell->resource, shell->ping_serial);
+}
+
+static void
+_e_xdg_shell_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ LOG("Destroy Xdg_Shell", NULL, NULL);
+
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
+{
+ E_Xdg_Shell *shell;
+ E_Xdg_Positioner *p;
+ struct wl_resource *new_res;
+
+ LOG("Create Positioner", NULL, NULL);
+
+ shell = wl_resource_get_user_data(resource);
+ if (!shell)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No resource for xdg_shell_v6");
+ return;
+ }
+
+ new_res = wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id);
+ if (!new_res)
+ {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ p = E_NEW(E_Xdg_Positioner, 1);
+ if (!p)
+ {
+ wl_resource_destroy(new_res);
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+ p->shell = shell;
+ p->resource = new_res;
+
+ shell->positioners = eina_list_append(shell->positioners, p);
+
+ wl_resource_set_implementation(new_res,
+ &_e_xdg_positioner_interface,
+ p,
+ _e_xdg_positioner_cb_resource_destroy);
+}
+
+static void
+_e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *wsurface)
+{
+ E_Xdg_Shell *shell;
+ E_Xdg_Surface *exsurf;
+
+ shell = wl_resource_get_user_data(resource);
+ if (!shell)
+ {
+ ERR("No E_Xdg_Shell data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No shell data in wl_resource");
+ return;
+ }
+
+ exsurf = _e_xdg_surface_create(shell, wsurface, id);
+ if (!exsurf)
+ {
+ ERR("Failed to create E_Xdg_Surface", NULL, NULL);
+ return;
+ }
+}
+
+static void
+_e_xdg_shell_cb_pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
+{
+ E_Xdg_Shell *shell;
+ E_Xdg_Surface *exsurf;
+ Eina_List *l;
+
+ LOG("Pong", NULL, NULL);
+
+ shell = wl_resource_get_user_data(resource);
+ if (!shell)
+ {
+ ERR("No E_Xdg_Shell data in wl_resource", NULL, NULL);
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No E_Xdg_Shell data in wl_resource");
+ return;
+ }
+
+ EINA_LIST_FOREACH(shell->surfaces, l, exsurf)
+ e_shell_e_client_pong(exsurf->ec);
+
+ shell->ping_serial = 0;
+}
+
+static const struct zxdg_shell_v6_interface _e_xdg_shell_interface =
+{
+ _e_xdg_shell_cb_destroy,
+ _e_xdg_shell_cb_positioner_create,
+ _e_xdg_shell_cb_surface_get,
+ _e_xdg_shell_cb_pong
+};
+
+static E_Xdg_Shell *
+_e_xdg_shell_create(struct wl_client *client, struct wl_resource *resource)
+{
+ E_Xdg_Shell *shell;
+
+ shell = E_NEW(E_Xdg_Shell, 1);
+ if (!shell)
+ return NULL;
+
+ shell->wclient = client;
+ shell->resource = resource;
+
+ return shell;
+}
+
+static void
+_e_xdg_shell_destroy(E_Xdg_Shell *shell)
+{
+ E_Xdg_Surface *exsurf;
+ E_Xdg_Positioner *p;
+
+ EINA_LIST_FREE(shell->surfaces, exsurf)
+ {
+ /* Do we need to do it even though shell is just about to be destroyed? */
+ e_shell_e_client_pong(exsurf->ec);
+ exsurf->shell = NULL;
+ }
+
+ EINA_LIST_FREE(shell->positioners, p)
+ p->shell = NULL;
+
+ free(shell);
+}
+
+static void
+_e_xdg_shell_cb_unbind(struct wl_resource *resource)
+{
+ E_Xdg_Shell *shell;
+
+ LOG("Unbind Xdg_Shell", NULL, NULL);
+
+ shell = wl_resource_get_user_data(resource);
+ if (!shell)
+ {
+ ERR("No E_Xdg_Shell in wl_resource", NULL, NULL);
+ return;
+ }
+
+ _e_xdg_shell_destroy(shell);
+}
+
+static void
+_e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
+{
+ E_Xdg_Shell *shell;
+ struct wl_resource *resource;
+
+ LOG("Bind Xdg_Shell", NULL, NULL);
+
+ /* Create resource for zxdg_shell_v6 */
+ resource = wl_resource_create(client,
+ &zxdg_shell_v6_interface,
+ version,
+ id);
+ if (!resource)
+ goto err_res;
+
+
+ shell = _e_xdg_shell_create(client, resource);
+ if (!shell)
+ {
+ ERR("Failed to create E_Xdg_Shell", NULL, NULL);
+ goto err_shell;
+ }
+
+ wl_resource_set_implementation(resource, &_e_xdg_shell_interface,
+ shell, _e_xdg_shell_cb_unbind);
+
+ return;
+err_shell:
+ wl_resource_destroy(resource);
+err_res:
+ wl_client_post_no_memory(client);
+}
+
+EINTERN Eina_Bool
+e_xdg_shell_v6_init(void)
+{
+ LOG("Initializing Xdg_Shell_V6", NULL, NULL);
+
+ /* try to create global xdg_shell interface */
+ global_resource = wl_global_create(e_comp_wl->wl.disp,
+ &zxdg_shell_v6_interface,
+ 1,
+ e_comp->wl_comp_data,
+ _e_xdg_shell_cb_bind);
+ if (!global_resource)
+ {
+ ERR("Could not create zxdg_shell_v6 global: %m", NULL, NULL);
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_xdg_shell_v6_shutdown(void)
+{
+ E_FREE_FUNC(global_resource, wl_global_destroy);
+}
+/* End of Xdg_shell */