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