1 #include "e.h"
2 #ifdef HAVE_WAYLAND
3 # include "e_comp_wl.h"
4 #endif
5 
6 #define OVER_FLOW 1
7 //#define BORDER_ZOOMAPS
8 //////////////////////////////////////////////////////////////////////////
9 //
10 // TODO (no specific order):
11 //   1. abstract evas object and compwin so we can duplicate the object N times
12 //      in N canvases - for winlist, everything, pager etc. too
13 //   2. implement "unmapped composite cache" -> N pixels worth of unmapped
14 //      windows to be fully composited. only the most active/recent.
15 //   3. for unmapped windows - when window goes out of unmapped comp cache
16 //      make a miniature copy (1/4 width+height?) and set property on window
17 //      with pixmap id
18 //
19 //////////////////////////////////////////////////////////////////////////
20 
21 static Eina_List *handlers = NULL;
22 static Eina_List *hooks = NULL;
23 E_API E_Comp *e_comp = NULL;
24 E_API E_Comp_X_Data *e_comp_x = NULL;
25 E_API E_Comp_Wl_Data *e_comp_wl = NULL;
26 static Eina_Hash *ignores = NULL;
27 static Eina_List *actions = NULL;
28 
29 static E_Comp_Config *conf = NULL;
30 static E_Config_DD *conf_edd = NULL;
31 static E_Config_DD *conf_match_edd = NULL;
32 
33 static Ecore_Timer *action_timeout = NULL;
34 static Eina_Bool gl_avail = EINA_FALSE;
35 static Eina_Bool shape_debug = EINA_FALSE;
36 
37 static double ecore_frametime = 0;
38 
39 static int _e_comp_log_dom = -1;
40 
41 E_API int E_EVENT_COMPOSITOR_UPDATE = -1;
42 E_API int E_EVENT_COMPOSITOR_DISABLE = -1;
43 E_API int E_EVENT_COMPOSITOR_ENABLE = -1;
44 E_API int E_EVENT_COMPOSITOR_XWAYLAND_INIT = -1;
45 
46 //////////////////////////////////////////////////////////////////////////
47 #undef DBG
48 #undef INF
49 #undef WRN
50 #undef ERR
51 #undef CRI
52 
53 #define SHAPE_DBG(...) do { if (shape_debug) EINA_LOG_DOM_DBG(_e_comp_log_dom, __VA_ARGS__); } while (0)
54 #define SHAPE_INF(...) do { if (shape_debug) EINA_LOG_DOM_INFO(_e_comp_log_dom, __VA_ARGS__); } while (0)
55 #define SHAPE_WRN(...) do { if (shape_debug) EINA_LOG_DOM_WARN(_e_comp_log_dom, __VA_ARGS__); } while (0)
56 #define SHAPE_ERR(...) do { if (shape_debug) EINA_LOG_DOM_ERR(_e_comp_log_dom, __VA_ARGS__); } while (0)
57 #define SHAPE_CRI(...) do { if (shape_debug) EINA_LOG_DOM_CRIT(_e_comp_log_dom, __VA_ARGS__); } while (0)
58 
59 #define DBG(...)            EINA_LOG_DOM_DBG(_e_comp_log_dom, __VA_ARGS__)
60 #define INF(...)            EINA_LOG_DOM_INFO(_e_comp_log_dom, __VA_ARGS__)
61 #define WRN(...)            EINA_LOG_DOM_WARN(_e_comp_log_dom, __VA_ARGS__)
62 #define ERR(...)            EINA_LOG_DOM_ERR(_e_comp_log_dom, __VA_ARGS__)
63 #define CRI(...)            EINA_LOG_DOM_CRIT(_e_comp_log_dom, __VA_ARGS__)
64 
65 static Eina_Bool
_e_comp_visible_object_clip_is(Evas_Object * obj)66 _e_comp_visible_object_clip_is(Evas_Object *obj)
67 {
68    Evas_Object *clip;
69    int a;
70 
71    clip = evas_object_clip_get(obj);
72    if (!evas_object_visible_get(clip)) return EINA_FALSE;
73    evas_object_color_get(clip, NULL, NULL, NULL, &a);
74    if (a <= 0) return EINA_FALSE;
75    if (evas_object_clip_get(clip))
76      return _e_comp_visible_object_clip_is(clip);
77    return EINA_TRUE;
78 }
79 
80 static Eina_Bool
_e_comp_visible_object_is(Evas_Object * obj,Evas_Coord x,Evas_Coord y,Evas_Coord w,Evas_Coord h)81 _e_comp_visible_object_is(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
82 {
83    const char *type = evas_object_type_get(obj);
84    Evas_Coord xx, yy, ww, hh;
85 
86    if ((!type) || (!e_util_strcmp(type, "e_comp_object"))) return EINA_FALSE;
87    if (evas_object_data_get(obj, "comp_skip")) return EINA_FALSE;
88    evas_object_geometry_get(obj, &xx, &yy, &ww, &hh);
89    if (E_INTERSECTS(x, y, w, h, xx, yy, ww, hh))
90      {
91         if ((evas_object_visible_get(obj))
92             && (!evas_object_clipees_get(obj))
93            )
94           {
95              int a;
96 
97              evas_object_color_get(obj, NULL, NULL, NULL, &a);
98              if (a > 0)
99                {
100                   if ((!strcmp(type, "rectangle")) ||
101                       (!strcmp(type, "image")) ||
102                       (!strcmp(type, "text")) ||
103                       (!strcmp(type, "textblock")) ||
104                       (!strcmp(type, "textgrid")) ||
105                       (!strcmp(type, "polygon")) ||
106                       (!strcmp(type, "line")))
107                     {
108                        if (evas_object_clip_get(obj))
109                          return _e_comp_visible_object_clip_is(obj);
110                        return EINA_TRUE;
111                     }
112                   else
113                     {
114                        Eina_List *children;
115 
116                        if ((children = evas_object_smart_members_get(obj)))
117                          {
118                             Eina_List *l;
119                             Evas_Object *o;
120 
121                             EINA_LIST_FOREACH(children, l, o)
122                               {
123                                  if (_e_comp_visible_object_is(o, x, y, w, h))
124                                    {
125                                       if (evas_object_clip_get(o))
126                                         {
127                                            eina_list_free(children);
128                                            return _e_comp_visible_object_clip_is(o);
129                                         }
130                                       eina_list_free(children);
131                                       return !!evas_object_data_get(o, "comp_skip");
132                                    }
133                               }
134                             eina_list_free(children);
135                          }
136                     }
137                }
138           }
139      }
140    return EINA_FALSE;
141 }
142 
143 static Eina_Bool
_e_comp_visible_object_is_above(Evas_Object * obj,Evas_Coord x,Evas_Coord y,Evas_Coord w,Evas_Coord h)144 _e_comp_visible_object_is_above(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
145 {
146    Evas_Object *above;
147 
148    for (above = evas_object_above_get(obj); above;
149         above = evas_object_above_get(above))
150      {
151         if (_e_comp_visible_object_is(above, x, y, w, h)) return EINA_TRUE;
152      }
153    return EINA_FALSE;
154 }
155 
156 static E_Client *
_e_comp_fullscreen_check(void)157 _e_comp_fullscreen_check(void)
158 {
159    E_Client *ec;
160 
161 //   printf("------------------------\n");
162    E_CLIENT_REVERSE_FOREACH(ec)
163      {
164         Evas_Object *o = ec->frame;
165 
166 //        printf("FSCK %p [%i %i %ix%i] [%s]\n",
167 //               ec, ec->x, ec->y, ec->w, ec->h,
168 //               e_client_util_name_get(ec));
169         if (ec->ignored || ec->input_only || (!evas_object_visible_get(ec->frame)))
170           continue;
171         if (!e_comp_util_client_is_fullscreen(ec))
172           {
173              if (evas_object_data_get(ec->frame, "comp_skip")) continue;
174              return NULL;
175           }
176         while (o)
177           {
178              if (_e_comp_visible_object_is_above
179                  (o, 0, 0, e_comp->w, e_comp->h)) return NULL;
180              o = evas_object_smart_parent_get(o);
181           }
182         return ec;
183      }
184    return NULL;
185 }
186 
187 static void
_e_comp_fps_update(void)188 _e_comp_fps_update(void)
189 {
190    if (conf->fps_show)
191      {
192         if (e_comp->canvas->fps_bg) return;
193 
194         e_comp->canvas->fps_bg = evas_object_rectangle_add(e_comp->evas);
195         evas_object_color_set(e_comp->canvas->fps_bg, 0, 0, 0, 128);
196         evas_object_layer_set(e_comp->canvas->fps_bg, E_LAYER_MAX);
197         evas_object_name_set(e_comp->canvas->fps_bg, "e_comp->canvas->fps_bg");
198         evas_object_lower(e_comp->canvas->fps_bg);
199         evas_object_show(e_comp->canvas->fps_bg);
200 
201         e_comp->canvas->fps_fg = evas_object_text_add(e_comp->evas);
202         evas_object_text_font_set(e_comp->canvas->fps_fg, "Sans", 10);
203         evas_object_text_text_set(e_comp->canvas->fps_fg, "???");
204         evas_object_color_set(e_comp->canvas->fps_fg, 255, 255, 255, 255);
205         evas_object_layer_set(e_comp->canvas->fps_fg, E_LAYER_MAX);
206         evas_object_name_set(e_comp->canvas->fps_bg, "e_comp->canvas->fps_fg");
207         evas_object_stack_above(e_comp->canvas->fps_fg, e_comp->canvas->fps_bg);
208         evas_object_show(e_comp->canvas->fps_fg);
209      }
210    else
211      {
212         E_FREE_FUNC(e_comp->canvas->fps_fg, evas_object_del);
213         E_FREE_FUNC(e_comp->canvas->fps_bg, evas_object_del);
214      }
215 }
216 
217 static void
_e_comp_cb_nocomp_begin(void)218 _e_comp_cb_nocomp_begin(void)
219 {
220    E_Client *ec, *ecf;
221 
222    if (e_comp->nocomp) return;
223 
224    E_FREE_FUNC(e_comp->nocomp_delay_timer, ecore_timer_del);
225 
226    ecf = _e_comp_fullscreen_check();
227    if (!ecf) return;
228    e_object_ref(E_OBJECT(ecf));
229    e_comp->nocomp_ec = ecf;
230    E_CLIENT_FOREACH(ec)
231      if (ec != ecf) e_client_redirected_set(ec, 0);
232 
233    INF("NOCOMP %p: frame %p", ecf, ecf->frame);
234    e_comp->nocomp = 1;
235 
236    {
237       Eina_Bool fs;
238 
239       fs = e_comp->nocomp_ec->fullscreen;
240       if (!fs)
241         e_comp->nocomp_ec->saved.layer = e_comp->nocomp_ec->layer;
242       e_comp->nocomp_ec->fullscreen = 0;
243       e_comp->nocomp_ec->layer = E_LAYER_CLIENT_PRIO;
244       evas_object_layer_set(e_comp->nocomp_ec->frame, E_LAYER_CLIENT_PRIO);
245       e_comp->nocomp_ec->fullscreen = fs;
246    }
247    e_client_redirected_set(ecf, 0);
248 
249    //ecore_evas_manual_render_set(e_comp->ee, EINA_TRUE);
250    ecore_evas_hide(e_comp->ee);
251    edje_file_cache_flush();
252    edje_collection_cache_flush();
253    evas_image_cache_flush(e_comp->evas);
254    evas_font_cache_flush(e_comp->evas);
255    evas_render_dump(e_comp->evas);
256 
257    DBG("JOB2...");
258    e_comp_render_queue();
259    e_comp_shape_queue_block(1);
260    ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
261 }
262 
263 static void
_e_comp_cb_nocomp_end(void)264 _e_comp_cb_nocomp_end(void)
265 {
266    E_Client *ec;
267 
268    if (!e_comp->nocomp) return;
269 
270    INF("COMP RESUME!");
271    //ecore_evas_manual_render_set(e_comp->ee, EINA_FALSE);
272    ecore_evas_show(e_comp->ee);
273    E_CLIENT_FOREACH(ec)
274      {
275         e_client_redirected_set(ec, 1);
276         if (ec->visible && (!ec->input_only))
277           e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
278      }
279 #ifndef HAVE_WAYLAND_ONLY
280    e_comp_x_nocomp_end();
281 #endif
282    e_comp_render_queue();
283    e_comp_shape_queue_block(0);
284    ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
285 }
286 
287 static Eina_Bool
_e_comp_cb_nocomp_begin_timeout(void * data EINA_UNUSED)288 _e_comp_cb_nocomp_begin_timeout(void *data EINA_UNUSED)
289 {
290    e_comp->nocomp_delay_timer = NULL;
291    if (e_comp->nocomp_override == 0)
292      {
293         if (_e_comp_fullscreen_check()) e_comp->nocomp_want = 1;
294         _e_comp_cb_nocomp_begin();
295      }
296    return EINA_FALSE;
297 }
298 
299 
300 static void
_e_comp_client_update(E_Client * ec)301 _e_comp_client_update(E_Client *ec)
302 {
303    int pw, ph;
304 
305    DBG("UPDATE [%p] pm = %p", ec, ec->pixmap);
306    if (e_object_is_del(E_OBJECT(ec))) return;
307 
308    e_pixmap_size_get(ec->pixmap, &pw, &ph);
309 
310    if (e_pixmap_dirty_get(ec->pixmap) && (!e_comp->nocomp))
311      {
312         int w, h;
313 
314         if (e_pixmap_refresh(ec->pixmap) &&
315             e_pixmap_size_get(ec->pixmap, &w, &h) &&
316             e_pixmap_size_changed(ec->pixmap, pw, ph))
317           {
318              e_pixmap_image_clear(ec->pixmap, 0);
319              e_comp_object_render_update_del(ec->frame); //clear update
320              if (ec->changes.visible && (!evas_object_visible_get(ec->frame)))
321                evas_object_show(ec->frame);
322           }
323         else if (!e_pixmap_size_get(ec->pixmap, NULL, NULL))
324           {
325              WRN("FAIL %p", ec);
326              e_comp_object_redirected_set(ec->frame, 0);
327              if (e_pixmap_failures_get(ec->pixmap) > 3)
328                e_comp_object_render_update_add(ec->frame);
329           }
330      }
331    if (!(e_comp->saver && ecore_evas_manual_render_get(e_comp->ee)) &&
332        e_pixmap_size_get(ec->pixmap, &pw, &ph))
333      {
334         //INF("PX DIRTY: PX(%dx%d) CLI(%dx%d)", pw, ph, ec->client.w, ec->client.h);
335         e_pixmap_image_refresh(ec->pixmap);
336         e_comp_object_dirty(ec->frame);
337         if (e_pixmap_is_x(ec->pixmap) && (!ec->override))
338           evas_object_resize(ec->frame, ec->w, ec->h);
339      }
340 }
341 
342 static void
_e_comp_nocomp_end(void)343 _e_comp_nocomp_end(void)
344 {
345    e_comp->nocomp_want = 0;
346    E_FREE_FUNC(e_comp->nocomp_delay_timer, ecore_timer_del);
347    _e_comp_cb_nocomp_end();
348    if (e_comp->nocomp_ec)
349      {
350         E_Layer layer = MAX(e_comp->nocomp_ec->saved.layer, E_LAYER_CLIENT_NORMAL);
351         Eina_Bool fs;
352 
353         fs = e_comp->nocomp_ec->fullscreen;
354         e_comp->nocomp_ec->fullscreen = 0;
355         if (fs)
356           {
357              if (!e_config->allow_above_fullscreen)
358                layer = E_LAYER_CLIENT_FULLSCREEN;
359              else if (e_config->mode.presentation)
360                layer = E_LAYER_CLIENT_TOP;
361           }
362         evas_object_layer_set(e_comp->nocomp_ec->frame, layer);
363         e_comp->nocomp_ec->fullscreen = fs;
364      }
365    E_FREE_FUNC(e_comp->nocomp_ec, e_object_unref);
366 }
367 
368 static Eina_Bool
_e_comp_cb_update(void)369 _e_comp_cb_update(void)
370 {
371    E_Client *ec;
372    Eina_List *l;
373    //   static int doframeinfo = -1;
374 
375    if (!e_comp) return EINA_FALSE;
376    if (e_comp->update_job)
377      e_comp->update_job = NULL;
378    else
379      ecore_animator_freeze(e_comp->render_animator);
380    DBG("UPDATE ALL");
381    if (e_comp->nocomp) goto nocomp;
382 //   if (conf->grab && (!e_comp->grabbed))
383 //     {
384 //        if (e_comp->grab_cb) e_comp->grab_cb();
385 //        e_comp->grabbed = 1;
386 //     }
387    e_comp->updating = 1;
388    l = e_comp->updates;
389    e_comp->updates = NULL;
390    EINA_LIST_FREE(l, ec)
391      {
392         /* clear update flag */
393         e_comp_object_render_update_del(ec->frame);
394         _e_comp_client_update(ec);
395      }
396    e_comp->updating = 0;
397    _e_comp_fps_update();
398    if (conf->fps_show)
399      {
400         char buf[128];
401         double fps = 0.0, t, dt;
402         int i;
403         Evas_Coord x = 0, y = 0, w = 0, h = 0;
404         E_Zone *z;
405 
406         t = ecore_loop_time_get();
407         if (conf->fps_average_range < 1)
408           conf->fps_average_range = 30;
409         else if (conf->fps_average_range > 120)
410           conf->fps_average_range = 120;
411         dt = t - e_comp->frametimes[conf->fps_average_range - 1];
412         if (dt > 0.0) fps = (double)conf->fps_average_range / dt;
413         else fps = 0.0;
414         if (fps > 0.0) snprintf(buf, sizeof(buf), "FPS: %1.1f", fps);
415         else snprintf(buf, sizeof(buf), "N/A");
416         for (i = 121; i >= 1; i--)
417           e_comp->frametimes[i] = e_comp->frametimes[i - 1];
418         e_comp->frametimes[0] = t;
419         e_comp->frameskip++;
420         if (e_comp->frameskip >= conf->fps_average_range)
421           {
422              e_comp->frameskip = 0;
423              evas_object_text_text_set(e_comp->canvas->fps_fg, buf);
424           }
425         evas_object_geometry_get(e_comp->canvas->fps_fg, NULL, NULL, &w, &h);
426         w += 8;
427         h += 8;
428         z = e_zone_current_get();
429         if (z)
430           {
431              switch (conf->fps_corner)
432                {
433                 case 3: // bottom-right
434                   x = z->x + z->w - w;
435                   y = z->y + z->h - h;
436                   break;
437 
438                 case 2: // bottom-left
439                   x = z->x;
440                   y = z->y + z->h - h;
441                   break;
442 
443                 case 1: // top-right
444                   x = z->x + z->w - w;
445                   y = z->y;
446                   break;
447                 default: // 0 // top-left
448                   x = z->x;
449                   y = z->y;
450                   break;
451                }
452           }
453         evas_object_move(e_comp->canvas->fps_bg, x, y);
454         evas_object_resize(e_comp->canvas->fps_bg, w, h);
455         evas_object_move(e_comp->canvas->fps_fg, x + 4, y + 4);
456      }
457    if (conf->lock_fps)
458      {
459         DBG("MANUAL RENDER...");
460         //        if (!e_comp->nocomp) ecore_evas_manual_render(e_comp->ee);
461      }
462 
463    if (e_comp->updates && (!e_comp->update_job))
464      ecore_animator_thaw(e_comp->render_animator);
465    /*
466       if (doframeinfo == -1)
467       {
468       doframeinfo = 0;
469       if (getenv("DFI")) doframeinfo = 1;
470       }
471       if (doframeinfo)
472       {
473       static double t0 = 0.0;
474       double td, t;
475 
476       t = ecore_time_get();
477       td = t - t0;
478       if (td > 0.0)
479       {
480       int fps, i;
481 
482       fps = 1.0 / td;
483       for (i = 0; i < fps; i+= 2) putchar('=');
484       printf(" : %3.3f", 1.0 / td);
485       }
486       t0 = t;
487       }
488     */
489 nocomp:
490    ec = _e_comp_fullscreen_check();
491    if (ec)
492      {
493         if (conf->nocomp_fs)
494           {
495              if (e_comp->nocomp && e_comp->nocomp_ec)
496                {
497                   E_Client *nec = NULL;
498                   for (ec = e_client_top_get(), nec = e_client_below_get(ec);
499                        (ec && nec) && (ec != nec); ec = nec, nec = e_client_below_get(ec))
500                     {
501                        if (ec == e_comp->nocomp_ec) break;
502                        if (evas_object_layer_get(ec->frame) < evas_object_layer_get(e_comp->nocomp_ec->frame)) break;
503                        if (e_client_is_stacking(ec)) continue;
504                        if (!ec->visible) continue;
505                        if (evas_object_data_get(ec->frame, "comp_skip")) continue;
506                        if (e_object_is_del(E_OBJECT(ec)) || (!e_client_util_desk_visible(ec, e_desk_current_get(ec->zone)))) continue;
507                        if (ec->override || (e_config->allow_above_fullscreen && (!e_config->mode.presentation)))
508                          {
509                             _e_comp_nocomp_end();
510                             break;
511                          }
512                        else
513                          evas_object_stack_below(ec->frame, e_comp->nocomp_ec->frame);
514                     }
515                }
516              else if ((!e_comp->nocomp) && (!e_comp->nocomp_override))
517                {
518                   if (!e_comp->nocomp_delay_timer)
519                     e_comp->nocomp_delay_timer = ecore_timer_loop_add(1.0, _e_comp_cb_nocomp_begin_timeout, NULL);
520                }
521           }
522      }
523    else
524      _e_comp_nocomp_end();
525 
526    return ECORE_CALLBACK_RENEW;
527 }
528 
529 static void
_e_comp_cb_job(void * data EINA_UNUSED)530 _e_comp_cb_job(void *data EINA_UNUSED)
531 {
532    DBG("UPDATE ALL JOB...");
533    _e_comp_cb_update();
534 }
535 
536 static Eina_Bool
_e_comp_cb_animator(void * data EINA_UNUSED)537 _e_comp_cb_animator(void *data EINA_UNUSED)
538 {
539    return _e_comp_cb_update();
540 }
541 
542 //////////////////////////////////////////////////////////////////////////
543 
544 
545 static void
_e_comp_shape_debug_rect(Eina_Rectangle * rect,E_Color * color)546 _e_comp_shape_debug_rect(Eina_Rectangle *rect, E_Color *color)
547 {
548    Evas_Object *o;
549 
550 #define COLOR_INCREMENT 30
551    o = evas_object_rectangle_add(e_comp->evas);
552    if (color->r < 256 - COLOR_INCREMENT)
553      evas_object_color_set(o, (color->r += COLOR_INCREMENT), 0, 0, 255);
554    else if (color->g < 256 - COLOR_INCREMENT)
555      evas_object_color_set(o, 0, (color->g += COLOR_INCREMENT), 0, 255);
556    else
557      evas_object_color_set(o, 0, 0, (color->b += COLOR_INCREMENT), 255);
558    evas_object_pass_events_set(o, 1);
559    evas_object_layer_set(o, E_LAYER_MENU - 1);
560    evas_object_move(o, rect->x, rect->y);
561    evas_object_resize(o, rect->w, rect->h);
562    e_comp->debug_rects = eina_list_append(e_comp->debug_rects, o);
563    evas_object_show(o);
564 }
565 
566 static Eina_Bool
_e_comp_shapes_update_object_checker_function_thingy(Evas_Object * o)567 _e_comp_shapes_update_object_checker_function_thingy(Evas_Object *o)
568 {
569    Eina_List *l;
570    E_Zone *zone;
571 
572    if (o == e_comp->canvas->resize_object) return EINA_TRUE;
573    EINA_LIST_FOREACH(e_comp->zones, l, zone)
574      {
575         if ((o == zone->over) || (o == zone->base)) return EINA_TRUE;
576         if ((o == zone->bg_object) || (o == zone->bg_event_object) ||
577             (o == zone->bg_clip_object) || (o == zone->prev_bg_object) ||
578             (o == zone->transition_object))
579           return EINA_TRUE;
580      }
581    return EINA_FALSE;
582 }
583 
584 static void
_e_comp_shapes_update_comp_client_shape_comp_helper(E_Client * ec,Eina_Tiler * tb,Eina_List ** rl)585 _e_comp_shapes_update_comp_client_shape_comp_helper(E_Client *ec, Eina_Tiler *tb, Eina_List **rl)
586 {
587    int x, y, w, h;
588 
589    /* ignore deleted shapes */
590    if (e_object_is_del(E_OBJECT(ec)))
591      {
592         SHAPE_INF("IGNORING DELETED: %p", ec);
593         return;
594      }
595    if ((!ec->visible) || (ec->hidden) || (!evas_object_visible_get(ec->frame)) || evas_object_pass_events_get(ec->frame))
596      {
597         SHAPE_DBG("SKIPPING SHAPE FOR %p", ec);
598         return;
599      }
600 
601    SHAPE_INF("COMP EC: %p", ec);
602 
603    if (ec->shaped || ec->shaped_input)
604      {
605         int num, tot;
606         int l, r, t, b;
607         Eina_Rectangle *rect, *rects;
608 
609         /* add the frame */
610         e_comp_object_frame_geometry_get(ec->frame, &l, &r, &t, &b);
611         e_comp_object_frame_extends_get(ec->frame, &x, &y, &w, &h);
612         if ((l + x) || (r + (w - ec->w + x)) || (t - y) || (b + (h - ec->h + y)))
613           {
614              if (t - y)
615                {
616                   eina_tiler_rect_add(tb, &(Eina_Rectangle){ec->x + x, ec->y + y, w, t - y});
617                   SHAPE_INF("ADD: %d,%d@%dx%d", ec->x + x, ec->y + y, w, t - y);
618                }
619              if (l - x)
620                {
621                   eina_tiler_rect_add(tb, &(Eina_Rectangle){ec->x + x, ec->y + y, l - x, h});
622                   SHAPE_INF("ADD: %d,%d@%dx%d", ec->x + x, ec->y + y, l - x, h);
623                }
624              if (r + (w - ec->w + x))
625                {
626                   eina_tiler_rect_add(tb, &(Eina_Rectangle){ec->x + l + ec->client.w + x, ec->y + y, r + (w - ec->w + x), h});
627                   SHAPE_INF("ADD: %d,%d@%dx%d", ec->x + l + ec->client.w + x, ec->y + y, r + (w - ec->w + x), h);
628                }
629              if (b + (h - ec->h + y))
630                {
631                   eina_tiler_rect_add(tb, &(Eina_Rectangle){ec->x + x, ec->y + t + ec->client.h + y, w, b + (h - ec->h + y)});
632                   SHAPE_INF("ADD: %d,%d@%dx%d", ec->x + x, ec->y + t + ec->client.h + y, w, b + (h - ec->h + y));
633                }
634           }
635         rects = ec->shape_rects ?: ec->shape_input_rects;
636         tot = ec->shape_rects_num ?: ec->shape_input_rects_num;
637         for (num = 0, rect = rects; num < tot; num++, rect++)
638           {
639              x = rect->x, y = rect->y, w = rect->w, h = rect->h;
640              x += ec->client.x, y += ec->client.y;
641              E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, e_comp->w, e_comp->h);
642              if ((w < 1) || (h < 1)) continue;
643    //#ifdef SHAPE_DEBUG not sure we can shape check these?
644              //r = E_NEW(Eina_Rectangle, 1);
645              //EINA_RECTANGLE_SET(r, x, y, w, h);
646              //rl = eina_list_append(rl, r);
647    //#endif
648              eina_tiler_rect_del(tb, &(Eina_Rectangle){x, y, w, h});
649              SHAPE_INF("DEL: %d,%d@%dx%d", x, y, w, h);
650           }
651         return;
652      }
653 
654    if (shape_debug)
655      {
656         Eina_Rectangle *r;
657 
658         r = E_NEW(Eina_Rectangle, 1);
659         EINA_RECTANGLE_SET(r, ec->client.x, ec->client.y, ec->client.w, ec->client.h);
660         *rl = eina_list_append(*rl, r);
661      }
662 
663    if (!e_client_util_borderless(ec))
664      {
665         e_comp_object_frame_extends_get(ec->frame, &x, &y, &w, &h);
666         /* add the frame */
667         eina_tiler_rect_add(tb, &(Eina_Rectangle){ec->x + x, ec->y + y, w, h});
668         SHAPE_INF("ADD: %d,%d@%dx%d", ec->x + x, ec->y + y, w, h);
669      }
670 
671    if ((!ec->shaded) && (!ec->shading))
672      {
673         /* delete the client if not shaded */
674         eina_tiler_rect_del(tb, &(Eina_Rectangle){ec->client.x, ec->client.y, ec->client.w, ec->client.h});
675         SHAPE_INF("DEL: %d,%d@%dx%d", ec->client.x, ec->client.y, ec->client.w, ec->client.h);
676      }
677 }
678 
679 static void
_e_comp_shapes_update_object_shape_comp_helper(Evas_Object * o,Eina_Tiler * tb)680 _e_comp_shapes_update_object_shape_comp_helper(Evas_Object *o, Eina_Tiler *tb)
681 {
682    int x, y, w, h;
683 
684    /* ignore hidden and pass-event objects */
685    if ((!evas_object_visible_get(o)) || evas_object_pass_events_get(o)) return;
686    if (evas_object_repeat_events_get(o) && (!evas_object_data_get(o, "comp_repeat"))) return;
687    /* ignore canvas objects */
688    if (_e_comp_shapes_update_object_checker_function_thingy(o)) return;
689    SHAPE_INF("OBJ: %p:%s", o, evas_object_name_get(o) ?: evas_object_type_get(o));
690    evas_object_geometry_get(o, &x, &y, &w, &h);
691    if ((!w) && (!h) && elm_object_widget_check(o))
692      {
693         Evas_Object *content = elm_object_content_get(o);
694         if (content)
695           evas_object_geometry_get(content, &x, &y, &w, &h);
696      }
697    eina_tiler_rect_add(tb, &(Eina_Rectangle){x, y, w, h});
698    SHAPE_INF("ADD: %d,%d@%dx%d", x, y, w, h);
699 }
700 
701 static void
_e_comp_shapes_update_job(void * d EINA_UNUSED)702 _e_comp_shapes_update_job(void *d EINA_UNUSED)
703 {
704    Eina_Tiler *tb;
705    E_Client *ec;
706    Evas_Object *o = NULL;
707    Eina_Rectangle *tr;
708    Eina_Iterator *ti;
709    Eina_Rectangle *exr;
710    unsigned int i, tile_count;
711    Ecore_Window win;
712    Eina_Rectangle *r;
713    Eina_List *rl = NULL;
714    E_Color color = {0};
715    const char *type;
716 
717    SHAPE_INF("---------------------");
718 
719    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
720      win = e_comp->win;
721    else
722      win = e_comp->cm_selection;
723    E_FREE_LIST(e_comp->debug_rects, evas_object_del);
724    tb = eina_tiler_new(e_comp->w, e_comp->h);
725    eina_tiler_tile_size_set(tb, 1, 1);
726    /* background */
727    eina_tiler_rect_add(tb, &(Eina_Rectangle){0, 0, e_comp->w, e_comp->h});
728 
729    ec = e_client_bottom_get();
730    if (ec) o = ec->frame;
731    for (; o; o = evas_object_above_get(o))
732      {
733         int layer;
734 
735         layer = evas_object_layer_get(o);
736         if (e_comp_canvas_client_layer_map(layer) == 9999) //not a client layer
737           {
738              _e_comp_shapes_update_object_shape_comp_helper(o, tb);
739              continue;
740           }
741         ec = NULL;
742         type = evas_object_type_get(o);
743         if ((type) && (!strcmp(type, "e_comp_object")))
744           ec = e_comp_object_client_get(o);
745         if (ec && (!ec->no_shape_cut))
746           _e_comp_shapes_update_comp_client_shape_comp_helper(ec, tb
747                                                               ,&rl
748                                                              );
749 
750         else
751           _e_comp_shapes_update_object_shape_comp_helper(o, tb);
752      }
753 
754    ti = eina_tiler_iterator_new(tb);
755    tile_count = 128;
756    exr = malloc(sizeof(Eina_Rectangle) * tile_count);
757    i = 0;
758    EINA_ITERATOR_FOREACH(ti, tr)
759      {
760         exr[i++] = *((Eina_Rectangle *)tr);
761         if (i == tile_count - 1)
762           exr = realloc(exr, sizeof(Eina_Rectangle) * (tile_count *= 2));
763         if (shape_debug)
764           {
765              Eina_List *l;
766 
767              _e_comp_shape_debug_rect(&exr[i - 1], &color);
768              SHAPE_INF("%d,%d @ %dx%d", exr[i - 1].x, exr[i - 1].y, exr[i - 1].w, exr[i - 1].h);
769              EINA_LIST_FOREACH(rl, l, r)
770                {
771                   if (E_INTERSECTS(r->x, r->y, r->w, r->h, tr->x, tr->y, tr->w, tr->h))
772                     SHAPE_ERR("POSSIBLE RECT FAIL!!!!");
773                }
774           }
775      }
776 
777 #ifndef HAVE_WAYLAND_ONLY
778    ecore_x_window_shape_input_rectangles_set(win, (Ecore_X_Rectangle*)exr, i);
779 #endif
780 
781    if (shape_debug)
782      {
783         E_FREE_LIST(rl, free);
784         printf("\n");
785      }
786    free(exr);
787    eina_iterator_free(ti);
788    eina_tiler_free(tb);
789    e_comp->shape_job = NULL;
790 }
791 
792 //////////////////////////////////////////////////////////////////////////
793 
794 
795 static Eina_Bool
_e_comp_key_down(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_Event_Key * ev)796 _e_comp_key_down(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Event_Key *ev)
797 {
798    if ((!strcasecmp(ev->key, "f")) &&
799        (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT) &&
800        (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
801        (ev->modifiers & ECORE_EVENT_MODIFIER_ALT))
802      {
803         e_comp_canvas_fps_toggle();
804      }
805    return ECORE_CALLBACK_PASS_ON;
806 }
807 
808 static Eina_Bool
_e_comp_signal_user(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_Event_Signal_User * ev)809 _e_comp_signal_user(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_Event_Signal_User *ev)
810 {
811    siginfo_t sig;
812 
813    sig = ev->data;
814    /* anything sent via 'kill' will set this code to SI_USER */
815    if (sig.si_code != SI_USER) return ECORE_CALLBACK_PASS_ON;
816 
817    if (ev->number == 1)
818      {
819         // e uses this to pop up config panel
820      }
821    else if (ev->number == 2)
822      {
823         e_comp_canvas_fps_toggle();
824      }
825    return ECORE_CALLBACK_PASS_ON;
826 }
827 
828 //////////////////////////////////////////////////////////////////////////
829 
830 static void
_e_comp_free(E_Comp * c)831 _e_comp_free(E_Comp *c)
832 {
833    E_FREE_LIST(c->zones, e_object_del);
834 
835    e_comp_canvas_clear();
836 
837    e_randr2_shutdown();
838 #ifdef HAVE_WAYLAND
839    if (c->comp_type == E_PIXMAP_TYPE_WL)
840      e_comp_wl_shutdown();
841 #endif
842 #ifndef HAVE_WAYLAND_ONLY
843    if (e_comp_util_has_x())
844      e_comp_x_shutdown();
845 #endif
846 
847    ecore_evas_free(c->ee);
848 
849    if (c->render_animator) ecore_animator_del(c->render_animator);
850    if (c->update_job) ecore_job_del(c->update_job);
851    if (c->nocomp_delay_timer) ecore_timer_del(c->nocomp_delay_timer);
852    if (c->nocomp_override_timer) ecore_timer_del(c->nocomp_override_timer);
853    ecore_job_del(c->shape_job);
854    free(c->canvas);
855    free(c);
856 }
857 
858 //////////////////////////////////////////////////////////////////////////
859 
860 static Eina_Bool
_e_comp_object_add(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Comp_Object * ev)861 _e_comp_object_add(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
862 {
863    if ((!e_comp->nocomp) || (!e_comp->nocomp_ec)) return ECORE_CALLBACK_RENEW;
864    if (evas_object_layer_get(ev->comp_object) > MAX(e_comp->nocomp_ec->saved.layer, E_LAYER_CLIENT_NORMAL))
865      _e_comp_nocomp_end();
866    return ECORE_CALLBACK_RENEW;
867 }
868 
869 static Eina_Bool
_e_comp_override_expire(void * data EINA_UNUSED)870 _e_comp_override_expire(void *data EINA_UNUSED)
871 {
872    e_comp->nocomp_override_timer = NULL;
873    e_comp->nocomp_override--;
874 
875    if (e_comp->nocomp_override <= 0)
876      {
877         e_comp->nocomp_override = 0;
878         if (e_comp->nocomp_want) _e_comp_cb_nocomp_begin();
879      }
880    return EINA_FALSE;
881 }
882 
883 //////////////////////////////////////////////////////////////////////////
884 
885 static Eina_Bool
_e_comp_screensaver_on(void * data EINA_UNUSED,int type EINA_UNUSED,void * event EINA_UNUSED)886 _e_comp_screensaver_on(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
887 {
888    Eina_List *l;
889    E_Zone *zone;
890 
891    ecore_frametime = ecore_animator_frametime_get();
892    if (e_comp->saver) return ECORE_CALLBACK_RENEW;
893    e_comp_override_add();
894    e_comp->saver = EINA_TRUE;
895    // XXX: this is not quite right - need to wait for signals from theme
896    // before freezing render animator
897    if (e_comp->render_animator)
898      ecore_animator_freeze(e_comp->render_animator);
899    EINA_LIST_FOREACH(e_comp->zones, l, zone)
900      {
901         e_zone_fade_handle(zone, 1, 3.0);
902         edje_object_signal_emit(zone->base, "e,state,screensaver,on", "e");
903         edje_object_signal_emit(zone->over, "e,state,screensaver,on", "e");
904      }
905 
906    return ECORE_CALLBACK_PASS_ON;
907 }
908 
909 static Eina_Bool
_e_comp_screensaver_off(void * data EINA_UNUSED,int type EINA_UNUSED,void * event EINA_UNUSED)910 _e_comp_screensaver_off(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
911 {
912    Eina_List *l;
913    E_Zone *zone;
914    E_Client *ec;
915 
916    ecore_animator_frametime_set(ecore_frametime);
917    if (!e_comp->saver) return ECORE_CALLBACK_RENEW;
918    e_comp_override_del();
919    e_comp->saver = EINA_FALSE;
920    if (!e_comp->nocomp)
921      ecore_evas_manual_render_set(e_comp->ee, EINA_FALSE);
922    EINA_LIST_FOREACH(e_comp->zones, l, zone)
923      {
924         edje_object_signal_emit(zone->base, "e,state,screensaver,off", "e");
925         edje_object_signal_emit(zone->over, "e,state,screensaver,off", "e");
926         e_zone_fade_handle(zone, 0, 0.5);
927      }
928    E_CLIENT_FOREACH(ec)
929      if (e_comp_object_damage_exists(ec->frame))
930        e_comp_object_render_update_add(ec->frame);
931 
932    return ECORE_CALLBACK_PASS_ON;
933 }
934 
935 static Evas_Object *
_e_comp_act_opacity_obj_finder(E_Object * obj)936 _e_comp_act_opacity_obj_finder(E_Object *obj)
937 {
938    E_Client *ec;
939 
940    switch (obj->type)
941      {
942       case E_CLIENT_TYPE:
943         return ((E_Client *)(void *)obj)->frame;
944       case E_ZONE_TYPE:
945       case E_COMP_TYPE:
946       case E_MENU_TYPE:
947         ec = e_client_focused_get();
948         return ec ? ec->frame : NULL;
949      }
950    if (e_obj_is_win(obj))
951      return e_win_client_get((void *)obj)->frame;
952    ec = e_client_focused_get();
953    return ec ? ec->frame : NULL;
954 }
955 
956 static void
_e_comp_act_opacity_change_go(E_Object * obj,const char * params)957 _e_comp_act_opacity_change_go(E_Object *obj, const char *params)
958 {
959    int opacity, cur;
960    Evas_Object *o;
961 
962    if ((!params) || (!params[0])) return;
963    o = _e_comp_act_opacity_obj_finder(obj);
964    if (!o) return;
965    opacity = atoi(params);
966    opacity = E_CLAMP(opacity, -255, 255);
967    evas_object_color_get(o, NULL, NULL, NULL, &cur);
968    opacity += cur;
969    opacity = E_CLAMP(opacity, 0, 255);
970    evas_object_color_set(o, opacity, opacity, opacity, opacity);
971 }
972 
973 static void
_e_comp_act_opacity_set_go(E_Object * obj EINA_UNUSED,const char * params)974 _e_comp_act_opacity_set_go(E_Object * obj EINA_UNUSED, const char *params)
975 {
976    int opacity;
977    Evas_Object *o;
978 
979    if ((!params) || (!params[0])) return;
980    o = _e_comp_act_opacity_obj_finder(obj);
981    if (!o) return;
982    opacity = atoi(params);
983    opacity = E_CLAMP(opacity, 0, 255);
984    evas_object_color_set(o, opacity, opacity, opacity, opacity);
985 }
986 
987 static void
_e_comp_act_redirect_toggle_go(E_Object * obj EINA_UNUSED,const char * params EINA_UNUSED)988 _e_comp_act_redirect_toggle_go(E_Object * obj EINA_UNUSED, const char *params EINA_UNUSED)
989 {
990    E_Client *ec;
991 
992    ec = e_client_focused_get();
993    if ((!ec) || (!e_pixmap_is_x(ec->pixmap)) || (ec == e_comp->nocomp_ec)) return;
994    e_comp_client_redirect_toggle(ec);
995 }
996 
997 //////////////////////////////////////////////////////////////////////////
998 
999 static void
_e_comp_resize(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1000 _e_comp_resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1001 {
1002    int w, h;
1003 
1004    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1005    if ((w == e_comp->w) && (h == e_comp->h)) return;
1006    e_randr2_screens_setup(w, h);
1007    e_comp_canvas_update();
1008 }
1009 
1010 static void
_e_comp_delete_request()1011 _e_comp_delete_request()
1012 {
1013    e_sys_action_do(E_SYS_LOGOUT, NULL);
1014 }
1015 
1016 EINTERN Eina_Bool
e_comp_init(void)1017 e_comp_init(void)
1018 {
1019    _e_comp_log_dom = eina_log_domain_register("e_comp", EINA_COLOR_YELLOW);
1020 
1021    ecore_frametime = ecore_animator_frametime_get();
1022    shape_debug = !!getenv("E_SHAPE_DEBUG");
1023 
1024    E_EVENT_COMPOSITOR_UPDATE = ecore_event_type_new();
1025    E_EVENT_COMP_OBJECT_ADD = ecore_event_type_new();
1026    E_EVENT_COMPOSITOR_DISABLE = ecore_event_type_new();
1027    E_EVENT_COMPOSITOR_ENABLE = ecore_event_type_new();
1028    E_EVENT_COMPOSITOR_XWAYLAND_INIT = ecore_event_type_new();
1029 
1030    ignores = eina_hash_pointer_new(NULL);
1031 
1032    e_comp_cfdata_edd_init(&conf_edd, &conf_match_edd);
1033    conf = e_config_domain_load("e_comp", conf_edd);
1034    if (conf)
1035      {
1036         conf->max_unmapped_pixels = 32 * 1024;
1037         conf->keep_unmapped = 1;
1038      }
1039    else
1040      conf = e_comp_cfdata_config_new();
1041 
1042    // comp config versioning - add this in. over time add epochs etc. if
1043    // necessary, but for now a simple version number will do
1044    if (conf->version < E_COMP_VERSION)
1045      {
1046         switch (conf->version)
1047           {
1048            case 0:
1049              // going from version 0 we should disable grab for smoothness
1050              conf->grab = 0;
1051              /* fallthrough */
1052            default:
1053              break;
1054           }
1055         e_config_save_queue();
1056         conf->version = E_COMP_VERSION;
1057      }
1058 
1059    {
1060       E_Action *act;
1061 
1062       act = e_action_add("opacity_change");
1063       act->func.go = _e_comp_act_opacity_change_go;
1064       e_action_predef_name_set(N_("Compositor"),
1065                                N_("Change current window opacity"), "opacity_change",
1066                                NULL, "syntax: +/- the amount to change opacity by (>0 for more opaque)", 1);
1067       actions = eina_list_append(actions, act);
1068       act = e_action_add("opacity_set");
1069       act->func.go = _e_comp_act_opacity_set_go;
1070       e_action_predef_name_set(N_("Compositor"),
1071                                N_("Set current window opacity"), "opacity_set",
1072                                "255", "syntax: number between 0-255 to set for transparent-opaque", 1);
1073       actions = eina_list_append(actions, act);
1074       act = e_action_add("redirect_toggle");
1075       act->func.go = _e_comp_act_redirect_toggle_go;
1076       e_action_predef_name_set(N_("Compositor"),
1077                                N_("Toggle focused client's redirect state"), "redirect_toggle",
1078                                NULL, NULL, 0);
1079       actions = eina_list_append(actions, act);
1080    }
1081 
1082    e_comp_new();
1083    e_comp->comp_type = E_PIXMAP_TYPE_NONE;
1084 
1085    {
1086       const char *gl;
1087 
1088       gl = getenv("E_COMP_ENGINE");
1089       if (gl)
1090         {
1091            int val;
1092 
1093            val = strtol(gl, NULL, 10);
1094            if ((val == E_COMP_ENGINE_SW) || (val == E_COMP_ENGINE_GL))
1095              e_comp_config_get()->engine = val;
1096            else if (!strcmp(gl, "gl"))
1097              e_comp_config_get()->engine = E_COMP_ENGINE_GL;
1098            else if (!strcmp(gl, "sw"))
1099              e_comp_config_get()->engine = E_COMP_ENGINE_SW;
1100            else
1101              {
1102                 fprintf(stderr,
1103                         "ERROR: E_COMP_ENGINE value '%s' invalid.\n"
1104                         "Please use 'gl' or 'sw'.\n"
1105                         "Valid values below that request a type of acceleration:\n"
1106                         "  'gl' : OpenGL based acceleration.\n"
1107                         "  'sw' : CPU based Software rendering.\n",
1108                         gl);
1109                 exit(101);
1110              }
1111         }
1112    }
1113    {
1114       const char *eng;
1115 
1116       eng = getenv("E_WL_FORCE");
1117       if (eng)
1118         {
1119            if ((!strcmp(eng, "buffer")) ||
1120                (!strcmp(eng, "drm")) ||
1121                (!strcmp(eng, "wl")) ||
1122                (!strcmp(eng, "x11")))
1123              {
1124                 char buf[128];
1125 
1126                 snprintf(buf, sizeof(buf), "wl_%s", eng);
1127                 e_xkb_init(E_PIXMAP_TYPE_WL);
1128                 if (e_module_enable(e_module_new(buf)))
1129                   {
1130                      e_comp->comp_type = E_PIXMAP_TYPE_WL;
1131                      goto out;
1132                   }
1133              }
1134            else
1135              {
1136                 fprintf(stderr,
1137                         "ERROR: E_WL_FORCE value '%s' invalid.\n"
1138                         "Please use 'buffer', 'drm', 'wl' or 'x11'\n"
1139                         "Valid values below that request a type of rendering output target:\n"
1140                         "  'buffer' : Invisible memory buffer. (Debugging/testing)\n"
1141                         "  'drm'    : DRM/KMS framebuffer. (You want this as a normal full-screen stand-alone Wayland compositor)\n"
1142                         "  'wl'     : Window as a Wayland application. (Compositor in a Window for debugging/development/testing)\n"
1143                         "  'x11'    : Window as a X11 application. (Compositor in a Window for debugging/development/testing)\n",
1144                         eng);
1145                 exit(101);
1146              }
1147         }
1148    }
1149 
1150 #ifndef HAVE_WAYLAND_ONLY
1151    if (e_comp_x_init())
1152      {
1153         e_comp->comp_type = E_PIXMAP_TYPE_X;
1154         e_xkb_init(E_PIXMAP_TYPE_X);
1155      }
1156    else
1157 #endif
1158      {
1159         const char **test, *eng[] =
1160         {
1161 #ifdef USE_MODULE_WL_WL
1162            "wl_wl",
1163 #endif
1164 #ifdef USE_MODULE_WL_X11
1165            "wl_x11",
1166 #endif
1167 #ifdef USE_MODULE_WL_DRM
1168            "wl_drm",
1169 #endif
1170 /* probably add other engines here; fb should be last? */
1171 #ifdef USE_MODULE_WL_FB
1172            "wl_fb",
1173 #endif
1174            NULL
1175         };
1176 
1177         e_xkb_init(E_PIXMAP_TYPE_WL);
1178         e_util_env_set("HYBRIS_EGLPLATFORM", "wayland");
1179         for (test = eng; *test; test++)
1180           {
1181              if (e_module_enable(e_module_new(*test)))
1182                {
1183                   e_comp->comp_type = E_PIXMAP_TYPE_WL;
1184                   goto out;
1185                }
1186           }
1187         return EINA_FALSE;
1188      }
1189 //#ifdef HAVE_WAYLAND_CLIENTS
1190    //e_comp_wl_init();
1191 //#endif
1192    if (e_comp->comp_type == E_PIXMAP_TYPE_NONE) return EINA_FALSE;
1193 out:
1194    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
1195      {
1196         e_comp_canvas_fake_layers_init();
1197         e_screensaver_update();
1198      }
1199    e_comp->elm = elm_win_fake_add(e_comp->ee);
1200    evas_object_event_callback_add(e_comp->elm, EVAS_CALLBACK_RESIZE, _e_comp_resize, NULL);
1201    elm_win_fullscreen_set(e_comp->elm, 1);
1202    elm_win_autodel_set(e_comp->elm, 1);
1203    if (!e_comp->screen)
1204      evas_object_smart_callback_add(e_comp->elm, "delete,request", _e_comp_delete_request, NULL);
1205    ecore_evas_focus_set(e_comp->ee, 0);
1206    ecore_evas_focus_set(e_comp->ee, 1);
1207    evas_object_show(e_comp->elm);
1208    e_util_env_set("HYBRIS_EGLPLATFORM", NULL);
1209    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON, _e_comp_screensaver_on, NULL);
1210    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_OFF, _e_comp_screensaver_off, NULL);
1211 
1212    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_KEY_DOWN, _e_comp_key_down, NULL);
1213    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_SIGNAL_USER, _e_comp_signal_user, NULL);
1214    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _e_comp_object_add, NULL);
1215 
1216    return EINA_TRUE;
1217 }
1218 
1219 
1220 static Eina_Bool
_style_demo(void * data)1221 _style_demo(void *data)
1222 {
1223    Eina_List *style_shadows, *l;
1224    int demo_state;
1225    const E_Comp_Demo_Style_Item *it;
1226 
1227    demo_state = (long)evas_object_data_get(data, "style_demo_state");
1228    demo_state = (demo_state + 1) % 4;
1229    evas_object_data_set(data, "style_demo_state", (void *)(long)demo_state);
1230 
1231    style_shadows = evas_object_data_get(data, "style_shadows");
1232    EINA_LIST_FOREACH(style_shadows, l, it)
1233      {
1234         Evas_Object *ob = it->preview;
1235         Evas_Object *of = it->frame;
1236 
1237         switch (demo_state)
1238           {
1239            case 0:
1240              edje_object_signal_emit(ob, "e,state,visible", "e");
1241              edje_object_signal_emit(ob, "e,state,focused", "e");
1242              edje_object_part_text_set(of, "e.text.label", _("Visible"));
1243              break;
1244 
1245            case 1:
1246              edje_object_signal_emit(ob, "e,state,unfocused", "e");
1247              edje_object_part_text_set(of, "e.text.label", _("Focus-Out"));
1248              break;
1249 
1250            case 2:
1251              edje_object_signal_emit(ob, "e,state,focused", "e");
1252              edje_object_part_text_set(of, "e.text.label", _("Focus-In"));
1253              break;
1254 
1255            case 3:
1256              edje_object_signal_emit(ob, "e,state,hidden", "e");
1257              edje_object_part_text_set(of, "e.text.label", _("Hidden"));
1258              break;
1259 
1260            default:
1261              break;
1262           }
1263      }
1264    return ECORE_CALLBACK_RENEW;
1265 }
1266 
1267 static void
_style_selector_del(void * data EINA_UNUSED,Evas * e,Evas_Object * o,void * event_info EINA_UNUSED)1268 _style_selector_del(void *data       EINA_UNUSED,
1269                     Evas *e,
1270                     Evas_Object *o,
1271                     void *event_info EINA_UNUSED)
1272 {
1273    Eina_List *style_shadows, *style_list;
1274    Ecore_Timer *timer;
1275    Evas_Object *orec0;
1276 
1277    orec0 = evas_object_name_find(e, "style_shadows");
1278    style_list = evas_object_data_get(orec0, "list");
1279 
1280    style_shadows = evas_object_data_get(o, "style_shadows");
1281    if (style_shadows)
1282      {
1283         E_Comp_Demo_Style_Item *ds_it;
1284 
1285         EINA_LIST_FREE(style_shadows, ds_it)
1286           {
1287              style_list = eina_list_remove(style_list, ds_it);
1288 
1289              evas_object_del(ds_it->frame);
1290              evas_object_del(ds_it->livethumb);
1291              free(ds_it);
1292           }
1293         evas_object_data_set(o, "style_shadows", NULL);
1294      }
1295 
1296    timer = evas_object_data_get(o, "style_timer");
1297    if (timer)
1298      {
1299         ecore_timer_del(timer);
1300         evas_object_data_set(o, "style_timer", NULL);
1301      }
1302 
1303    evas_object_data_set(orec0, "list", style_list);
1304 }
1305 
1306 EINTERN Evas_Object *
e_comp_style_selector_create(Evas * evas,const char ** source)1307 e_comp_style_selector_create(Evas *evas, const char **source)
1308 {
1309    Evas_Object *oi, *ob, *oo, *obd, *orec, *oly, *orec0;
1310    Eina_List *styles, *l, *style_shadows = NULL, *style_list;
1311    char *style;
1312    const char *str;
1313    int n, sel;
1314    Evas_Coord wmw, wmh;
1315    Ecore_Timer *timer;
1316 
1317    orec0 = evas_object_name_find(evas, "style_shadows");
1318    style_list = evas_object_data_get(orec0, "list");
1319    oi = e_widget_ilist_add(evas, 80, 80, source);
1320    evas_object_event_callback_add(oi, EVAS_CALLBACK_DEL,
1321                                   _style_selector_del, oi);
1322    sel = 0;
1323    styles = e_theme_comp_frame_list();
1324    n = 0;
1325    EINA_LIST_FOREACH(styles, l, style)
1326      {
1327         E_Comp_Demo_Style_Item *ds_it;
1328         char buf[4096];
1329 
1330         ds_it = malloc(sizeof(E_Comp_Demo_Style_Item));
1331 
1332         ob = e_livethumb_add(evas);
1333         ds_it->livethumb = ob;
1334         e_livethumb_vsize_set(ob, 240, 240);
1335 
1336         oly = e_layout_add(e_livethumb_evas_get(ob));
1337         ds_it->layout = ob;
1338         e_layout_virtual_size_set(oly, 240, 240);
1339         e_livethumb_thumb_set(ob, oly);
1340         evas_object_show(oly);
1341 
1342         oo = edje_object_add(e_livethumb_evas_get(ob));
1343         ds_it->preview = oo;
1344         snprintf(buf, sizeof(buf), "e/comp/frame/%s", style);
1345         e_theme_edje_object_set(oo, "base/theme/borders", buf);
1346         e_layout_pack(oly, oo);
1347         e_layout_child_move(oo, 39, 39);
1348         e_layout_child_resize(oo, 162, 162);
1349         edje_object_signal_emit(oo, "e,state,visible", "e");
1350         edje_object_signal_emit(oo, "e,state,focused", "e");
1351         evas_object_show(oo);
1352 
1353         ds_it->frame = edje_object_add(evas);
1354         e_theme_edje_object_set
1355           (ds_it->frame, "base/theme/comp", "e/comp/preview");
1356         edje_object_part_swallow(ds_it->frame, "e.swallow.preview", ob);
1357         evas_object_show(ds_it->frame);
1358         style_shadows = eina_list_append(style_shadows, ds_it);
1359 
1360         obd = edje_object_add(e_livethumb_evas_get(ob));
1361         ds_it->border = obd;
1362         e_theme_edje_object_set(obd, "base/theme/borders",
1363                                 "e/widgets/border/default/border");
1364         edje_object_part_text_set(obd, "e.text.title", _("Title"));
1365         edje_object_signal_emit(obd, "e,state,shadow,on", "e");
1366         edje_object_part_swallow(oo, "e.swallow.content", obd);
1367         evas_object_show(obd);
1368 
1369         orec = evas_object_rectangle_add(e_livethumb_evas_get(ob));
1370         ds_it->client = orec;
1371         evas_object_color_set(orec, 0, 0, 0, 128);
1372         edje_object_part_swallow(obd, "e.swallow.client", orec);
1373         evas_object_show(orec);
1374 
1375         e_widget_ilist_append(oi, ds_it->frame, style, NULL, NULL, style);
1376         evas_object_show(ob);
1377         if (*source)
1378           {
1379              if (!strcmp(*source, style)) sel = n;
1380           }
1381         n++;
1382 
1383         style_list = eina_list_append(style_list, ds_it);
1384      }
1385    evas_object_data_set(orec0, "list", style_list);
1386    evas_object_data_set(oi, "style_shadows", style_shadows);
1387    timer = ecore_timer_loop_add(3.0, _style_demo, oi);
1388    evas_object_data_set(oi, "style_timer", timer);
1389    evas_object_data_set(oi, "style_demo_state", (void *)1);
1390    e_widget_size_min_get(oi, &wmw, &wmh);
1391    e_widget_size_min_set(oi, 160, 100);
1392    e_widget_ilist_selected_set(oi, sel);
1393    e_widget_ilist_go(oi);
1394 
1395    EINA_LIST_FREE(styles, str)
1396      eina_stringshare_del(str);
1397 
1398    return oi;
1399 }
1400 
1401 E_API E_Comp *
e_comp_new(void)1402 e_comp_new(void)
1403 {
1404    if (e_comp)
1405      CRI("CANNOT REPLACE EXISTING COMPOSITOR");
1406    e_comp = E_OBJECT_ALLOC(E_Comp, E_COMP_TYPE, _e_comp_free);
1407    if (!e_comp) return NULL;
1408    e_comp->canvas = E_NEW(E_Comp_Canvas, 1);
1409 
1410    e_comp->render_animator = ecore_animator_add(_e_comp_cb_animator, NULL);
1411    ecore_animator_freeze(e_comp->render_animator);
1412    return e_comp;
1413 }
1414 
1415 E_API int
e_comp_internal_save(void)1416 e_comp_internal_save(void)
1417 {
1418    return e_config_domain_save("e_comp", conf_edd, conf);
1419 }
1420 
1421 EINTERN int
e_comp_shutdown(void)1422 e_comp_shutdown(void)
1423 {
1424    Eina_List *l, *ll;
1425    E_Client *ec;
1426 
1427    E_FREE_FUNC(action_timeout, ecore_timer_del);
1428    EINA_LIST_FOREACH_SAFE(e_comp->clients, l, ll, ec)
1429      {
1430         DELD(ec, 99999);
1431         e_object_del(E_OBJECT(ec));
1432      }
1433 
1434    e_object_del(E_OBJECT(e_comp));
1435    e_comp = NULL;
1436    E_FREE_LIST(handlers, ecore_event_handler_del);
1437    E_FREE_LIST(actions, e_object_del);
1438    E_FREE_LIST(hooks, e_client_hook_del);
1439 
1440    gl_avail = EINA_FALSE;
1441    e_comp_cfdata_config_free(conf);
1442    E_CONFIG_DD_FREE(conf_match_edd);
1443    E_CONFIG_DD_FREE(conf_edd);
1444    conf = NULL;
1445    conf_match_edd = NULL;
1446    conf_edd = NULL;
1447 
1448    E_FREE_FUNC(ignores, eina_hash_free);
1449 
1450    return 1;
1451 }
1452 
1453 E_API void
e_comp_render_queue(void)1454 e_comp_render_queue(void)
1455 {
1456    if (conf->lock_fps)
1457      {
1458         ecore_animator_thaw(e_comp->render_animator);
1459      }
1460    else
1461      {
1462         if (e_comp->update_job)
1463           {
1464              DBG("UPDATE JOB DEL...");
1465              E_FREE_FUNC(e_comp->update_job, ecore_job_del);
1466           }
1467         DBG("UPDATE JOB ADD...");
1468         e_comp->update_job = ecore_job_add(_e_comp_cb_job, e_comp);
1469      }
1470 }
1471 
1472 E_API void
e_comp_client_post_update_add(E_Client * ec)1473 e_comp_client_post_update_add(E_Client *ec)
1474 {
1475    if (ec->on_post_updates) return;
1476    ec->on_post_updates = EINA_TRUE;
1477    e_comp->post_updates = eina_list_append(e_comp->post_updates, ec);
1478    REFD(ec, 111);
1479    e_object_ref(E_OBJECT(ec));
1480 }
1481 
1482 E_API void
e_comp_shape_queue(void)1483 e_comp_shape_queue(void)
1484 {
1485    if ((e_comp->comp_type != E_PIXMAP_TYPE_X) && (!e_comp_util_has_x())) return;
1486    if (!e_comp->shape_job)
1487      e_comp->shape_job = ecore_job_add(_e_comp_shapes_update_job, NULL);
1488 }
1489 
1490 E_API void
e_comp_shape_queue_block(Eina_Bool block)1491 e_comp_shape_queue_block(Eina_Bool block)
1492 {
1493    e_comp->shape_queue_blocked = !!block;
1494    if (block)
1495      E_FREE_FUNC(e_comp->shape_job, ecore_job_del);
1496    else
1497      e_comp_shape_queue();
1498 }
1499 
1500 E_API E_Comp_Config *
e_comp_config_get(void)1501 e_comp_config_get(void)
1502 {
1503    return conf;
1504 }
1505 
1506 E_API void
e_comp_shadows_reset(void)1507 e_comp_shadows_reset(void)
1508 {
1509    E_Client *ec;
1510 
1511    _e_comp_fps_update();
1512    E_LIST_FOREACH(e_comp->zones, e_comp_canvas_zone_update);
1513    E_CLIENT_FOREACH(ec)
1514      e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
1515 }
1516 
1517 E_API Ecore_Window
e_comp_top_window_at_xy_get(Evas_Coord x,Evas_Coord y)1518 e_comp_top_window_at_xy_get(Evas_Coord x, Evas_Coord y)
1519 {
1520    E_Client *ec;
1521    Evas_Object *o;
1522 
1523    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, 0);
1524    o = evas_object_top_at_xy_get(e_comp->evas, x, y, 0, 0);
1525    if (!o) return e_comp->ee_win;
1526    ec = evas_object_data_get(o, "E_Client");
1527    if (ec) return e_client_util_pwin_get(ec);
1528    return e_comp->ee_win;
1529 }
1530 
1531 E_API void
e_comp_util_wins_print(void)1532 e_comp_util_wins_print(void)
1533 {
1534    Evas_Object *o;
1535 
1536    o = evas_object_top_get(e_comp->evas);
1537    while (o)
1538      {
1539         E_Client *ec;
1540         int x, y, w, h;
1541 
1542         ec = evas_object_data_get(o, "E_Client");
1543         evas_object_geometry_get(o, &x, &y, &w, &h);
1544         fprintf(stderr, "LAYER %d  ", evas_object_layer_get(o));
1545         if (ec)
1546           fprintf(stderr, "EC%s%s:  %p - '%s:%s' || %d,%d @ %dx%d\n",
1547                   ec->override ? "O" : "", ec->focused ? "*" : "", ec,
1548                   e_client_util_name_get(ec) ?: ec->icccm.name, ec->icccm.class, x, y, w, h);
1549         else
1550           fprintf(stderr, "OBJ: %p - %s || %d,%d @ %dx%d\n", o, evas_object_name_get(o), x, y, w, h);
1551         o = evas_object_below_get(o);
1552      }
1553    fputc('\n', stderr);
1554 }
1555 
1556 E_API void
e_comp_ignore_win_add(E_Pixmap_Type type,Ecore_Window win)1557 e_comp_ignore_win_add(E_Pixmap_Type type, Ecore_Window win)
1558 {
1559    E_Client *ec;
1560 
1561    eina_hash_add(ignores, &win, (void*)1);
1562    ec = e_pixmap_find_client(type, win);
1563    if (!ec) return;
1564    ec->ignored = 1;
1565    if (ec->visible) evas_object_hide(ec->frame);
1566 }
1567 
1568 E_API void
e_comp_ignore_win_del(E_Pixmap_Type type,Ecore_Window win)1569 e_comp_ignore_win_del(E_Pixmap_Type type, Ecore_Window win)
1570 {
1571    E_Client *ec;
1572 
1573    eina_hash_del_by_key(ignores, &win);
1574    ec = e_pixmap_find_client(type, win);
1575    if ((!ec) || (e_object_is_del(E_OBJECT(ec)))) return;
1576    ec->ignored = 0;
1577    if (ec->visible) evas_object_show(ec->frame);
1578 }
1579 
1580 E_API Eina_Bool
e_comp_ignore_win_find(Ecore_Window win)1581 e_comp_ignore_win_find(Ecore_Window win)
1582 {
1583    return !!eina_hash_find(ignores, &win);
1584 }
1585 
1586 E_API void
e_comp_override_del(void)1587 e_comp_override_del(void)
1588 {
1589    e_comp->nocomp_override--;
1590    if (e_comp->nocomp_override <= 0)
1591      {
1592         e_comp->nocomp_override = 0;
1593         if (e_comp->nocomp_want) _e_comp_cb_nocomp_begin();
1594      }
1595 }
1596 
1597 E_API void
e_comp_override_add(void)1598 e_comp_override_add(void)
1599 {
1600    e_comp->nocomp_override++;
1601    if ((e_comp->nocomp_override > 0) && (e_comp->nocomp)) _e_comp_nocomp_end();
1602 }
1603 
1604 #if 0
1605 FIXME
1606 E_API void
1607 e_comp_block_window_add(void)
1608 {
1609    e_comp->block_count++;
1610    if (e_comp->block_win) return;
1611    e_comp->block_win = ecore_x_window_new(e_comp->root, 0, 0, e_comp->w, e_comp->h);
1612    INF("BLOCK WIN: %x", e_comp->block_win);
1613    ecore_x_window_background_color_set(e_comp->block_win, 0, 0, 0);
1614    e_comp_ignore_win_add(e_comp->block_win);
1615    ecore_x_window_configure(e_comp->block_win,
1616      ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING | ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1617      0, 0, 0, 0, 0, ((E_Comp_Win*)e_comp->wins)->win, ECORE_X_WINDOW_STACK_ABOVE);
1618    ecore_x_window_show(e_comp->block_win);
1619 }
1620 
1621 E_API void
1622 e_comp_block_window_del(void)
1623 {
1624    if (!e_comp->block_count) return;
1625    e_comp->block_count--;
1626    if (e_comp->block_count) return;
1627    if (e_comp->block_win) ecore_x_window_free(e_comp->block_win);
1628    e_comp->block_win = 0;
1629 }
1630 #endif
1631 
1632 E_API E_Comp *
e_comp_find_by_window(Ecore_Window win)1633 e_comp_find_by_window(Ecore_Window win)
1634 {
1635    if ((e_comp->win == win) || (e_comp->ee_win == win) || (e_comp->root == win)) return e_comp;
1636    return NULL;
1637 }
1638 
1639 E_API void
e_comp_override_timed_pop(void)1640 e_comp_override_timed_pop(void)
1641 {
1642    if (e_comp->nocomp_override <= 0) return;
1643    if (e_comp->nocomp_override_timer)
1644      e_comp->nocomp_override--;
1645    else
1646      e_comp->nocomp_override_timer = ecore_timer_loop_add(1.0, _e_comp_override_expire, NULL);
1647 }
1648 
1649 E_API unsigned int
e_comp_e_object_layer_get(const E_Object * obj)1650 e_comp_e_object_layer_get(const E_Object *obj)
1651 {
1652    E_Gadcon *gc = NULL;
1653 
1654    if (!obj) return 0;
1655 
1656    switch (obj->type)
1657      {
1658       case E_GADCON_CLIENT_TYPE:
1659         gc = ((E_Gadcon_Client *)(void *)(obj))->gadcon;
1660         EINA_SAFETY_ON_NULL_RETURN_VAL(gc, 0);
1661         EINA_FALLTHROUGH;
1662         /* no break */
1663 
1664       case E_GADCON_TYPE:
1665         if (!gc) gc = (E_Gadcon *)obj;
1666         if (gc->shelf) return gc->shelf->layer;
1667         if (!gc->toolbar) return E_LAYER_DESKTOP;
1668         return e_win_client_get(gc->toolbar->fwin)->layer;
1669 
1670       case E_ZONE_TYPE:
1671         return E_LAYER_DESKTOP;
1672 
1673       case E_CLIENT_TYPE:
1674         return ((E_Client *)(void *)(obj))->layer;
1675 
1676       /* FIXME: add more types as needed */
1677       default:
1678         break;
1679      }
1680    if (e_obj_is_win(obj))
1681      return e_win_client_get((void*)obj)->layer;
1682    return 0;
1683 }
1684 
1685 E_API Eina_Bool
e_comp_grab_input(Eina_Bool mouse,Eina_Bool kbd)1686 e_comp_grab_input(Eina_Bool mouse, Eina_Bool kbd)
1687 {
1688    Eina_Bool ret = EINA_FALSE;
1689    Ecore_Window mwin = 0, kwin = 0;
1690 
1691    mouse = !!mouse;
1692    kbd = !!kbd;
1693    if (mouse || e_comp->input_mouse_grabs)
1694      mwin = e_comp->ee_win;
1695    if (kbd || e_comp->input_mouse_grabs)
1696      kwin = e_comp->ee_win;
1697    e_comp_override_add();
1698    if ((e_comp->input_mouse_grabs && e_comp->input_key_grabs) ||
1699        e_grabinput_get(mwin, 0, kwin))
1700      {
1701         E_Client *ec = e_client_focused_get();
1702 
1703         if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
1704           {
1705              if (ec)
1706                evas_object_focus_set(ec->frame, 0);
1707 
1708 #ifdef HAVE_WAYLAND
1709              e_comp_wl_extension_pointer_unconstrain(NULL);
1710 #endif
1711           }
1712 
1713         ret = EINA_TRUE;
1714         e_comp->input_mouse_grabs += mouse;
1715         e_comp->input_key_grabs += kbd;
1716 
1717         if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
1718           {
1719              if (ec && (!e_object_is_del(E_OBJECT(ec))))
1720                evas_object_focus_set(ec->frame, 1);
1721           }
1722      }
1723    return ret;
1724 }
1725 
1726 E_API void
e_comp_ungrab_input(Eina_Bool mouse,Eina_Bool kbd)1727 e_comp_ungrab_input(Eina_Bool mouse, Eina_Bool kbd)
1728 {
1729    Ecore_Window mwin = 0, kwin = 0;
1730 
1731    mouse = !!mouse;
1732    kbd = !!kbd;
1733    if (e_comp->input_mouse_grabs)
1734      e_comp->input_mouse_grabs -= mouse;
1735    if (e_comp->input_key_grabs)
1736      e_comp->input_key_grabs -= kbd;
1737    if (mouse && (!e_comp->input_mouse_grabs))
1738      mwin = e_comp->ee_win;
1739    if (kbd && (!e_comp->input_key_grabs))
1740      kwin = e_comp->ee_win;
1741    e_comp_override_timed_pop();
1742    if ((!mwin) && (!kwin)) return;
1743    e_grabinput_release(mwin, kwin);
1744    evas_event_feed_mouse_out(e_comp->evas, 0, NULL);
1745    evas_event_feed_mouse_in(e_comp->evas, 0, NULL);
1746    if (e_client_focused_get())
1747      {
1748         E_Client *ec = e_client_focused_get();
1749 
1750         if ((!e_object_is_del(E_OBJECT(ec))) && (e_comp->comp_type == E_PIXMAP_TYPE_WL))
1751           {
1752              Eina_Bool mouse_in = ec->mouse.in;
1753              int x, y;
1754 
1755              x = ec->mouse.current.mx;
1756              y = ec->mouse.current.my;
1757              evas_object_focus_set(ec->frame, 0);
1758              evas_object_focus_set(ec->frame, 1);
1759              if (mouse_in)
1760                e_client_mouse_in(ec, x, y);
1761           }
1762         return;
1763      }
1764    if (e_config->focus_policy != E_FOCUS_MOUSE)
1765      e_client_refocus();
1766 }
1767 
1768 E_API Eina_Bool
e_comp_util_kbd_grabbed(void)1769 e_comp_util_kbd_grabbed(void)
1770 {
1771    return e_menu_is_active() || e_client_action_get() || e_grabinput_key_win_get();
1772 }
1773 
1774 E_API Eina_Bool
e_comp_util_mouse_grabbed(void)1775 e_comp_util_mouse_grabbed(void)
1776 {
1777    return e_menu_is_active() || e_client_action_get() || e_grabinput_mouse_win_get();
1778 }
1779 
1780 E_API void
e_comp_gl_set(Eina_Bool set)1781 e_comp_gl_set(Eina_Bool set)
1782 {
1783    gl_avail = !!set;
1784 }
1785 
1786 E_API Eina_Bool
e_comp_gl_get(void)1787 e_comp_gl_get(void)
1788 {
1789    return gl_avail;
1790 }
1791 
1792 E_API void
e_comp_button_bindings_ungrab_all(void)1793 e_comp_button_bindings_ungrab_all(void)
1794 {
1795    if (e_comp->bindings_ungrab_cb)
1796      e_comp->bindings_ungrab_cb();
1797 }
1798 
1799 E_API void
e_comp_button_bindings_grab_all(void)1800 e_comp_button_bindings_grab_all(void)
1801 {
1802    if (e_comp->bindings_grab_cb)
1803      e_comp->bindings_grab_cb();
1804 }
1805 
1806 E_API void
e_comp_client_redirect_toggle(E_Client * ec)1807 e_comp_client_redirect_toggle(E_Client *ec)
1808 {
1809    EINA_SAFETY_ON_NULL_RETURN(ec);
1810    if (!conf->enable_advanced_features) return;
1811    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) return;
1812    ec->unredirected_single = !ec->unredirected_single;
1813    e_client_redirected_set(ec, !ec->redirected);
1814    ec->no_shape_cut = !ec->redirected;
1815    e_comp_shape_queue();
1816 }
1817 
1818 E_API Eina_Bool
e_comp_util_object_is_above_nocomp(Evas_Object * obj)1819 e_comp_util_object_is_above_nocomp(Evas_Object *obj)
1820 {
1821    Evas_Object *o;
1822    int cl, ol;
1823 
1824    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1825    if (!evas_object_visible_get(obj)) return EINA_FALSE;
1826    if (!e_comp->nocomp_ec) return EINA_FALSE;
1827    cl = evas_object_layer_get(e_comp->nocomp_ec->frame);
1828    ol = evas_object_layer_get(obj);
1829    if (cl > ol) return EINA_FALSE;
1830    o = evas_object_above_get(e_comp->nocomp_ec->frame);
1831    if ((cl == ol) && (evas_object_layer_get(o) == cl))
1832      {
1833         do {
1834            if (o == obj)
1835              return EINA_TRUE;
1836            o = evas_object_above_get(o);
1837         } while (o && (evas_object_layer_get(o) == cl));
1838      }
1839    else
1840      return EINA_TRUE;
1841    return EINA_FALSE;
1842 }
1843 
1844 E_API void
e_comp_clients_rescale(void)1845 e_comp_clients_rescale(void)
1846 {
1847    int i;
1848 
1849    if (stopping) return;
1850    for (i = 0; i < 11; i++)
1851      {
1852         Eina_List *tmp = NULL;
1853         E_Client *ec;
1854 
1855         if (!e_comp->layers[i].clients) continue;
1856         /* Make temporary list as e_client_res_change_geometry_restore
1857          * rearranges the order. */
1858         EINA_INLIST_FOREACH(e_comp->layers[i].clients, ec)
1859           {
1860              if ((!e_client_util_ignored_get(ec)) && (!e_object_is_del(E_OBJECT(ec))))
1861                tmp = eina_list_append(tmp, ec);
1862           }
1863 
1864         EINA_LIST_FREE(tmp, ec)
1865           {
1866              ec->pre_res_change.valid = 0;
1867              if (ec->maximized || ec->fullscreen)
1868                e_client_rescale(ec);
1869           }
1870      }
1871 }
1872