1 #include "e.h"
2 
3 /* E_Desk is a child object of E_Zone. A desk is essentially a background
4  * and an associated set of client windows. Each zone can have an arbitrary
5  * number of desktops.
6  */
7 
8 static void      _e_desk_free(E_Desk *desk);
9 static void      _e_desk_event_desk_show_free(void *data, void *ev);
10 static void      _e_desk_event_desk_before_show_free(void *data, void *ev);
11 static void      _e_desk_event_desk_after_show_free(void *data, void *ev);
12 static void      _e_desk_event_desk_deskshow_free(void *data, void *ev);
13 static void      _e_desk_event_desk_name_change_free(void *data, void *ev);
14 static void      _e_desk_show_begin(E_Desk *desk, int dx, int dy);
15 static void      _e_desk_hide_begin(E_Desk *desk, int dx, int dy);
16 static void      _e_desk_event_desk_window_profile_change_free(void *data, void *ev);
17 static void      _e_desk_window_profile_change_protocol_set(void);
18 
19 static E_Desk_Flip_Cb _e_desk_flip_cb = NULL;
20 static void *_e_desk_flip_data = NULL;
21 
22 E_API int E_EVENT_DESK_SHOW = 0;
23 E_API int E_EVENT_DESK_BEFORE_SHOW = 0;
24 E_API int E_EVENT_DESK_AFTER_SHOW = 0;
25 E_API int E_EVENT_DESK_DESKSHOW = 0;
26 E_API int E_EVENT_DESK_NAME_CHANGE = 0;
27 E_API int E_EVENT_DESK_WINDOW_PROFILE_CHANGE = 0;
28 
29 EINTERN int
e_desk_init(void)30 e_desk_init(void)
31 {
32    E_EVENT_DESK_SHOW = ecore_event_type_new();
33    E_EVENT_DESK_BEFORE_SHOW = ecore_event_type_new();
34    E_EVENT_DESK_AFTER_SHOW = ecore_event_type_new();
35    E_EVENT_DESK_DESKSHOW = ecore_event_type_new();
36    E_EVENT_DESK_NAME_CHANGE = ecore_event_type_new();
37    E_EVENT_DESK_WINDOW_PROFILE_CHANGE = ecore_event_type_new();
38    return 1;
39 }
40 
41 EINTERN int
e_desk_shutdown(void)42 e_desk_shutdown(void)
43 {
44    return 1;
45 }
46 
47 static void
_do_profile(E_Desk * desk,E_Randr2_Screen * sc)48 _do_profile(E_Desk *desk, E_Randr2_Screen *sc)
49 {
50    int scale = 100;
51    char buf[PATH_MAX], buf2[PATH_MAX + 256];
52 
53    eina_stringshare_del(desk->window_profile);
54    desk->window_profile = NULL;
55 
56    if (sc->config.scale_multiplier > 0.0)
57      {
58         scale = (int)(sc->config.scale_multiplier * 100.0);
59      }
60    else if (e_config->scale.use_dpi)
61      {
62         double dpi = e_randr2_screen_dpi_get(sc);
63 
64         if ((dpi > 0.0) && (e_config->scale.base_dpi > 0))
65           scale = (int)((100.0 * dpi) / (double)e_config->scale.base_dpi);
66      }
67 
68    if (scale == 100)
69      snprintf(buf, sizeof(buf), "%s", sc->config.profile);
70    else
71      {
72         snprintf(buf, sizeof(buf), ".scale-%04i-%s",
73                  scale, sc->config.profile);
74         if (!elm_config_profile_exists(buf))
75           {
76              snprintf(buf2, sizeof(buf2),
77                       "%s/enlightenment/utils/enlightenment_elm_cfgtool "
78                       "set %s %s 'scale-mul %i'",
79                       e_prefix_lib_get(), sc->config.profile, buf, scale);
80              if (system(buf2) != 0)
81                ERR("Error code from trying to run \"%s\"", buf2);
82           }
83      }
84    desk->window_profile = eina_stringshare_add(buf);
85 }
86 
87 E_API E_Desk *
e_desk_new(E_Zone * zone,int x,int y)88 e_desk_new(E_Zone *zone, int x, int y)
89 {
90    E_Desk *desk;
91    Eina_List *l;
92    E_Config_Desktop_Name *cfname;
93    int ok = 0;
94 
95    E_OBJECT_CHECK_RETURN(zone, NULL);
96    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
97 
98    desk = E_OBJECT_ALLOC(E_Desk, E_DESK_TYPE, _e_desk_free);
99    if (!desk) return NULL;
100 
101    _e_desk_window_profile_change_protocol_set();
102 
103    desk->zone = zone;
104    desk->x = x;
105    desk->y = y;
106 
107    /* Get current desktop's name */
108    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
109      {
110         if ((cfname->zone >= 0) &&
111             ((int)zone->num != cfname->zone)) continue;
112         if ((cfname->desk_x != desk->x) || (cfname->desk_y != desk->y))
113           continue;
114         desk->name = eina_stringshare_ref(cfname->name);
115         ok = 1;
116         break;
117      }
118 
119    if (!ok) desk->name = eina_stringshare_add("");
120 
121    /* Get window profile name for current desktop */
122    if (zone->randr2_id)
123      {
124         E_Randr2_Screen *sc = e_randr2_screen_id_find(zone->randr2_id);
125 
126         if ((sc) && (sc->config.profile)) _do_profile(desk, sc);
127      }
128 
129    return desk;
130 }
131 
132 E_API E_Client *
e_desk_client_top_visible_get(const E_Desk * desk)133 e_desk_client_top_visible_get(const E_Desk *desk)
134 {
135    E_Client *ec;
136 
137    E_OBJECT_CHECK_RETURN(desk, NULL);
138    E_OBJECT_TYPE_CHECK_RETURN(desk, E_DESK_TYPE, NULL);
139 
140    E_CLIENT_REVERSE_FOREACH(ec)
141      if (e_client_util_desk_visible(ec, desk) && evas_object_visible_get(ec->frame)) return ec;
142    return NULL;
143 }
144 
145 E_API void
e_desk_name_set(E_Desk * desk,const char * name)146 e_desk_name_set(E_Desk *desk, const char *name)
147 {
148    E_Event_Desk_Name_Change *ev;
149 
150    E_OBJECT_CHECK(desk);
151    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
152 
153    eina_stringshare_replace(&desk->name, name);
154 
155    ev = E_NEW(E_Event_Desk_Name_Change, 1);
156    ev->desk = desk;
157    e_object_ref(E_OBJECT(desk));
158    ecore_event_add(E_EVENT_DESK_NAME_CHANGE, ev,
159                    _e_desk_event_desk_name_change_free, NULL);
160 }
161 
162 E_API void
e_desk_name_add(int zone,int desk_x,int desk_y,const char * name)163 e_desk_name_add(int zone, int desk_x, int desk_y, const char *name)
164 {
165    E_Config_Desktop_Name *cfname;
166 
167    e_desk_name_del(zone, desk_x, desk_y);
168 
169    cfname = E_NEW(E_Config_Desktop_Name, 1);
170    cfname->zone = zone;
171    cfname->desk_x = desk_x;
172    cfname->desk_y = desk_y;
173    if (name) cfname->name = eina_stringshare_add(name);
174    else cfname->name = NULL;
175    e_config->desktop_names = eina_list_append(e_config->desktop_names, cfname);
176 }
177 
178 E_API void
e_desk_name_del(int zone,int desk_x,int desk_y)179 e_desk_name_del(int zone, int desk_x, int desk_y)
180 {
181    Eina_List *l = NULL;
182    E_Config_Desktop_Name *cfname = NULL;
183 
184    EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
185      {
186         if ((cfname->zone == zone) &&
187             (cfname->desk_x == desk_x) && (cfname->desk_y == desk_y))
188           {
189              e_config->desktop_names =
190                eina_list_remove_list(e_config->desktop_names, l);
191              if (cfname->name) eina_stringshare_del(cfname->name);
192              E_FREE(cfname);
193              break;
194           }
195      }
196 }
197 
198 E_API void
e_desk_name_update(void)199 e_desk_name_update(void)
200 {
201    const Eina_List *z, *l;
202    E_Zone *zone;
203    E_Desk *desk;
204    E_Config_Desktop_Name *cfname;
205    int d_x, d_y, ok;
206 
207    EINA_LIST_FOREACH(e_comp->zones, z, zone)
208      {
209         for (d_x = 0; d_x < zone->desk_x_count; d_x++)
210           {
211              for (d_y = 0; d_y < zone->desk_y_count; d_y++)
212                {
213                   desk = zone->desks[d_x + zone->desk_x_count * d_y];
214                   ok = 0;
215 
216                   EINA_LIST_FOREACH(e_config->desktop_names, l, cfname)
217                     {
218                        if ((cfname->zone >= 0) &&
219                            ((int)zone->num != cfname->zone)) continue;
220                        if ((cfname->desk_x != d_x) ||
221                            (cfname->desk_y != d_y)) continue;
222                        e_desk_name_set(desk, cfname->name);
223                        ok = 1;
224                        break;
225                     }
226 
227                   if (!ok) e_desk_name_set(desk, "");
228                }
229           }
230      }
231 }
232 
233 E_API void
e_desk_show(E_Desk * desk)234 e_desk_show(E_Desk *desk)
235 {
236    E_Event_Desk_Show *ev;
237    E_Event_Desk_Before_Show *eev;
238    E_Event_Desk_After_Show *eeev;
239    Edje_Message_Float_Set *msg;
240    Eina_List *l;
241    E_Shelf *es;
242    E_Desk *desk2;
243    int was_zone = 0, dx = 0, dy = 0;
244 
245    E_OBJECT_CHECK(desk);
246    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
247    if (desk->visible) return;
248    if (e_client_action_get() && e_client_util_resizing_get(e_client_action_get())) return;
249 
250    desk2 = e_desk_at_xy_get(desk->zone, desk->zone->desk_x_current, desk->zone->desk_y_current);
251    if ((!starting) && (!desk2->visible)) return;
252    eev = E_NEW(E_Event_Desk_Before_Show, 1);
253    eev->desk = e_desk_current_get(desk->zone);
254    e_object_ref(E_OBJECT(eev->desk));
255    ecore_event_add(E_EVENT_DESK_BEFORE_SHOW, eev,
256                    _e_desk_event_desk_before_show_free, NULL);
257 
258    if (desk2->visible)
259      {
260         desk2->visible = 0;
261         if (e_config->desk_flip_wrap)
262           {
263              /* current desk (desk2) is last desk, switching to first desk (desk) */
264              if ((!desk->x) && (!desk->y) && (desk2->x + 1 == desk->zone->desk_x_count) && (desk2->y + 1 == desk->zone->desk_y_count))
265                {
266                   dx = (desk->x != desk2->x) ? 1 : 0;
267                   dy = (desk->y != desk2->y) ? 1 : 0;
268                }
269              /* current desk (desk2) is first desk, switching to last desk (desk) */
270              else if ((!desk2->x) && (!desk2->y) && (desk->x + 1 == desk->zone->desk_x_count) && (desk->y + 1 == desk->zone->desk_y_count))
271                {
272                   dx = (desk->x != desk2->x) ? -1 : 0;
273                   dy = (desk->y != desk2->y) ? -1 : 0;
274                }
275           }
276         if ((!dx) && (!dy))
277           {
278              dx = desk->x - desk2->x;
279              dy = desk->y - desk2->y;
280           }
281         _e_desk_hide_begin(desk2, dx, dy);
282         if (desk2->obstacles || desk->obstacles)
283           e_zone_useful_geometry_dirty(desk->zone);
284      }
285 
286    desk->zone->desk_x_prev = desk->zone->desk_x_current;
287    desk->zone->desk_y_prev = desk->zone->desk_y_current;
288    desk->zone->desk_x_current = desk->x;
289    desk->zone->desk_y_current = desk->y;
290    desk->visible = 1;
291 
292    msg = alloca(sizeof(Edje_Message_Float_Set) + (4 * sizeof(double)));
293    msg->count = 5;
294    msg->val[0] = 0.2 * (!!e_config->desk_flip_animate_mode);//e_config->desk_flip_animate_time;
295    msg->val[1] = desk->x;
296    msg->val[2] = desk->zone->desk_x_count;
297    msg->val[3] = desk->y;
298    msg->val[4] = desk->zone->desk_y_count;
299    if (desk->zone->bg_object)
300      edje_object_message_send(desk->zone->bg_object, EDJE_MESSAGE_FLOAT_SET, 0, msg);
301 
302    if (desk->zone->bg_object) was_zone = 1;
303    _e_desk_show_begin(desk, dx, dy);
304 
305    if (was_zone)
306      e_bg_zone_update(desk->zone, E_BG_TRANSITION_DESK);
307    else
308      e_bg_zone_update(desk->zone, E_BG_TRANSITION_START);
309 
310    ev = E_NEW(E_Event_Desk_Show, 1);
311    ev->desk = desk;
312    e_object_ref(E_OBJECT(desk));
313    ecore_event_add(E_EVENT_DESK_SHOW, ev, _e_desk_event_desk_show_free, NULL);
314 
315    EINA_LIST_FOREACH(e_shelf_list(), l, es)
316      {
317         if (es->zone != desk->zone) continue;
318         if (e_shelf_desk_visible(es, desk))
319           e_shelf_show(es);
320         else
321           e_shelf_hide(es);
322      }
323 
324    if (e_config->desk_flip_animate_mode == 0)
325      {
326         eeev = E_NEW(E_Event_Desk_After_Show, 1);
327         eeev->desk = e_desk_current_get(desk->zone);
328         e_object_ref(E_OBJECT(eeev->desk));
329         ecore_event_add(E_EVENT_DESK_AFTER_SHOW, eeev,
330                         _e_desk_event_desk_after_show_free, NULL);
331      }
332    e_zone_edge_flip_eval(desk->zone);
333 }
334 
335 E_API void
e_desk_deskshow(E_Zone * zone)336 e_desk_deskshow(E_Zone *zone)
337 {
338    E_Client *ec;
339    E_Desk *desk;
340    E_Event_Desk_Show *ev;
341 
342    E_OBJECT_CHECK(zone);
343    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
344 
345    desk = e_desk_current_get(zone);
346    if (desk->deskshow_toggle)
347      {
348         /* uniconify raises windows and changes stacking order
349          * go top-down to avoid skipping windows
350          */
351         E_CLIENT_REVERSE_FOREACH(ec)
352           {
353              if (e_client_util_ignored_get(ec)) continue;
354              if (ec->desk != desk) continue;
355              if (ec->deskshow)
356                {
357                   ec->deskshow = 0;
358                   e_client_uniconify(ec);
359                }
360           }
361      }
362    else
363      {
364         /*
365          * iconify raises, so we have to start from the bottom so we are going forward
366          */
367         E_CLIENT_FOREACH(ec)
368           {
369              if (e_client_util_ignored_get(ec)) continue;
370              if (ec->desk != desk) continue;
371              if (ec->iconic) continue;
372              if (ec->netwm.state.skip_taskbar) continue;
373              if (ec->user_skip_winlist) continue;
374              ec->deskshow = 1;
375              e_client_iconify(ec);
376           }
377      }
378    desk->deskshow_toggle = !desk->deskshow_toggle;
379    ev = E_NEW(E_Event_Desk_Show, 1);
380    ev->desk = desk;
381    e_object_ref(E_OBJECT(desk));
382    ecore_event_add(E_EVENT_DESK_DESKSHOW, ev,
383                    _e_desk_event_desk_deskshow_free, NULL);
384 }
385 
386 E_API E_Client *
e_desk_last_focused_focus(E_Desk * desk)387 e_desk_last_focused_focus(E_Desk *desk)
388 {
389    Eina_List *l = NULL;
390    E_Client *ec, *ecs = NULL;
391 
392    EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
393      {
394         if ((!ec->iconic) && (evas_object_visible_get(ec->frame) || ec->changes.visible) &&
395             ((desk &&
396             ((ec->desk == desk) || ((ec->zone == desk->zone) && ec->sticky))) ||
397             ((!desk) && ec->desk->visible)) &&
398             (ec->icccm.accepts_focus || ec->icccm.take_focus) &&
399             (ec->netwm.type != E_WINDOW_TYPE_DOCK) &&
400             (ec->netwm.type != E_WINDOW_TYPE_TOOLBAR) &&
401             (ec->netwm.type != E_WINDOW_TYPE_MENU) &&
402             (ec->netwm.type != E_WINDOW_TYPE_SPLASH) &&
403             (ec->netwm.type != E_WINDOW_TYPE_DESKTOP) &&
404             (!e_object_is_del(E_OBJECT(ec))))
405           {
406              /* this was the window last focused in this desktop */
407              if (!ec->lock_focus_out)
408                {
409                   if (ec->sticky && (!e_config->focus_revert_allow_sticky))
410                     {
411                        ecs = ec;
412                        continue;
413                     }
414                   if (ec->changes.visible && (!evas_object_visible_get(ec->frame)))
415                     ec->want_focus = ec->take_focus = 1;
416                   else
417                     e_client_focus_set_with_pointer(ec);
418                   if (e_config->raise_on_revert_focus)
419                     evas_object_raise(ec->frame);
420                   return ec;
421                }
422           }
423      }
424    if (ecs)
425      {
426         if (ecs->changes.visible && (!evas_object_visible_get(ecs->frame)))
427           ecs->want_focus = ecs->take_focus = 1;
428         else
429           e_client_focus_set_with_pointer(ecs);
430         if (e_config->raise_on_revert_focus)
431           evas_object_raise(ecs->frame);
432         return ecs;
433      }
434    if (e_client_focused_get())
435      evas_object_focus_set(e_client_focused_get()->frame, 0);
436    return NULL;
437 }
438 
439 E_API void
e_desk_row_add(E_Zone * zone)440 e_desk_row_add(E_Zone *zone)
441 {
442    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count + 1);
443 }
444 
445 E_API void
e_desk_row_remove(E_Zone * zone)446 e_desk_row_remove(E_Zone *zone)
447 {
448    e_zone_desk_count_set(zone, zone->desk_x_count, zone->desk_y_count - 1);
449 }
450 
451 E_API void
e_desk_col_add(E_Zone * zone)452 e_desk_col_add(E_Zone *zone)
453 {
454    e_zone_desk_count_set(zone, zone->desk_x_count + 1, zone->desk_y_count);
455 }
456 
457 E_API void
e_desk_col_remove(E_Zone * zone)458 e_desk_col_remove(E_Zone *zone)
459 {
460    e_zone_desk_count_set(zone, zone->desk_x_count - 1, zone->desk_y_count);
461 }
462 
463 E_API E_Desk *
e_desk_current_get(E_Zone * zone)464 e_desk_current_get(E_Zone *zone)
465 {
466    E_OBJECT_CHECK_RETURN(zone, NULL);
467    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
468 
469    return e_desk_at_xy_get(zone, zone->desk_x_current, zone->desk_y_current);
470 }
471 
472 E_API E_Desk *
e_desk_at_xy_get(const E_Zone * zone,int x,int y)473 e_desk_at_xy_get(const E_Zone *zone, int x, int y)
474 {
475    E_OBJECT_CHECK_RETURN(zone, NULL);
476    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
477 
478    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
479      return NULL;
480    else if ((x < 0) || (y < 0))
481      return NULL;
482 
483    if (!zone->desks) return NULL;
484    return zone->desks[x + (y * zone->desk_x_count)];
485 }
486 
487 E_API E_Desk *
e_desk_at_pos_get(E_Zone * zone,int pos)488 e_desk_at_pos_get(E_Zone *zone, int pos)
489 {
490    int x, y;
491 
492    E_OBJECT_CHECK_RETURN(zone, NULL);
493    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
494 
495    y = pos / zone->desk_x_count;
496    x = pos - (y * zone->desk_x_count);
497 
498    if ((x >= zone->desk_x_count) || (y >= zone->desk_y_count))
499      return NULL;
500 
501    return zone->desks[x + (y * zone->desk_x_count)];
502 }
503 
504 E_API void
e_desk_xy_get(E_Desk * desk,int * x,int * y)505 e_desk_xy_get(E_Desk *desk, int *x, int *y)
506 {
507    E_OBJECT_CHECK(desk);
508    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
509 
510    if (x) *x = desk->x;
511    if (y) *y = desk->y;
512 }
513 
514 E_API void
e_desk_next(E_Zone * zone)515 e_desk_next(E_Zone *zone)
516 {
517    int x, y;
518 
519    E_OBJECT_CHECK(zone);
520    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
521 
522    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
523      return;
524 
525    x = zone->desk_x_current;
526    y = zone->desk_y_current;
527 
528    x++;
529    if (x >= zone->desk_x_count)
530      {
531         x = 0;
532         y++;
533         if (y >= zone->desk_y_count) y = 0;
534      }
535 
536    e_desk_show(e_desk_at_xy_get(zone, x, y));
537 }
538 
539 E_API void
e_desk_prev(E_Zone * zone)540 e_desk_prev(E_Zone *zone)
541 {
542    int x, y;
543 
544    E_OBJECT_CHECK(zone);
545    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
546 
547    if ((zone->desk_x_count < 2) && (zone->desk_y_count < 2))
548      return;
549 
550    x = zone->desk_x_current;
551    y = zone->desk_y_current;
552 
553    x--;
554    if (x < 0)
555      {
556         x = zone->desk_x_count - 1;
557         y--;
558         if (y < 0) y = zone->desk_y_count - 1;
559      }
560    e_desk_show(e_desk_at_xy_get(zone, x, y));
561 }
562 
563 E_API void
e_desk_window_profile_set(E_Desk * desk,const char * profile)564 e_desk_window_profile_set(E_Desk *desk,
565                           const char *profile)
566 {
567    E_Event_Desk_Window_Profile_Change *ev;
568 
569    E_OBJECT_CHECK(desk);
570    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
571 
572    eina_stringshare_replace(&desk->window_profile, profile);
573 
574    ev = E_NEW(E_Event_Desk_Window_Profile_Change, 1);
575    ev->desk = desk;
576    e_object_ref(E_OBJECT(desk));
577    ecore_event_add(E_EVENT_DESK_WINDOW_PROFILE_CHANGE, ev,
578                    _e_desk_event_desk_window_profile_change_free, NULL);
579 }
580 
581 E_API void
e_desk_window_profile_update(E_Zone * zone)582 e_desk_window_profile_update(E_Zone *zone)
583 {
584    if (zone->randr2_id)
585      {
586         E_Randr2_Screen *sc = e_randr2_screen_id_find(zone->randr2_id);
587 
588         if ((sc) && (sc->config.profile))
589           {
590              int x, y;
591 
592              for (y = 0; y < zone->desk_y_count; y++)
593                {
594                   for (x = 0; x < zone->desk_x_count; x++)
595                     _do_profile(zone->desks[x + (y * zone->desk_x_count)], sc);
596                }
597           }
598      }
599 }
600 
601 E_API void
e_desk_flip_cb_set(E_Desk_Flip_Cb cb,const void * data)602 e_desk_flip_cb_set(E_Desk_Flip_Cb cb, const void *data)
603 {
604    _e_desk_flip_cb = cb;
605    _e_desk_flip_data = (void*)data;
606 }
607 
608 E_API void
e_desk_flip_end(E_Desk * desk)609 e_desk_flip_end(E_Desk *desk)
610 {
611    E_Event_Desk_After_Show *ev;
612    E_Client *ec;
613    Eina_Bool do_global_focus = EINA_FALSE;
614 
615    ev = E_NEW(E_Event_Desk_After_Show, 1);
616    ev->desk = desk;
617    e_object_ref(E_OBJECT(ev->desk));
618    ecore_event_add(E_EVENT_DESK_AFTER_SHOW, ev,
619                    _e_desk_event_desk_after_show_free, NULL);
620 
621    e_comp_shape_queue();
622    if (desk->zone->desk_flip_sync)
623      {
624         Eina_List *l;
625         E_Zone *zone;
626         Eina_Bool sync = EINA_FALSE;
627 
628         EINA_LIST_FOREACH(e_comp->zones, l, zone)
629           {
630              if (zone != desk->zone)
631                sync |= zone->desk_flip_sync;
632           }
633         do_global_focus = !sync;
634         desk->zone->desk_flip_sync = 0;
635         if (!do_global_focus) return;
636      }
637    if (!e_config->focus_last_focused_per_desktop) return;
638    if ((e_config->focus_policy == E_FOCUS_MOUSE) ||
639        (e_config->focus_policy == E_FOCUS_SLOPPY))
640      {
641         ec = e_client_focused_get();
642         /* only set focus/warp pointer if currently focused window
643          * is on same screen (user hasn't switched screens during transition)
644          */
645         if (do_global_focus)
646           {
647              if (ec && e_client_util_desk_visible(ec, ec->desk)) return;
648           }
649         else
650           {
651              if (ec && ec->desk && (ec->desk->zone != desk->zone)) return;
652           }
653      }
654    if (starting) return;
655    ec = e_desk_last_focused_focus(do_global_focus ? NULL : desk);
656    if ((e_config->focus_policy != E_FOCUS_MOUSE) && (!ec))
657      {
658         /* we didn't previously have a focused window on this desk
659          * but we should, so this is probably the first time the
660          * user has flipped to this desk. let's be helpful and
661          * focus a random window!
662          */
663          E_CLIENT_REVERSE_FOREACH(ec)
664            {
665               /* start with top and go down... */
666               if (e_client_util_ignored_get(ec)) continue;
667               if (!evas_object_visible_get(ec->frame)) continue;
668               if (ec->iconic) continue;
669               evas_object_focus_set(ec->frame, 1);
670               if (e_config->raise_on_revert_focus)
671                 evas_object_raise(ec->frame);
672               return;
673            }
674      }
675 }
676 
677 E_API unsigned int
e_desks_count(void)678 e_desks_count(void)
679 {
680    Eina_List *l;
681    E_Zone *zone;
682    unsigned int count = 0;
683 
684    EINA_LIST_FOREACH(e_comp->zones, l, zone)
685      {
686         int cx = 0, cy = 0;
687 
688         e_zone_desk_count_get(zone, &cx, &cy);
689         count += cx * cy;
690      }
691    return count;
692 }
693 
694 static void
_e_desk_free(E_Desk * desk)695 _e_desk_free(E_Desk *desk)
696 {
697    while (desk->obstacles)
698      {
699         E_Object *obs = (void*)EINA_INLIST_CONTAINER_GET(desk->obstacles, E_Zone_Obstacle);
700         e_object_del(obs);
701      }
702    eina_stringshare_del(desk->name);
703    desk->name = NULL;
704    free(desk);
705 }
706 
707 static void
_e_desk_event_desk_show_free(void * data EINA_UNUSED,void * event)708 _e_desk_event_desk_show_free(void *data EINA_UNUSED, void *event)
709 {
710    E_Event_Desk_Show *ev;
711 
712    ev = event;
713    e_object_unref(E_OBJECT(ev->desk));
714    free(ev);
715 }
716 
717 static void
_e_desk_event_desk_before_show_free(void * data EINA_UNUSED,void * event)718 _e_desk_event_desk_before_show_free(void *data EINA_UNUSED, void *event)
719 {
720    E_Event_Desk_Before_Show *ev;
721 
722    ev = event;
723    e_object_unref(E_OBJECT(ev->desk));
724    free(ev);
725 }
726 
727 static void
_e_desk_event_desk_after_show_free(void * data EINA_UNUSED,void * event)728 _e_desk_event_desk_after_show_free(void *data EINA_UNUSED, void *event)
729 {
730    E_Event_Desk_After_Show *ev;
731 
732    ev = event;
733    e_object_unref(E_OBJECT(ev->desk));
734    free(ev);
735 }
736 
737 static void
_e_desk_event_desk_deskshow_free(void * data EINA_UNUSED,void * event)738 _e_desk_event_desk_deskshow_free(void *data EINA_UNUSED, void *event)
739 {
740    E_Event_Desk_Show *ev;
741 
742    ev = event;
743    e_object_unref(E_OBJECT(ev->desk));
744    free(ev);
745 }
746 
747 static void
_e_desk_event_desk_name_change_free(void * data EINA_UNUSED,void * event)748 _e_desk_event_desk_name_change_free(void *data EINA_UNUSED, void *event)
749 {
750    E_Event_Desk_Name_Change *ev = event;
751    e_object_unref(E_OBJECT(ev->desk));
752    free(ev);
753 }
754 
755 static void
_e_desk_event_desk_window_profile_change_free(void * data EINA_UNUSED,void * event)756 _e_desk_event_desk_window_profile_change_free(void *data EINA_UNUSED, void *event)
757 {
758    E_Event_Desk_Window_Profile_Change *ev = event;
759    e_object_unref(E_OBJECT(ev->desk));
760    E_FREE(ev);
761 }
762 
763 static Eina_Bool
_e_desk_transition_setup(E_Client * ec,int dx,int dy,int state)764 _e_desk_transition_setup(E_Client *ec, int dx, int dy, int state)
765 {
766    e_comp_object_effect_set(ec->frame, e_config->desk_flip_animate_type ?: "none");
767    if (e_config->desk_flip_animate_type)
768      {
769         /* set geoms */
770         e_comp_object_effect_params_set(ec->frame, 1, (int[]){ec->x - ec->zone->x, ec->y - ec->zone->y, ec->w, ec->h, ec->zone->w, ec->zone->h, dx, dy}, 8);
771         e_comp_object_effect_params_set(ec->frame, 0, (int[]){state}, 1);
772      }
773 
774    return !!e_config->desk_flip_animate_type;
775 }
776 
777 static void
_e_desk_show_end(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)778 _e_desk_show_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
779 {
780    E_Client *ec = data;
781 
782    ec->desk->animate_count--;
783    e_client_comp_hidden_set(ec, ec->shaded);
784    e_comp_object_effect_unclip(ec->frame);
785    ec->hidden = 0;
786    if (!ec->visible) evas_object_show(ec->frame);
787    if (ec->desk != e_desk_current_get(ec->zone)) return;
788    if (!ec->desk->animate_count) e_desk_flip_end(ec->desk);
789 }
790 
791 static void
_e_desk_hide_end(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)792 _e_desk_hide_end(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
793 {
794    E_Client *ec = data;
795 
796    ec->desk->animate_count--;
797    ec->hidden = 1;
798    evas_object_hide(ec->frame);
799 }
800 
801 static void
_e_desk_show_begin(E_Desk * desk,int dx,int dy)802 _e_desk_show_begin(E_Desk *desk, int dx, int dy)
803 {
804    E_Client *ec;
805 
806    if (dx < 0) dx = -1;
807    if (dx > 0) dx = 1;
808    if (dy < 0) dy = -1;
809    if (dy > 0) dy = 1;
810 
811    desk->animate_count = 0;
812    if (_e_desk_flip_cb && e_config->desk_flip_animate_type)
813      {
814         _e_desk_flip_cb(_e_desk_flip_data, desk, dx, dy, 1);
815         return;
816      }
817    E_CLIENT_FOREACH(ec)
818      {
819         if (e_client_util_ignored_get(ec) || (ec->desk->zone != desk->zone) || (ec->iconic)) continue;
820         if (ec->moving)
821           {
822              e_client_desk_set(ec, desk);
823              evas_object_show(ec->frame);
824              continue;
825           }
826         if ((ec->desk != desk) || (ec->sticky)) continue;
827         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, dx, dy, 1))
828           {
829              e_comp_object_effect_stop(ec->frame, _e_desk_hide_end);
830              e_comp_object_effect_start(ec->frame, _e_desk_show_end, ec);
831              desk->animate_count++;
832           }
833         else
834           ec->hidden = 0;
835 
836         e_client_comp_hidden_set(ec, ec->hidden || ec->shaded);
837         evas_object_show(ec->frame);
838      }
839    if ((!e_config->desk_flip_animate_type) || (!desk->animate_count))
840      e_desk_flip_end(desk);
841 }
842 
843 static void
_e_desk_hide_begin(E_Desk * desk,int dx,int dy)844 _e_desk_hide_begin(E_Desk *desk, int dx, int dy)
845 {
846    E_Client *ec;
847 
848    if (dx < 0) dx = -1;
849    if (dx > 0) dx = 1;
850    if (dy < 0) dy = -1;
851    if (dy > 0) dy = 1;
852 
853    desk->animate_count = 0;
854    if (_e_desk_flip_cb && e_config->desk_flip_animate_type)
855      {
856         _e_desk_flip_cb(_e_desk_flip_data, desk, dx, dy, 0);
857         return;
858      }
859    E_CLIENT_FOREACH(ec)
860      {
861         if (e_client_util_ignored_get(ec) || (ec->desk->zone != desk->zone) || (ec->iconic)) continue;
862         if (ec->moving) continue;
863         if ((ec->desk != desk) || (ec->sticky)) continue;
864         if ((!starting) && (!ec->new_client) && _e_desk_transition_setup(ec, -dx, -dy, 0))
865           {
866              e_comp_object_effect_stop(ec->frame, _e_desk_show_end);
867              e_comp_object_effect_start(ec->frame, _e_desk_hide_end, ec);
868              desk->animate_count++;
869           }
870         else
871           {
872              ec->hidden = 1;
873              evas_object_show(ec->frame);
874              ec->changes.visible = 0;
875              evas_object_hide(ec->frame);
876           }
877         e_client_comp_hidden_set(ec, EINA_TRUE);
878      }
879 }
880 
881 static void
_e_desk_window_profile_change_protocol_set(void)882 _e_desk_window_profile_change_protocol_set(void)
883 {
884 #ifndef HAVE_WAYLAND_ONLY
885    static Eina_Bool is_set = EINA_FALSE;
886 
887    if (!is_set)
888      {
889         if (e_comp->root)
890           {
891              is_set = EINA_TRUE;
892              ecore_x_e_window_profile_supported_set(e_comp->root, EINA_TRUE);
893           }
894      }
895 #endif
896 }
897