summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2016-11-11 12:28:49 -0500
committerMike Blumenkrantz <zmike@osg.samsung.com>2016-11-21 11:34:48 -0500
commit0ef8cebebc4965ec466d6ac036d2ac1be238dddb (patch)
tree972242a4106f4c5ff2b31bd4b6046a91f092bed1
parent25bdc475d57039b07253fd397df6f8fa18a0f1ca (diff)
downloadenlightenment-devs/discomfitor/an_unfinished_mastahpiece.tar.gz
-rw-r--r--src/bin/e_comp_canvas.c28
-rw-r--r--src/bin/e_comp_wl.c142
-rw-r--r--src/bin/e_comp_wl.h10
-rw-r--r--src/modules/Makefile_wl_desktop_shell.mk6
-rw-r--r--src/modules/wl_desktop_shell/e_mod_main.c26
-rw-r--r--src/modules/wl_desktop_shell/e_mod_main.h6
-rw-r--r--src/modules/wl_desktop_shell/xdg5.c4
-rw-r--r--src/modules/wl_desktop_shell/xdg6.c1348
8 files changed, 1553 insertions, 17 deletions
diff --git a/src/bin/e_comp_canvas.c b/src/bin/e_comp_canvas.c
index deab362f05..be5f5816a4 100644
--- a/src/bin/e_comp_canvas.c
+++ b/src/bin/e_comp_canvas.c
@@ -170,7 +170,14 @@ _e_comp_cb_mouse_up(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Bu
{
if ((e_comp->comp_type == E_PIXMAP_TYPE_X) && (ev->event_window != e_comp->root))
return ECORE_CALLBACK_PASS_ON;
- return !e_bindings_mouse_down_ecore_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev);
+ if (e_bindings_mouse_down_ecore_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev))
+ return ECORE_CALLBACK_DONE;
+
+#ifdef HAVE_WAYLAND
+ return e_comp_wl_grab_client_mouse_button(ev);
+#else
+ return ECORE_CALLBACK_RENEW;
+#endif
}
static Eina_Bool
@@ -178,7 +185,13 @@ _e_comp_cb_mouse_down(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_
{
if ((e_comp->comp_type == E_PIXMAP_TYPE_X) && (ev->event_window != e_comp->root))
return ECORE_CALLBACK_PASS_ON;
- return !e_bindings_mouse_down_ecore_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev);
+ if (e_bindings_mouse_down_ecore_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev))
+ return ECORE_CALLBACK_DONE;
+#ifdef HAVE_WAYLAND
+ return e_comp_wl_grab_client_mouse_button(ev);
+#else
+ return ECORE_CALLBACK_RENEW;
+#endif
}
static Eina_Bool
@@ -189,6 +202,14 @@ _e_comp_cb_mouse_wheel(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse
return !e_bindings_wheel_ecore_event_handle(E_BINDING_CONTEXT_MANAGER, E_OBJECT(e_comp), ev);
}
+#ifdef HAVE_WAYLAND
+static Eina_Bool
+_e_comp_cb_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
+{
+ return e_comp_wl_grab_client_mouse_move(ev);
+}
+#endif
+
////////////////////////////////////
static Eina_Bool
@@ -794,6 +815,9 @@ e_comp_canvas_intercept(void)
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_comp_cb_mouse_down, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_UP, _e_comp_cb_mouse_up, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_WHEEL, _e_comp_cb_mouse_wheel, NULL);
+#ifdef HAVE_WAYLAND
+ E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE, _e_comp_cb_mouse_move, NULL);
+#endif
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_DOWN, _e_comp_cb_key_down, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_UP, _e_comp_cb_key_up, NULL);
}
diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index b31dde91d2..e9d000b8fb 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -42,6 +42,9 @@ static double _last_event_time = 0.0;
static int64_t surface_id = 0;
+static Eina_List *grab_clients;
+static Eina_List *grab_cbs;
+
/* local functions */
static Eina_Bool
@@ -116,13 +119,16 @@ _e_comp_wl_surface_outputs_update(E_Client *ec)
static void
_e_comp_wl_configure_send(E_Client *ec, Eina_Bool edges)
{
- int w, h;
+ int w = 0, h = 0;
if (e_object_is_del(E_OBJECT(ec))) return;
- if (e_comp_object_frame_exists(ec->frame))
- w = ec->client.w, h = ec->client.h;
- else
- w = ec->w, h = ec->h;
+ if (e_pixmap_usable_get(ec->pixmap))
+ {
+ if (e_comp_object_frame_exists(ec->frame))
+ w = ec->client.w, h = ec->client.h;
+ else
+ w = ec->w, h = ec->h;
+ }
ec->comp_data->shell.configure_send(ec->comp_data->shell.surface,
edges * e_comp_wl->resize.edges,
w, h);
@@ -1334,6 +1340,26 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
if (ec->comp_data->shell.surface)
{
+ if (ec->comp_data->shell.set.min_size.w)
+ ec->icccm.min_w = ec->comp_data->shell.set.min_size.w;
+ ec->comp_data->shell.set.min_size.w = 0;
+ if (ec->comp_data->shell.set.min_size.h)
+ ec->icccm.min_h = ec->comp_data->shell.set.min_size.h;
+ ec->comp_data->shell.set.min_size.h = 0;
+ if (ec->comp_data->shell.set.max_size.w)
+ ec->icccm.max_w = ec->comp_data->shell.set.max_size.w;
+ ec->comp_data->shell.set.max_size.w = 0;
+ if (ec->comp_data->shell.set.max_size.h)
+ ec->icccm.max_h = ec->comp_data->shell.set.max_size.h;
+ ec->comp_data->shell.set.max_size.h = 0;
+ if (ec->icccm.min_w && ec->icccm.max_w && (ec->icccm.min_w > ec->icccm.max_w))
+ wl_resource_post_error(ec->comp_data->shell.surface,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "min surface width cannot be larger than max surface width");
+ if (ec->icccm.min_h && ec->icccm.max_h && (ec->icccm.min_h > ec->icccm.max_h))
+ wl_resource_post_error(ec->comp_data->shell.surface,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "min surface height cannot be larger than max surface height");
if (ec->comp_data->shell.set.fullscreen && (!ec->fullscreen))
{
e_client_fullscreen(ec, E_FULLSCREEN_RESIZE);
@@ -1473,6 +1499,8 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
ec->want_focus |= ec->icccm.accepts_focus && (!ec->override);
}
}
+ else if (first && ec->comp_data->shell.surface)
+ _e_comp_wl_configure_send(ec, 0);
state->sx = 0;
state->sy = 0;
@@ -1839,6 +1867,11 @@ _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_reso
ec->client.w = ec->client.h = 1;
ec->comp_data->surface = res;
ec->netwm.pid = pid;
+ if (!ec->internal)
+ {
+ ec->icccm.min_w = ec->icccm.min_h =
+ ec->icccm.max_w = ec->icccm.max_h = 0;
+ }
if (client != e_comp_wl->xwl_client)
ec->internal = pid == getpid();
@@ -3342,3 +3375,102 @@ e_comp_wl_xwayland_client_queue(E_Client *ec)
{
e_comp_wl->xwl_pending = eina_list_append(e_comp_wl->xwl_pending, ec);
}
+
+E_API void
+e_comp_wl_grab_client_add(E_Client *ec, E_Comp_Wl_Grab_End_Cb cb)
+{
+ E_Client *gec, *parent = e_client_util_top_parent_get(ec);
+ E_Comp_Wl_Grab_End_Cb grabcb;
+
+ if (grab_clients && (parent != e_client_util_top_parent_get(eina_list_data_get(grab_clients))))
+ {
+ /* dismiss grabs in order when grabbing from new toplevel */
+ EINA_LIST_FREE(grab_clients, gec)
+ {
+ grabcb = eina_list_data_get(grab_cbs);
+ if (grabcb) grabcb(gec);
+ grab_cbs = eina_list_remove_list(grab_cbs, grab_cbs);
+ }
+ }
+ grab_clients = eina_list_prepend(grab_clients, ec);
+ grab_cbs = eina_list_prepend(grab_cbs, cb);
+ ec->comp_data->grab = 1;
+ if (eina_list_count(grab_clients) == 1) e_bindings_disabled_set(1);
+}
+
+E_API void
+e_comp_wl_grab_client_del(E_Client *ec, Eina_Bool dismiss)
+{
+ Eina_List *l, *ll;
+ E_Client *gec;
+ int n = -1;
+ E_Comp_Wl_Grab_End_Cb cb;
+
+ EINA_LIST_FOREACH(grab_clients, l, gec)
+ {
+ n++;
+ if (gec != ec) continue;
+ ll = eina_list_nth_list(grab_cbs, n);
+ cb = eina_list_data_get(ll);
+ if (dismiss && cb) cb(gec);
+ grab_cbs = eina_list_remove_list(grab_cbs, ll);
+ grab_clients = eina_list_remove_list(grab_clients, l);
+ break;
+ }
+ if (!grab_clients)
+ e_bindings_disabled_set(0);
+}
+
+E_API Eina_Bool
+e_comp_wl_client_is_grabbed(const E_Client *ec)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
+ if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
+ return ec->comp_data->grab && evas_object_visible_get(ec->frame);
+}
+
+static Eina_Bool
+_check_grab_coords(E_Client *ec, int x, int y)
+{
+ if (e_comp_object_coords_inside_input_area(ec->frame, x, y)) return EINA_TRUE;
+ while (ec->parent)
+ {
+ ec = ec->parent;
+ if (e_comp_object_coords_inside_input_area(ec->frame, x, y)) return EINA_TRUE;
+ }
+ return EINA_FALSE;
+}
+
+E_API Eina_Bool
+e_comp_wl_grab_client_mouse_move(const Ecore_Event_Mouse_Move *ev)
+{
+ E_Client *ec;
+ if (e_comp->comp_type != E_PIXMAP_TYPE_WL) return ECORE_CALLBACK_RENEW;
+ ec = e_client_focused_get();
+ if (!ec) return ECORE_CALLBACK_RENEW;
+ if (!e_client_util_is_popup(ec)) return ECORE_CALLBACK_RENEW;
+ if (!e_comp_wl_client_is_grabbed(ec)) return ECORE_CALLBACK_RENEW;
+ /* reject mouse moves from outside the popup */
+ if (_check_grab_coords(ec, ev->x, ev->y)) return ECORE_CALLBACK_RENEW;
+ /* manually move the pointer since we're about to block the event globally */
+ evas_object_move(e_comp->pointer->o_ptr, ev->x, ev->y);
+ return ECORE_CALLBACK_DONE;
+}
+
+E_API Eina_Bool
+e_comp_wl_grab_client_mouse_button(const Ecore_Event_Mouse_Button *ev)
+{
+ E_Client *ec;
+
+ if (e_comp->comp_type != E_PIXMAP_TYPE_WL) return ECORE_CALLBACK_RENEW;
+ ec = e_client_focused_get();
+ if (!ec) return ECORE_CALLBACK_RENEW;
+ if (!e_client_util_is_popup(ec)) return ECORE_CALLBACK_RENEW;
+ if (!e_comp_wl_client_is_grabbed(ec)) return ECORE_CALLBACK_RENEW;
+ /* reject mouse moves from outside the popup */
+ if (_check_grab_coords(ec, ev->x, ev->y)) return ECORE_CALLBACK_RENEW;
+ e_comp_wl_grab_client_del(ec, 1);
+ while (grab_clients)
+ e_comp_wl_grab_client_del(eina_list_last_data_get(grab_clients), 1);
+ return ECORE_CALLBACK_DONE;
+}
diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h
index 2ee3aedca3..48ff97ad62 100644
--- a/src/bin/e_comp_wl.h
+++ b/src/bin/e_comp_wl.h
@@ -49,6 +49,7 @@ typedef struct _E_Comp_Wl_Client_Data E_Comp_Wl_Client_Data;
typedef struct _E_Comp_Wl_Data E_Comp_Wl_Data;
typedef struct _E_Comp_Wl_Output E_Comp_Wl_Output;
typedef struct E_Shell_Data E_Shell_Data;
+typedef void (*E_Comp_Wl_Grab_End_Cb)(E_Client*);
struct _E_Comp_Wl_Buffer
{
@@ -287,6 +288,8 @@ struct _E_Comp_Wl_Client_Data
E_Shell_Data *data;
struct
{
+ Evas_Coord_Size min_size;
+ Evas_Coord_Size max_size;
Eina_Bool fullscreen : 1;
Eina_Bool unfullscreen : 1;
Eina_Bool maximize : 1;
@@ -329,6 +332,7 @@ struct _E_Comp_Wl_Client_Data
Eina_Bool maximizing : 1;
Eina_Bool in_commit : 1;
Eina_Bool is_xdg_surface : 1;
+ Eina_Bool grab;
};
struct _E_Comp_Wl_Output
@@ -369,6 +373,12 @@ E_API Eina_Bool e_comp_wl_evas_handle_mouse_button(E_Client *ec, uint32_t timest
E_API extern int E_EVENT_WAYLAND_GLOBAL_ADD;
+E_API void e_comp_wl_grab_client_add(E_Client *ec, E_Comp_Wl_Grab_End_Cb cb);
+E_API void e_comp_wl_grab_client_del(E_Client *ec, Eina_Bool dismiss);
+E_API Eina_Bool e_comp_wl_client_is_grabbed(const E_Client *ec);
+E_API Eina_Bool e_comp_wl_grab_client_mouse_move(const Ecore_Event_Mouse_Move *ev);
+E_API Eina_Bool e_comp_wl_grab_client_mouse_button(const Ecore_Event_Mouse_Button *ev);
+
# ifndef HAVE_WAYLAND_ONLY
EINTERN void e_comp_wl_xwayland_client_queue(E_Client *ec);
static inline E_Comp_X_Client_Data *
diff --git a/src/modules/Makefile_wl_desktop_shell.mk b/src/modules/Makefile_wl_desktop_shell.mk
index 399579913b..6b5b74e873 100644
--- a/src/modules/Makefile_wl_desktop_shell.mk
+++ b/src/modules/Makefile_wl_desktop_shell.mk
@@ -13,6 +13,8 @@ wl_desktop_shellpkg_LTLIBRARIES = src/modules/wl_desktop_shell/module.la
wl_desktop_shell_wayland_sources = \
src/modules/wl_desktop_shell/xdg-shell-unstable-v5-protocol.c \
src/modules/wl_desktop_shell/xdg-shell-unstable-v5-server-protocol.h \
+ src/modules/wl_desktop_shell/xdg-shell-unstable-v6-protocol.c \
+ src/modules/wl_desktop_shell/xdg-shell-unstable-v6-server-protocol.h \
src/modules/wl_desktop_shell/input-method-unstable-v1-protocol.c \
src/modules/wl_desktop_shell/input-method-unstable-v1-server-protocol.h
@@ -27,7 +29,8 @@ src/modules/wl_desktop_shell/e_mod_main.c \
src/modules/wl_desktop_shell/e_mod_main.h \
src/modules/wl_desktop_shell/e_mod_input_panel.c \
src/modules/wl_desktop_shell/wl_shell.c \
-src/modules/wl_desktop_shell/xdg5.c
+src/modules/wl_desktop_shell/xdg5.c \
+src/modules/wl_desktop_shell/xdg6.c
nodist_src_modules_wl_desktop_shell_module_la_SOURCES = \
@@ -38,6 +41,7 @@ MAINTAINERCLEANFILES += \
src/modules/wl_desktop_shell/e_mod_main.c: \
src/modules/wl_desktop_shell/xdg-shell-unstable-v5-server-protocol.h \
+ src/modules/wl_desktop_shell/xdg-shell-unstable-v6-server-protocol.h \
src/modules/wl_desktop_shell/input-method-unstable-v1-server-protocol.h
PHONIES += wl_desktop_shell install-wl_desktop_shell
diff --git a/src/modules/wl_desktop_shell/e_mod_main.c b/src/modules/wl_desktop_shell/e_mod_main.c
index 8d7a897eed..c818b9f044 100644
--- a/src/modules/wl_desktop_shell/e_mod_main.c
+++ b/src/modules/wl_desktop_shell/e_mod_main.c
@@ -16,15 +16,27 @@ e_shell_surface_destroy(struct wl_resource *resource)
/* get the client for this resource */
ec = wl_resource_get_user_data(resource);
if (!ec) return;
- if (!e_object_unref(E_OBJECT(ec))) return;
if (e_object_is_del(E_OBJECT(ec))) return;
+ if (ec->comp_data->grab)
+ {
+ e_comp_wl_grab_client_del(ec, 0);
+ ec->comp_data->grab = 0;
+ }
+
shd = ec->comp_data->shell.data;
if (shd)
{
E_FREE_LIST(shd->pending, free);
- E_FREE(ec->comp_data->shell.data);
+ if ((resource == ec->comp_data->shell.surface) || (resource == shd->surface))
+ {
+ if (ec->comp_data->shell.surface == resource)
+ ec->comp_data->shell.surface = NULL;
+ else
+ shd->surface = NULL;
+ E_FREE(ec->comp_data->shell.data);
+ }
}
if (ec->comp_data->mapped)
@@ -38,8 +50,8 @@ e_shell_surface_destroy(struct wl_resource *resource)
ec->parent->transients =
eina_list_remove(ec->parent->transients, ec);
}
- /* wl_resource_destroy(ec->comp_data->shell.surface); */
- ec->comp_data->shell.surface = NULL;
+
+ e_object_unref(E_OBJECT(ec));
}
EINTERN void
@@ -140,6 +152,8 @@ E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Desktop_Shell" };
E_API void *
e_modapi_init(E_Module *m)
{
+ Eina_Bool have_shell;
+
/* try to create global shell interface */
if (!wl_global_create(e_comp_wl->wl.disp, &wl_shell_interface, 1,
NULL, wl_shell_cb_bind))
@@ -148,7 +162,9 @@ e_modapi_init(E_Module *m)
return NULL;
}
- if (!e_xdg_shell_init()) return NULL;
+ have_shell = e_xdg_shell_v5_init();
+ have_shell &= e_xdg_shell_v6_init();
+ if (!have_shell) return NULL;
#ifdef HAVE_WL_TEXT_INPUT
if (!e_input_panel_init())
diff --git a/src/modules/wl_desktop_shell/e_mod_main.h b/src/modules/wl_desktop_shell/e_mod_main.h
index 24a7fc85ee..77c404c502 100644
--- a/src/modules/wl_desktop_shell/e_mod_main.h
+++ b/src/modules/wl_desktop_shell/e_mod_main.h
@@ -12,7 +12,8 @@ EINTERN void e_shell_surface_cb_destroy(struct wl_resource *resource);
EINTERN void e_shell_surface_parent_set(E_Client *ec, struct wl_resource *parent_resource);
EINTERN void e_shell_surface_mouse_down_helper(E_Client *ec, E_Binding_Event_Mouse_Button *ev, Eina_Bool move);
-EINTERN Eina_Bool e_xdg_shell_init(void);
+EINTERN Eina_Bool e_xdg_shell_v5_init(void);
+EINTERN Eina_Bool e_xdg_shell_v6_init(void);
EINTERN void wl_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id);
struct E_Shell_Data
@@ -21,10 +22,11 @@ struct E_Shell_Data
int32_t width;
int32_t height;
Eina_List *pending;
+ struct wl_resource *surface;
+ void *shell;
Eina_Bool fullscreen : 1;
Eina_Bool maximized : 1;
Eina_Bool activated : 1;
};
-
#endif
diff --git a/src/modules/wl_desktop_shell/xdg5.c b/src/modules/wl_desktop_shell/xdg5.c
index 2af720648e..577393b377 100644
--- a/src/modules/wl_desktop_shell/xdg5.c
+++ b/src/modules/wl_desktop_shell/xdg5.c
@@ -860,7 +860,7 @@ _e_xdg_shell_cb_dispatch(const void *implementation EINA_UNUSED, void *target, u
return 1;
}
-EINTERN void
+static void
_e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
{
struct wl_resource *res;
@@ -877,7 +877,7 @@ _e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t
}
EINTERN Eina_Bool
-e_xdg_shell_init(void)
+e_xdg_shell_v5_init(void)
{
/* try to create global xdg_shell interface */
if (!wl_global_create(e_comp_wl->wl.disp, &xdg_shell_interface, 1,
diff --git a/src/modules/wl_desktop_shell/xdg6.c b/src/modules/wl_desktop_shell/xdg6.c
new file mode 100644
index 0000000000..274b453ac1
--- /dev/null
+++ b/src/modules/wl_desktop_shell/xdg6.c
@@ -0,0 +1,1348 @@
+#define E_COMP_WL
+#include "e.h"
+#include "e_mod_main.h"
+
+#include "xdg-shell-unstable-v6-server-protocol.h"
+
+#define XDG_SERVER_VERSION 6
+
+typedef enum
+{
+ STATE_MAXIMIZED = (1 << 0),
+ STATE_UNMAXIMIZED = (1 << 1),
+ STATE_FULLSCREEN = (1 << 2),
+ STATE_UNFULLSCREEN = (1 << 3),
+} State;
+
+typedef struct Pending_State
+{
+ State state;
+ uint32_t serial;
+} Pending_State;
+
+typedef struct v6_Shell_Data
+{
+ Eina_List *surfaces;
+ Eina_List *positioners;
+} v6_Shell_Data;
+
+typedef struct Positioner
+{
+ v6_Shell_Data *v;
+ Evas_Coord_Size size;
+ Eina_Rectangle anchor_rect;
+ enum zxdg_positioner_v6_anchor anchor;
+ enum zxdg_positioner_v6_gravity gravity;
+ enum zxdg_positioner_v6_constraint_adjustment constrain;
+ Evas_Coord_Point offset;
+} Positioner;
+
+
+static void
+_e_xdg_shell_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ v6_Shell_Data *v = wl_resource_get_user_data(resource);
+ if (v->surfaces)
+ wl_resource_post_error(resource, ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES, "shell destroyed before surfaces");
+ wl_resource_destroy(resource);
+}
+
+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");
+}
+
+static void
+_e_xdg_positioner_set_size(struct wl_client *wl_client EINA_UNUSED, struct wl_resource *resource, int32_t w, int32_t h)
+{
+ Positioner *p = wl_resource_get_user_data(resource);
+
+ _validate_size(resource, w);
+ _validate_size(resource, h);
+
+ p->size.w = w;
+ p->size.h = h;
+}
+
+static void
+_e_xdg_positioner_set_anchor_rect(struct wl_client *wl_client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+ Positioner *p = wl_resource_get_user_data(resource);
+
+ _validate_size(resource, w);
+ _validate_size(resource, h);
+
+ EINA_RECTANGLE_SET(&p->anchor_rect, x, y, w, h);
+}
+
+static void
+_e_xdg_positioner_set_anchor(struct wl_client *wl_client EINA_UNUSED, struct wl_resource *resource, enum zxdg_positioner_v6_anchor anchor)
+{
+ Positioner *p = wl_resource_get_user_data(resource);
+
+ 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->anchor = anchor;
+}
+
+static void
+_e_xdg_positioner_set_gravity(struct wl_client *wl_client EINA_UNUSED, struct wl_resource *resource, enum zxdg_positioner_v6_gravity gravity)
+{
+ Positioner *p = wl_resource_get_user_data(resource);
+
+ 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->gravity = gravity;
+}
+
+static void
+_e_xdg_positioner_set_constraint_adjustment(struct wl_client *wl_client EINA_UNUSED, struct wl_resource *resource, enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
+{
+ Positioner *p = wl_resource_get_user_data(resource);
+
+ p->constrain = constraint_adjustment;
+}
+
+static void
+_e_xdg_positioner_set_offset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y)
+{
+ Positioner *p = wl_resource_get_user_data(resource);
+
+ p->offset.x = x;
+ p->offset.y = y;
+}
+
+static void
+_e_xdg_positioner_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct zxdg_positioner_v6_interface _e_xdg_positioner_interface =
+{
+ .destroy = _e_xdg_positioner_destroy,
+ .set_size = _e_xdg_positioner_set_size,
+ .set_anchor_rect = _e_xdg_positioner_set_anchor_rect,
+ .set_anchor = _e_xdg_positioner_set_anchor,
+ .set_gravity = _e_xdg_positioner_set_gravity,
+ .set_constraint_adjustment = _e_xdg_positioner_set_constraint_adjustment,
+ .set_offset = _e_xdg_positioner_set_offset,
+};
+
+static void
+_e_xdg_shell_positioner_destroy(struct wl_resource *resource)
+{
+ Positioner *p;
+
+ p = wl_resource_get_user_data(resource);
+ if (p->v) p->v->positioners = eina_list_remove(p->v->positioners, p);
+ free(p);
+}
+
+static void
+_e_xdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
+{
+ struct wl_resource *res;
+ v6_Shell_Data *v;
+ Positioner *p;
+
+ v = wl_resource_get_user_data(resource);
+ res = wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id);
+ p = E_NEW(Positioner, 1);
+ p->v = v;
+ wl_resource_set_implementation(res, &_e_xdg_positioner_interface, p, _e_xdg_shell_positioner_destroy);
+ wl_resource_set_user_data(res, p);
+}
+
+static void
+_e_xdg_shell_surface_configure(struct wl_resource *resource, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
+{
+ E_Client *ec;
+
+ /* DBG("XDG_SHELL: Surface Configure: %d \t%d %d %d %d", */
+ /* wl_resource_get_id(resource), x, y, w, h); */
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (!e_object_is_del(E_OBJECT(ec)))
+ e_client_util_move_resize_without_frame(ec, x, y, w, h);
+}
+
+static void
+_e_xdg_shell_surface_ping(struct wl_resource *resource)
+{
+ E_Client *ec;
+ uint32_t serial;
+ struct wl_client *client;
+ struct wl_resource *xdg_shell;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+ client = wl_resource_get_client(resource);
+ xdg_shell = eina_hash_find(xdg_shell_resources, &client);
+
+ if (!xdg_shell) return;
+ serial = wl_display_next_serial(e_comp_wl->wl.disp);
+ zxdg_shell_v6_send_ping(xdg_shell, serial);
+}
+
+static void
+_e_xdg_shell_surface_map(struct wl_resource *resource)
+{
+ E_Client *ec;
+
+ /* DBG("XDG_SHELL: Map Surface: %d", wl_resource_get_id(resource)); */
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if ((!ec->comp_data->mapped) && (e_pixmap_usable_get(ec->pixmap)))
+ {
+ /* map this surface if needed */
+ ec->visible = EINA_TRUE;
+ evas_object_show(ec->frame);
+ ec->comp_data->mapped = EINA_TRUE;
+
+ /* FIXME: sometimes popup surfaces Do Not raise above their
+ * respective parents... */
+ /* if (e_client_util_is_popup(ec)) */
+ /* e_client_raise_latest_set(ec); */
+ }
+}
+
+static void
+_e_xdg_shell_surface_unmap(struct wl_resource *resource)
+{
+ E_Client *ec;
+
+ /* DBG("XDG_SHELL: Unmap Surface: %d", wl_resource_get_id(resource)); */
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (ec->comp_data->mapped)
+ {
+ ec->visible = EINA_FALSE;
+ evas_object_hide(ec->frame);
+ ec->comp_data->mapped = EINA_FALSE;
+ }
+}
+
+static void
+_e_xdg_surface_state_add(struct wl_resource *resource, struct wl_array *states, uint32_t state)
+{
+ uint32_t *s;
+
+ s = wl_array_add(states, sizeof(*s));
+ if (s)
+ *s = state;
+ else
+ wl_resource_post_no_memory(resource);
+}
+
+static void
+_xdg_shell_surface_send_configure(struct wl_resource *resource, Eina_Bool fullscreen, Eina_Bool maximized, uint32_t edges, int32_t width, int32_t height)
+{
+ struct wl_array states;
+ uint32_t serial;
+ E_Client *focused, *ec;
+ E_Shell_Data *shd;
+ State pending = 0;
+ Eina_Bool activated = EINA_FALSE;
+
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_client_util_is_popup(ec)) return;
+ focused = e_client_focused_get();
+ if (ec == focused)
+ activated = 1;
+ else if (focused && focused->parent)
+ {
+ do
+ {
+ if (focused->parent != ec)
+ focused = focused->parent;
+ else
+ activated = 1;
+ } while (focused && (!activated));
+ }
+ shd = ec->comp_data->shell.data;
+ if ((shd->edges == edges) && (shd->width == width) && (shd->height == height) &&
+ (shd->fullscreen == fullscreen) &&
+ (shd->maximized == maximized) &&
+ (shd->activated == activated)) return;
+ shd->edges = edges;
+ shd->width = width;
+ shd->height = height;
+ if (shd->fullscreen != fullscreen)
+ {
+ if (fullscreen)
+ pending |= STATE_FULLSCREEN;
+ else
+ pending |= STATE_UNFULLSCREEN;
+ }
+ shd->fullscreen = fullscreen;
+ if (shd->maximized != maximized)
+ {
+ if (maximized)
+ pending |= STATE_MAXIMIZED;
+ else
+ pending |= STATE_UNMAXIMIZED;
+ }
+ shd->maximized = maximized;
+ shd->activated = activated;
+ wl_array_init(&states);
+
+ if (fullscreen)
+ _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN);
+ else if (maximized)
+ _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED);
+ if (edges)
+ _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_RESIZING);
+ if (activated)
+ _e_xdg_surface_state_add(resource, &states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED);
+
+ serial = wl_display_next_serial(e_comp_wl->wl.disp);
+ zxdg_toplevel_v6_send_configure(resource, width, height, &states);
+ {
+ Pending_State *ps;
+
+ ps = E_NEW(Pending_State, 1);
+ ps->state = pending;
+ ps->serial = serial;
+ shd->pending = eina_list_append(shd->pending, ps);
+ }
+ zxdg_surface_v6_send_configure(shd->surface, serial);
+
+ wl_array_release(&states);
+}
+
+static void
+_e_xdg_shell_surface_configure_send(struct wl_resource *resource, uint32_t edges, int32_t width, int32_t height)
+{
+ E_Client *ec;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+ if (e_client_util_is_popup(ec))
+ {
+ E_Shell_Data *shd;
+ uint32_t serial;
+
+ shd = ec->comp_data->shell.data;
+ serial = wl_display_next_serial(e_comp_wl->wl.disp);
+ zxdg_popup_v6_send_configure(resource, ec->x - ec->parent->x, ec->y - ec->parent->y, width, height);
+ zxdg_surface_v6_send_configure(shd->surface, serial);
+ return;
+ }
+
+ _xdg_shell_surface_send_configure(resource, ec->fullscreen, !!ec->maximized || ec->comp_data->max, edges, width, height);
+}
+
+static void
+_e_xdg_popup_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_popup_grab_dismiss(E_Client *ec)
+{
+ zxdg_popup_v6_send_popup_done(ec->comp_data->shell.surface);
+ ec->comp_data->grab = 0;
+}
+
+static void
+_e_xdg_popup_cb_grab(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial)
+{
+ E_Client *ec;
+
+ ec = wl_resource_get_user_data(resource);
+ if ((!ec) || e_object_is_del(E_OBJECT(ec)))
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (ec->comp_data->mapped)
+ {
+ wl_resource_post_error(resource, ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
+ "grab requested on mapped popup");
+ return;
+ }
+ if (e_client_util_is_popup(ec->parent) && (!ec->parent->comp_data->grab))
+ {
+ wl_resource_post_error(resource, ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
+ "grab requested on ungrabbed nested popup");
+ return;
+ }
+ e_comp_wl_grab_client_add(ec, _e_xdg_popup_grab_dismiss);
+}
+
+static const struct zxdg_popup_v6_interface _e_xdg_popup_interface = {
+ _e_xdg_popup_cb_destroy,
+ _e_xdg_popup_cb_grab,
+};
+
+static void
+_e_xdg_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_surface_cb_ack_configure(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial)
+{
+ E_Client *ec;
+ Pending_State *ps;
+ E_Shell_Data *shd;
+ Eina_List *l, *ll;
+
+ ec = wl_resource_get_user_data(resource);
+ if (!ec)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+ shd = ec->comp_data->shell.data;
+ EINA_LIST_FOREACH_SAFE(shd->pending, l, ll, ps)
+ {
+ if (ps->serial > serial) break;
+ if (ps->state & STATE_FULLSCREEN)
+ {
+ ec->comp_data->shell.set.fullscreen = 1;
+ ec->comp_data->shell.set.unfullscreen = 0;
+ }
+ if (ps->state & STATE_UNFULLSCREEN)
+ {
+ ec->comp_data->shell.set.unfullscreen = 1;
+ ec->comp_data->shell.set.fullscreen = 0;
+ }
+ if (ps->state & STATE_MAXIMIZED)
+ {
+ ec->comp_data->shell.set.maximize = 1;
+ ec->comp_data->shell.set.unmaximize = 0;
+ }
+ if (ps->state & STATE_UNMAXIMIZED)
+ {
+ ec->comp_data->shell.set.unmaximize = 1;
+ ec->comp_data->shell.set.maximize = 0;
+ }
+ shd->pending = eina_list_remove_list(shd->pending, l);
+ free(ps);
+ }
+}
+
+static void
+_e_xdg_surface_cb_window_geometry_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+ E_Client *ec;
+
+ ec = wl_resource_get_user_data(resource);
+ if (!ec)
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+ EINA_RECTANGLE_SET(&ec->comp_data->shell.window, x, y, w, h);
+ //DBG("XDG_SHELL: Window Geom Set: %d \t%d %d, %d %d", wl_resource_get_id(resource), x, y, w, h);
+}
+
+static void
+_e_xdg_toplevel_cb_maximized_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ E_Client *ec;
+ int w, h;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (ec->lock_user_maximize) return;
+ if (e_config->window_maximize_animate && (!ec->maximize_anims_disabled))
+ w = ec->w, h = ec->h;
+ else
+ {
+ switch (e_config->maximize_policy & E_MAXIMIZE_TYPE)
+ {
+ case E_MAXIMIZE_FULLSCREEN:
+ w = ec->zone->w, h = ec->zone->h;
+ break;
+ default:
+ e_zone_useful_geometry_get(ec->zone, NULL, NULL, &w, &h);
+ }
+ }
+ _xdg_shell_surface_send_configure(resource, ec->fullscreen, 1, 0, w, h);
+}
+
+static void
+_e_xdg_toplevel_cb_maximized_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ E_Client *ec;
+ int w, h;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (ec->lock_user_maximize) return;
+ ec->comp_data->unmax = (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_BOTH;
+ if (e_config->window_maximize_animate && (!ec->maximize_anims_disabled))
+ w = ec->w, h = ec->h;
+ else
+ w = ec->saved.w, h = ec->saved.h;
+ _xdg_shell_surface_send_configure(resource, ec->fullscreen, 0, 0, w, h);
+}
+
+static void
+_e_xdg_toplevel_cb_fullscreen_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *output_resource EINA_UNUSED)
+{
+ E_Client *ec;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+
+ if (ec->lock_user_fullscreen) return;
+ _xdg_shell_surface_send_configure(resource, 1, !!ec->maximized || ec->comp_data->max, 0, ec->zone->w, ec->zone->h);
+}
+
+static void
+_e_xdg_toplevel_cb_fullscreen_unset(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ E_Client *ec;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (ec->lock_user_fullscreen) return;
+ _xdg_shell_surface_send_configure(resource, 0, !!ec->maximized || ec->comp_data->max, 0, ec->saved.w, ec->saved.h);
+}
+
+static void
+_e_xdg_toplevel_cb_minimized_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ E_Client *ec;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ if (ec->lock_user_iconify) return;
+ ec->comp_data->shell.set.minimize = 1;
+ ec->comp_data->max = (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_BOTH;
+}
+
+static int
+_apply_positioner_x(int x, Positioner *p, Eina_Bool invert)
+{
+ enum zxdg_positioner_v6_anchor an = ZXDG_POSITIONER_V6_ANCHOR_NONE;
+ enum zxdg_positioner_v6_gravity grav = ZXDG_POSITIONER_V6_GRAVITY_NONE;
+
+ if (invert)
+ {
+ if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT)
+ an |= ZXDG_POSITIONER_V6_ANCHOR_RIGHT;
+ else if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT)
+ an |= ZXDG_POSITIONER_V6_ANCHOR_LEFT;
+ if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT)
+ grav |= ZXDG_POSITIONER_V6_GRAVITY_RIGHT;
+ else if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT)
+ grav |= ZXDG_POSITIONER_V6_GRAVITY_LEFT;
+ }
+ else
+ {
+ an = p->anchor;
+ grav = p->gravity;
+ }
+
+ /* left edge */
+ if (an & ZXDG_POSITIONER_V6_ANCHOR_LEFT)
+ x += p->anchor_rect.x;
+ /* right edge */
+ else if (an & ZXDG_POSITIONER_V6_ANCHOR_RIGHT)
+ x += p->anchor_rect.x + p->anchor_rect.w;
+ /* center */
+ else
+ x += p->anchor_rect.x + (p->anchor_rect.w / 2);
+
+ /* flip left over anchor */
+ if (grav & ZXDG_POSITIONER_V6_GRAVITY_LEFT)
+ x -= p->size.w;
+ /* center on anchor */
+ else if (!(an & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))
+ x -= p->size.w / 2;
+ return x;
+}
+
+static int
+_apply_positioner_y(int y, Positioner *p, Eina_Bool invert)
+{
+ enum zxdg_positioner_v6_anchor an = ZXDG_POSITIONER_V6_ANCHOR_NONE;
+ enum zxdg_positioner_v6_gravity grav = ZXDG_POSITIONER_V6_GRAVITY_NONE;
+
+ if (invert)
+ {
+ if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP)
+ an |= ZXDG_POSITIONER_V6_ANCHOR_BOTTOM;
+ else if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)
+ an |= ZXDG_POSITIONER_V6_ANCHOR_TOP;
+ if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP)
+ grav |= ZXDG_POSITIONER_V6_GRAVITY_BOTTOM;
+ else if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)
+ grav |= ZXDG_POSITIONER_V6_GRAVITY_TOP;
+ }
+ else
+ {
+ an = p->anchor;
+ grav = p->gravity;
+ }
+
+ /* up edge */
+ if (an & ZXDG_POSITIONER_V6_ANCHOR_TOP)
+ y += p->anchor_rect.y;
+ /* bottom edge */
+ else if (an & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)
+ y += p->anchor_rect.y + p->anchor_rect.h;
+ /* center */
+ else
+ y += p->anchor_rect.y + (p->anchor_rect.h / 2);
+
+ /* flip up over anchor */
+ if (grav & ZXDG_POSITIONER_V6_GRAVITY_TOP)
+ y -= p->size.h;
+ /* center on anchor */
+ else if (!(an & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM))
+ y -= p->size.h / 2;
+ return y;
+}
+
+static void
+_apply_positioner(E_Client *ec, Positioner *p)
+{
+ int x, y;
+ int zx, zy, zw, zh;
+ /* apply base geometry:
+ * coords are relative to parent
+ */
+ x = ec->x = ec->parent->x + p->offset.x;
+ y = ec->y = ec->parent->y + p->offset.y;
+
+ if (p->size.w && p->size.h)
+ {
+ ec->w = p->size.w;
+ ec->h = p->size.h;
+ }
+
+ /* apply policies in order:
+ - anchor (add anchor_rect using anchor point)
+ - gravity (perform flips if gravity is not right|bottom)
+ - constrain (adjust if popup does not fit)
+ */
+ ec->x = _apply_positioner_x(ec->x, p, 0);
+ ec->y = _apply_positioner_y(ec->y, p, 0);
+
+ e_zone_useful_geometry_get(ec->parent->zone, &zx, &zy, &zw, &zh);
+
+#define CONSTRAINED(EC, X, Y) \
+ !E_CONTAINS((X), (Y), (EC)->w, (EC)->h, zx, zy, zw, zh)
+
+ if (!CONSTRAINED(ec, ec->x, ec->y)) return;
+
+ /* assume smart placement:
+ - flip
+ - slide
+ - resize
+ */
+ if ((p->constrain & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X) &&
+ (!E_CONTAINS(ec->x, zy, ec->w, 1, zx, zy, zw, zh)))
+ {
+ int fx;
+
+ fx = _apply_positioner_x(x, p, 1);
+ if (E_CONTAINS(fx, zy, ec->w, 1, zx, zy, zw, zh))
+ ec->x = fx;
+ }
+ if (!CONSTRAINED(ec, ec->x, ec->y)) return;
+ if ((p->constrain & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y) &&
+ (!E_CONTAINS(zx, ec->y, 1, ec->h, zx, zy, zw, zh)))
+ {
+ int fy;
+
+ fy = _apply_positioner_y(y, p, 1);
+ if (E_CONTAINS(zx, fy, 1, ec->h, zx, zy, zw, zh))
+ ec->y = fy;
+ }
+ if (!CONSTRAINED(ec, ec->x, ec->y)) return;
+
+ if ((p->constrain & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X) &&
+ (!E_CONTAINS(ec->x, zy, ec->w, 1, zx, zy, zw, zh)))
+ {
+ int sx = ec->x;
+
+ if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT)
+ {
+ if (ec->x + ec->w > zx + zw)
+ sx = MAX(zx + zw - ec->w, ec->parent->x);
+ else if (ec->x + ec->w < zx)
+ sx = zx;
+ }
+ else if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT)
+ {
+ if (ec->x + ec->w < zx)
+ sx = zx;
+ else if (ec->x + ec->w > zx + zw)
+ sx = MAX(zx + zw - ec->w, ec->parent->x);
+ }
+ if (E_CONTAINS(sx, zy, ec->w, 1, zx, zy, zw, zh))
+ ec->x = sx;
+ }
+ if (!CONSTRAINED(ec, ec->x, ec->y)) return;
+ if ((p->constrain & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y) &&
+ (!E_CONTAINS(zx, ec->y, 1, ec->h, zx, zy, zw, zh)))
+ {
+ int sy = ec->y;
+
+ if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP)
+ {
+ if (ec->y + ec->h > zy + zh)
+ sy = MAX(zy + zh - ec->h, ec->parent->y);
+ else if (ec->y + ec->h < zy)
+ sy = zy;
+ }
+ else if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)
+ {
+ if (ec->y + ec->h < zy)
+ sy = zy;
+ else if (ec->y + ec->h > zy + zh)
+ sy = MAX(zy + zh - ec->h, ec->parent->y);
+ }
+ if (E_CONTAINS(zx, sy, 1, ec->h, zx, zy, zw, zh))
+ ec->y = sy;
+ }
+ if (!CONSTRAINED(ec, ec->x, ec->y)) return;
+
+ if ((p->constrain & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X) &&
+ (!E_CONTAINS(ec->x, zy, ec->w, 1, zx, zy, zw, zh)))
+ {
+ ec->w = zx + zw - ec->x;
+ ec->changes.size = 1;
+ if (!CONSTRAINED(ec, ec->x, ec->y)) return;
+ }
+ if ((p->constrain & ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y) &&
+ (!E_CONTAINS(zx, ec->y, 1, ec->h, zx, zy, zw, zh)))
+ {
+ ec->h = zy + zh - ec->y;
+ ec->changes.size = 1;
+ }
+}
+
+static void
+_e_xdg_surface_cb_popup_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *parent_resource, struct wl_resource *positioner_resource)
+{
+ E_Client *ec;
+ E_Comp_Client_Data *cdata;
+ Positioner *p;
+
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Pixmap Set On Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+ p = wl_resource_get_user_data(positioner_resource);
+ if (!p)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "invalid positioner");
+ return;
+ }
+
+ if ((!p->size.w) || (!p->anchor_rect.w))
+ {
+ wl_resource_post_error(resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
+ "invalid positioner");
+ return;
+ }
+
+ cdata = ec->comp_data;
+
+ if (cdata->shell.surface)
+ {
+ wl_resource_post_error(resource,
+ ZXDG_SHELL_V6_ERROR_ROLE,
+ "surface already has assigned role");
+ return;
+ }
+
+ /* check for the parent surface */
+ if (!parent_resource)
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Popup requires a parent shell surface");
+ return;
+ }
+
+ /* try to create a shell surface */
+ if (!(cdata->shell.surface =
+ wl_resource_create(client, &zxdg_popup_v6_interface, 1, id)))
+ {
+ ERR("Could not create xdg shell surface");
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_resource_set_implementation(cdata->shell.surface,
+ &_e_xdg_popup_interface, ec, e_shell_surface_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.map = _e_xdg_shell_surface_map;
+ cdata->shell.unmap = _e_xdg_shell_surface_unmap;
+
+ 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->placed = ec->comp_data->set_win_type = EINA_TRUE;
+
+ /* set this client as a transient for parent */
+ e_shell_surface_parent_set(ec, parent_resource);
+
+ _apply_positioner(ec, p);
+ ec->client.x = ec->x;
+ ec->client.y = ec->y;
+
+ if (ec->internal_elm_win && evas_object_visible_get(ec->internal_elm_win))
+ _e_xdg_shell_surface_map(resource);
+}
+
+static void
+_e_xdg_toplevel_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+static void
+_e_xdg_toplevel_cb_parent_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *parent_resource)
+{
+ E_Client *ec;
+
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ /* set this client as a transient for parent */
+ e_shell_surface_parent_set(ec, parent_resource);
+}
+
+static void
+_e_xdg_toplevel_cb_title_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *title)
+{
+ E_Client *ec;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ /* set title */
+ eina_stringshare_replace(&ec->icccm.title, title);
+ if (ec->frame) e_comp_object_frame_title_set(ec->frame, title);
+}
+
+static void
+_e_xdg_toplevel_cb_app_id_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *id)
+{
+ E_Client *ec;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) 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, id);
+ /* eina_stringshare_replace(&ec->netwm.name, id); */
+ ec->changes.icon = !!ec->icccm.class;
+ EC_CHANGED(ec);
+}
+
+static void
+_e_xdg_toplevel_cb_window_menu_show(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *seat_resource EINA_UNUSED, uint32_t serial EINA_UNUSED, int32_t x, int32_t y)
+{
+ E_Client *ec;
+ double timestamp;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ timestamp = ecore_loop_time_get();
+ e_int_client_menu_show(ec, ec->x + x, ec->y + y, 0, timestamp);
+}
+
+static void
+_e_xdg_toplevel_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_Client *ec;
+ E_Binding_Event_Mouse_Button ev;
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) 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);
+}
+
+static void
+_e_xdg_toplevel_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_Client *ec;
+ E_Binding_Event_Mouse_Button ev;
+
+ /* DBG("XDG_SHELL: Surface Resize: %d\tEdges: %d", */
+ /* wl_resource_get_id(resource), edges); */
+
+ /* get the client for this resource */
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) 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);
+}
+
+static void
+_e_xdg_toplevel_cb_max_size_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t width, int32_t height)
+{
+ E_Client *ec;
+
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ ec->comp_data->shell.set.max_size.w = width;
+ ec->comp_data->shell.set.max_size.h = height;
+}
+
+static void
+_e_xdg_toplevel_cb_min_size_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t width, int32_t height)
+{
+ E_Client *ec;
+
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "No Client For Shell Surface");
+ return;
+ }
+ ec->comp_data->shell.set.min_size.w = width;
+ ec->comp_data->shell.set.min_size.h = height;
+}
+
+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_window_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,
+};
+
+static void
+_e_xdg_surface_cb_toplevel_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id)
+{
+ E_Client *ec;
+ E_Comp_Client_Data *cdata;
+
+ if (!(ec = wl_resource_get_user_data(resource)))
+ {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "resource does not have xdg_shell surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ cdata = ec->comp_data;
+ if (cdata->shell.surface)
+ {
+ wl_resource_post_error(resource,
+ ZXDG_SHELL_V6_ERROR_ROLE,
+ "surface already has assigned role");
+ return;
+ }
+
+ if (!(cdata->shell.surface =
+ wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id)))
+ {
+ ERR("Could not create xdg shell surface");
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ wl_resource_set_implementation(cdata->shell.surface,
+ &_e_xdg_toplevel_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.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;
+ ec->netwm.type = E_WINDOW_TYPE_NORMAL;
+ ec->comp_data->set_win_type = EINA_TRUE;
+
+ if (ec->internal_elm_win && evas_object_visible_get(ec->internal_elm_win))
+ _e_xdg_shell_surface_map(resource);
+}
+
+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_window_geometry_set,
+ _e_xdg_surface_cb_ack_configure,
+};
+
+static void
+_e_xdg_shell_surface_cb_destroy(struct wl_resource *resource)
+{
+ E_Shell_Data *shd;
+ E_Client *ec = wl_resource_get_user_data(resource);
+
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ shd = ec->comp_data->shell.data;
+ if (shd)
+ ((v6_Shell_Data*)shd->shell)->surfaces = eina_list_remove(((v6_Shell_Data*)shd->shell)->surfaces, resource);
+ e_shell_surface_cb_destroy(resource);
+}
+
+static void
+_e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
+{
+ E_Client *ec;
+ E_Comp_Client_Data *cdata;
+ E_Shell_Data *shd;
+ v6_Shell_Data *v;
+
+ /* DBG("XDG_SHELL: Surface Get %d", wl_resource_get_id(surface_resource)); */
+
+ /* 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 Pixmap Set On Surface");
+ return;
+ }
+ if (e_object_is_del(E_OBJECT(ec))) return;
+
+ ec->netwm.ping = 1;
+ cdata = ec->comp_data;
+
+ /* check for existing shell surface */
+ if (cdata->shell.data)
+ {
+ wl_resource_post_error(surface_resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Client already has XDG shell surface");
+ return;
+ }
+ shd = cdata->shell.data = E_NEW(E_Shell_Data, 1);
+ shd->width = shd->height = -1;
+
+ /* try to create a shell surface */
+ if (!(shd->surface =
+ wl_resource_create(client, &zxdg_surface_v6_interface, 1, id)))
+ {
+ ERR("Could not create xdg shell surface");
+ wl_resource_post_no_memory(surface_resource);
+ return;
+ }
+
+ wl_resource_set_implementation(shd->surface,
+ &_e_xdg_surface_interface, ec,
+ _e_xdg_shell_surface_cb_destroy);
+ v = wl_resource_get_user_data(resource);
+ v->surfaces = eina_list_append(v->surfaces, shd->surface);
+ shd->shell = v;
+
+ e_object_ref(E_OBJECT(ec));
+
+ cdata->shell.ping = _e_xdg_shell_surface_ping;
+ cdata->is_xdg_surface = EINA_TRUE;
+
+ if (!ec->internal)
+ e_client_ping(ec);
+}
+
+static void
+_e_xdg_shell_cb_pong(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial EINA_UNUSED)
+{
+ E_Client *ec;
+
+ if ((ec = wl_resource_get_user_data(resource)))
+ {
+ ec->ping_ok = EINA_TRUE;
+ ec->hung = EINA_FALSE;
+ }
+}
+
+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 void
+_e_xdg_shell_cb_unbind(struct wl_resource *resource)
+{
+ v6_Shell_Data *v;
+ struct wl_client *client = wl_resource_get_client(resource);
+
+ v = wl_resource_get_user_data(resource);
+ eina_hash_set(shell_resources, &client, NULL);
+ E_FREE_LIST(v->surfaces, e_shell_surface_cb_destroy);
+ v->positioners = eina_list_free(v->positioners);
+ free(v);
+}
+
+static void
+_e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
+{
+ struct wl_resource *res;
+ v6_Shell_Data *v;
+
+ if (!(res = wl_resource_create(client, &zxdg_shell_v6_interface, version, id)))
+ {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ eina_hash_set(xdg_shell_resources, &client, res);
+ v = E_NEW(v6_Shell_Data, 1);
+ wl_resource_set_user_data(res, v);
+ wl_resource_set_implementation(res, &_e_xdg_shell_interface,
+ v, _e_xdg_shell_cb_unbind);
+}
+
+EINTERN Eina_Bool
+e_xdg_shell_v6_init(void)
+{
+ /* try to create global xdg_shell interface */
+ if (!wl_global_create(e_comp_wl->wl.disp, &zxdg_shell_v6_interface, 1,
+ NULL, _e_xdg_shell_cb_bind))
+ {
+ ERR("Could not create xdg_shell global");
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
+}