upload tizen1.0 source
[framework/uifw/e17.git] / src / modules / comp / e_mod_comp_wl_shell.c
1 #include "e.h"
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"
10 #endif
11
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);
20
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__);
29
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);
33
34 /* wayland interfaces */
35 static const struct wl_shell_interface _wl_shell_interface = 
36 {
37    _e_mod_comp_wl_shell_shell_surface_get
38 };
39 static const struct wl_shell_surface_interface _wl_shell_surface_interface = 
40 {
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
48 };
49
50 /* private variables */
51 struct wl_shell *_wl_shell;
52
53 Eina_Bool 
54 e_mod_comp_wl_shell_init(void)
55 {
56    LOGFN(__FILE__, __LINE__, __FUNCTION__);
57
58    if (!(_wl_shell = malloc(sizeof(*_wl_shell))))
59      {
60         EINA_LOG_ERR("Could not allocate space for shell\n");
61         return EINA_FALSE;
62      }
63
64    memset(_wl_shell, 0, sizeof(*_wl_shell));
65
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;
71
72    if (!wl_display_add_global(_wl_disp, &wl_shell_interface, _wl_shell, 
73                              _e_mod_comp_wl_shell_bind))
74      {
75         EINA_LOG_ERR("Could not create shell\n");
76         free(_wl_shell);
77         return EINA_FALSE;
78      }
79
80    return EINA_TRUE;
81 }
82
83 void 
84 e_mod_comp_wl_shell_shutdown(void)
85 {
86    LOGFN(__FILE__, __LINE__, __FUNCTION__);
87
88    if (_wl_shell)
89      _wl_shell->shell.destroy(&_wl_shell->shell);
90 }
91
92 struct wl_shell *
93 e_mod_comp_wl_shell_get(void)
94 {
95    return _wl_shell;
96 }
97
98 /* local functions */
99 static void 
100 _e_mod_comp_wl_shell_bind(struct wl_client *client, void *data, uint32_t version __UNUSED__, uint32_t id)
101 {
102    struct wl_shell *shell;
103
104    LOGFN(__FILE__, __LINE__, __FUNCTION__);
105
106    shell = data;
107    wl_client_add_object(client, &wl_shell_interface, &_wl_shell_interface, 
108                         id, shell);
109 }
110
111 static void 
112 _e_mod_comp_wl_shell_lock(Wayland_Shell *base)
113 {
114    struct wl_shell *shell;
115
116    LOGFN(__FILE__, __LINE__, __FUNCTION__);
117
118    shell = container_of(base, struct wl_shell, shell);
119 }
120
121 static void 
122 _e_mod_comp_wl_shell_unlock(Wayland_Shell *base)
123 {
124    struct wl_shell *shell;
125
126    LOGFN(__FILE__, __LINE__, __FUNCTION__);
127
128    shell = container_of(base, struct wl_shell, shell);
129 }
130
131 static void 
132 _e_mod_comp_wl_shell_map(Wayland_Shell *base, Wayland_Surface *surface, int32_t width, int32_t height)
133 {
134    Wayland_Compositor *comp;
135    Wayland_Shell_Surface *wss;
136    struct wl_shell *shell;
137    struct wl_list *list;
138    uint32_t type;
139    Eina_Bool do_configure = EINA_FALSE;
140
141    LOGFN(__FILE__, __LINE__, __FUNCTION__);
142
143    comp = e_mod_comp_wl_comp_get();
144    type = SHELL_SURFACE_NONE;
145    shell = container_of(base, struct wl_shell, shell);
146
147    if ((wss = _e_mod_comp_wl_shell_get_shell_surface(surface)))
148      type = wss->type;
149
150    if (shell->locked)
151      {
152         list = &shell->hidden_surfaces;
153         do_configure = EINA_FALSE;
154      }
155    else
156      {
157         list = &comp->surfaces;
158         do_configure = EINA_TRUE;
159      }
160
161    surface->w = width;
162    surface->h = height;
163
164    switch (type)
165      {
166       case SHELL_SURFACE_TOPLEVEL:
167         surface->x = 10 + random() % 400;
168         surface->y = 10 + random() % 400;
169         break;
170       default:
171         wl_list_insert(list, &surface->link);
172         break;
173      }
174
175    if (do_configure)
176      e_mod_comp_wl_surface_configure(surface, surface->x, surface->y, 
177                                      surface->w, surface->h);
178
179    switch (type)
180      {
181       case SHELL_SURFACE_TOPLEVEL:
182       case SHELL_SURFACE_TRANSIENT:
183       case SHELL_SURFACE_FULLSCREEN:
184         if (!shell->locked)
185           _e_mod_comp_wl_shell_activate(base, surface, e_mod_comp_wl_time_get());
186         break;
187      }
188 }
189
190 static void 
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)
192 {
193    struct wl_shell *shell;
194    Wayland_Shell_Surface *wss;
195    Wayland_Shell_Surface_Type type;
196    Eina_Bool do_configure = EINA_FALSE;
197
198    LOGFN(__FILE__, __LINE__, __FUNCTION__);
199
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)))
204      type = wss->type;
205
206    surface->w = width;
207    surface->h = height;
208
209    switch (type)
210      {
211       case SHELL_SURFACE_SCREENSAVER:
212         do_configure = !do_configure;
213       case SHELL_SURFACE_FULLSCREEN:
214         break;
215       default:
216         break;
217      }
218
219    if (do_configure)
220      e_mod_comp_wl_surface_configure(surface, x, y, width, height);
221 }
222
223 static void 
224 _e_mod_comp_wl_shell_destroy(Wayland_Shell *base)
225 {
226    struct wl_shell *shell;
227
228    LOGFN(__FILE__, __LINE__, __FUNCTION__);
229
230    shell = container_of(base, struct wl_shell, shell);
231    if (shell->child.client) wl_client_destroy(shell->child.client);
232    free(shell);
233 }
234
235 static void 
236 _e_mod_comp_wl_shell_activate(Wayland_Shell *base, Wayland_Surface *surface, uint32_t timestamp)
237 {
238    struct wl_shell *shell;
239
240    LOGFN(__FILE__, __LINE__, __FUNCTION__);
241
242    shell = container_of(base, struct wl_shell, shell);
243    e_mod_comp_wl_surface_activate(surface, e_mod_comp_wl_input_get(), timestamp);
244 }
245
246 static void 
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)
248 {
249    Wayland_Surface *ws;
250    Wayland_Shell_Surface *wss;
251
252    LOGFN(__FILE__, __LINE__, __FUNCTION__);
253
254    ws = surface_resource->data;
255    if (_e_mod_comp_wl_shell_get_shell_surface(ws))
256      {
257         wl_resource_post_error(surface_resource, 
258                                WL_DISPLAY_ERROR_INVALID_OBJECT, 
259                                "get_shell_surface already requested");
260         return;
261      }
262
263    if (!(wss = calloc(1, sizeof(*wss))))
264      {
265         wl_resource_post_no_memory(resource);
266         return;
267      }
268
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;
275
276    wss->surface = ws;
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);
281
282    wl_list_init(&wss->link);
283
284    wss->type = SHELL_SURFACE_NONE;
285    wl_client_add_resource(client, &wss->resource);
286 }
287
288 static void 
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)
290 {
291    LOGFN(__FILE__, __LINE__, __FUNCTION__);
292
293 }
294
295 static void 
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)
297 {
298    LOGFN(__FILE__, __LINE__, __FUNCTION__);
299
300 }
301
302 static void 
303 _e_mod_comp_wl_shell_surface_set_toplevel(struct wl_client *client __UNUSED__, struct wl_resource *resource)
304 {
305    Wayland_Shell_Surface *wss;
306
307    LOGFN(__FILE__, __LINE__, __FUNCTION__);
308
309    wss = resource->data;
310
311    /* TODO: Surface type reset */
312
313    e_mod_comp_wl_surface_damage_surface(wss->surface);
314    wss->type = SHELL_SURFACE_TOPLEVEL;
315 }
316
317 static void 
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__)
319 {
320    Wayland_Shell_Surface *wss, *pss;
321    Wayland_Surface *ws, *pws;
322
323    LOGFN(__FILE__, __LINE__, __FUNCTION__);
324
325    wss = resource->data;
326    pss = parent_resource->data;
327    ws = wss->surface;
328    pws = pss->surface;
329
330    /* TODO: Surface type reset */
331
332    ws->x = pws->x + x;
333    ws->y = pws->y + y;
334
335    e_mod_comp_wl_surface_damage_surface(ws);
336
337    wss->type = SHELL_SURFACE_TRANSIENT;
338 }
339
340 static void 
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__)
342 {
343    Wayland_Shell_Surface *wss;
344    Wayland_Surface *ws;
345    Wayland_Output *output;
346
347    LOGFN(__FILE__, __LINE__, __FUNCTION__);
348
349    wss = resource->data;
350    ws = wss->surface;
351    output = e_mod_comp_wl_output_get();
352
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;
359 }
360
361 static void 
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__)
363 {
364    Wayland_Shell_Surface *wss;
365    Wayland_Surface *ws;
366
367    LOGFN(__FILE__, __LINE__, __FUNCTION__);
368
369    wss = resource->data;
370    ws = wss->surface;
371    e_mod_comp_wl_surface_damage_surface(ws);
372    wss->type = SHELL_SURFACE_POPUP;
373    wss->parent = parent_resource->data;
374    wss->popup.x = x;
375    wss->popup.y = y;
376 }
377
378 static void 
379 _e_mod_comp_wl_shell_surface_set_maximized(struct wl_client *client __UNUSED__, struct wl_resource *resource, struct wl_resource *output_resource __UNUSED__)
380 {
381    Wayland_Shell_Surface *wss;
382    Wayland_Surface *ws;
383
384    LOGFN(__FILE__, __LINE__, __FUNCTION__);
385
386    wss = resource->data;
387    ws = wss->surface;
388    /* FIXME: Implement */
389 }
390
391 static void 
392 _e_mod_comp_wl_shell_surface_destroy_handle(struct wl_listener *listener, struct wl_resource *resource __UNUSED__, uint32_t timestamp)
393 {
394    Wayland_Shell_Surface *wss;
395
396    LOGFN(__FILE__, __LINE__, __FUNCTION__);
397
398    wss = container_of(listener, Wayland_Shell_Surface, surface_destroy_listener);
399    wss->surface = NULL;
400    wl_resource_destroy(&wss->resource, timestamp);
401 }
402
403 static Wayland_Shell_Surface *
404 _e_mod_comp_wl_shell_get_shell_surface(Wayland_Surface *ws)
405 {
406    struct wl_list *list;
407    struct wl_listener *listener;
408
409    LOGFN(__FILE__, __LINE__, __FUNCTION__);
410
411    list = &ws->surface.resource.destroy_listener_list;
412    wl_list_for_each(listener, list, link)
413      {
414         if (listener->func == _e_mod_comp_wl_shell_surface_destroy_handle)
415           return container_of(listener, Wayland_Shell_Surface, 
416                               surface_destroy_listener);
417      }
418    return NULL;
419 }
420
421 static void 
422 _e_mod_comp_wl_shell_surface_destroy(struct wl_resource *resource)
423 {
424    Wayland_Shell_Surface *wss;
425
426    LOGFN(__FILE__, __LINE__, __FUNCTION__);
427
428    wss = resource->data;
429
430    /* TODO: popup grab input */
431
432    if (wss->surface) wl_list_remove(&wss->surface_destroy_listener.link);
433    wl_list_remove(&wss->link);
434    free(wss);
435 }