diff options
author | Chris Michael <cp.michael@samsung.com> | 2013-03-08 12:46:53 +0000 |
---|---|---|
committer | Chris Michael <cp.michael@samsung.com> | 2013-03-21 07:21:45 +0000 |
commit | c3b96cdcfbe03461b98791fb021b4721c102517d (patch) | |
tree | 16f94ad2383d2f4661eff2992d2d3cc751e24c23 | |
parent | 6151c86e7969746efb8f93ace995812e8b6cb05b (diff) | |
download | enlightenment-c3b96cdcfbe03461b98791fb021b4721c102517d.tar.gz |
Add shell_surface interface.
Add code to handle shell_surface callbacks (pong, move, resize, etc).
Setup compositor ping callback when we create the shell.
Add function to map a shell_surface.
Add function to handle surface_ping event.
Add function for shell_surface_configure.
Add code to handle setting the shell_surface type (toplevel,
fullscreen, etc).
Add code for destroy of shell_surface.
Add code to handle setting title and class.
Signed-off-by: Chris Michael <cp.michael@samsung.com>
-rw-r--r-- | src/modules/wl_shell/e_mod_main.c | 490 |
1 files changed, 485 insertions, 5 deletions
diff --git a/src/modules/wl_shell/e_mod_main.c b/src/modules/wl_shell/e_mod_main.c index 5b13dec64e..6500713902 100644 --- a/src/modules/wl_shell/e_mod_main.c +++ b/src/modules/wl_shell/e_mod_main.c @@ -8,14 +8,35 @@ static void _e_wl_shell_cb_destroy(struct wl_listener *listener, void *data); static void _e_wl_shell_cb_bind(struct wl_client *client, void *data, unsigned int version EINA_UNUSED, unsigned int id); static void _e_wl_shell_cb_bind_desktop(struct wl_client *client, void *data, unsigned int version EINA_UNUSED, unsigned int id); static void _e_wl_shell_cb_unbind_desktop(struct wl_resource *resource); -static void _e_wl_shell_shell_surface_get(struct wl_client *client, struct wl_resource *resource, unsigned int id, struct wl_resource *surf_resource); -static E_Wayland_Shell_Surface *_e_wl_shell_shell_surface_create(void *shell, E_Wayland_Surface *ews, const void *client); +static void _e_wl_shell_surface_map(E_Wayland_Surface *ews, int x, int y, int w, int h); +static void _e_wl_shell_surface_ping(E_Wayland_Surface *ews, unsigned int serial); +static int _e_wl_shell_surface_ping_cb_timeout(void *data); + +static void _e_wl_shell_shell_surface_get(struct wl_client *client, struct wl_resource *resource, unsigned int id, struct wl_resource *surf_resource); +static void _e_wl_shell_shell_surface_configure(E_Wayland_Surface *ews, int x, int y, int w, int h); +static E_Wayland_Shell_Surface *_e_wl_shell_shell_surface_create(void *shell EINA_UNUSED, E_Wayland_Surface *ews, const void *client EINA_UNUSED); static void _e_wl_shell_shell_surface_toplevel_set(E_Wayland_Shell_Surface *ewss); static void _e_wl_shell_shell_surface_transient_set(E_Wayland_Shell_Surface *ewss, E_Wayland_Surface *ews, int x, int y, unsigned int flags); static void _e_wl_shell_shell_surface_fullscreen_set(E_Wayland_Shell_Surface *ewss, unsigned int method, unsigned int framerate, void *output); +static E_Wayland_Shell_Surface_Type _e_wl_shell_shell_surface_type_get(E_Wayland_Shell_Surface *ewss); +static void _e_wl_shell_shell_surface_type_set(E_Wayland_Shell_Surface *ewss); +static void _e_wl_shell_shell_surface_type_reset(E_Wayland_Shell_Surface *ewss); static int _e_wl_shell_shell_surface_move(E_Wayland_Shell_Surface *ewss, void *seat); static int _e_wl_shell_shell_surface_resize(E_Wayland_Shell_Surface *ewss, void *seat, unsigned int edges); +static void _e_wl_shell_shell_surface_destroy(struct wl_listener *listener, void *data EINA_UNUSED); + +static void _e_wl_shell_shell_surface_cb_destroy(struct wl_resource *resource); +static void _e_wl_shell_shell_surface_cb_pong(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, unsigned int serial); +static void _e_wl_shell_shell_surface_cb_move(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, unsigned int serial); +static void _e_wl_shell_shell_surface_cb_resize(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, unsigned int serial, unsigned int edges); +static void _e_wl_shell_shell_surface_cb_toplevel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource); +static void _e_wl_shell_shell_surface_cb_transient_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *parent_resource, int x, int y, unsigned int flags); +static void _e_wl_shell_shell_surface_cb_fullscreen_set(struct wl_client *client, struct wl_resource *resource, unsigned int method, unsigned int framerate, struct wl_resource *output_resource); +static void _e_wl_shell_shell_surface_cb_popup_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, unsigned int serial, struct wl_resource *parent_resource, int x, int y, unsigned int flags); +static void _e_wl_shell_shell_surface_cb_maximized_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *output_resource); +static void _e_wl_shell_shell_surface_cb_title_set(struct wl_client *client, struct wl_resource *resource, const char *title); +static void _e_wl_shell_shell_surface_cb_class_set(struct wl_client *client, struct wl_resource *resource, const char *clas); static void _e_wl_shell_desktop_background_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, struct wl_resource *output_resource EINA_UNUSED, struct wl_resource *surf_resource EINA_UNUSED); static void _e_wl_shell_desktop_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, struct wl_resource *output_resource EINA_UNUSED, struct wl_resource *surf_resource EINA_UNUSED); @@ -40,6 +61,20 @@ static const struct e_desktop_shell_interface _e_desktop_shell_interface = _e_wl_shell_desktop_grab_surface_set }; +static const struct wl_shell_surface_interface _e_wl_shell_surface_interface = +{ + _e_wl_shell_shell_surface_cb_pong, + _e_wl_shell_shell_surface_cb_move, + _e_wl_shell_shell_surface_cb_resize, + _e_wl_shell_shell_surface_cb_toplevel_set, + _e_wl_shell_shell_surface_cb_transient_set, + _e_wl_shell_shell_surface_cb_fullscreen_set, + _e_wl_shell_shell_surface_cb_popup_set, + _e_wl_shell_shell_surface_cb_maximized_set, + _e_wl_shell_shell_surface_cb_title_set, + _e_wl_shell_shell_surface_cb_class_set +}; + /* external variables */ EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Shell" }; @@ -59,7 +94,7 @@ e_modapi_init(E_Module *m) shell->wl.destroy_listener.notify = _e_wl_shell_cb_destroy; wl_signal_add(&_e_wl_comp->wl.signals.destroy, &shell->wl.destroy_listener); - /* TODO: set compositor ping handler */ + _e_wl_comp->ping_cb = _e_wl_shell_surface_ping; _e_wl_comp->wl.shell_interface.shell = shell; _e_wl_comp->wl.shell_interface.shell_surface_create = @@ -97,6 +132,9 @@ e_modapi_shutdown(E_Module *m EINA_UNUSED) { SLOGFN(__FILE__, __LINE__, __FUNCTION__); + /* nothing to do here as shell will get the destroy callback from + * the compositor and we can cleanup there */ + return 1; } @@ -106,6 +144,8 @@ _e_wl_shell_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED) { E_Wayland_Desktop_Shell *shell = NULL; + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + shell = container_of(listener, E_Wayland_Desktop_Shell, wl.destroy_listener); @@ -151,29 +191,256 @@ _e_wl_shell_cb_unbind_desktop(struct wl_resource *resource) } static void +_e_wl_shell_surface_map(E_Wayland_Surface *ews, int x, int y, int w, int h) +{ + /* E_Wayland_Shell_Surface *ewss = NULL; */ + E_Wayland_Shell_Surface_Type type = E_WAYLAND_SHELL_SURFACE_NONE; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ews) return; + + ews->geometry.w = w; + ews->geometry.h = h; + ews->geometry.changed = EINA_TRUE; + + if (ews->img) evas_object_resize(ews->img, w, h); + + type = _e_wl_shell_shell_surface_type_get(ews->shell_surface); + switch (type) + { + /* TODO */ + case E_WAYLAND_SHELL_SURFACE_FULLSCREEN: + break; + case E_WAYLAND_SHELL_SURFACE_MAXIMIZED: + break; + case E_WAYLAND_SHELL_SURFACE_POPUP: + break; + case E_WAYLAND_SHELL_SURFACE_TOPLEVEL: + case E_WAYLAND_SHELL_SURFACE_NONE: + ews->geometry.x = x; + ews->geometry.y = y; + if (ews->win) + e_win_move_resize(ews->win, ews->geometry.x, ews->geometry.y, + ews->geometry.w, ews->geometry.h); + break; + default: + break; + } + + /* stacking order */ + switch (type) + { + case E_WAYLAND_SHELL_SURFACE_POPUP: + case E_WAYLAND_SHELL_SURFACE_TRANSIENT: + break; + default: + break; + } + + /* activate */ + switch (type) + { + /* TODO */ + case E_WAYLAND_SHELL_SURFACE_TRANSIENT: + break; + case E_WAYLAND_SHELL_SURFACE_TOPLEVEL: + case E_WAYLAND_SHELL_SURFACE_MAXIMIZED: + case E_WAYLAND_SHELL_SURFACE_FULLSCREEN: + /* TODO: activate. Hmmm, this basically emits an activate signal to + * the compositor (passing the surface). Since we do not really use + * an activate signal, we'll need another method here */ + if (ews->win) e_win_show(ews->win); + + /* restack */ + break; + default: + break; + } +} + +static void +_e_wl_shell_surface_ping(E_Wayland_Surface *ews, unsigned int serial) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ews) return; + if (!(ewss = ews->shell_surface)) return; + + if (!ewss->ping_timer) + { + E_Wayland_Ping_Timer *timer = NULL; + struct wl_event_loop *loop; + + if (!(timer = E_NEW(E_Wayland_Ping_Timer, 1))) + return; + + timer->serial = serial; + + loop = wl_display_get_event_loop(_e_wl_comp->wl.display); + + timer->source = + wl_event_loop_add_timer(loop, + _e_wl_shell_surface_ping_cb_timeout, ewss); + + /* FIXME: Make this timeout configurable ?? */ + wl_event_source_timer_update(timer->source, 200); + + ewss->ping_timer = timer; + + wl_shell_surface_send_ping(&ewss->wl.resource, serial); + } +} + +static int +_e_wl_shell_surface_ping_cb_timeout(void *data) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = data)) return 1; + + ewss->responsive = EINA_FALSE; + + /* TODO: Set busy cursor ?? */ + + return 1; +} + +static void _e_wl_shell_shell_surface_get(struct wl_client *client, struct wl_resource *resource, unsigned int id, struct wl_resource *surf_resource) { + E_Wayland_Surface *ews = NULL; + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ews = surf_resource->data)) return; + + /* does this surface already have a shell_surface ?? */ + if ((ews->configure) && + (ews->configure == _e_wl_shell_shell_surface_configure)) + { + wl_resource_post_error(surf_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "Shell Surface already requested for Surface"); + return; + } + + if (!(ewss = _e_wl_shell_shell_surface_create(NULL, ews, NULL))) + { + wl_resource_post_no_memory(resource); + return; + } + + ewss->wl.resource.destroy = _e_wl_shell_shell_surface_cb_destroy; + ewss->wl.resource.object.id = id; + ewss->wl.resource.object.interface = &wl_shell_surface_interface; + ewss->wl.resource.object.implementation = + (void (**)(void))&_e_wl_shell_surface_interface; + ewss->wl.resource.data = ewss; + + wl_client_add_resource(client, &ewss->wl.resource); +} + +static void +_e_wl_shell_shell_surface_configure(E_Wayland_Surface *ews, int x, int y, int w, int h) +{ + E_Wayland_Shell_Surface *ewss = NULL; + Eina_Bool changed_type = EINA_FALSE; + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((ews->configure == _e_wl_shell_shell_surface_configure)) + { + if (!(ewss = ews->shell_surface)) return; + } + else + return; + + if ((ewss->ntype != E_WAYLAND_SHELL_SURFACE_NONE) && + (ewss->type != ewss->ntype)) + { + _e_wl_shell_shell_surface_type_set(ewss); + changed_type = EINA_TRUE; + } + + if (!ews->mapped) + _e_wl_shell_surface_map(ews, x, y, w, h); + else if ((changed_type) || (x != 0) || (y != 0) || + (ews->geometry.w != w) || (ews->geometry.h != h)) + { + ews->geometry.x = x; + ews->geometry.y = y; + ews->geometry.w = w; + ews->geometry.h = h; + ews->geometry.changed = EINA_TRUE; + + /* TODO: finish me configure */ + + switch (ewss->type) + { + case E_WAYLAND_SHELL_SURFACE_FULLSCREEN: + /* TODO: stack fullscreen, configure fullscreen */ + break; + case E_WAYLAND_SHELL_SURFACE_MAXIMIZED: + break; + default: + break; + } + } } static E_Wayland_Shell_Surface * -_e_wl_shell_shell_surface_create(void *shell, E_Wayland_Surface *ews, const void *client) +_e_wl_shell_shell_surface_create(void *shell EINA_UNUSED, E_Wayland_Surface *ews, const void *client EINA_UNUSED) { + E_Wayland_Shell_Surface *ewss = NULL; + SLOGFN(__FILE__, __LINE__, __FUNCTION__); - return NULL; + if (!(ewss = E_NEW(E_Wayland_Shell_Surface, 1))) + return NULL; + + ews->configure = _e_wl_shell_shell_surface_configure; + ewss->surface = ews; + ews->shell_surface = ewss; + + wl_signal_init(&ewss->wl.resource.destroy_signal); + ewss->wl.surface_destroy.notify = _e_wl_shell_shell_surface_destroy; + wl_signal_add(&ews->wl.surface.resource.destroy_signal, + &ewss->wl.surface_destroy); + + wl_list_init(&ewss->wl.link); + + ewss->responsive = EINA_TRUE; + + ewss->type = E_WAYLAND_SHELL_SURFACE_NONE; + ewss->ntype = E_WAYLAND_SHELL_SURFACE_NONE; + + return ewss; } static void _e_wl_shell_shell_surface_toplevel_set(E_Wayland_Shell_Surface *ewss) { SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ewss) return; + ewss->ntype = E_WAYLAND_SHELL_SURFACE_TOPLEVEL; } static void _e_wl_shell_shell_surface_transient_set(E_Wayland_Shell_Surface *ewss, E_Wayland_Surface *ews, int x, int y, unsigned int flags) { SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ewss) return; + ewss->ntype = E_WAYLAND_SHELL_SURFACE_TRANSIENT; + + /* TODO */ } static void @@ -182,6 +449,65 @@ _e_wl_shell_shell_surface_fullscreen_set(E_Wayland_Shell_Surface *ewss, unsigned SLOGFN(__FILE__, __LINE__, __FUNCTION__); } +static E_Wayland_Shell_Surface_Type +_e_wl_shell_shell_surface_type_get(E_Wayland_Shell_Surface *ewss) +{ + if (!ewss) return E_WAYLAND_SHELL_SURFACE_NONE; + return ewss->type; +} + +static void +_e_wl_shell_shell_surface_type_set(E_Wayland_Shell_Surface *ewss) +{ + E_Wayland_Surface *ews = NULL; + E_Wayland_Surface *pews = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ewss) return; + if (!(ews = ewss->surface)) return; + + _e_wl_shell_shell_surface_type_reset(ewss); + + ewss->type = ewss->ntype; + ewss->ntype = E_WAYLAND_SHELL_SURFACE_NONE; + + switch (ewss->type) + { + case E_WAYLAND_SHELL_SURFACE_TOPLEVEL: + break; + case E_WAYLAND_SHELL_SURFACE_TRANSIENT: + if ((pews = ewss->parent)) + { + + } + break; + default: + /* TODO: handle other surface type cases */ + break; + } +} + +static void +_e_wl_shell_shell_surface_type_reset(E_Wayland_Shell_Surface *ewss) +{ + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ewss) return; + switch (ewss->type) + { + /* TODO */ + case E_WAYLAND_SHELL_SURFACE_FULLSCREEN: + break; + case E_WAYLAND_SHELL_SURFACE_MAXIMIZED: + break; + default: + break; + } + + ewss->type = E_WAYLAND_SHELL_SURFACE_NONE; +} + static int _e_wl_shell_shell_surface_move(E_Wayland_Shell_Surface *ewss, void *seat) { @@ -197,6 +523,160 @@ _e_wl_shell_shell_surface_resize(E_Wayland_Shell_Surface *ewss, void *seat, unsi } static void +_e_wl_shell_shell_surface_destroy(struct wl_listener *listener, void *data EINA_UNUSED) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + ewss = container_of(listener, E_Wayland_Shell_Surface, wl.surface_destroy); + if (!ewss) return; + + if (ewss->wl.resource.client) + wl_resource_destroy(&ewss->wl.resource); + else + wl_signal_emit(&ewss->wl.resource.destroy_signal, &ewss->wl.resource); +} + +static void +_e_wl_shell_shell_surface_cb_destroy(struct wl_resource *resource) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = resource->data)) return; + + wl_list_remove(&ewss->wl.surface_destroy.link); + ewss->surface->configure = NULL; + + if (ewss->ping_timer) + { + E_Wayland_Ping_Timer *timer = NULL; + + timer = (E_Wayland_Ping_Timer *)ewss->ping_timer; + + if (timer->source) wl_event_source_remove(timer->source); + + E_FREE(timer); + ewss->ping_timer = NULL; + } + + wl_list_remove(&ewss->wl.link); + + free(ewss); +} + +static void +_e_wl_shell_shell_surface_cb_pong(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, unsigned int serial) +{ + E_Wayland_Shell_Surface *ewss = NULL; + E_Wayland_Ping_Timer *timer = NULL; + Eina_Bool responsive = EINA_FALSE; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = resource->data)) return; + + if (!(timer = (E_Wayland_Ping_Timer *)ewss->ping_timer)) + return; + + if (timer->serial == serial) + { + responsive = ewss->responsive; + ewss->responsive = EINA_TRUE; + + if (!responsive) + { + /* TODO: end busy cursor */ + } + + if (timer->source) wl_event_source_remove(timer->source); + + E_FREE(timer); + ewss->ping_timer = NULL; + } +} + +static void +_e_wl_shell_shell_surface_cb_move(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, unsigned int serial) +{ + SLOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_e_wl_shell_shell_surface_cb_resize(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, unsigned int serial, unsigned int edges) +{ + SLOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_e_wl_shell_shell_surface_cb_toplevel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = resource->data)) return; + _e_wl_shell_shell_surface_toplevel_set(ewss); +} + +static void +_e_wl_shell_shell_surface_cb_transient_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *parent_resource, int x, int y, unsigned int flags) +{ + E_Wayland_Shell_Surface *ewss = NULL; + E_Wayland_Surface *ews = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = resource->data)) return; + if (!(ews = parent_resource->data)) return; + _e_wl_shell_shell_surface_transient_set(ewss, ews, x, y, flags); +} + +static void +_e_wl_shell_shell_surface_cb_fullscreen_set(struct wl_client *client, struct wl_resource *resource, unsigned int method, unsigned int framerate, struct wl_resource *output_resource) +{ + SLOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_e_wl_shell_shell_surface_cb_popup_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, unsigned int serial, struct wl_resource *parent_resource, int x, int y, unsigned int flags) +{ + SLOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_e_wl_shell_shell_surface_cb_maximized_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *output_resource) +{ + SLOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +static void +_e_wl_shell_shell_surface_cb_title_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *title) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = resource->data)) return; + free(ewss->title); + ewss->title = strdup(title); +} + +static void +_e_wl_shell_shell_surface_cb_class_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *clas) +{ + E_Wayland_Shell_Surface *ewss = NULL; + + SLOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(ewss = resource->data)) return; + free(ewss->clas); + ewss->clas = strdup(clas); +} + +static void _e_wl_shell_desktop_background_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, struct wl_resource *output_resource EINA_UNUSED, struct wl_resource *surf_resource EINA_UNUSED) { SLOGFN(__FILE__, __LINE__, __FUNCTION__); |