2 #include "e_mod_main.h"
3 #ifdef HAVE_WAYLAND_CLIENTS
4 # include "e_mod_comp_wl.h"
5 # include "e_mod_comp_wl_comp.h"
6 # include "e_mod_comp_wl_output.h"
7 # include "e_mod_comp_wl_input.h"
8 # include "e_mod_comp_wl_shell.h"
9 # include "e_mod_comp_wl_surface.h"
12 /* local function prototypes */
13 static void _e_mod_comp_wl_shell_bind(struct wl_client *client, void *data, uint32_t version __UNUSED__, uint32_t id);
14 static void _e_mod_comp_wl_shell_lock(Wayland_Shell *base);
15 static void _e_mod_comp_wl_shell_unlock(Wayland_Shell *base);
16 static void _e_mod_comp_wl_shell_map(Wayland_Shell *base, Wayland_Surface *surface, int32_t width, int32_t height);
17 static void _e_mod_comp_wl_shell_configure(Wayland_Shell *base, Wayland_Surface *surface, int32_t x, int32_t y, int32_t width, int32_t height);
18 static void _e_mod_comp_wl_shell_destroy(Wayland_Shell *base);
19 static void _e_mod_comp_wl_shell_activate(Wayland_Shell *base, Wayland_Surface *surface, uint32_t timestamp);
21 static void _e_mod_comp_wl_shell_shell_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource);
22 static void _e_mod_comp_wl_shell_surface_move(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *input_resource, uint32_t timestamp);
23 static void _e_mod_comp_wl_shell_surface_resize(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *input_resource, uint32_t timestamp, uint32_t edges);
24 static void _e_mod_comp_wl_shell_surface_set_toplevel(struct wl_client *client __UNUSED__, struct wl_resource *resource);
25 static void _e_mod_comp_wl_shell_surface_set_transient(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *parent_resource, int32_t x, int32_t y, uint32_t flags __UNUSED__);
26 static void _e_mod_comp_wl_shell_surface_set_fullscreen(struct wl_client *client __UNUSED__, struct wl_resource *resource, uint32_t method __UNUSED__, uint32_t framerate __UNUSED__, struct wl_resource *output_resource __UNUSED__);
27 static void _e_mod_comp_wl_shell_surface_set_popup(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *input_resource __UNUSED__, uint32_t timestamp __UNUSED__, struct wl_resource *parent_resource, int32_t x, int32_t y, uint32_t flags __UNUSED__);
28 static void _e_mod_comp_wl_shell_surface_set_maximized(struct wl_client *client, struct wl_resource *resource, struct wl_resource *output_resource __UNUSED__);
30 static void _e_mod_comp_wl_shell_surface_destroy_handle(struct wl_listener *listener, struct wl_resource *resource __UNUSED__, uint32_t timestamp);
31 static Wayland_Shell_Surface *_e_mod_comp_wl_shell_get_shell_surface(Wayland_Surface *ws);
32 static void _e_mod_comp_wl_shell_surface_destroy(struct wl_resource *resource);
34 /* wayland interfaces */
35 static const struct wl_shell_interface _wl_shell_interface =
37 _e_mod_comp_wl_shell_shell_surface_get
39 static const struct wl_shell_surface_interface _wl_shell_surface_interface =
41 _e_mod_comp_wl_shell_surface_move,
42 _e_mod_comp_wl_shell_surface_resize,
43 _e_mod_comp_wl_shell_surface_set_toplevel,
44 _e_mod_comp_wl_shell_surface_set_transient,
45 _e_mod_comp_wl_shell_surface_set_fullscreen,
46 _e_mod_comp_wl_shell_surface_set_popup,
47 _e_mod_comp_wl_shell_surface_set_maximized
50 /* private variables */
51 struct wl_shell *_wl_shell;
54 e_mod_comp_wl_shell_init(void)
56 LOGFN(__FILE__, __LINE__, __FUNCTION__);
58 if (!(_wl_shell = malloc(sizeof(*_wl_shell))))
60 EINA_LOG_ERR("Could not allocate space for shell\n");
64 memset(_wl_shell, 0, sizeof(*_wl_shell));
66 _wl_shell->shell.lock = _e_mod_comp_wl_shell_lock;
67 _wl_shell->shell.unlock = _e_mod_comp_wl_shell_unlock;
68 _wl_shell->shell.map = _e_mod_comp_wl_shell_map;
69 _wl_shell->shell.configure = _e_mod_comp_wl_shell_configure;
70 _wl_shell->shell.destroy = _e_mod_comp_wl_shell_destroy;
72 if (!wl_display_add_global(_wl_disp, &wl_shell_interface, _wl_shell,
73 _e_mod_comp_wl_shell_bind))
75 EINA_LOG_ERR("Could not create shell\n");
84 e_mod_comp_wl_shell_shutdown(void)
86 LOGFN(__FILE__, __LINE__, __FUNCTION__);
89 _wl_shell->shell.destroy(&_wl_shell->shell);
93 e_mod_comp_wl_shell_get(void)
100 _e_mod_comp_wl_shell_bind(struct wl_client *client, void *data, uint32_t version __UNUSED__, uint32_t id)
102 struct wl_shell *shell;
104 LOGFN(__FILE__, __LINE__, __FUNCTION__);
107 wl_client_add_object(client, &wl_shell_interface, &_wl_shell_interface,
112 _e_mod_comp_wl_shell_lock(Wayland_Shell *base)
114 struct wl_shell *shell;
116 LOGFN(__FILE__, __LINE__, __FUNCTION__);
118 shell = container_of(base, struct wl_shell, shell);
122 _e_mod_comp_wl_shell_unlock(Wayland_Shell *base)
124 struct wl_shell *shell;
126 LOGFN(__FILE__, __LINE__, __FUNCTION__);
128 shell = container_of(base, struct wl_shell, shell);
132 _e_mod_comp_wl_shell_map(Wayland_Shell *base, Wayland_Surface *surface, int32_t width, int32_t height)
134 Wayland_Compositor *comp;
135 Wayland_Shell_Surface *wss;
136 struct wl_shell *shell;
137 struct wl_list *list;
139 Eina_Bool do_configure = EINA_FALSE;
141 LOGFN(__FILE__, __LINE__, __FUNCTION__);
143 comp = e_mod_comp_wl_comp_get();
144 type = SHELL_SURFACE_NONE;
145 shell = container_of(base, struct wl_shell, shell);
147 if ((wss = _e_mod_comp_wl_shell_get_shell_surface(surface)))
152 list = &shell->hidden_surfaces;
153 do_configure = EINA_FALSE;
157 list = &comp->surfaces;
158 do_configure = EINA_TRUE;
166 case SHELL_SURFACE_TOPLEVEL:
167 surface->x = 10 + random() % 400;
168 surface->y = 10 + random() % 400;
171 wl_list_insert(list, &surface->link);
176 e_mod_comp_wl_surface_configure(surface, surface->x, surface->y,
177 surface->w, surface->h);
181 case SHELL_SURFACE_TOPLEVEL:
182 case SHELL_SURFACE_TRANSIENT:
183 case SHELL_SURFACE_FULLSCREEN:
185 _e_mod_comp_wl_shell_activate(base, surface, e_mod_comp_wl_time_get());
191 _e_mod_comp_wl_shell_configure(Wayland_Shell *base, Wayland_Surface *surface, int32_t x, int32_t y, int32_t width, int32_t height)
193 struct wl_shell *shell;
194 Wayland_Shell_Surface *wss;
195 Wayland_Shell_Surface_Type type;
196 Eina_Bool do_configure = EINA_FALSE;
198 LOGFN(__FILE__, __LINE__, __FUNCTION__);
200 type = SHELL_SURFACE_NONE;
201 shell = container_of(base, struct wl_shell, shell);
202 do_configure = !shell->locked;
203 if ((wss = _e_mod_comp_wl_shell_get_shell_surface(surface)))
211 case SHELL_SURFACE_SCREENSAVER:
212 do_configure = !do_configure;
213 case SHELL_SURFACE_FULLSCREEN:
220 e_mod_comp_wl_surface_configure(surface, x, y, width, height);
224 _e_mod_comp_wl_shell_destroy(Wayland_Shell *base)
226 struct wl_shell *shell;
228 LOGFN(__FILE__, __LINE__, __FUNCTION__);
230 shell = container_of(base, struct wl_shell, shell);
231 if (shell->child.client) wl_client_destroy(shell->child.client);
236 _e_mod_comp_wl_shell_activate(Wayland_Shell *base, Wayland_Surface *surface, uint32_t timestamp)
238 struct wl_shell *shell;
240 LOGFN(__FILE__, __LINE__, __FUNCTION__);
242 shell = container_of(base, struct wl_shell, shell);
243 e_mod_comp_wl_surface_activate(surface, e_mod_comp_wl_input_get(), timestamp);
247 _e_mod_comp_wl_shell_shell_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
250 Wayland_Shell_Surface *wss;
252 LOGFN(__FILE__, __LINE__, __FUNCTION__);
254 ws = surface_resource->data;
255 if (_e_mod_comp_wl_shell_get_shell_surface(ws))
257 wl_resource_post_error(surface_resource,
258 WL_DISPLAY_ERROR_INVALID_OBJECT,
259 "get_shell_surface already requested");
263 if (!(wss = calloc(1, sizeof(*wss))))
265 wl_resource_post_no_memory(resource);
269 wss->resource.destroy = _e_mod_comp_wl_shell_surface_destroy;
270 wss->resource.object.id = id;
271 wss->resource.object.interface = &wl_shell_surface_interface;
272 wss->resource.object.implementation =
273 (void (**)(void)) &_wl_shell_surface_interface;
274 wss->resource.data = wss;
277 wss->surface_destroy_listener.func =
278 _e_mod_comp_wl_shell_surface_destroy_handle;
279 wl_list_insert(ws->surface.resource.destroy_listener_list.prev,
280 &wss->surface_destroy_listener.link);
282 wl_list_init(&wss->link);
284 wss->type = SHELL_SURFACE_NONE;
285 wl_client_add_resource(client, &wss->resource);
289 _e_mod_comp_wl_shell_surface_move(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *input_resource, uint32_t timestamp)
291 LOGFN(__FILE__, __LINE__, __FUNCTION__);
296 _e_mod_comp_wl_shell_surface_resize(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *input_resource, uint32_t timestamp, uint32_t edges)
298 LOGFN(__FILE__, __LINE__, __FUNCTION__);
303 _e_mod_comp_wl_shell_surface_set_toplevel(struct wl_client *client __UNUSED__, struct wl_resource *resource)
305 Wayland_Shell_Surface *wss;
307 LOGFN(__FILE__, __LINE__, __FUNCTION__);
309 wss = resource->data;
311 /* TODO: Surface type reset */
313 e_mod_comp_wl_surface_damage_surface(wss->surface);
314 wss->type = SHELL_SURFACE_TOPLEVEL;
318 _e_mod_comp_wl_shell_surface_set_transient(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *parent_resource, int32_t x, int32_t y, uint32_t flags __UNUSED__)
320 Wayland_Shell_Surface *wss, *pss;
321 Wayland_Surface *ws, *pws;
323 LOGFN(__FILE__, __LINE__, __FUNCTION__);
325 wss = resource->data;
326 pss = parent_resource->data;
330 /* TODO: Surface type reset */
335 e_mod_comp_wl_surface_damage_surface(ws);
337 wss->type = SHELL_SURFACE_TRANSIENT;
341 _e_mod_comp_wl_shell_surface_set_fullscreen(struct wl_client *client __UNUSED__, struct wl_resource *resource, uint32_t method __UNUSED__, uint32_t framerate __UNUSED__, struct wl_resource *output_resource __UNUSED__)
343 Wayland_Shell_Surface *wss;
345 Wayland_Output *output;
347 LOGFN(__FILE__, __LINE__, __FUNCTION__);
349 wss = resource->data;
351 output = e_mod_comp_wl_output_get();
353 wss->saved_x = ws->x;
354 wss->saved_y = ws->y;
355 ws->x = (output->w - ws->w) / 2;
356 ws->y = (output->h - ws->h) / 2;
357 e_mod_comp_wl_surface_damage_surface(ws);
358 wss->type = SHELL_SURFACE_FULLSCREEN;
362 _e_mod_comp_wl_shell_surface_set_popup(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *input_resource __UNUSED__, uint32_t timestamp __UNUSED__, struct wl_resource *parent_resource, int32_t x, int32_t y, uint32_t flags __UNUSED__)
364 Wayland_Shell_Surface *wss;
367 LOGFN(__FILE__, __LINE__, __FUNCTION__);
369 wss = resource->data;
371 e_mod_comp_wl_surface_damage_surface(ws);
372 wss->type = SHELL_SURFACE_POPUP;
373 wss->parent = parent_resource->data;
379 _e_mod_comp_wl_shell_surface_set_maximized(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *output_resource __UNUSED__)
381 Wayland_Shell_Surface *wss;
384 LOGFN(__FILE__, __LINE__, __FUNCTION__);
386 wss = resource->data;
388 /* FIXME: Implement */
392 _e_mod_comp_wl_shell_surface_destroy_handle(struct wl_listener *listener, struct wl_resource *resource __UNUSED__, uint32_t timestamp)
394 Wayland_Shell_Surface *wss;
396 LOGFN(__FILE__, __LINE__, __FUNCTION__);
398 wss = container_of(listener, Wayland_Shell_Surface, surface_destroy_listener);
400 wl_resource_destroy(&wss->resource, timestamp);
403 static Wayland_Shell_Surface *
404 _e_mod_comp_wl_shell_get_shell_surface(Wayland_Surface *ws)
406 struct wl_list *list;
407 struct wl_listener *listener;
409 LOGFN(__FILE__, __LINE__, __FUNCTION__);
411 list = &ws->surface.resource.destroy_listener_list;
412 wl_list_for_each(listener, list, link)
414 if (listener->func == _e_mod_comp_wl_shell_surface_destroy_handle)
415 return container_of(listener, Wayland_Shell_Surface,
416 surface_destroy_listener);
422 _e_mod_comp_wl_shell_surface_destroy(struct wl_resource *resource)
424 Wayland_Shell_Surface *wss;
426 LOGFN(__FILE__, __LINE__, __FUNCTION__);
428 wss = resource->data;
430 /* TODO: popup grab input */
432 if (wss->surface) wl_list_remove(&wss->surface_destroy_listener.link);
433 wl_list_remove(&wss->link);