1 #include "e.h"
2 
3 #define SMART_NAME "e_deskmirror"
4 
5 #define INTERNAL_ENTRY E_Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
6 
7 #define API_ENTRY(X)   E_Smart_Data *sd; \
8                        sd = evas_object_smart_data_get(X); \
9                        if ((!X) || (!sd) || (e_util_strcmp(evas_object_type_get(X), SMART_NAME))) return
10 
11 typedef struct E_Smart_Data
12 {
13    Evas *e;
14    Evas_Object *obj;
15    Evas_Object *clip;
16    Evas_Object *bgpreview;
17    Evas_Object *layout;
18    Evas_Object *events;
19    Eina_Inlist *mirrors;
20    Eina_Hash *mirror_hash;
21 
22    Eina_List *handlers;
23 
24    Evas_Coord x, y;
25    int w, h;
26 
27    E_Desk *desk;
28    E_Object_Delfn *desk_delfn;
29 
30    Eina_Bool pager E_BITFIELD;
31    Eina_Bool taskbar E_BITFIELD;
32 
33    Eina_Bool resize E_BITFIELD;
34    Eina_Bool force E_BITFIELD;
35 } E_Smart_Data;
36 
37 typedef struct Mirror
38 {
39    EINA_INLIST;
40    E_Smart_Data *sd;
41    E_Client *ec;
42    Evas_Object *comp_object;
43    Evas_Object *mirror;
44    int x, y, w, h;
45    int ref;
46    Eina_Bool added E_BITFIELD;
47 } Mirror;
48 
49 typedef struct Mirror_Border
50 {
51    Mirror *m;
52    Evas_Object *mirror;
53    Evas_Object *frame;
54    Evas_Object *obj;
55 } Mirror_Border;
56 
57 static Evas_Smart *_e_deskmirror_smart = NULL;
58 static Evas_Smart *_mirror_client_smart = NULL;
59 
60 static void _e_deskmirror_mirror_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
61 static void _e_deskmirror_mirror_color_set_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED);
62 
63 static void _e_deskmirror_mirror_setup(Mirror *m);
64 static void _comp_object_dirty(void *data, Evas_Object *obj, void *event_info EINA_UNUSED);
65 static void _comp_object_hide(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
66 static void _comp_object_show(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
67 static void _comp_object_stack(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
68 static void _comp_object_configure(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED);
69 
70 static Eina_Bool
_e_deskmirror_visible_get(E_Smart_Data * sd,Mirror * m)71 _e_deskmirror_visible_get(E_Smart_Data *sd, Mirror *m)
72 {
73    Eina_Bool visible = evas_object_visible_get(m->comp_object);
74    if (m->ec && (!e_object_is_del(E_OBJECT(m->ec))))
75      {
76         visible = m->ec->visible;
77         /* all iconic visibility changes occur with iconic flag set:
78          * visibility here is determined by frame visibility
79          */
80         if (m->sd->handlers && m->ec->iconic)
81           visible = evas_object_visible_get(m->ec->frame);
82         if (visible)
83           {
84              visible = (sd->desk == m->ec->desk) || (m->ec->sticky && (!m->ec->hidden));
85              if (sd->pager)
86                visible = !m->ec->netwm.state.skip_pager;
87              if (visible && sd->taskbar)
88                visible = !m->ec->netwm.state.skip_taskbar;
89           }
90      }
91    if ((m->w < 1) || (m->h < 1)) visible = EINA_FALSE;
92    return visible;
93 }
94 
95 static void
_mirror_visible_apply(Mirror * m)96 _mirror_visible_apply(Mirror *m)
97 {
98    if (_e_deskmirror_visible_get(m->sd, m))
99      {
100         evas_object_show(m->mirror);
101      }
102    else
103      {
104         evas_object_hide(m->mirror);
105      }
106 }
107 
108 static void
_mirror_scale_set(Mirror * m,float sc)109 _mirror_scale_set(Mirror *m, float sc)
110 {
111    Edje_Message_Float msg;
112    Mirror_Border *mb;
113 
114    if (!m->mirror) return;
115    mb = evas_object_smart_data_get(m->mirror);
116    if (!mb) return;
117    msg.val = sc;
118    edje_object_message_send(mb->frame, EDJE_MESSAGE_FLOAT, 0, &msg);
119 }
120 
121 static void
_mirror_ref(Mirror * m)122 _mirror_ref(Mirror *m)
123 {
124    m->ref++;
125 }
126 
127 static void
_mirror_unref(Mirror * m)128 _mirror_unref(Mirror *m)
129 {
130    m->ref--;
131    if (m->ref > 0) return;
132    free(m);
133 }
134 
135 static void
_e_deskmirror_smart_reconfigure(E_Smart_Data * sd)136 _e_deskmirror_smart_reconfigure(E_Smart_Data *sd)
137 {
138    e_layout_freeze(sd->layout);
139    evas_object_move(sd->clip, sd->x, sd->y);
140    evas_object_move(sd->bgpreview, sd->x, sd->y);
141    evas_object_move(sd->layout, sd->x, sd->y);
142    if (sd->events)
143      evas_object_move(sd->events, sd->x, sd->y);
144 
145    if (sd->resize)
146      {
147         Mirror *m;
148 
149         evas_object_resize(sd->clip, sd->w, sd->h);
150         evas_object_resize(sd->bgpreview, sd->w, sd->h);
151         evas_object_resize(sd->layout, sd->w, sd->h);
152         if (sd->events)
153           evas_object_resize(sd->events, sd->w, sd->h);
154         EINA_INLIST_FOREACH(sd->mirrors, m)
155           _mirror_scale_set(m, (float)sd->h / (float)sd->desk->zone->h);
156      }
157    e_layout_thaw(sd->layout);
158    sd->resize = 0;
159 }
160 
161 ///////////////////////////////////////////////
162 
163 static void
_e_deskmirror_smart_add(Evas_Object * obj)164 _e_deskmirror_smart_add(Evas_Object *obj)
165 {
166    E_Smart_Data *sd;
167 
168    sd = E_NEW(E_Smart_Data, 1);
169    if (!sd) return;
170    sd->obj = obj;
171    sd->e = evas_object_evas_get(obj);
172    sd->x = sd->y = sd->w = sd->h = 0;
173    sd->clip = evas_object_rectangle_add(sd->e);
174    evas_object_smart_member_add(sd->clip, sd->obj);
175    evas_object_smart_data_set(obj, sd);
176 }
177 
178 static void
_e_deskmirror_smart_del(Evas_Object * obj)179 _e_deskmirror_smart_del(Evas_Object *obj)
180 {
181    INTERNAL_ENTRY;
182    e_object_unref(E_OBJECT(sd->desk));
183    if (sd->desk_delfn)
184      {
185         e_object_delfn_del(E_OBJECT(sd->desk), sd->desk_delfn);
186         sd->desk_delfn = NULL;
187         sd->desk = NULL;
188      }
189    E_FREE_LIST(sd->handlers, ecore_event_handler_del);
190    eina_hash_free(sd->mirror_hash);
191    evas_object_del(sd->clip);
192    evas_object_del(sd->bgpreview);
193    evas_object_del(sd->layout);
194    evas_object_del(sd->events);
195    free(sd);
196 }
197 
198 static void
_e_deskmirror_smart_move(Evas_Object * obj,Evas_Coord x,Evas_Coord y)199 _e_deskmirror_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
200 {
201    INTERNAL_ENTRY;
202    sd->x = x;
203    sd->y = y;
204    _e_deskmirror_smart_reconfigure(sd);
205 }
206 
207 static void
_e_deskmirror_smart_resize(Evas_Object * obj,Evas_Coord w,Evas_Coord h)208 _e_deskmirror_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
209 {
210    INTERNAL_ENTRY;
211    sd->w = w;
212    sd->h = h;
213    sd->resize = 1;
214    _e_deskmirror_smart_reconfigure(sd);
215 }
216 
217 static void
_e_deskmirror_smart_show(Evas_Object * obj)218 _e_deskmirror_smart_show(Evas_Object *obj)
219 {
220    Mirror *m;
221 
222    INTERNAL_ENTRY;
223    EINA_INLIST_FOREACH(sd->mirrors, m)
224      {
225         Mirror_Border *mb;
226 
227         if ((!m->ec) || (!m->mirror)) continue;
228         mb = evas_object_smart_data_get(m->mirror);
229         if (!mb) continue;
230         edje_object_thaw(mb->frame);
231         edje_object_play_set(mb->frame, 1);
232         evas_object_show(mb->mirror);
233      }
234    evas_object_show(sd->clip);
235 }
236 
237 static void
_e_deskmirror_smart_hide(Evas_Object * obj)238 _e_deskmirror_smart_hide(Evas_Object *obj)
239 {
240    Mirror *m;
241 
242    INTERNAL_ENTRY;
243    EINA_INLIST_FOREACH(sd->mirrors, m)
244      {
245         Mirror_Border *mb;
246 
247         if ((!m->ec) || (!m->mirror)) continue;
248         mb = evas_object_smart_data_get(m->mirror);
249         if (!mb) continue;
250         edje_object_freeze(mb->frame);
251         edje_object_play_set(mb->frame, 0);
252         evas_object_hide(mb->mirror);
253      }
254    evas_object_hide(sd->clip);
255 }
256 
257 static void
_e_deskmirror_smart_color_set(Evas_Object * obj,int r,int g,int b,int a)258 _e_deskmirror_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
259 {
260    INTERNAL_ENTRY;
261    evas_object_color_set(sd->clip, r, g, b, a);
262 }
263 
264 static void
_e_deskmirror_smart_clip_set(Evas_Object * obj,Evas_Object * clip)265 _e_deskmirror_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
266 {
267    INTERNAL_ENTRY;
268    evas_object_clip_set(sd->clip, clip);
269 }
270 
271 static void
_e_deskmirror_smart_clip_unset(Evas_Object * obj)272 _e_deskmirror_smart_clip_unset(Evas_Object *obj)
273 {
274    INTERNAL_ENTRY;
275    evas_object_clip_unset(sd->clip);
276 }
277 
278 ////////////////////////////////////////////////////////
279 
280 static void
_mirror_client_theme_setup(Mirror_Border * mb,Evas_Object * o)281 _mirror_client_theme_setup(Mirror_Border *mb, Evas_Object *o)
282 {
283    char buf[4096];
284 
285    if (e_comp_object_frame_exists(mb->m->ec->frame))
286      snprintf(buf, sizeof(buf), "e/deskmirror/frame/%s", mb->m->ec->border.name);
287    else
288      snprintf(buf, sizeof(buf), "e/deskmirror/frame/borderless");
289    e_theme_edje_object_set(o, "base/theme/borders", buf);
290    if (e_client_util_shadow_state_get(mb->m->ec))
291      edje_object_signal_emit(o, "e,state,shadow,on", "e");
292    else
293      edje_object_signal_emit(o, "e,state,shadow,off", "e");
294    if (mb->m->ec->focused)
295      edje_object_signal_emit(o, "e,state,focused", "e");
296    if (mb->m->ec->shaded)
297      edje_object_signal_emit(o, "e,state,shaded", "e");
298    if (mb->m->ec->maximized)
299      edje_object_signal_emit(o, "e,action,maximize", "e");
300    if (mb->m->ec->sticky)
301      edje_object_signal_emit(o, "e,state,sticky", "e");
302    if (mb->m->ec->iconic)
303      edje_object_signal_emit(o, "e,action,iconify", "e");
304 }
305 
306 static void
_e_deskmirror_mirror_frame_recalc_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)307 _e_deskmirror_mirror_frame_recalc_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
308 {
309    Mirror *m = data;
310    Mirror_Border *mb;
311 
312    if (!m->mirror) return;
313    mb = evas_object_smart_data_get(m->mirror);
314    if (mb->m->ec && (!e_object_is_del(E_OBJECT(mb->m->ec))))
315      {
316         _mirror_client_theme_setup(mb, mb->frame);
317         _mirror_scale_set(mb->m, (float)mb->m->sd->h / (float)mb->m->sd->desk->zone->h);
318      }
319    else
320      {
321         m = mb->m;
322         if (m->comp_object)
323           {
324              evas_object_smart_callback_del_full(m->comp_object, "dirty", _comp_object_dirty, m);
325              evas_object_smart_callback_del_full(m->comp_object, "frame_recalc_done", _e_deskmirror_mirror_frame_recalc_cb, m);
326              evas_object_smart_callback_del_full(m->comp_object, "color_set", _e_deskmirror_mirror_color_set_cb, m);
327              evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_del_cb, m);
328              evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_comp_object_show, m);
329              evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_HIDE, (Evas_Object_Event_Cb)_comp_object_hide, m);
330              evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_RESTACK, (Evas_Object_Event_Cb)_comp_object_stack, m);
331              evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_comp_object_configure, m);
332              evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_comp_object_configure, m);
333              m->comp_object = NULL;
334           }
335      }
336 }
337 
338 static void
_e_deskmirror_mirror_color_set_cb(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)339 _e_deskmirror_mirror_color_set_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
340 {
341    Mirror *m = data;
342    int r, g, b, a;
343 
344    if (!m->mirror) return;
345    evas_object_color_get(obj, &r, &g, &b, &a);
346    evas_object_color_set(m->mirror, r, g, b, a);
347 }
348 
349 static void
_mirror_client_smart_add(Evas_Object * obj)350 _mirror_client_smart_add(Evas_Object *obj)
351 {
352    Mirror_Border *mb;
353 
354    mb = E_NEW(Mirror_Border, 1);
355    mb->obj = obj;
356    evas_object_smart_data_set(obj, mb);
357 }
358 
359 static void
_mirror_client_signal_cb(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * src)360 _mirror_client_signal_cb(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *src)
361 {
362    if (!strncmp(emission, "e,state,shadow", sizeof("e,state,shadow") - 1)) return;
363    edje_object_signal_emit(data, emission, src);
364    edje_object_message_signal_process(data);
365    edje_object_calc_force(data);
366 }
367 
368 static void
_mirror_client_shadow_change(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)369 _mirror_client_shadow_change(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
370 {
371    E_Client *ec = event_info;
372 
373    if (e_client_util_shadow_state_get(ec))
374      edje_object_signal_emit(data, "e,state,shadow,on", "e");
375    else
376      edje_object_signal_emit(data, "e,state,shadow,off", "e");
377 }
378 
379 static void
_mirror_client_smart_del(Evas_Object * obj)380 _mirror_client_smart_del(Evas_Object *obj)
381 {
382    Mirror_Border *mb = evas_object_smart_data_get(obj);
383    if (mb->m->comp_object && mb->m->ec)
384      {
385         e_comp_object_signal_callback_del_full(mb->m->ec->frame, "*", "*", _mirror_client_signal_cb, mb->frame);
386         evas_object_smart_callback_del_full(mb->m->ec->frame, "shadow_change", _mirror_client_shadow_change, mb->frame);
387      }
388    evas_object_del(mb->frame);
389    mb->frame = NULL;
390    evas_object_del(mb->mirror);
391    mb->mirror = NULL;
392    _mirror_unref(mb->m);
393    free(mb);
394 }
395 
396 static void
_mirror_client_smart_move(Evas_Object * obj,Evas_Coord x,Evas_Coord y)397 _mirror_client_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
398 {
399    Mirror_Border *mb = evas_object_smart_data_get(obj);
400 
401    evas_object_move(mb->frame, x, y);
402 }
403 
404 static void
_mirror_client_smart_resize(Evas_Object * obj,Evas_Coord w,Evas_Coord h)405 _mirror_client_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
406 {
407    Mirror_Border *mb = evas_object_smart_data_get(obj);
408    evas_object_resize(mb->frame, w, h);
409 }
410 
411 static void
_mirror_client_smart_show(Evas_Object * obj)412 _mirror_client_smart_show(Evas_Object *obj)
413 {
414    Mirror_Border *mb = evas_object_smart_data_get(obj);
415    evas_object_show(mb->frame);
416 }
417 
418 static void
_mirror_client_smart_hide(Evas_Object * obj)419 _mirror_client_smart_hide(Evas_Object *obj)
420 {
421    Mirror_Border *mb = evas_object_smart_data_get(obj);
422    evas_object_hide(mb->frame);
423 }
424 
425 static void
_mirror_client_smart_color_set(Evas_Object * obj,int r,int g,int b,int a)426 _mirror_client_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
427 {
428    Mirror_Border *mb = evas_object_smart_data_get(obj);
429    evas_object_color_set(mb->frame, r, g, b, a);
430 }
431 
432 static void
_mirror_client_smart_clip_set(Evas_Object * obj,Evas_Object * clip)433 _mirror_client_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
434 {
435    Mirror_Border *mb = evas_object_smart_data_get(obj);
436    evas_object_clip_set(mb->frame, clip);
437 }
438 
439 static void
_mirror_client_smart_clip_unset(Evas_Object * obj)440 _mirror_client_smart_clip_unset(Evas_Object *obj)
441 {
442    Mirror_Border *mb = evas_object_smart_data_get(obj);
443    evas_object_clip_unset(mb->frame);
444 }
445 
446 static void
_mirror_client_smart_init(void)447 _mirror_client_smart_init(void)
448 {
449    static const Evas_Smart_Class sc =
450      {
451         "mirror_border", EVAS_SMART_CLASS_VERSION,
452         _mirror_client_smart_add, _mirror_client_smart_del, _mirror_client_smart_move, _mirror_client_smart_resize,
453         _mirror_client_smart_show, _mirror_client_smart_hide, _mirror_client_smart_color_set, _mirror_client_smart_clip_set,
454         _mirror_client_smart_clip_unset, NULL, NULL, NULL, NULL, NULL, NULL, NULL
455      };
456    if (_mirror_client_smart) return;
457    _mirror_client_smart = evas_smart_class_new(&sc);
458 }
459 
460 static void
_e_deskmirror_smart_init(void)461 _e_deskmirror_smart_init(void)
462 {
463    static const Evas_Smart_Class sc =
464      {
465         SMART_NAME, EVAS_SMART_CLASS_VERSION,
466         _e_deskmirror_smart_add, _e_deskmirror_smart_del, _e_deskmirror_smart_move, _e_deskmirror_smart_resize,
467         _e_deskmirror_smart_show, _e_deskmirror_smart_hide, _e_deskmirror_smart_color_set, _e_deskmirror_smart_clip_set,
468         _e_deskmirror_smart_clip_unset, NULL, NULL, NULL, NULL, NULL, NULL, NULL
469      };
470    if (_e_deskmirror_smart) return;
471    _e_deskmirror_smart = evas_smart_class_new(&sc);
472 }
473 
474 static void
_e_deskmirror_delfn(E_Smart_Data * sd,void * desk EINA_UNUSED)475 _e_deskmirror_delfn(E_Smart_Data *sd, void *desk EINA_UNUSED)
476 {
477    sd->desk_delfn = NULL;
478    sd->desk = NULL;
479    evas_object_del(sd->obj);
480 }
481 
482 static void
_e_deskmirror_mirror_del(Mirror * m)483 _e_deskmirror_mirror_del(Mirror *m)
484 {
485    void *val = m->comp_object;
486 
487    m->comp_object = NULL;
488    eina_hash_del_by_key(m->sd->mirror_hash, &val);
489 }
490 
491 static void
_e_deskmirror_mirror_del_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)492 _e_deskmirror_mirror_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
493 {
494    _e_deskmirror_mirror_del(data);
495 }
496 
497 static void
_e_deskmirror_mirror_geometry_get(Mirror * m)498 _e_deskmirror_mirror_geometry_get(Mirror *m)
499 {
500    E_Zone *zone;
501 
502    evas_object_geometry_get(m->comp_object, &m->x, &m->y, &m->w, &m->h);
503    zone = e_comp_object_util_zone_get(m->comp_object);
504    if (zone)
505      m->x -= zone->x, m->y -= zone->y;
506    /* double check here if we get zeroes */
507    if ((!m->w) || (!m->h))
508      {
509         ERR("ACK!");
510      }
511 }
512 
513 static void
_e_deskmirror_mirror_reconfigure(Mirror * m)514 _e_deskmirror_mirror_reconfigure(Mirror *m)
515 {
516    _e_deskmirror_mirror_geometry_get(m);
517    if (m->mirror)
518      {
519         e_layout_child_move(m->mirror, m->x, m->y);
520         e_layout_child_resize(m->mirror, m->w, m->h);
521         /* assume that anything happening here is the result of a drag */
522         if (((!m->sd->force) && (!e_drag_current_get())) || (m->sd->force))
523           _mirror_visible_apply(m);
524      }
525 }
526 
527 static void
_e_deskmirror_mirror_del_hash(Mirror * m)528 _e_deskmirror_mirror_del_hash(Mirror *m)
529 {
530    m->sd->mirrors = eina_inlist_remove(m->sd->mirrors, EINA_INLIST_GET(m));
531    if (m->mirror)
532      {
533         evas_object_del(m->mirror);
534         m->mirror = NULL;
535      }
536    if (m->comp_object)
537      {
538         evas_object_smart_callback_del_full(m->comp_object, "dirty", _comp_object_dirty, m);
539         evas_object_smart_callback_del_full(m->comp_object, "frame_recalc_done", _e_deskmirror_mirror_frame_recalc_cb, m);
540         evas_object_smart_callback_del_full(m->comp_object, "color_set", _e_deskmirror_mirror_color_set_cb, m);
541         evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_del_cb, m);
542         evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_comp_object_show, m);
543         evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_HIDE, (Evas_Object_Event_Cb)_comp_object_hide, m);
544         evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_RESTACK, (Evas_Object_Event_Cb)_comp_object_stack, m);
545         evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_comp_object_configure, m);
546         evas_object_event_callback_del_full(m->comp_object, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_comp_object_configure, m);
547         m->comp_object = NULL;
548      }
549    _mirror_unref(m);
550 }
551 
552 static Evas_Object *
_mirror_client_new(Mirror * m)553 _mirror_client_new(Mirror *m)
554 {
555    Evas_Object *o;
556    Mirror_Border *mb;
557 
558    _mirror_client_smart_init();
559    o = evas_object_smart_add(m->sd->e, _mirror_client_smart);
560    mb = evas_object_smart_data_get(o);
561    mb->m = m;
562    _mirror_ref(m);
563    mb->frame = edje_object_add(m->sd->e);
564    evas_object_name_set(mb->frame, "mirror_border");
565    _mirror_client_theme_setup(mb, mb->frame);
566    if (m->comp_object)
567      {
568         e_comp_object_signal_callback_add(m->comp_object, "*", "*", _mirror_client_signal_cb, mb->frame);
569         evas_object_smart_callback_add(m->comp_object, "shadow_change", _mirror_client_shadow_change, mb->frame);
570      }
571 
572    mb->mirror = m->mirror;
573    evas_object_smart_member_add(mb->frame, o);
574    evas_object_name_set(mb->mirror, "mirror");
575    edje_object_part_swallow(mb->frame, "e.swallow.client", m->mirror);
576    edje_object_part_text_set(mb->frame, "e.text.title", e_client_util_name_get(m->ec));
577    return o;
578 }
579 
580 static void
_e_deskmirror_mirror_setup(Mirror * m)581 _e_deskmirror_mirror_setup(Mirror *m)
582 {
583    if (!m->mirror) return;
584    if (m->ec)
585      {
586         m->mirror = _mirror_client_new(m);
587         _mirror_scale_set(m, (double)m->sd->h / (double)m->sd->desk->zone->h);
588      }
589    else
590      {
591         evas_object_pass_events_set(m->mirror, !m->ec);
592      }
593    if (m->ec) evas_object_data_set(m->mirror, "E_Client", m->ec);
594    evas_object_precise_is_inside_set(m->mirror, m->ec && (m->ec->shaped || m->ec->shaped_input));
595    e_layout_pack(m->sd->layout, m->mirror);
596    _e_deskmirror_mirror_reconfigure(m);
597    if (m->sd->handlers) // no handlers = we're setting up = there's no possible listeners
598      {
599         _comp_object_stack(m, NULL, m->comp_object, NULL);
600         if (!m->added)
601           evas_object_smart_callback_call(m->sd->obj, "mirror_add", m->mirror);
602      }
603    else
604      e_layout_child_raise(m->mirror);
605    m->added = 1;
606 }
607 
608 static Eina_Bool
_comp_object_check(Mirror * m)609 _comp_object_check(Mirror *m)
610 {
611    int w, h;
612 
613    evas_object_geometry_get(m->comp_object, NULL, NULL, &w, &h);
614    if ((w < 2) || (h < 2)) return EINA_FALSE;
615    if (!m->mirror)
616      {
617         m->mirror = e_comp_object_util_mirror_add(m->comp_object);
618         if (!m->mirror) return EINA_FALSE;
619      }
620    evas_object_smart_callback_del(m->comp_object, "dirty", _comp_object_dirty);
621    if (m->added) return EINA_TRUE;
622    evas_object_name_set(m->mirror, "m->mirror");
623    _e_deskmirror_mirror_setup(m);
624    return EINA_TRUE;
625 }
626 
627 static void
_comp_object_hide(Mirror * m,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)628 _comp_object_hide(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
629 {
630    _mirror_visible_apply(m);
631 }
632 
633 static void
_comp_object_show(Mirror * m,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)634 _comp_object_show(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
635 {
636    if (!m->mirror)
637      {
638         if (!_comp_object_check(m)) return;
639      }
640    _mirror_visible_apply(m);
641 }
642 
643 static void
_comp_object_stack(Mirror * m,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)644 _comp_object_stack(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
645 {
646    Evas_Object *comp_object;
647 
648    if (!m->mirror)
649      {
650         if (!_comp_object_check(m)) return;
651      }
652    comp_object = evas_object_below_get(obj);
653    while (comp_object)
654      {
655         Mirror *m2;
656 
657         m2 = eina_hash_find(m->sd->mirror_hash, &comp_object);
658         if (m2 && m2->mirror)
659           {
660              e_layout_child_raise_above(m->mirror, m2->mirror);
661              return;
662           }
663         comp_object = evas_object_below_get(comp_object);
664      }
665    e_layout_child_lower(m->mirror);
666 }
667 
668 static void
_comp_object_configure(Mirror * m,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)669 _comp_object_configure(Mirror *m, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
670 {
671    if (!m->mirror)
672      {
673         if (!_comp_object_check(m)) return;
674      }
675    _e_deskmirror_mirror_reconfigure(m);
676 }
677 
678 static void
_comp_object_dirty(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)679 _comp_object_dirty(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
680 {
681    _comp_object_check(data);
682 }
683 
684 static Mirror *
_e_deskmirror_mirror_add(E_Smart_Data * sd,Evas_Object * obj)685 _e_deskmirror_mirror_add(E_Smart_Data *sd, Evas_Object *obj)
686 {
687    Mirror *m;
688    Evas_Object *o = NULL;
689    E_Client *ec;
690    int w, h;
691 
692    if (sd->desk->zone != e_comp_object_util_zone_get(obj)) return NULL;
693 
694    ec = e_comp_object_client_get(obj);
695    if (ec)
696      {
697         if ((ec->desk != sd->desk) && (!ec->sticky))
698           return NULL;
699         if (ec->input_only || ec->ignored)
700           return NULL;
701      }
702    else
703      {
704         E_Shelf *es;
705 
706         if (sd->pager || sd->taskbar) return NULL;
707         es = evas_object_data_get(obj, "E_Shelf");
708         if (es)
709           {
710              if (!e_shelf_desk_visible(es, sd->desk)) return NULL;
711           }
712         else
713           {
714              if (sd->desk != e_desk_current_get(sd->desk->zone)) return NULL;
715           }
716      }
717    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
718    if ((w > 1) && (h > 1))
719      {
720         o = e_comp_object_util_mirror_add(obj);
721         evas_object_name_set(o, "m->mirror");
722      }
723    m = calloc(1, sizeof(Mirror));
724    m->comp_object = obj;
725    m->ec = ec;
726    m->sd = sd;
727    m->mirror = o;
728    m->ref = 1;
729    evas_object_event_callback_add(m->comp_object, EVAS_CALLBACK_DEL, _e_deskmirror_mirror_del_cb, m);
730    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, (Evas_Object_Event_Cb)_comp_object_show, m);
731    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, (Evas_Object_Event_Cb)_comp_object_hide, m);
732    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, (Evas_Object_Event_Cb)_comp_object_stack, m);
733    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, (Evas_Object_Event_Cb)_comp_object_configure, m);
734    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, (Evas_Object_Event_Cb)_comp_object_configure, m);
735    evas_object_smart_callback_add(obj, "frame_recalc_done", _e_deskmirror_mirror_frame_recalc_cb, m);
736    evas_object_smart_callback_add(obj, "color_set", _e_deskmirror_mirror_color_set_cb, m);
737    if (ec && (!ec->redirected) && (!ec->new_client) && e_pixmap_usable_get(ec->pixmap))
738      evas_object_smart_callback_add(obj, "dirty", _comp_object_dirty, m);
739    sd->mirrors = eina_inlist_append(sd->mirrors, EINA_INLIST_GET(m));
740    eina_hash_add(sd->mirror_hash, &obj, m);
741    _e_deskmirror_mirror_setup(m);
742    return m;
743 }
744 
745 static Eina_Bool
_comp_object_add(E_Smart_Data * sd,int type EINA_UNUSED,E_Event_Comp_Object * ev)746 _comp_object_add(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Comp_Object *ev)
747 {
748    if (eina_hash_find(sd->mirror_hash, &ev->comp_object)) return ECORE_CALLBACK_RENEW;
749    _e_deskmirror_mirror_add(sd, ev->comp_object);
750    return ECORE_CALLBACK_RENEW;
751 }
752 
753 static Eina_Bool
_client_del(E_Smart_Data * sd,int type EINA_UNUSED,E_Event_Client * ev)754 _client_del(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Client *ev)
755 {
756    Mirror *m = eina_hash_find(sd->mirror_hash, &ev->ec->frame);
757 
758    if (m) m->ec = NULL;
759 
760    return ECORE_CALLBACK_RENEW;
761 }
762 
763 static Eina_Bool
_client_add(E_Smart_Data * sd,int type EINA_UNUSED,E_Event_Client * ev)764 _client_add(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Client *ev)
765 {
766    if (!eina_hash_find(sd->mirror_hash, &ev->ec->frame))
767      _e_deskmirror_mirror_add(sd, ev->ec->frame);
768    return ECORE_CALLBACK_RENEW;
769 }
770 
771 static Eina_Bool
_client_desk_set(E_Smart_Data * sd,int type EINA_UNUSED,E_Event_Client_Desk_Set * ev)772 _client_desk_set(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Client_Desk_Set *ev)
773 {
774    Mirror *m;
775 
776    m = eina_hash_find(sd->mirror_hash, &ev->ec->frame);
777    if (m)
778      {
779         /* ev->desk is previous desk */
780         _mirror_visible_apply(m);
781         if (!e_client_util_desk_visible(ev->ec, sd->desk))
782           eina_hash_del_by_key(sd->mirror_hash, &ev->ec->frame);
783      }
784    if ((!m) && (sd->desk == ev->ec->desk))
785      _e_deskmirror_mirror_add(sd, ev->ec->frame);
786    return ECORE_CALLBACK_RENEW;
787 }
788 
789 static Eina_Bool
_client_property(E_Smart_Data * sd,int type EINA_UNUSED,E_Event_Client_Property * ev)790 _client_property(E_Smart_Data *sd, int type EINA_UNUSED, E_Event_Client_Property *ev)
791 {
792    Mirror *m;
793 
794    if ((!(ev->property & E_CLIENT_PROPERTY_NETWM_STATE)) &&
795        (!(ev->property & E_CLIENT_PROPERTY_STICKY)))
796      return ECORE_CALLBACK_RENEW;
797 
798    m = eina_hash_find(sd->mirror_hash, &ev->ec->frame);
799    if (m)
800      {
801         _mirror_visible_apply(m);
802         if (ev->property & E_CLIENT_PROPERTY_STICKY)
803           {
804              if ((!ev->ec->sticky) && (ev->ec->desk != sd->desk))
805                eina_hash_del_by_key(sd->mirror_hash, &ev->ec->frame);
806           }
807      }
808    else if (ev->ec->sticky)
809      _e_deskmirror_mirror_add(sd, ev->ec->frame);
810    return ECORE_CALLBACK_RENEW;
811 }
812 
813 /* externally accessible functions */
814 E_API Evas_Object *
e_deskmirror_add(E_Desk * desk,Eina_Bool pager,Eina_Bool taskbar)815 e_deskmirror_add(E_Desk *desk, Eina_Bool pager, Eina_Bool taskbar)
816 {
817    E_Smart_Data *sd;
818    Evas_Object *o, *l;
819    Evas *e;
820 
821    e = e_comp->evas;
822    _e_deskmirror_smart_init();
823    o = evas_object_smart_add(e, _e_deskmirror_smart);
824    e_object_ref(E_OBJECT(desk));
825    sd = evas_object_smart_data_get(o);
826    sd->pager = !!pager;
827    sd->taskbar = !!taskbar;
828    sd->desk = desk;
829    sd->mirror_hash = eina_hash_pointer_new((Eina_Free_Cb)_e_deskmirror_mirror_del_hash);
830    sd->desk_delfn = e_object_delfn_add(E_OBJECT(desk), (Ecore_End_Cb)_e_deskmirror_delfn, sd);
831    if (pager || taskbar)
832      {
833         sd->events = evas_object_rectangle_add(e);
834         evas_object_color_set(sd->events, 0, 0, 0, 0);
835         evas_object_clip_set(sd->events, sd->clip);
836         evas_object_smart_member_add(sd->events, o);
837         evas_object_show(sd->events);
838      }
839    sd->bgpreview = e_widget_bgpreview_desk_add(e, desk->zone, desk->x, desk->y);
840    evas_object_pass_events_set(sd->bgpreview, 1);
841    evas_object_clip_set(sd->bgpreview, sd->clip);
842    evas_object_smart_member_add(sd->bgpreview, o);
843    evas_object_show(sd->bgpreview);
844    sd->layout = e_layout_add(e);
845    evas_object_clip_set(sd->layout, sd->clip);
846    e_layout_virtual_size_set(sd->layout, desk->zone->w, desk->zone->h);
847    evas_object_smart_member_add(sd->layout, o);
848    evas_object_show(sd->layout);
849 
850    e_comp_object_util_center_on(o, sd->desk->zone->bg_clip_object);
851 
852    e_layout_freeze(sd->layout);
853 
854    l = evas_object_bottom_get(e_comp->evas);
855    do
856      {
857         if (evas_object_data_get(l, "comp_object"))
858           _e_deskmirror_mirror_add(sd, l);
859         l = evas_object_above_get(l);
860      } while (l);
861 
862    e_layout_thaw(sd->layout);
863 
864    E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_COMP_OBJECT_ADD, (Ecore_Event_Handler_Cb)_comp_object_add, sd);
865    E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb)_client_add, sd);
866    E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_CLIENT_REMOVE, (Ecore_Event_Handler_Cb)_client_del, sd);
867    E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_CLIENT_PROPERTY, (Ecore_Event_Handler_Cb)_client_property, sd);
868    E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_CLIENT_DESK_SET, (Ecore_Event_Handler_Cb)_client_desk_set, sd);
869    return o;
870 }
871 
872 E_API Evas_Object *
e_deskmirror_mirror_find(Evas_Object * deskmirror,Evas_Object * comp_object)873 e_deskmirror_mirror_find(Evas_Object *deskmirror, Evas_Object *comp_object)
874 {
875    Mirror *m;
876    EINA_SAFETY_ON_NULL_RETURN_VAL(deskmirror, NULL);
877    EINA_SAFETY_ON_NULL_RETURN_VAL(comp_object, NULL);
878    API_ENTRY(deskmirror) NULL;
879 
880    m = eina_hash_find(sd->mirror_hash, &comp_object);
881    return m ? m->mirror : NULL;
882 }
883 
884 E_API Eina_List *
e_deskmirror_mirror_list(Evas_Object * deskmirror)885 e_deskmirror_mirror_list(Evas_Object *deskmirror)
886 {
887    Eina_List *l = NULL;
888    Mirror *m;
889 
890    EINA_SAFETY_ON_NULL_RETURN_VAL(deskmirror, NULL);
891    API_ENTRY(deskmirror) NULL;
892 
893    EINA_INLIST_FOREACH(sd->mirrors, m)
894      {
895         if (m->mirror)
896           l = eina_list_append(l, m->mirror);
897      }
898    return l;
899 }
900 
901 static void
_mirror_copy_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)902 _mirror_copy_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
903 {
904    e_comp_object_signal_callback_del_full(data, "*", "*", _mirror_client_signal_cb, obj);
905    evas_object_smart_callback_del_full(data, "shadow_change", _mirror_client_shadow_change, obj);
906 }
907 
908 E_API Evas_Object *
e_deskmirror_mirror_copy(Evas_Object * obj)909 e_deskmirror_mirror_copy(Evas_Object *obj)
910 {
911    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
912 
913    if (!e_util_strcmp(evas_object_type_get(obj), "mirror_border"))
914      {
915         Evas_Object *o, *oo;
916         Edje_Message_Float msg;
917         Mirror_Border *mb;
918 
919         mb = evas_object_smart_data_get(obj);
920         o = edje_object_add(evas_object_evas_get(obj));
921         _mirror_client_theme_setup(mb, o);
922         if (mb->m->comp_object)
923           {
924              e_comp_object_signal_callback_add(mb->m->comp_object, "*", "*", _mirror_client_signal_cb, o);
925              evas_object_smart_callback_add(mb->m->comp_object, "shadow_change", _mirror_client_shadow_change, o);
926              evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _mirror_copy_del, mb->m->comp_object);
927           }
928         msg.val = mb->m->sd->h / mb->m->sd->desk->zone->h;
929         edje_object_message_send(o, EDJE_MESSAGE_FLOAT, 0, &msg);
930 
931         oo = e_comp_object_util_mirror_add(mb->m->comp_object);
932         edje_object_part_swallow(o, "e.swallow.client", oo);
933         if (e_comp_object_frame_exists(mb->m->ec->frame))
934           edje_object_part_text_set(o, "e.text.title", e_client_util_name_get(mb->m->ec));
935         e_comp_object_util_del_list_append(o, oo);
936         return o;
937      }
938    else if (!e_util_strcmp(evas_object_type_get(obj), "image"))
939      return e_comp_object_util_mirror_add(obj);
940    CRI("NOT A DESKMIRROR CLIENT");
941    return NULL;
942 }
943 
944 E_API void
e_deskmirror_coord_canvas_to_virtual(Evas_Object * obj,Evas_Coord cx,Evas_Coord cy,Evas_Coord * vx,Evas_Coord * vy)945 e_deskmirror_coord_canvas_to_virtual(Evas_Object *obj, Evas_Coord cx, Evas_Coord cy, Evas_Coord *vx, Evas_Coord *vy)
946 {
947    API_ENTRY(obj);
948 
949    e_layout_coord_canvas_to_virtual(sd->layout, cx, cy, vx, vy);
950 }
951 
952 E_API void
e_deskmirror_coord_virtual_to_canvas(Evas_Object * obj,Evas_Coord vx,Evas_Coord vy,Evas_Coord * cx,Evas_Coord * cy)953 e_deskmirror_coord_virtual_to_canvas(Evas_Object *obj, Evas_Coord vx, Evas_Coord vy, Evas_Coord *cx, Evas_Coord *cy)
954 {
955    API_ENTRY(obj);
956 
957    e_layout_coord_virtual_to_canvas(sd->layout, vx, vy, cx, cy);
958 }
959 
960 E_API E_Desk *
e_deskmirror_desk_get(Evas_Object * obj)961 e_deskmirror_desk_get(Evas_Object *obj)
962 {
963    API_ENTRY(obj) NULL;
964    return sd->desk;
965 }
966 
967 E_API void
e_deskmirror_util_wins_print(Evas_Object * obj)968 e_deskmirror_util_wins_print(Evas_Object *obj)
969 {
970    E_Smart_Data *sd;
971    Mirror *m;
972 
973    EINA_SAFETY_ON_NULL_RETURN(obj);
974    sd = evas_object_smart_data_get(obj);
975    EINA_INLIST_FOREACH(sd->mirrors, m)
976      {
977         if (m->ec)
978           {
979              if (m->ec->override)
980                fprintf(stderr, "MIRROR OVERRIDE: %p - %p%s\n", m->comp_object, m->ec, m->ec->input_only ? " INPUT" : "");
981              else
982                fprintf(stderr, "MIRROR EC:  %p - %p '%s:%s'\n", m->comp_object, m->ec, m->ec->icccm.name, m->ec->icccm.class);
983           }
984         else
985           fprintf(stderr, "MIRROR OBJ: %p\n", m->comp_object);
986      }
987 }
988 
989 E_API void
e_deskmirror_update_force(Evas_Object * obj)990 e_deskmirror_update_force(Evas_Object *obj)
991 {
992    API_ENTRY(obj);
993 
994    e_layout_freeze(sd->layout);
995    sd->force = EINA_TRUE;
996    _e_deskmirror_smart_hide(obj);
997    _e_deskmirror_smart_reconfigure(sd);
998    _e_deskmirror_smart_show(obj);
999    sd->force = EINA_FALSE;
1000    e_layout_thaw(sd->layout);
1001 }
1002