1 #include "e.h"
2 
3 /* data keys:
4 
5    = keys that return objects =
6    - E_Client: the client associated with the object (E_Client*)
7    - comp_smart_obj: cw->smart_obj (Evas_Object*)
8    - comp_obj: cw (E_Comp_Object*)
9 
10    = keys that are bool flags =
11    - client_restack: client needs a protocol-level restack
12    - comp_override: object is triggering a nocomp override to force compositing
13    - comp_ref: object has a ref from visibility animations
14    - comp_showing: object is currently running its show animation
15    - comp_hiding: object is currently running its hiding animation
16    - comp_object: object is a compositor-created object
17    - comp_object_skip: object has a name which prohibits theme shadows
18    - comp_object-to_del: list of objects which will be deleted when this object is deleted
19    - comp_mirror: object is the result of e_comp_object_util_mirror_add()
20 */
21 
22 #define UPDATE_MAX 512 // same as evas
23 #define FAILURE_MAX 2 // seems reasonable
24 #define SMART_NAME     "e_comp_object"
25 
26 /* for non-util functions */
27 #define API_ENTRY      E_Comp_Object *cw; \
28                        cw = evas_object_smart_data_get(obj); \
29                        if ((!obj) || (!cw) || (e_util_strcmp(evas_object_type_get(obj), SMART_NAME))) return
30 
31 /* for util functions (obj may or may not be E_Comp_Object */
32 #define SOFT_ENTRY(...)      E_Comp_Object *cw; \
33                        if (!obj) \
34                          { \
35                             CRI("YOU PASSED NULL! ARGH!"); \
36                             return __VA_ARGS__; \
37                          } \
38                        cw = evas_object_smart_data_get(obj); \
39                        if ((!cw) || (e_util_strcmp(evas_object_type_get(obj), SMART_NAME))) \
40                          cw = NULL
41 #define INTERNAL_ENTRY E_Comp_Object *cw; cw = evas_object_smart_data_get(obj);
42 
43 /* enable for lots of client size info in console output */
44 #if 1
45 # define e_util_size_debug_set(x, y)
46 #endif
47 
48 /* enable along with display-specific damage INF calls to enable render tracing
49  * SLOW!
50  */
51 static int render_debug_enabled;
52 #define RENDER_DEBUG(...) do { if ((render_debug_enabled == 1) || ((render_debug_enabled == -1) && cw->ec->focused)) INF(__VA_ARGS__); } while (0)
53 
54 typedef struct _E_Comp_Object
55 {
56    //EINA_INLIST;
57 
58    int                  x, y, w, h;  // geometry
59    Eina_Tiler          *input_area;
60 
61    E_Client *ec;
62 
63    E_Comp_Object_Frame client_inset;
64    struct {
65       double          start;
66       double          val;
67       int             x, y;
68       E_Direction     dir;
69       Ecore_Animator *anim;
70    } shade;
71    struct {
72       int             bx, by, bxx, byy, w, h;
73    } border;
74 
75    Eina_Stringshare   *frame_theme;
76    Eina_Stringshare   *frame_name;
77    Eina_Stringshare   *visibility_effect; //effect when toggling visibility
78 
79    Evas_Object         *smart_obj;  // smart object
80    Evas_Object         *clip; // clipper over effect object
81    Eina_Array          *input_objs; // input rect
82    Evas_Object         *obj;  // composite object
83    Evas_Object         *frame_object; // for client frames
84    Evas_Object         *frame_icon; // for client frames
85    Evas_Object         *zoomobj; // zoomap
86    Evas_Object         *shobj;  // shadow object
87    Evas_Object         *effect_obj; // effects object
88    Evas_Object         *frame_volume; // volume level object
89    unsigned int         layer; //e_comp_canvas_layer_map(cw->ec->layer)
90    Eina_List           *obj_mirror;  // extra mirror objects
91    Eina_List           *obj_agent;  // extra agent objects
92    Eina_Tiler          *updates; //render update regions
93    Eina_Tiler          *pending_updates; //render update regions which are about to render
94 
95    Evas_Native_Surface *ns; //for custom gl rendering
96 
97    double               action_client_loop_time; //loop time when client's action ended
98 
99    unsigned int         update_count;  // how many updates have happened to this obj
100 
101    unsigned int         opacity;  // opacity set with _NET_WM_WINDOW_OPACITY
102 
103    unsigned int         animating;  // it's busy animating
104    unsigned int         failures; //number of consecutive e_pixmap_image_draw() failures
105    unsigned int         force_visible; //number of visible obj_mirror objects
106    Eina_Bool            deleted E_BITFIELD;  // deleted
107    Eina_Bool            defer_hide E_BITFIELD;  // flag to get hide to work on deferred hide
108    Eina_Bool            showing E_BITFIELD;  // object is currently in "show" animation
109    Eina_Bool            visible E_BITFIELD;  // is visible
110 
111    Eina_Bool            shaped E_BITFIELD;  // is shaped
112    Eina_Bool            update E_BITFIELD;  // has updates to fetch
113    Eina_Bool            redirected E_BITFIELD;  // has updates to fetch
114    Eina_Bool            native E_BITFIELD;  // native
115 
116    Eina_Bool            nocomp E_BITFIELD;  // nocomp applied
117    Eina_Bool            nocomp_need_update E_BITFIELD;  // nocomp in effect, but this window updated while in nocomp mode
118    Eina_Bool            real_hid E_BITFIELD;  // last hide was a real window unmap
119 
120    Eina_Bool            effect_set E_BITFIELD; //effect_obj has a valid group
121    Eina_Bool            effect_running E_BITFIELD; //effect_obj is playing an animation
122    Eina_Bool            effect_clip E_BITFIELD; //effect_obj is clipped
123    Eina_Bool            effect_clip_able E_BITFIELD; //effect_obj will be clipped for effects
124 
125    Eina_Bool            zoomap_disabled E_BITFIELD; //whether zoomap is usable
126    Eina_Bool            updates_exist E_BITFIELD;
127    Eina_Bool            updates_full E_BITFIELD; // entire object will be updated
128 
129    Eina_Bool            force_move E_BITFIELD;
130    Eina_Bool            frame_extends E_BITFIELD; //frame may extend beyond object size
131    Eina_Bool            blanked E_BITFIELD; //window is rendering blank content (externally composited)
132 
133    Eina_Bool            agent_updating E_BITFIELD; //updating agents
134 } E_Comp_Object;
135 
136 
137 struct E_Comp_Object_Mover
138 {
139    EINA_INLIST;
140    E_Comp_Object_Mover_Cb func;
141    const char *sig;
142    void *data;
143    int pri;
144 };
145 
146 static Eina_Inlist *_e_comp_object_movers = NULL;
147 static Evas_Smart *_e_comp_smart = NULL;
148 
149 /* sekrit functionzzz */
150 EINTERN void e_client_focused_set(E_Client *ec);
151 
152 /* emitted every time a new noteworthy comp object is added */
153 E_API int E_EVENT_COMP_OBJECT_ADD = -1;
154 
155 static void
_e_comp_object_event_free(void * d EINA_UNUSED,void * event)156 _e_comp_object_event_free(void *d EINA_UNUSED, void *event)
157 {
158    E_Event_Comp_Object *ev = event;
159    E_Client *ec;
160 
161    ec = evas_object_data_get(ev->comp_object, "E_Client");
162    if (ec)
163      {
164         UNREFD(ec, 1);
165         e_object_unref(E_OBJECT(ec));
166      }
167    evas_object_unref(ev->comp_object);
168    free(ev);
169 }
170 
171 static void
_e_comp_object_event_add(Evas_Object * obj)172 _e_comp_object_event_add(Evas_Object *obj)
173 {
174    E_Event_Comp_Object *ev;
175    E_Client *ec;
176 
177    ev = E_NEW(E_Event_Comp_Object, 1);
178    evas_object_ref(obj);
179    ev->comp_object = obj;
180    ec = evas_object_data_get(ev->comp_object, "E_Client");
181    if (ec)
182      {
183         REFD(ec, 1);
184         e_object_ref(E_OBJECT(ec));
185      }
186    ecore_event_add(E_EVENT_COMP_OBJECT_ADD, ev, _e_comp_object_event_free, NULL);
187 }
188 
189 /////////////////////////////////////
190 
191 static void
_e_comp_object_cb_agent_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)192 _e_comp_object_cb_agent_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
193 {
194    E_Comp_Object *cw = data;
195 
196    cw->obj_agent = eina_list_remove(cw->obj_agent, obj);
197 }
198 
199 static void
_e_comp_object_cb_agent_resize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)200 _e_comp_object_cb_agent_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
201 {
202    E_Comp_Object *cw = data;
203    int w, h;
204 
205    if (cw->agent_updating) return;
206    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
207    evas_object_resize(cw->smart_obj, w, h);
208 }
209 
210 static void
_e_comp_object_cb_agent_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)211 _e_comp_object_cb_agent_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
212 {
213    E_Comp_Object *cw = data;
214    int x, y;
215 
216    if (cw->agent_updating) return;
217    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
218    evas_object_move(cw->smart_obj, x, y);
219 }
220 
221 /////////////////////////////////////
222 
223 static void
_e_comp_object_cb_mirror_del(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)224 _e_comp_object_cb_mirror_del(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
225 {
226    E_Comp_Object *cw = data;
227 
228    cw->obj_mirror = eina_list_remove(cw->obj_mirror, obj);
229 }
230 
231 static void
_e_comp_object_cb_mirror_show(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)232 _e_comp_object_cb_mirror_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
233 {
234    E_Comp_Object *cw = data;
235 
236    if ((!cw->force_visible) && (!cw->deleted) && (!e_object_is_del(E_OBJECT(cw->ec))))
237      evas_object_smart_callback_call(cw->smart_obj, "visibility_force", cw->ec);
238    cw->force_visible++;
239    if ((!cw->native) && cw->pending_updates && (!cw->update) && cw->real_hid)
240      e_comp_object_render(cw->smart_obj);
241 }
242 
243 static void
_e_comp_object_cb_mirror_hide(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)244 _e_comp_object_cb_mirror_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
245 {
246    E_Comp_Object *cw = data;
247 
248    cw->force_visible--;
249    if ((!cw->force_visible) && (!cw->deleted) && (!e_object_is_del(E_OBJECT(cw->ec))))
250      evas_object_smart_callback_call(cw->smart_obj, "visibility_normal", cw->ec);
251 }
252 
253 /////////////////////////////////////
254 
255 static inline Eina_Bool
_e_comp_shaped_check(int w,int h,const Eina_Rectangle * rects,int num)256 _e_comp_shaped_check(int w, int h, const Eina_Rectangle *rects, int num)
257 {
258    if (num > 1) return EINA_TRUE;
259    if ((rects[0].x == 0) && (rects[0].y == 0) &&
260        ((int)rects[0].w == w) && ((int)rects[0].h == h))
261      return EINA_FALSE;
262    return EINA_TRUE;
263 }
264 
265 /////////////////////////////////////
266 
267 /* add a client to the layer-client list */
268 static void
_e_comp_object_layers_add(E_Comp_Object * cw,E_Comp_Object * above,E_Comp_Object * below,Eina_Bool prepend)269 _e_comp_object_layers_add(E_Comp_Object *cw, E_Comp_Object *above, E_Comp_Object *below, Eina_Bool prepend)
270 {
271    E_Comp_Object *layer_cw = NULL;
272 
273    /* try to get the internal data for the layer;
274     * will return NULL for fake layers (eg. wayland)
275     */
276    if (e_comp->layers[cw->layer].obj)
277      layer_cw = evas_object_smart_data_get(e_comp->layers[cw->layer].obj);
278    if (layer_cw == cw) layer_cw = NULL;
279 /*
280    if (above)
281      e_comp->layers[cw->layer].objs = eina_inlist_append_relative(e_comp->layers[cw->layer].objs, EINA_INLIST_GET(cw), EINA_INLIST_GET(cw2));
282    else if (below)
283      e_comp->layers[cw->layer].objs = eina_inlist_prepend_relative(e_comp->layers[cw->layer].objs, EINA_INLIST_GET(cw), EINA_INLIST_GET(cw2));
284    else
285      {
286         if (prepend)
287           e_comp->layers[cw->layer].objs = eina_inlist_prepend(e_comp->layers[cw->layer].objs, EINA_INLIST_GET(cw));
288         else
289           e_comp->layers[cw->layer].objs = eina_inlist_append(e_comp->layers[cw->layer].objs, EINA_INLIST_GET(cw));
290      }
291    e_comp->layers[cw->layer].objs_count++;
292    if (!cw->ec) return;
293 */
294    if (above)
295      {
296         cw->layer = above->layer;
297         e_comp->layers[above->layer].clients = eina_inlist_append_relative(e_comp->layers[above->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(above->ec));
298         e_comp->layers[above->layer].clients_count++;
299      }
300    else if (below)
301      {
302         cw->layer = below->layer;
303         e_comp->layers[below->layer].clients = eina_inlist_prepend_relative(e_comp->layers[below->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(below->ec));
304         e_comp->layers[below->layer].clients_count++;
305      }
306    else
307      {
308         if (prepend)
309           e_comp->layers[cw->layer].clients = eina_inlist_prepend(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
310         else if (layer_cw)
311           e_comp->layers[cw->layer].clients = eina_inlist_prepend_relative(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec), EINA_INLIST_GET(layer_cw->ec));
312         else //this is either the layer object or a tough actin tinactin^W^W^Wfast stacking client
313           e_comp->layers[cw->layer].clients = eina_inlist_append(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
314         e_comp->layers[cw->layer].clients_count++;
315      }
316 #ifndef E_RELEASE_BUILD
317    if (layer_cw)
318      {
319         E_Client *below_ec = e_client_below_get(cw->ec);
320         if (below_ec)
321           {
322              if (e_comp->layers[cw->layer].obj == below_ec->frame)
323                CRI("ACK!");
324           }
325      }
326 #endif
327 }
328 
329 static void
_e_comp_object_layers_remove(E_Comp_Object * cw)330 _e_comp_object_layers_remove(E_Comp_Object *cw)
331 {
332    if (cw->ec && e_comp->layers[cw->layer].clients)
333      {
334         e_comp->layers[cw->layer].clients = eina_inlist_remove(e_comp->layers[cw->layer].clients, EINA_INLIST_GET(cw->ec));
335         e_comp->layers[cw->layer].clients_count--;
336      }
337 /*
338    e_comp->layers[cw->layer].objs = eina_inlist_remove(e_comp->layers[cw->layer].objs, EINA_INLIST_GET(cw));
339    e_comp->layers[cw->layer].objs_count--;
340 */
341 }
342 
343 /////////////////////////////////////
344 static void
_e_comp_object_updates_init(E_Comp_Object * cw)345 _e_comp_object_updates_init(E_Comp_Object *cw)
346 {
347    int pw, ph;
348 
349    if (cw->updates) return;
350    pw = cw->ec->client.w, ph = cw->ec->client.h;
351    if ((!pw) || (!ph))
352      e_pixmap_size_get(cw->ec->pixmap, &pw, &ph);
353    if ((!pw) || (!ph)) return;
354    cw->updates = eina_tiler_new(pw, ph);
355    if (cw->updates)
356      eina_tiler_tile_size_set(cw->updates, 1, 1);
357 }
358 
359 
360 static void
_e_comp_object_alpha_set(E_Comp_Object * cw)361 _e_comp_object_alpha_set(E_Comp_Object *cw)
362 {
363    Eina_Bool alpha;
364 
365    if (!e_pixmap_is_x(cw->ec->pixmap))
366      alpha = e_pixmap_image_is_argb(cw->ec->pixmap);
367    else
368      alpha = cw->ec->argb;
369 
370    if (cw->blanked || cw->ns || cw->ec->shaped) alpha = EINA_TRUE;
371 
372    evas_object_image_alpha_set(cw->obj, alpha);
373 }
374 
375 static void
_e_comp_object_shadow(E_Comp_Object * cw)376 _e_comp_object_shadow(E_Comp_Object *cw)
377 {
378    if (e_client_util_shadow_state_get(cw->ec))
379      edje_object_signal_emit(cw->frame_object ?: cw->shobj, "e,state,shadow,on", "e");
380    else
381      edje_object_signal_emit(cw->frame_object ?: cw->shobj, "e,state,shadow,off", "e");
382    if (cw->frame_object)
383      edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
384    evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
385 }
386 
387 /* trigger e_binding from an edje signal on a client frame */
388 static void
_e_comp_object_cb_signal_bind(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * source)389 _e_comp_object_cb_signal_bind(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source)
390 {
391    E_Comp_Object *cw = data;
392 
393 #ifndef HAVE_WAYLAND_ONLY
394    if (e_dnd_active()) return;
395 #endif
396    if (cw->ec->iconic || cw->ec->cur_mouse_action) return;
397    if (!dblequal(cw->action_client_loop_time, ecore_loop_time_get()))
398      e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(cw->ec),
399                               emission, source);
400 }
401 
402 /////////////////////////////////////
403 
404 /* handle evas mouse-in events on client object */
405 static void
_e_comp_object_cb_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)406 _e_comp_object_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
407 {
408    Evas_Event_Mouse_In *ev = event_info;
409    E_Comp_Object *cw = data;
410 
411    if (e_pixmap_is_x(cw->ec->pixmap))
412      {
413         if (!e_comp_object_frame_allowed(obj)) return;
414         if (E_INSIDE(ev->output.x, ev->output.y, cw->ec->client.x, cw->ec->client.y,
415             cw->ec->client.w, cw->ec->client.h)) return;
416      }
417    if (e_grabinput_mouse_win_get() && (e_grabinput_mouse_win_get() != e_client_util_win_get(cw->ec)))
418      return;
419    e_client_mouse_in(cw->ec, ev->output.x, ev->output.y);
420 }
421 
422 /* handle evas mouse-out events on client object */
423 static void
_e_comp_object_cb_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)424 _e_comp_object_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
425 {
426    Evas_Event_Mouse_Out *ev = event_info;
427    E_Comp_Object *cw = data;
428 
429    if (e_grabinput_mouse_win_get() && (e_grabinput_mouse_win_get() != e_client_util_win_get(cw->ec)))
430      return;
431    e_client_mouse_out(cw->ec, ev->output.x, ev->output.y);
432 }
433 
434 /* handle evas mouse wheel events on client object */
435 static void
_e_comp_object_cb_mouse_wheel(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)436 _e_comp_object_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
437 {
438    Evas_Event_Mouse_Wheel *ev = event_info;
439    E_Comp_Object *cw = data;
440    E_Binding_Event_Wheel ev2;
441 
442    if (!cw->ec) return;
443    if (e_client_action_get()) return;
444    e_bindings_evas_event_mouse_wheel_convert(ev, &ev2);
445    e_client_mouse_wheel(cw->ec, &ev->output, &ev2);
446 }
447 
448 /* handle evas mouse down events on client object */
449 static void
_e_comp_object_cb_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)450 _e_comp_object_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
451 {
452    Evas_Event_Mouse_Down *ev = event_info;
453    E_Comp_Object *cw = data;
454    E_Binding_Event_Mouse_Button ev2;
455 
456    if (!cw->ec) return;
457    if (e_client_action_get()) return;
458    e_bindings_evas_event_mouse_button_convert(ev, &ev2);
459    e_client_mouse_down(cw->ec, ev->button, &ev->output, &ev2);
460 }
461 
462 /* handle evas mouse up events on client object */
463 static void
_e_comp_object_cb_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)464 _e_comp_object_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
465 {
466    Evas_Event_Mouse_Down *ev = event_info;
467    E_Comp_Object *cw = data;
468    E_Binding_Event_Mouse_Button ev2;
469    Eina_Bool acting;
470 
471    if (!cw->ec) return;
472    if (e_client_action_get() && (e_client_action_get() != cw->ec)) return;
473    e_bindings_evas_event_mouse_button_convert(ev, &ev2);
474    acting = !!cw->ec->cur_mouse_action;
475    e_client_mouse_up(cw->ec, ev->button, &ev->output, &ev2);
476    if (acting && (!e_client_action_get()))
477      cw->action_client_loop_time = ecore_loop_time_get();
478 }
479 
480 /* handle evas mouse movement events on client object */
481 static void
_e_comp_object_cb_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)482 _e_comp_object_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
483 {
484    Evas_Event_Mouse_Move *ev = event_info;
485    E_Comp_Object *cw = data;
486 
487    if (!cw->ec) return;
488    if (e_client_action_get() && (e_client_action_get() != cw->ec)) return;
489    e_client_mouse_move(cw->ec, &ev->cur.output);
490 }
491 /////////////////////////////////////
492 
493 /* helper function for checking compositor themes based on user-defined matches */
494 static Eina_Bool
_e_comp_object_shadow_client_match(const E_Client * ec,E_Comp_Match * m)495 _e_comp_object_shadow_client_match(const E_Client *ec, E_Comp_Match *m)
496 {
497    if (((m->title) && (!ec->netwm.name)) ||
498        ((ec->netwm.name) && (m->title) && (!e_util_glob_match(ec->netwm.name, m->title))))
499      return EINA_FALSE;
500    if (((m->clas) && (!ec->icccm.class)) ||
501        ((ec->icccm.class) && (m->clas) && (!e_util_glob_match(ec->icccm.class, m->clas))))
502      return EINA_FALSE;
503    if (((m->role) && (!ec->icccm.window_role)) ||
504        ((ec->icccm.window_role) && (m->role) && (!e_util_glob_match(ec->icccm.window_role, m->role))))
505      return EINA_FALSE;
506    if (m->primary_type)
507      {
508         if (ec->netwm.type)
509           {
510              if ((int)ec->netwm.type != m->primary_type)
511                return EINA_FALSE;
512           }
513         else if (m->primary_type != E_WINDOW_TYPE_REAL_UNKNOWN)
514           return EINA_FALSE;
515      }
516   if (m->borderless != 0)
517     {
518        int borderless = 0;
519 
520        if (e_client_util_borderless(ec))
521          borderless = 1;
522        if (!(((m->borderless == -1) && (!borderless)) ||
523              ((m->borderless == 1) && (borderless))))
524          return EINA_FALSE;
525     }
526   if (m->dialog != 0)
527     {
528        int dialog = 0;
529 
530        if (((ec->icccm.transient_for != 0) ||
531             (ec->dialog)))
532          dialog = 1;
533        if (!(((m->dialog == -1) && (!dialog)) ||
534              ((m->dialog == 1) && (dialog))))
535          return EINA_FALSE;
536     }
537   if (m->accepts_focus != 0)
538     {
539        int accepts_focus = 0;
540 
541        if (ec->icccm.accepts_focus)
542          accepts_focus = 1;
543        if (!(((m->accepts_focus == -1) && (!accepts_focus)) ||
544              ((m->accepts_focus == 1) && (accepts_focus))))
545          return EINA_FALSE;
546     }
547   if (m->vkbd != 0)
548     {
549        int vkbd = 0;
550 
551        if (ec->vkbd.vkbd)
552          vkbd = 1;
553        if (!(((m->vkbd == -1) && (!vkbd)) ||
554              ((m->vkbd == 1) && (vkbd))))
555          return EINA_FALSE;
556     }
557   if (m->argb != 0)
558     {
559        if (!(((m->argb == -1) && (!ec->argb)) ||
560              ((m->argb == 1) && (ec->argb))))
561          return EINA_FALSE;
562     }
563   if (m->fullscreen != 0)
564     {
565        int fullscreen = ec->fullscreen;
566 
567        if (!(((m->fullscreen == -1) && (!fullscreen)) ||
568              ((m->fullscreen == 1) && (fullscreen))))
569          return EINA_FALSE;
570     }
571   if (m->modal != 0)
572     {
573        int modal = 0;
574 
575        if (ec->netwm.state.modal)
576          modal = 1;
577        if (!(((m->modal == -1) && (!modal)) ||
578              ((m->modal == 1) && (modal))))
579          return EINA_FALSE;
580     }
581   return EINA_TRUE;
582 }
583 
584 /* function for setting up a client's compositor frame theme (cw->shobj) */
585 static Eina_Bool
_e_comp_object_shadow_setup(E_Comp_Object * cw)586 _e_comp_object_shadow_setup(E_Comp_Object *cw)
587 {
588    int ok = 0;
589    char buf[4096];
590    Eina_List *list = NULL, *l;
591    E_Comp_Match *m;
592    Eina_Stringshare *reshadow_group = NULL;
593    Eina_Bool focus = EINA_FALSE, urgent = EINA_FALSE, skip = EINA_FALSE,
594              reshadow = EINA_FALSE, no_shadow = EINA_FALSE, override;
595    Eina_Stringshare *name, *title;
596    E_Comp_Config *conf = e_comp_config_get();
597 
598    edje_object_file_get(cw->shobj, NULL, &reshadow_group);
599    override = cw->ec->override || (cw->ec->netwm.type == E_WINDOW_TYPE_POPUP_MENU);
600    /* match correct client type */
601    list = override ? conf->match.overrides : conf->match.borders;
602    name = cw->ec->icccm.name;
603    title = cw->ec->icccm.title;
604    skip = (title && (!strncmp(title, "noshadow", 8)));
605 
606    /* skipping here is mostly a hack for systray because I hate it */
607    if (!skip)
608      {
609         EINA_LIST_FOREACH(list, l, m)
610           {
611              if (((m->name) && (!name)) ||
612                  ((name) && (m->name) && (!e_util_glob_match(name, m->name))))
613                continue;
614              if (!_e_comp_object_shadow_client_match(cw->ec, m)) continue;
615 
616              focus = m->focus;
617              urgent = m->urgent;
618              no_shadow = m->no_shadow;
619              if (m->shadow_style)
620                {
621                   if (!ok)
622                     {
623                        snprintf(buf, sizeof(buf), "e/comp/frame/%s", m->shadow_style);
624                        reshadow = ok = !e_util_strcmp(reshadow_group, buf);
625                        if (!ok)
626                          ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
627                     }
628                   if (ok && m->visibility_effect)
629                     eina_stringshare_refplace(&cw->visibility_effect, m->visibility_effect);
630                   if (ok) break;
631                }
632           }
633      }
634    while (!ok)
635      {
636         if (skip || (cw->ec->e.state.video))
637           {
638              reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/none");
639              if (!ok)
640                ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/none");
641           }
642         if (ok) break;
643         if (conf->shadow_style)
644           {
645              if (!ok)
646                {
647                   snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
648                   reshadow = ok = !e_util_strcmp(reshadow_group, buf);
649                   if (!ok)
650                     ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", buf);
651                }
652           }
653         if (!ok)
654           {
655              reshadow = ok = !e_util_strcmp(reshadow_group, "e/comp/frame/default");
656              if (!ok)
657                ok = e_theme_edje_object_set(cw->shobj, "base/theme/comp", "e/comp/frame/default");
658           }
659         break;
660      }
661    /* reshadow means this entire function call has been a no-op since we're re-setting the current style */
662    if (reshadow)
663      {
664         if (cw->zoomap_disabled)
665           {
666              if (cw->frame_object && (cw->zoomobj && e_zoomap_child_get(cw->zoomobj) == cw->frame_object)) return EINA_FALSE;
667           }
668         else
669           {
670              if (cw->frame_object && (edje_object_part_swallow_get(cw->shobj, "e.swallow.content") == cw->frame_object)) return EINA_FALSE;
671           }
672      }
673    if (override)
674      {
675         if ((!cw->ec->shaped) && (!no_shadow) && (!cw->ec->argb))
676           edje_object_signal_emit(cw->shobj, "e,state,shadow,on", "e");
677         else
678           edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
679         evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
680      }
681    else
682      {
683         if (no_shadow)
684           {
685              edje_object_signal_emit(cw->shobj, "e,state,shadow,off", "e");
686              evas_object_smart_callback_call(cw->smart_obj, "shadow_change", cw->ec);
687           }
688         else
689           _e_comp_object_shadow(cw);
690      }
691 
692    if (focus || cw->ec->focused || override)
693      e_comp_object_signal_emit(cw->smart_obj, "e,state,focused", "e");
694    else
695      e_comp_object_signal_emit(cw->smart_obj, "e,state,unfocused", "e");
696    if (urgent || cw->ec->urgent)
697      e_comp_object_signal_emit(cw->smart_obj, "e,state,urgent", "e");
698    else
699      e_comp_object_signal_emit(cw->smart_obj, "e,state,not_urgent", "e");
700    if (cw->ec->shaded)
701      e_comp_object_signal_emit(cw->smart_obj, "e,state,shaded", "e");
702    if (cw->ec->sticky)
703      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
704    if (cw->ec->hung)
705      e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
706    /* visibility must always be enabled for re_manage clients to prevent
707     * pop-in animations every time the user sees a persistent client again;
708     * applying visibility for iconic clients prevents the client from getting
709     * stuck as hidden
710     */
711    if (cw->visible || cw->ec->iconic || cw->ec->re_manage)
712      {
713         if ((cw->w > 0) && (cw->h > 0))
714           e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
715      }
716    else
717      e_comp_object_signal_emit(cw->smart_obj, "e,state,hidden", "e");
718    if (e_comp_object_frame_allowed(cw->smart_obj))
719      e_comp_object_signal_emit(cw->smart_obj, "e,state,focus,enabled", "e");
720    else
721      e_comp_object_signal_emit(cw->smart_obj, "e,state,focus,disabled", "e");
722 
723    /* breaks animation counter */
724    //if (cw->ec->iconic)
725      //e_comp_object_signal_emit(cw->smart_obj, "e,action,iconify", "e");
726    if (!cw->zoomap_disabled)
727      e_zoomap_child_set(cw->zoomobj, NULL);
728    if (cw->frame_object)
729      {
730         edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
731         edje_object_part_swallow(cw->frame_object, "e.swallow.icon", cw->frame_icon);
732         edje_object_part_swallow(cw->frame_object, "e.swallow.volume", cw->frame_volume);
733         if (cw->zoomap_disabled)
734           edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object);
735         else
736           {
737              e_zoomap_child_set(cw->zoomobj, cw->frame_object);
738              edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->zoomobj);
739           }
740         no_shadow = 1;
741      }
742    else
743      {
744         no_shadow = 1;
745         if (cw->zoomobj)
746           {
747              e_zoomap_child_set(cw->zoomobj, cw->obj);
748              edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->zoomobj);
749           }
750         else
751           edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->obj);
752      }
753    if (cw->input_objs)
754      evas_object_pass_events_set(cw->obj, 1);
755    else
756      evas_object_pass_events_set(cw->obj, 0);
757 #ifdef BORDER_ZOOMAPS
758    e_zoomap_child_edje_solid_setup(cw->zoomobj);
759 #endif
760    return EINA_TRUE;
761 }
762 
763 /////////////////////////////////////////////
764 
765 static void
_e_comp_object_animating_begin(E_Comp_Object * cw)766 _e_comp_object_animating_begin(E_Comp_Object *cw)
767 {
768    cw->animating++;
769    if (cw->animating == 1)
770      {
771         e_comp->animating++;
772         REFD(cw->ec, 2);
773         e_object_ref(E_OBJECT(cw->ec));
774         evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_DEFAULT);
775      }
776 }
777 
778 static Eina_Bool
_e_comp_object_animating_end(E_Comp_Object * cw)779 _e_comp_object_animating_end(E_Comp_Object *cw)
780 {
781    if (cw->animating)
782      {
783         cw->animating--;
784         if (!cw->animating)
785           {
786              e_comp->animating--;
787              cw->showing = 0;
788              evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
789              UNREFD(cw->ec, 2);
790              /* remove ref from animation start, account for possibility of deletion from unref */
791              return !!e_object_unref(E_OBJECT(cw->ec));
792           }
793      }
794    return EINA_TRUE;
795 }
796 
797 /* handle the end of a compositor animation */
798 static void
_e_comp_object_done_defer(void * data,Evas_Object * obj EINA_UNUSED,const char * emission,const char * source EINA_UNUSED)799 _e_comp_object_done_defer(void *data, Evas_Object *obj EINA_UNUSED, const char *emission, const char *source EINA_UNUSED)
800 {
801    E_Comp_Object *cw = data;
802 
803    //INF("DONE DEFER %p: %dx%d - %s", cw->ec, cw->w, cw->h, emission);
804    /* visible clients which have never been sized are a bug */
805    if ((!cw->ec->new_client) && (!cw->ec->changes.size) && ((cw->w < 0) || (cw->h < 0)) && (!strcmp(emission, "e,action,show,done")))
806      CRI("ACK!");
807    if (!_e_comp_object_animating_end(cw)) return;
808    if (cw->animating) return;
809    /* hide only after animation finishes to guarantee a full run of the animation */
810    if (cw->defer_hide && ((!strcmp(emission, "e,action,hide,done")) || (!strcmp(emission, "e,action,done"))))
811      evas_object_hide(cw->smart_obj);
812    else if (!cw->deleted)
813      {
814         e_comp_shape_queue();
815         if (cw->visible && cw->updates_exist)
816           e_comp_object_render_update_add(cw->smart_obj);
817      }
818 }
819 
820 /* run a visibility compositor effect if available, return false if object is dead */
821 static Eina_Bool
_e_comp_object_effect_visibility_start(E_Comp_Object * cw,Eina_Bool state)822 _e_comp_object_effect_visibility_start(E_Comp_Object *cw, Eina_Bool state)
823 {
824    int x, y, zw, zh;
825 
826    if ((!cw->visibility_effect) || (!e_comp_object_effect_allowed_get(cw->smart_obj))) return EINA_TRUE;;
827    if (!cw->effect_running)
828      _e_comp_object_animating_begin(cw);
829    if (!e_comp_object_effect_stop(cw->smart_obj, _e_comp_object_done_defer))
830      return _e_comp_object_animating_end(cw);
831    if (!e_comp_object_effect_set(cw->smart_obj, cw->visibility_effect))
832      return _e_comp_object_animating_end(cw);
833    /* mouse position is not available for some windows under X11
834     * only fetch pointer position if absolutely necessary
835     */
836    if (edje_object_data_get(cw->effect_obj, "need_pointer") &&
837        (e_comp->comp_type == E_PIXMAP_TYPE_X))
838      ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
839    else
840      evas_pointer_canvas_xy_get(e_comp->evas, &x, &y);
841    x -= cw->ec->x;
842    y -= cw->ec->y;
843    if (cw->ec->zone)
844      zw = cw->ec->zone->w, zh = cw->ec->zone->h;
845    else
846      {
847         E_Zone *zone;
848 
849         zone = e_comp_object_util_zone_get(cw->smart_obj);
850         if (!zone) zone = e_zone_current_get();
851         zw = zone->w, zh = zone->h;
852      }
853    e_comp_object_effect_params_set(cw->smart_obj, 1, (int[]){cw->ec->x, cw->ec->y,
854       cw->ec->w, cw->ec->h, zw, zh, x, y}, 8);
855    e_comp_object_effect_params_set(cw->smart_obj, 0, (int[]){state}, 1);
856    e_comp_object_effect_start(cw->smart_obj, _e_comp_object_done_defer, cw);
857    return EINA_TRUE;
858 }
859 /////////////////////////////////////////////
860 
861 /* create necessary objects for clients that e manages */
862 static void
_e_comp_object_setup(E_Comp_Object * cw)863 _e_comp_object_setup(E_Comp_Object *cw)
864 {
865    cw->clip = evas_object_rectangle_add(e_comp->evas);
866    evas_object_resize(cw->clip, 999999, 999999);
867    evas_object_smart_member_add(cw->clip, cw->smart_obj);
868    cw->effect_obj = edje_object_add(e_comp->evas);
869    evas_object_move(cw->effect_obj, cw->x, cw->y);
870    evas_object_clip_set(cw->effect_obj, cw->clip);
871    evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
872    e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none");
873    cw->shobj = edje_object_add(e_comp->evas);
874    evas_object_data_set(cw->shobj, "comp_smart_obj", cw->smart_obj);
875    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
876    edje_object_signal_callback_add(cw->shobj, "e,action,*,done", "e", _e_comp_object_done_defer, cw);
877 
878    /* name objects appropriately for nicer printing when using e_comp_util_wins_print() */
879    if (cw->ec->override)
880      {
881         evas_object_name_set(cw->shobj, "cw->shobj::WINDOW");
882         evas_object_name_set(cw->effect_obj, "cw->effect_obj::WINDOW");
883         evas_object_name_set(cw->clip, "cw->clip::WINDOW");
884      }
885    else if (!cw->ec->input_only)
886      {
887         evas_object_name_set(cw->shobj, "cw->shobj::CLIENT");
888         evas_object_name_set(cw->effect_obj, "cw->effect_obj::CLIENT");
889         evas_object_name_set(cw->clip, "cw->clip::CLIENT");
890      }
891    cw->real_hid = !cw->ec->input_only;
892    if (!cw->ec->input_only)
893      {
894         //e_util_size_debug_set(cw->clip, 1);
895         e_util_size_debug_set(cw->effect_obj, 1);
896         //e_util_size_debug_set(cw->shobj, 1);
897         evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_cb_mouse_in, cw);
898         evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_cb_mouse_out, cw);
899         evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_DOWN, _e_comp_object_cb_mouse_down, cw);
900         evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_cb_mouse_up, cw);
901         evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_MOVE, _e_comp_object_cb_mouse_move, cw);
902         evas_object_event_callback_add(cw->smart_obj, EVAS_CALLBACK_MOUSE_WHEEL, _e_comp_object_cb_mouse_wheel, cw);
903      }
904 }
905 
906 static void
_e_comp_object_mirror_pixels_get(void * data,Evas_Object * obj)907 _e_comp_object_mirror_pixels_get(void *data, Evas_Object *obj)
908 {
909    E_Comp_Object *cw = data;
910    E_Client *ec = cw->ec;
911    int pw, ph;
912 
913    if ((!ec->pixmap) || (!e_pixmap_size_get(ec->pixmap, &pw, &ph)))
914      {
915         evas_object_image_data_set(obj, NULL);
916         return;
917      }
918 
919    /* This is a big fat hack - ideally we're already on this list
920     * if the parent is visible, but there are some circumstances
921     * where a client receives damage while visible but its own pixels_get
922     * callback doesn't fire (new damage during the start frame of a desk
923     * switch animation).
924     * Thus we can't make this addition conditional on visibility or we can
925     * (under wayland at least) lose a frame callback and stop updating.
926     *
927     * e_comp_client_post_update_add() prevents clients from being
928     * on the list twice, so this is theoretically not harmful.
929     */
930    e_comp_client_post_update_add(ec);
931 
932    if (cw->native) return;
933 
934    evas_object_image_data_set(obj, e_pixmap_image_data_get(cw->ec->pixmap));
935 }
936 
937 /////////////////////////////////////////////
938 
939 /* for fast path evas rendering; only called during render */
940 static void
_e_comp_object_pixels_get(void * data,Evas_Object * obj)941 _e_comp_object_pixels_get(void *data, Evas_Object *obj)
942 {
943    E_Comp_Object *cw = data;
944    E_Client *ec = cw->ec;
945    int pw, ph;
946 
947    if ((!ec->pixmap) || (!e_pixmap_size_get(ec->pixmap, &pw, &ph)))
948      {
949         evas_object_image_data_set(obj, NULL);
950         return;
951      }
952    //INF("PIXEL GET %p: %dx%d || %dx%d", ec, ec->w, ec->h, pw, ph);
953 
954    /* queue another render if client is still dirty; cannot refresh here. */
955    if (e_pixmap_dirty_get(ec->pixmap) && e_pixmap_size_get(ec->pixmap, &pw, &ph))
956      {
957         e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
958         /* if updates for existing pixmap don't exist then avoid unsetting existing image */
959         if ((!cw->pending_updates) || eina_tiler_empty(cw->pending_updates)) return;
960      }
961 
962    if (cw->native)
963      {
964         E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
965         e_comp_client_post_update_add(cw->ec);
966      }
967    else if (e_comp_object_render(ec->frame))
968      {
969         /* apply shape mask if necessary */
970         if ((!cw->native) && (ec->shaped || ec->shape_changed))
971           e_comp_object_shape_apply(ec->frame);
972         ec->shape_changed = 0;
973      }
974    if (e_object_is_del(E_OBJECT(ec))) return;
975    /* shaped clients get precise mouse events to handle transparent pixels */
976    evas_object_precise_is_inside_set(cw->obj, ec->shaped || ec->shaped_input);
977 
978    //INF("%p PX(%dx%d) EC(%dx%d) CW(%dx%d)", ec, pw, ph, ec->w, ec->h, cw->w, cw->h);
979    //e_comp_object_frame_wh_adjust(cw->smart_obj, pw, ph, &pw, &ph);
980    //if ((ec->w != pw) || (ec->h != ph))
981      //{
982         ///* DO NOT RESIZE HERE. */
983         //INF("CW RSZ FIX: %dx%d -> %dx%d", ec->w, ec->h, pw, ph);
984         //ec->w = pw, ec->h = ph;
985         //ec->changes.size = 1;
986         //EC_CHANGED(ec);
987      //}
988 }
989 
990 /////////////////////////////////////////////
991 
992 static void
_e_comp_object_ssd_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)993 _e_comp_object_ssd_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
994 {
995    E_Comp_Object *cw = data;
996 
997    evas_object_smart_callback_call(cw->smart_obj, "mouse_in", event_info);
998 }
999 
1000 static void
_e_comp_object_ssd_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)1001 _e_comp_object_ssd_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
1002 {
1003    E_Comp_Object *cw = data;
1004 
1005    evas_object_smart_callback_call(cw->smart_obj, "mouse_out", event_info);
1006 }
1007 
1008 /////////////////////////////////////////////
1009 
1010 static void
_e_comp_object_client_pending_resize_add(E_Client * ec,int w,int h,unsigned int serial)1011 _e_comp_object_client_pending_resize_add(E_Client *ec,
1012                                          int w,
1013                                          int h,
1014                                          unsigned int serial)
1015 {
1016    E_Client_Pending_Resize *pnd;
1017 
1018    pnd = E_NEW(E_Client_Pending_Resize, 1);
1019    if (!pnd) return;
1020    pnd->w = w;
1021    pnd->h = h;
1022    pnd->serial = serial;
1023    ec->pending_resize = eina_list_append(ec->pending_resize, pnd);
1024 }
1025 
1026 static void
_e_comp_intercept_move(void * data,Evas_Object * obj,int x,int y)1027 _e_comp_intercept_move(void *data, Evas_Object *obj, int x, int y)
1028 {
1029    E_Comp_Object *cw = data;
1030    int ix, iy, fx, fy;
1031 
1032    /* if frame_object does not exist, client_inset indicates CSD.
1033     * this means that ec->client matches cw->x/y, the opposite
1034     * of SSD.
1035     */
1036    fx = (!cw->frame_object) * cw->client_inset.l;
1037    fy = (!cw->frame_object) * cw->client_inset.t;
1038    if ((cw->x == x + fx) && (cw->y == y + fy))
1039      {
1040         if ((cw->ec->x != x) || (cw->ec->y != y))
1041           {
1042              /* handle case where client tries to move to position and back very quickly */
1043              cw->ec->x = x, cw->ec->y = y;
1044              cw->ec->client.x = x + cw->client_inset.l;
1045              cw->ec->client.y = y + cw->client_inset.t;
1046           }
1047         return;
1048      }
1049    if (!cw->ec->maximize_override)
1050      {
1051         /* prevent moving in some directions while directionally maximized */
1052         if ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
1053           y = cw->y;
1054         if ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
1055           x = cw->x;
1056      }
1057    ix = x + cw->client_inset.l;
1058    iy = y + cw->client_inset.t;
1059    if (cw->ec->maximized && (!cw->ec->maximize_override) && ((cw->ec->x != x) || (cw->ec->y != y)) &&
1060        ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_VERTICAL) &&
1061        ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_HORIZONTAL))
1062      {
1063         /* prevent moving at all if move isn't allowed in current maximize state */
1064         if ((!e_config->allow_manip) && ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
1065         /* queue unmaximize if we are allowing move and update unmaximize geometry */
1066         if ((!cw->ec->shading) && (!cw->ec->shaded))
1067           {
1068              cw->ec->changes.need_unmaximize = 1;
1069              cw->ec->saved.x = ix - cw->ec->zone->x;
1070              cw->ec->saved.y = iy - cw->ec->zone->y;
1071              cw->ec->saved.w = cw->ec->client.w;
1072              cw->ec->saved.h = cw->ec->client.h;
1073              EC_CHANGED(cw->ec);
1074              return;
1075           }
1076         return;
1077      }
1078    /* only update during resize if triggered by resize */
1079    if (e_client_util_resizing_get(cw->ec) && (!cw->force_move)) return;
1080    cw->ec->x = x, cw->ec->y = y;
1081    if (cw->ec->new_client)
1082      {
1083         /* don't actually do anything until first client idler loop */
1084         if (!cw->ec->placed)
1085           cw->ec->placed = ((!cw->ec->dialog) && (!cw->ec->parent));
1086         cw->ec->changes.pos = 1;
1087         EC_CHANGED(cw->ec);
1088      }
1089    else
1090      {
1091         /* only update xy position of client to avoid invalid
1092          * first damage region if it is not a new_client. */
1093         cw->ec->placed = 1;
1094         if (!cw->ec->shading)
1095           {
1096              cw->ec->client.x = ix;
1097              cw->ec->client.y = iy;
1098           }
1099         /* flip SSD->CSD */
1100         if (!cw->frame_object)
1101           x = ix, y = iy;
1102         evas_object_move(obj, x, y);
1103      }
1104 }
1105 
1106 static void
_e_comp_intercept_resize(void * data,Evas_Object * obj,int w,int h)1107 _e_comp_intercept_resize(void *data, Evas_Object *obj, int w, int h)
1108 {
1109    E_Comp_Object *cw = data;
1110    int pw = 0, ph = 0, fw, fh, iw, ih, prev_w, prev_h, x, y;
1111 
1112 
1113    if ((w < 1) || (h < 1)) return;
1114    /* if frame_object does not exist, client_inset indicates CSD.
1115     * this means that ec->client matches cw->w/h, the opposite
1116     * of SSD.
1117     */
1118    fw = (!cw->frame_object) * (-cw->client_inset.l - cw->client_inset.r);
1119    fh = (!cw->frame_object) * (-cw->client_inset.t - cw->client_inset.b);
1120    if ((cw->w == w + fw) && (cw->h == h + fh))
1121      {
1122         if (cw->ec->shading || cw->ec->shaded) return;
1123         if (((cw->ec->w != w) || (cw->ec->h != h)) ||
1124             (cw->ec->client.w != w - cw->client_inset.l - cw->client_inset.r) ||
1125             (cw->ec->client.h != h - cw->client_inset.t - cw->client_inset.b))
1126           {
1127              /* handle case where client tries to resize itself and back very quickly */
1128              cw->ec->w = w, cw->ec->h = h;
1129              cw->ec->client.w = w - cw->client_inset.l - cw->client_inset.r;
1130              cw->ec->client.h = h - cw->client_inset.t - cw->client_inset.b;
1131              evas_object_smart_callback_call(obj, "client_resize", NULL);
1132           }
1133         return;
1134      }
1135    /* guarantee that fullscreen is fullscreen */
1136    if (cw->ec->fullscreen && ((w != cw->ec->zone->w) || (h != cw->ec->zone->h)))
1137      return;
1138    /* calculate client size */
1139    iw = w - cw->client_inset.l - cw->client_inset.r;
1140    ih = h - cw->client_inset.t - cw->client_inset.b;
1141    if (cw->ec->maximized && (!cw->ec->maximize_override) && ((cw->ec->w != w) || (cw->ec->h != h)))
1142      {
1143         /* prevent resizing while maximized depending on direction and config */
1144         if ((!e_config->allow_manip) && ((cw->ec->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
1145         if ((!cw->ec->shading) && (!cw->ec->shaded))
1146           {
1147              Eina_Bool reject = EINA_FALSE;
1148              if (cw->ec->maximized & E_MAXIMIZE_VERTICAL)
1149                {
1150                   if (cw->ec->client.h != ih)
1151                     {
1152                        cw->ec->saved.h = ih;
1153                        cw->ec->saved.y = cw->ec->client.y - cw->ec->zone->y;
1154                        reject = cw->ec->changes.need_unmaximize = 1;
1155                     }
1156                }
1157              if (cw->ec->maximized & E_MAXIMIZE_HORIZONTAL)
1158                {
1159                   if (cw->ec->client.w != iw)
1160                     {
1161                        cw->ec->saved.w = iw;
1162                        cw->ec->saved.x = cw->ec->client.x - cw->ec->zone->x;
1163                        reject = cw->ec->changes.need_unmaximize = 1;
1164                     }
1165                }
1166              if (reject)
1167                {
1168                   EC_CHANGED(cw->ec);
1169                   return;
1170                }
1171           }
1172      }
1173    if (cw->ec->new_client || (!cw->ec->visible) || (!cw->effect_obj))
1174      {
1175         /* do nothing until client idler loops */
1176         if (!cw->ec->maximized)
1177           {
1178              /* NO. DO NOT DO THIS OR YOU WILL BREAK WINDOW RESIZING. */
1179              //if ((w != cw->ec->w) || (h != cw->ec->h))
1180                {
1181                   cw->ec->w = w, cw->ec->h = h;
1182                   cw->ec->changes.size = 1;
1183                   EC_CHANGED(cw->ec);
1184                }
1185           }
1186         return;
1187      }
1188    if ((!cw->ec->internal) && e_client_util_resizing_get(cw->ec) && cw->ec->netwm.sync.request &&
1189        ((cw->ec->w != w) || (cw->ec->h != h)))
1190      {
1191         /* this is ugly. */
1192         //INF("PENDING %dx%d", iw, ih);
1193         /* netwm sync resizes queue themselves and then trigger later on */
1194         _e_comp_object_client_pending_resize_add(cw->ec, iw, ih, cw->ec->netwm.sync.serial);
1195      }
1196    cw->ec->w = w, cw->ec->h = h;
1197    if ((!cw->ec->shading) && (!cw->ec->shaded))
1198      {
1199         /* client geom never changes when shading since the client is never altered */
1200         INF("%p: CUR(%dx%d) || REQ(%dx%d)", cw->ec, cw->ec->client.w, cw->ec->client.h, iw, ih);
1201         cw->ec->client.w = iw;
1202         cw->ec->client.h = ih;
1203         if ((cw->ec->client.w < 0) || (cw->ec->client.h < 0)) CRI("WTF");
1204      }
1205    if ((!cw->ec->input_only) && cw->redirected && (!cw->ec->shading) && (!cw->ec->shaded) &&
1206        (e_pixmap_dirty_get(cw->ec->pixmap) || (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph))))
1207      {
1208         if (e_comp->comp_type != E_PIXMAP_TYPE_X) return;
1209         if (e_object_is_del(E_OBJECT(cw->ec))) return;
1210         /* shapeless clients smh */
1211         if (cw->ec->shaped && (!cw->ec->shape_rects)) return;
1212         /* pending shape change gtfo */
1213         if (!cw->ec->changes.shape)
1214           {
1215              /* client can't be resized if its pixmap isn't usable, try again */
1216              e_pixmap_dirty(cw->ec->pixmap);
1217              if (e_comp->nocomp)
1218                e_pixmap_refresh(cw->ec->pixmap);
1219              else
1220                {
1221                   e_comp_object_render_update_add(obj);
1222                   e_comp_render_queue();
1223                }
1224           }
1225         cw->ec->changes.size = 1;
1226         EC_CHANGED(cw->ec);
1227         return;
1228      }
1229    if (e_pixmap_failures_get(cw->ec->pixmap) && (!cw->redirected))
1230      {
1231         e_comp_object_redirected_set(obj, 1);
1232         return;
1233      }
1234    prev_w = cw->w, prev_h = cw->h;
1235    e_comp_object_frame_wh_adjust(obj, 0, 0, &fw, &fh);
1236    /* check shading and clamp to pixmap size for regular clients */
1237    if ((!cw->ec->shading) && (!cw->ec->shaded) && (!cw->ec->input_only) && (!cw->ec->override) &&
1238        (((w - fw != pw) || (h - fh != ph))))
1239      {
1240         //INF("CALLBACK: REQ(%dx%d) != CUR(%dx%d)", w - fw, h - fh, pw, ph);
1241         evas_object_smart_callback_call(obj, "client_resize", NULL);
1242         /* flip for CSD */
1243         if (cw->frame_object || cw->ec->input_only)
1244           e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
1245         else
1246           w = pw, h = ph;
1247         if ((cw->w == w) && (cw->h == h))
1248           {
1249              /* going to be a noop resize which won't trigger smart resize */
1250              RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
1251              if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
1252           }
1253         evas_object_resize(obj, w, h);
1254      }
1255    else
1256      {
1257         /* flip for CSD */
1258         if ((!cw->frame_object) && (!cw->ec->input_only))
1259           w = pw, h = ph;
1260         /* "just do it" for overrides */
1261         //INF("INTERCEPT %dx%d", w, h);
1262         evas_object_resize(obj, w, h);
1263      }
1264    if (!cw->ec->override)
1265      {
1266         /* shape probably changed for non-overrides */
1267         cw->ec->need_shape_merge |= cw->ec->shaped || cw->ec->shaped_input;
1268         cw->ec->need_shape_export |= cw->ec->shaped;
1269         if (cw->ec->shaped || cw->ec->shaped_input)
1270           EC_CHANGED(cw->ec);
1271      }
1272 
1273    /* this fixes positioning jiggles when using a resize mode
1274     * which also changes the client's position
1275     */
1276    cw->force_move = 1;
1277    if (cw->frame_object)
1278      x = cw->x, y = cw->y;
1279    else
1280      x = cw->ec->x, y = cw->ec->y;
1281    switch (cw->ec->resize_mode)
1282      {
1283       case E_POINTER_RESIZE_BL:
1284       case E_POINTER_RESIZE_L:
1285         evas_object_move(obj, x + prev_w - cw->w, y);
1286         break;
1287       case E_POINTER_RESIZE_TL:
1288         evas_object_move(obj, x + prev_w - cw->w, y + prev_h - cw->h);
1289         break;
1290       case E_POINTER_RESIZE_T:
1291       case E_POINTER_RESIZE_TR:
1292         evas_object_move(obj, x, y + prev_h - cw->h);
1293         break;
1294       default:
1295         break;
1296      }
1297    if (cw->ec->internal_elm_win && (!cw->ec->moving) && (!e_client_util_resizing_get(cw->ec)) &&
1298        (!cw->ec->fullscreen) && (!cw->ec->maximized) &&
1299        e_win_centered_get(cw->ec->internal_elm_win))
1300      {
1301         e_comp_object_util_center(obj);
1302      }
1303    cw->force_move = 0;
1304 }
1305 
1306 static void
_e_comp_intercept_layer_set(void * data,Evas_Object * obj,int layer)1307 _e_comp_intercept_layer_set(void *data, Evas_Object *obj, int layer)
1308 {
1309    E_Comp_Object *cw = data;
1310    unsigned int l = e_comp_canvas_layer_map(layer);
1311    int oldraise;
1312    E_Client *ec;
1313 
1314    if (cw->ec->layer_block)
1315      {
1316         /* doing a compositor effect, follow directions */
1317         evas_object_layer_set(obj, layer);
1318         if (layer == cw->ec->layer) //trying to put layer back
1319           {
1320              if (cw->visible)
1321                {
1322                   e_comp_shape_queue();
1323                   e_comp_render_queue();
1324                }
1325              ec = e_client_above_get(cw->ec);
1326              if (ec && (evas_object_layer_get(ec->frame) != evas_object_layer_get(obj)))
1327                {
1328                   ec = e_client_below_get(cw->ec);
1329                   if (ec && (evas_object_layer_get(ec->frame) == evas_object_layer_get(cw->smart_obj)))
1330                     {
1331                        evas_object_stack_above(obj, ec->frame);
1332                        return;
1333                     }
1334                   ec = NULL;
1335                }
1336              if (ec && (cw->ec->parent == ec))
1337                evas_object_stack_above(obj, ec->frame);
1338              else
1339                evas_object_stack_below(obj, ec ? ec->frame : e_comp->layers[cw->layer].obj);
1340           }
1341         return;
1342      }
1343    if (cw->layer == l) return;
1344    if (e_comp_canvas_client_layer_map(layer) == 9999)
1345      return; //invalid layer for clients not doing comp effects
1346    if (cw->ec->fullscreen)
1347      {
1348         cw->ec->saved.layer = layer;
1349         return;
1350      }
1351    oldraise = e_config->transient.raise;
1352    _e_comp_object_layers_remove(cw);
1353    /* clamp to valid client layer */
1354    layer = e_comp_canvas_client_layer_map_nearest(layer);
1355    ec = cw->ec;
1356    ec->layer = layer;
1357    if (ec->stack.prev || ec->stack.next)
1358      {
1359         if (ec->stack.ignore == 0)
1360           {
1361              Eina_List *ll, *list = e_client_stack_list_prepare(ec);
1362              E_Client *child;
1363 
1364              EINA_LIST_FOREACH(list, ll, child)
1365                {
1366                   if (child == ec) continue;
1367                   evas_object_layer_set(child->frame, layer);
1368                }
1369              e_client_stack_list_finish(list);
1370              evas_object_raise(ec->frame);
1371           }
1372      }
1373    else
1374      {
1375         if (e_config->transient.layer)
1376           {
1377              E_Client *child;
1378              Eina_List *list = eina_list_clone(cw->ec->transients);
1379 
1380              /* We need to set raise to one, else the child won't
1381               * follow to the new layer. It should be like this,
1382               * even if the user usually doesn't want to raise
1383               * the transients.
1384               */
1385              e_config->transient.raise = 1;
1386              EINA_LIST_FREE(list, child)
1387                evas_object_layer_set(child->frame, layer);
1388           }
1389      }
1390    if (!cw->ec->override)
1391      {
1392         /* set client stacking hints based on layer */
1393         if (layer == E_LAYER_CLIENT_BELOW)
1394           e_hints_window_stacking_set(cw->ec, E_STACKING_BELOW);
1395         else if (layer == E_LAYER_CLIENT_ABOVE)
1396           e_hints_window_stacking_set(cw->ec, E_STACKING_ABOVE);
1397         else
1398           e_hints_window_stacking_set(cw->ec, E_STACKING_NONE);
1399      }
1400 
1401    e_config->transient.raise = oldraise;
1402    cw->layer = e_comp_canvas_layer_map(layer);
1403    _e_comp_object_layers_add(cw, NULL, NULL, 0);
1404    //if (cw->ec->new_client)
1405      //INF("CLIENT STACKED %p: %u", cw->ec, layer);
1406    evas_object_layer_set(obj, layer);
1407    if (!e_comp->layers[cw->layer].obj) return; //this is a layer marker
1408    evas_object_stack_below(obj, e_comp->layers[cw->layer].obj);
1409    if (evas_object_below_get(obj) == e_comp->layers[cw->layer].obj)
1410      {
1411         /* can't stack a client above its own layer marker */
1412         CRI("STACKING ERROR!!!");
1413      }
1414    if (!cw->visible) return;
1415    e_comp_render_queue();
1416    e_comp_shape_queue();
1417 }
1418 
1419 typedef void (*E_Comp_Object_Stack_Func)(Evas_Object *obj, Evas_Object *stack);
1420 
1421 static void
_e_comp_intercept_stack_helper(E_Comp_Object * cw,Evas_Object * stack,E_Comp_Object_Stack_Func stack_cb)1422 _e_comp_intercept_stack_helper(E_Comp_Object *cw, Evas_Object *stack, E_Comp_Object_Stack_Func stack_cb)
1423 {
1424    E_Comp_Object *cw2 = NULL;
1425    E_Client *ecstack;
1426    short layer;
1427    Evas_Object *o = stack;
1428    Eina_Bool raising = stack_cb == evas_object_stack_above;
1429 
1430    if (cw->ec->layer_block)
1431      {
1432         /* obey compositor effects! */
1433         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
1434           evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
1435         stack_cb(cw->smart_obj, stack);
1436         if (cw->ec->layer == evas_object_layer_get(cw->smart_obj))
1437           evas_object_data_del(cw->smart_obj, "client_restack");
1438         return;
1439      }
1440    /* assume someone knew what they were doing during client init */
1441    if (cw->ec->new_client)
1442      layer = cw->ec->layer;
1443    else
1444      layer = evas_object_layer_get(stack);
1445    ecstack = e_client_below_get(cw->ec);
1446    if (layer != e_comp_canvas_layer_map_to(cw->layer))
1447      {
1448         /* some FOOL is trying to restack a layer marker */
1449         if (cw->smart_obj == e_comp->layers[cw->layer].obj) return;
1450         evas_object_layer_set(cw->smart_obj, layer);
1451         /* we got our layer wrangled, return now! */
1452         if (layer != e_comp_canvas_layer_map_to(cw->layer)) return;
1453      }
1454 
1455    /* check if we're stacking below another client */
1456    cw2 = evas_object_data_get(o, "comp_obj");
1457    while (!cw2)
1458      {
1459         /* check for non-client layer object */
1460         if (!e_util_strcmp(evas_object_name_get(o), "layer_obj"))
1461           break;
1462         /* find an existing client to use for layering
1463          * by walking up the object stack
1464          *
1465          * this is guaranteed to be pretty quick since we'll either:
1466          * - run out of client layers
1467          * - find a stacking client
1468          */
1469         o = evas_object_above_get(o);
1470         if ((!o) || (o == cw->smart_obj)) break;
1471         if (evas_object_layer_get(o) != layer)
1472           {
1473              /* reached the top client layer somehow
1474               * use top client object
1475               */
1476              o = e_comp->layers[e_comp_canvas_layer_map(E_LAYER_CLIENT_PRIO)].obj;
1477           }
1478         if (!o)
1479           /* top client layer window hasn't been stacked yet. this probably shouldn't happen?
1480            * return here since the top client layer window
1481            */
1482           {
1483              E_Client *ec;
1484 
1485              ec = e_client_top_get();
1486              if (ec)
1487                o = ec->frame;
1488              //else //wat
1489           }
1490         if (o) cw2 = evas_object_data_get(o, "comp_obj");
1491      }
1492 
1493 
1494    /* remove existing layers */
1495    _e_comp_object_layers_remove(cw);
1496    if (cw2)
1497      {
1498         if (o == stack) //if stacking above, cw2 is above; else cw2 is below
1499           _e_comp_object_layers_add(cw, raising ? cw2 : NULL, raising ? NULL : cw2, 0);
1500         else if (o == cw->smart_obj) //prepend (lower) if not stacking above
1501           _e_comp_object_layers_add(cw, NULL, NULL, !raising);
1502         else //if no stacking objects found, either raise or lower
1503           _e_comp_object_layers_add(cw, raising ? NULL : cw2, raising ? cw2 : NULL, 0);
1504      }
1505    else
1506      _e_comp_object_layers_add(cw, NULL, NULL, 0);
1507    /* set restack if stacking has changed */
1508    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
1509      evas_object_data_set(cw->smart_obj, "client_restack", (void*)1);
1510    stack_cb(cw->smart_obj, stack);
1511    if (e_comp->layers[cw->layer].obj)
1512      if (evas_object_below_get(cw->smart_obj) == e_comp->layers[cw->layer].obj)
1513        {
1514           CRI("STACKING ERROR!!!");
1515        }
1516    if (cw->ec->new_client || (!ecstack) || (ecstack->frame != o))
1517      evas_object_data_del(cw->smart_obj, "client_restack");
1518    if (!cw->visible) return;
1519    e_comp_render_queue();
1520    e_comp_shape_queue();
1521 }
1522 
1523 static void
_e_comp_intercept_stack_above(void * data,Evas_Object * obj,Evas_Object * above)1524 _e_comp_intercept_stack_above(void *data, Evas_Object *obj, Evas_Object *above)
1525 {
1526    EINA_SAFETY_ON_TRUE_RETURN(obj == above);
1527    if (evas_object_below_get(obj) == above) return;
1528    _e_comp_intercept_stack_helper(data, above, evas_object_stack_above);
1529 }
1530 
1531 static void
_e_comp_intercept_stack_below(void * data,Evas_Object * obj,Evas_Object * below)1532 _e_comp_intercept_stack_below(void *data, Evas_Object *obj, Evas_Object *below)
1533 {
1534    EINA_SAFETY_ON_TRUE_RETURN(obj == below);
1535    if (evas_object_above_get(obj) == below) return;
1536    _e_comp_intercept_stack_helper(data, below, evas_object_stack_below);
1537 }
1538 
1539 static void
_e_comp_intercept_lower(void * data,Evas_Object * obj)1540 _e_comp_intercept_lower(void *data, Evas_Object *obj)
1541 {
1542    E_Comp_Object *cw = data;
1543    Evas_Object *o;
1544 
1545    if (cw->ec->layer_block)
1546      {
1547         evas_object_lower(obj);
1548         return;
1549      }
1550    if (!EINA_INLIST_GET(cw->ec)->prev) return; //already lowest on layer
1551    o = evas_object_below_get(obj);
1552    _e_comp_object_layers_remove(cw);
1553    /* prepend to client list since this client should be the first item now */
1554    _e_comp_object_layers_add(cw, NULL, NULL, 1);
1555    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) return; //already at bottom!
1556    if (obj == e_comp->layers[cw->layer].obj) return; //never lower a layer marker!
1557    evas_object_data_set(obj, "client_restack", (void*)1);
1558    evas_object_lower(obj);
1559    evas_object_data_del(obj, "client_restack");
1560    if (!cw->visible) return;
1561    e_comp_render_queue();
1562    e_comp_shape_queue();
1563 }
1564 
1565 static void
_e_comp_intercept_raise(void * data,Evas_Object * obj)1566 _e_comp_intercept_raise(void *data, Evas_Object *obj)
1567 {
1568    E_Comp_Object *cw = data;
1569    Evas_Object *o;
1570 
1571    if (cw->ec->layer_block)
1572      {
1573         evas_object_raise(obj);
1574         return;
1575      }
1576    if (!EINA_INLIST_GET(cw->ec)->next) return;//already highest on layer
1577    o = evas_object_above_get(obj);
1578    {
1579       E_Client *ecabove = e_client_above_get(cw->ec);
1580       if (ecabove && (ecabove->frame == e_comp->layers[cw->layer].obj) &&
1581           (ecabove->frame == o)) return; //highest below marker
1582    }
1583    if (evas_object_layer_get(o) != evas_object_layer_get(obj)) return; //already at top!
1584    if (obj == e_comp->layers[cw->layer].obj) //never raise a non-layer marker!
1585      evas_object_raise(obj);
1586    else
1587      {
1588         Evas_Object *op;
1589 
1590         /* still stack below override below the layer marker */
1591         for (op = o = e_comp->layers[cw->layer].obj;
1592              o && o != e_comp->layers[cw->layer - 1].obj;
1593              op = o, o = evas_object_below_get(o))
1594           {
1595              E_Client *ec;
1596 
1597              ec = e_comp_object_client_get(o);
1598              if (ec && (!ec->override)) break;
1599           }
1600         evas_object_stack_below(obj, op);
1601         if (e_client_focus_track_enabled())
1602           e_client_raise_latest_set(cw->ec); //modify raise list if necessary
1603      }
1604    if (!cw->visible) return;
1605    e_comp_render_queue();
1606    e_comp_shape_queue();
1607 }
1608 
1609 static void
_e_comp_intercept_hide(void * data,Evas_Object * obj)1610 _e_comp_intercept_hide(void *data, Evas_Object *obj)
1611 {
1612    E_Comp_Object *cw = data;
1613 
1614    if (cw->ec->hidden)
1615      {
1616         /* hidden flag = just do it */
1617         evas_object_hide(obj);
1618         return;
1619      }
1620 
1621    if (cw->ec->input_only)
1622      {
1623         /* input_only = who cares */
1624         evas_object_hide(obj);
1625         return;
1626      }
1627    /* already hidden or currently animating */
1628    if ((!cw->visible) || (cw->animating && (!cw->showing) && (!cw->ec->iconic))) return;
1629 
1630    /* don't try hiding during shutdown */
1631    cw->defer_hide |= stopping;
1632    if (!cw->defer_hide)
1633      {
1634         if ((!cw->ec->iconic) && (!cw->ec->override))
1635           /* unset delete requested so the client doesn't break */
1636           cw->ec->delete_requested = 0;
1637         if ((!cw->animating) || cw->showing || cw->ec->iconic)
1638           {
1639              if (cw->ec->iconic)
1640                e_comp_object_signal_emit(obj, "e,action,iconify", "e");
1641              if ((!cw->ec->iconic) || (cw->ec->iconic && (!cw->animating)))
1642                {
1643                   e_comp_object_signal_emit(obj, "e,state,hidden", "e");
1644                   if (!cw->showing)
1645                     _e_comp_object_animating_begin(cw);
1646                   if (!_e_comp_object_effect_visibility_start(cw, 0)) return;
1647                }
1648              evas_object_smart_callback_call(obj, "hiding", cw->ec);
1649              cw->defer_hide = !!cw->animating;
1650              if (!cw->animating)
1651                e_comp_object_effect_set(obj, NULL);
1652           }
1653      }
1654    if (cw->animating) return;
1655    /* if we have no animations running, go ahead and hide */
1656    cw->defer_hide = 0;
1657    evas_object_hide(obj);
1658 }
1659 
1660 static void
_e_comp_intercept_show_helper(E_Comp_Object * cw)1661 _e_comp_intercept_show_helper(E_Comp_Object *cw)
1662 {
1663    int w = 0, h = 0;
1664 
1665    if (cw->ec->sticky)
1666      e_comp_object_signal_emit(cw->smart_obj, "e,state,sticky", "e");
1667    if (cw->visible)
1668      {
1669         if (cw->ec->iconic && cw->animating)
1670           {
1671              /* triggered during iconify animation */
1672              e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
1673              cw->defer_hide = 0;
1674           }
1675         return;
1676      }
1677    if ((!cw->updates) && (!cw->ec->input_only) && (!cw->ec->ignored))
1678      {
1679         _e_comp_object_updates_init(cw);
1680         if (!cw->updates)
1681           {
1682              cw->ec->changes.visible = !cw->ec->hidden;
1683              cw->ec->visible = 1;
1684              EC_CHANGED(cw->ec);
1685              return;
1686           }
1687      }
1688    if (cw->ec->new_client)
1689      {
1690         /* ignore until client idler first run */
1691         cw->ec->changes.visible = !cw->ec->hidden;
1692         cw->ec->visible = 1;
1693         EC_CHANGED(cw->ec);
1694         return;
1695      }
1696    /* ensure that some kind of frame calc has occurred if there's a frame */
1697    if (e_pixmap_is_x(cw->ec->pixmap) && cw->frame_object &&
1698        (cw->ec->h == cw->ec->client.h) && (cw->ec->w == cw->ec->client.w))
1699      ERR("Frame calc hasn't happened");
1700    /* force resize in case it hasn't happened yet, or just to update size */
1701    evas_object_resize(cw->smart_obj, cw->ec->w, cw->ec->h);
1702    if ((cw->w < 1) || (cw->h < 1))
1703      {
1704         /* if resize didn't go through, try again */
1705         cw->ec->visible = cw->ec->changes.visible = 1;
1706         EC_CHANGED(cw->ec);
1707         return;
1708      }
1709    /* re-set geometry */
1710    if (cw->ec->placed)
1711      evas_object_move(cw->smart_obj, cw->ec->x, cw->ec->y);
1712 
1713    /* if pixmap not available, clear pixmap since we're going to fetch it again */
1714    if (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))
1715      e_pixmap_clear(cw->ec->pixmap);
1716 
1717    if (cw->real_hid && w && h)
1718      {
1719         DBG("  [%p] real hid - fix", cw->ec);
1720         cw->real_hid = 0;
1721         /* force comp theming in case it didn't happen already */
1722         e_comp_object_frame_theme_set(cw->smart_obj, E_COMP_OBJECT_FRAME_RESHADOW);
1723      }
1724 
1725    /* only do the show if show is allowed */
1726    if (!cw->real_hid)
1727      {
1728         if (cw->ec->internal) //internal clients render when they feel like it
1729           e_comp_object_damage(cw->smart_obj, 0, 0, cw->w, cw->h);
1730         evas_object_show(cw->smart_obj);
1731      }
1732 }
1733 
1734 static void
_e_comp_intercept_show(void * data,Evas_Object * obj EINA_UNUSED)1735 _e_comp_intercept_show(void *data, Evas_Object *obj EINA_UNUSED)
1736 {
1737    E_Comp_Object *cw = data;
1738    E_Client *ec = cw->ec;
1739 
1740    if (ec->ignored) return;
1741    if (cw->effect_obj)
1742      {
1743         //INF("SHOW2 %p", ec);
1744         _e_comp_intercept_show_helper(cw);
1745         return;
1746      }
1747    //INF("SHOW %p", ec);
1748    if (ec->input_only)
1749      {
1750         cw->effect_obj = evas_object_rectangle_add(e_comp->evas);
1751         evas_object_color_set(cw->effect_obj, 0, 0, 0, 0);
1752         evas_object_smart_member_add(cw->effect_obj, cw->smart_obj);
1753      }
1754    else
1755      {
1756         _e_comp_object_setup(cw);
1757         cw->obj = evas_object_image_filled_add(e_comp->evas);
1758         evas_object_image_border_center_fill_set(cw->obj, EVAS_BORDER_FILL_SOLID);
1759         e_util_size_debug_set(cw->obj, 1);
1760         evas_object_image_pixels_get_callback_set(cw->obj, _e_comp_object_pixels_get, cw);
1761         evas_object_image_smooth_scale_set(cw->obj, e_comp_config_get()->smooth_windows);
1762         evas_object_name_set(cw->obj, "cw->obj");
1763         evas_object_image_colorspace_set(cw->obj, EVAS_COLORSPACE_ARGB8888);
1764         _e_comp_object_alpha_set(cw);
1765 
1766         if (cw->frame_object)
1767           {
1768              evas_object_event_callback_add(cw->obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_ssd_mouse_in, cw);
1769              evas_object_event_callback_add(cw->obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_ssd_mouse_out, cw);
1770           }
1771 
1772 #ifdef BORDER_ZOOMAPS
1773         e_comp_object_zoomap_set(o, 1);
1774 #else
1775         cw->zoomap_disabled = 1;
1776 #endif
1777         cw->redirected = 1;
1778         evas_object_color_set(cw->clip, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity, ec->netwm.opacity);
1779      }
1780 
1781    _e_comp_intercept_show_helper(cw);
1782 }
1783 
1784 static void
_e_comp_intercept_focus(void * data,Evas_Object * obj,Eina_Bool focus)1785 _e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus)
1786 {
1787    E_Comp_Object *cw = data;
1788    E_Client *ec = cw->ec;
1789 
1790    if (focus)
1791      {
1792         ec = e_client_stack_active_adjust(ec);
1793         obj = ec->frame;
1794         cw = evas_object_data_get(obj, "comp_obj");
1795      }
1796    /* note: this is here as it seems there are enough apps that do not even
1797     * expect us to emulate a look of focus but not actually set x input
1798     * focus as we do - so simply abort any focus set on such windows */
1799    /* be strict about accepting focus hint */
1800    if (e_client_has_xwindow(ec))
1801      {
1802         /* be strict about accepting focus hint */
1803         if ((!ec->icccm.accepts_focus) &&
1804             (!ec->icccm.take_focus)) return;
1805      }
1806    if (focus && ec->lock_focus_out) return;
1807    if (e_object_is_del(E_OBJECT(ec)) && focus)
1808      {
1809         CRI("CAN'T FOCUS DELETED CLIENT!");
1810         return;
1811      }
1812 
1813    /* filter focus setting based on current state */
1814    if (focus)
1815      {
1816         if (ec->focused)
1817           {
1818              evas_object_focus_set(obj, focus);
1819              return;
1820           }
1821         if ((ec->iconic) && (!ec->deskshow))
1822           {
1823              /* don't focus an iconified window. that's silly! */
1824              e_client_uniconify(ec);
1825              if (e_client_focus_track_enabled())
1826                e_client_focus_latest_set(ec);
1827              return;
1828           }
1829         if (!ec->visible)
1830           {
1831              return;
1832           }
1833         if ((!ec->sticky) && (ec->desk) && (!ec->desk->visible))
1834           {
1835              if (ec->desk->animate_count) return;
1836              e_desk_show(ec->desk);
1837              if (!ec->desk->visible) return;
1838           }
1839      }
1840 
1841    if (focus)
1842      {
1843         /* check for dialog children that steal focus */
1844         if ((ec->modal) && (ec->modal != ec) &&
1845             (ec->modal->visible) && (!e_object_is_del(E_OBJECT(ec->modal))))
1846           {
1847              evas_object_focus_set(ec->modal->frame, focus);
1848              return;
1849           }
1850         else if ((ec->leader) && (ec->leader->modal) &&
1851                  (ec->leader->modal != ec) && ec->leader->modal->visible &&
1852                  (!e_object_is_del(E_OBJECT(ec->leader->modal))))
1853           {
1854              evas_object_focus_set(ec->leader->modal->frame, focus);
1855              return;
1856           }
1857         if (!cw->visible)
1858           {
1859              /* not yet visible, wait till the next time... */
1860              ec->want_focus = !ec->hidden;
1861              if (ec->want_focus)
1862                EC_CHANGED(ec);
1863              return;
1864           }
1865         e_client_focused_set(ec);
1866      }
1867    else
1868      {
1869         if (e_client_focused_get() == ec)
1870           e_client_focused_set(NULL);
1871      }
1872    evas_object_focus_set(obj, focus);
1873 }
1874 
1875 ////////////////////////////////////////////////////
1876 
1877 static void
_e_comp_object_frame_recalc(E_Comp_Object * cw)1878 _e_comp_object_frame_recalc(E_Comp_Object *cw)
1879 {
1880    int w, h, ox, oy, ow, oh;
1881 
1882    if (cw->frame_object)
1883      {
1884         if (cw->obj) edje_object_part_unswallow(cw->frame_object, cw->obj);
1885         evas_object_geometry_get(cw->frame_object, NULL, NULL, &w, &h);
1886         /* set a fixed size, force edje calc, check size difference */
1887         evas_object_resize(cw->frame_object, MAX(w, 50), MAX(h, 50));
1888         edje_object_message_signal_process(cw->frame_object);
1889         edje_object_calc_force(cw->frame_object);
1890         edje_object_part_geometry_get(cw->frame_object, "e.swallow.client", &ox, &oy, &ow, &oh);
1891         cw->client_inset.l = ox;
1892         cw->client_inset.r = MAX(w, 50) - (ox + ow);
1893         cw->client_inset.t = oy;
1894         cw->client_inset.b = MAX(h, 50) - (oy + oh);
1895         if (cw->obj) edje_object_part_swallow(cw->frame_object, "e.swallow.client", cw->obj);
1896         evas_object_resize(cw->frame_object, w, h);
1897         if (!cw->input_objs)
1898           evas_object_pass_events_set(cw->obj, 0);
1899      }
1900    else
1901      {
1902         cw->client_inset.l = 0;
1903         cw->client_inset.r = 0;
1904         cw->client_inset.t = 0;
1905         cw->client_inset.b = 0;
1906      }
1907    cw->client_inset.calc = !!cw->frame_object;
1908 }
1909 
1910 static void
_e_comp_smart_cb_frame_recalc(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)1911 _e_comp_smart_cb_frame_recalc(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
1912 {
1913    E_Comp_Object *cw = data;
1914    int w = 0, h = 0, pw = 0, ph = 0;
1915 
1916    /* - get current size
1917     * - calc new size
1918     * - readjust for new frame size
1919     */
1920 
1921    w = cw->ec->w, h = cw->ec->h;
1922    e_comp_object_frame_wh_unadjust(obj, w, h, &pw, &ph);
1923 
1924    _e_comp_object_frame_recalc(cw);
1925 
1926    if (!cw->ec->fullscreen)
1927      e_comp_object_frame_wh_adjust(obj, cw->ec->client.w, cw->ec->client.h, &w, &h);
1928 
1929    evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
1930    if (cw->ec->shading || cw->ec->shaded) return;
1931    if (cw->ec->fullscreen)
1932      evas_object_resize(cw->ec->frame, cw->ec->zone->w, cw->ec->zone->h);
1933    else if (cw->ec->new_client)
1934      {
1935         if ((cw->ec->w < 1) || (cw->ec->h < 1)) return;
1936         e_comp_object_frame_wh_adjust(obj, pw, ph, &w, &h);
1937         evas_object_resize(cw->ec->frame, w, h);
1938      }
1939    else if ((w != cw->ec->w) || (h != cw->ec->h))
1940      evas_object_resize(cw->ec->frame, w, h);
1941 }
1942 
1943 static Eina_Bool
_e_comp_object_shade_animator(void * data)1944 _e_comp_object_shade_animator(void *data)
1945 {
1946    E_Comp_Object *cw = data;
1947    Eina_Bool move = EINA_FALSE;
1948    int x, y, w, h;
1949    double dt, val;
1950    double dur;
1951 
1952    dt = ecore_loop_time_get() - cw->shade.start;
1953    dur = cw->ec->client.h / e_config->border_shade_speed;
1954    val = dt / dur;
1955 
1956    if (val < 0.0)
1957      val = 0.0;
1958    else if (val > 1.0)
1959      val = 1.0;
1960 
1961    if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
1962      {
1963         cw->shade.val =
1964           ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
1965         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
1966      }
1967    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
1968      {
1969         cw->shade.val =
1970           ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
1971         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
1972      }
1973    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
1974      {
1975         cw->shade.val =
1976           ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
1977         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
1978      }
1979    else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
1980      {
1981         cw->shade.val =
1982           ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
1983         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
1984      }
1985    else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
1986      {
1987         cw->shade.val =
1988           ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
1989         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
1990      }
1991    else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
1992      {
1993         cw->shade.val =
1994           ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
1995         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
1996      }
1997    else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
1998      {
1999         cw->shade.val =
2000           ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
2001         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
2002      }
2003    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
2004      {
2005         cw->shade.val =
2006           ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
2007         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
2008      }
2009    else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
2010      {
2011         cw->shade.val =
2012           ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
2013         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
2014      }
2015    else
2016      {
2017         cw->shade.val =
2018           ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
2019         if (!cw->ec->shaded) cw->shade.val = 1.0 - cw->shade.val;
2020      }
2021 
2022    /* due to M_PI's inaccuracy, cos(M_PI/2) != 0.0, so we need this */
2023    if (cw->shade.val < 0.001) cw->shade.val = 0.0;
2024    else if (cw->shade.val > .999)
2025      cw->shade.val = 1.0;
2026 
2027    x = cw->ec->x, y = cw->ec->y, w = cw->ec->w, h = cw->ec->h;
2028    if (cw->shade.dir == E_DIRECTION_UP)
2029      h = cw->client_inset.t + cw->ec->client.h * cw->shade.val;
2030    else if (cw->shade.dir == E_DIRECTION_DOWN)
2031      {
2032         h = cw->client_inset.t + cw->ec->client.h * cw->shade.val;
2033         y = cw->shade.y + cw->ec->client.h * (1 - cw->shade.val);
2034         move = EINA_TRUE;
2035      }
2036    else if (cw->shade.dir == E_DIRECTION_LEFT)
2037      w = cw->client_inset.t + cw->ec->client.w * cw->shade.val;
2038    else if (cw->shade.dir == E_DIRECTION_RIGHT)
2039      {
2040         w = cw->client_inset.t + cw->ec->client.w * cw->shade.val;
2041         x = cw->shade.x + cw->ec->client.w * (1 - cw->shade.val);
2042         move = EINA_TRUE;
2043      }
2044 
2045    if (move) evas_object_move(cw->smart_obj, x, y);
2046    evas_object_resize(cw->smart_obj, w, h);
2047 
2048    /* we're done */
2049    if (EINA_DBL_EQ(val, 1))
2050      {
2051         cw->shade.anim = NULL;
2052 
2053         evas_object_smart_callback_call(cw->smart_obj, "shade_done", NULL);
2054         if (cw->ec->shaded)
2055           e_comp_object_signal_emit(cw->smart_obj, "e,state,shaded", "e");
2056         else
2057           e_comp_object_signal_emit(cw->smart_obj, "e,state,unshaded", "e");
2058         edje_object_message_signal_process(cw->frame_object);
2059         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
2060      }
2061    return cw->ec->shading;
2062 }
2063 
2064 static void
_e_comp_smart_cb_shaded(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)2065 _e_comp_smart_cb_shaded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2066 {
2067    E_Comp_Object *cw = data;
2068 
2069    if (!cw->ec) return; //NYI
2070    E_FREE_FUNC(cw->shade.anim, ecore_animator_del);
2071 
2072    e_comp_object_signal_emit(cw->smart_obj, "e,state,shaded", "e");
2073    cw->shade.start = -100;
2074    cw->shade.dir = (E_Direction)event_info;
2075    _e_comp_object_shade_animator(cw);
2076 }
2077 
2078 static void
_e_comp_smart_cb_shading(void * data,Evas_Object * obj,void * event_info)2079 _e_comp_smart_cb_shading(void *data, Evas_Object *obj, void *event_info)
2080 {
2081    E_Comp_Object *cw = data;
2082 
2083    if (!cw->ec) return; //NYI
2084    if (cw->shade.anim && EINA_DBL_EQ(cw->shade.val, 0.0))
2085      {
2086         cw->ec->shaded = 0;
2087         _e_comp_smart_cb_shaded(data, obj, event_info);
2088         return;
2089      }
2090    E_FREE_FUNC(cw->shade.anim, ecore_animator_del);
2091 
2092    cw->shade.x = cw->x;
2093    cw->shade.y = cw->y;
2094    e_comp_object_signal_emit(cw->smart_obj, "e,state,shading", "e");
2095    cw->shade.start = ecore_loop_time_get();
2096    cw->shade.dir = (E_Direction)event_info;
2097    cw->shade.anim = ecore_animator_add(_e_comp_object_shade_animator, cw);
2098 }
2099 
2100 static void
_e_comp_smart_cb_unshaded(void * data,Evas_Object * obj EINA_UNUSED,void * event_info)2101 _e_comp_smart_cb_unshaded(void *data, Evas_Object *obj EINA_UNUSED, void *event_info)
2102 {
2103    E_Comp_Object *cw = data;
2104 
2105    if (!cw->ec) return; //NYI
2106    E_FREE_FUNC(cw->shade.anim, ecore_animator_del);
2107 
2108    cw->shade.dir = (E_Direction)event_info;
2109    if (cw->shade.dir == E_DIRECTION_UP ||
2110        cw->shade.dir == E_DIRECTION_LEFT)
2111      {
2112         cw->shade.x = cw->x;
2113         cw->shade.y = cw->y;
2114      }
2115    else
2116      {
2117         cw->shade.x = cw->x - cw->w;
2118         cw->shade.y = cw->y - cw->h;
2119      }
2120    e_comp_object_signal_emit(cw->smart_obj, "e,state,unshaded", "e");
2121    cw->shade.start = -100;
2122    _e_comp_object_shade_animator(cw);
2123 }
2124 
2125 static void
_e_comp_smart_cb_unshading(void * data,Evas_Object * obj,void * event_info)2126 _e_comp_smart_cb_unshading(void *data, Evas_Object *obj, void *event_info)
2127 {
2128    E_Comp_Object *cw = data;
2129 
2130    if (!cw->ec) return; //NYI
2131    if (cw->shade.anim && EINA_DBL_EQ(cw->shade.val, 0.0))
2132      {
2133         cw->ec->shaded = 1;
2134         _e_comp_smart_cb_unshaded(data, obj, event_info);
2135         return;
2136      }
2137    E_FREE_FUNC(cw->shade.anim, ecore_animator_del);
2138 
2139    cw->shade.dir = (E_Direction)event_info;
2140    e_comp_object_signal_emit(cw->smart_obj, "e,state,unshading", "e");
2141    cw->shade.start = ecore_loop_time_get();
2142    cw->shade.anim = ecore_animator_add(_e_comp_object_shade_animator, cw);
2143 }
2144 
2145 static void
_e_comp_smart_cb_maximize(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2146 _e_comp_smart_cb_maximize(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2147 {
2148    E_Comp_Object *cw = data;
2149 
2150    _e_comp_object_shadow_setup(cw);
2151    if (cw->frame_object)
2152      {
2153         _e_comp_object_shadow(cw);
2154         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize", "e");
2155         _e_comp_object_frame_recalc(cw);
2156         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2157      }
2158 }
2159 
2160 static void
_e_comp_smart_cb_fullscreen(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2161 _e_comp_smart_cb_fullscreen(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2162 {
2163    E_Comp_Object *cw = data;
2164 
2165    if (_e_comp_object_shadow_setup(cw))
2166      e_comp_object_damage(cw->smart_obj, 0, 0, cw->ec->w, cw->ec->h);
2167    if (cw->frame_object)
2168      {
2169         _e_comp_object_shadow(cw);
2170         e_comp_object_signal_emit(cw->smart_obj, "e,action,maximize,fullscreen", "e");
2171         _e_comp_object_frame_recalc(cw);
2172         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2173      }
2174 }
2175 
2176 static void
_e_comp_smart_cb_unmaximize(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)2177 _e_comp_smart_cb_unmaximize(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2178 {
2179    E_Comp_Object *cw = data;
2180 
2181    if (cw->frame_object)
2182      {
2183         _e_comp_object_shadow(cw);
2184         e_comp_object_signal_emit(obj, "e,action,unmaximize", "e");
2185         _e_comp_object_frame_recalc(cw);
2186         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2187      }
2188 }
2189 
2190 static void
_e_comp_smart_cb_unfullscreen(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)2191 _e_comp_smart_cb_unfullscreen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
2192 {
2193    E_Comp_Object *cw = data;
2194 
2195    if (_e_comp_object_shadow_setup(cw))
2196      {
2197         EC_CHANGED(cw->ec);
2198         cw->ec->changes.size = 1;
2199      }
2200    if (cw->frame_object)
2201      {
2202         _e_comp_object_shadow(cw);
2203         e_comp_object_signal_emit(obj, "e,action,unmaximize,unfullscreen", "e");
2204         _e_comp_object_frame_recalc(cw);
2205         evas_object_smart_callback_call(cw->smart_obj, "frame_recalc_done", &cw->client_inset);
2206      }
2207 }
2208 
2209 static void
_e_comp_smart_cb_sticky(void * data EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2210 _e_comp_smart_cb_sticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2211 {
2212    e_comp_object_signal_emit(obj, "e,state,sticky", "e");
2213 }
2214 
2215 static void
_e_comp_smart_cb_unsticky(void * data EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2216 _e_comp_smart_cb_unsticky(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2217 {
2218    e_comp_object_signal_emit(obj, "e,state,unsticky", "e");
2219 }
2220 
2221 static void
_e_comp_smart_cb_unhung(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2222 _e_comp_smart_cb_unhung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2223 {
2224    E_Comp_Object *cw = data;
2225 
2226    if (!cw->ec) return; //NYI
2227    e_comp_object_signal_emit(cw->smart_obj, "e,state,unhung", "e");
2228 }
2229 
2230 static void
_e_comp_smart_cb_hung(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)2231 _e_comp_smart_cb_hung(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2232 {
2233    E_Comp_Object *cw = data;
2234 
2235    if (!cw->ec) return; //NYI
2236    e_comp_object_signal_emit(cw->smart_obj, "e,state,hung", "e");
2237 }
2238 
2239 static void
_e_comp_smart_focus_in(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2240 _e_comp_smart_focus_in(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2241 {
2242    e_comp_object_signal_emit(obj, "e,state,focused", "e");
2243 }
2244 
2245 static void
_e_comp_smart_focus_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2246 _e_comp_smart_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2247 {
2248    E_Comp_Object *cw = data;
2249 
2250    if ((!cw->deleted) && (!e_object_is_del(E_OBJECT(cw->ec))))
2251      e_comp_object_signal_emit(obj, "e,state,unfocused", "e");
2252 }
2253 
2254 static void
_e_comp_smart_add(Evas_Object * obj)2255 _e_comp_smart_add(Evas_Object *obj)
2256 {
2257    E_Comp_Object *cw;
2258 
2259    cw = E_NEW(E_Comp_Object, 1);
2260    cw->smart_obj = obj;
2261    cw->x = cw->y = cw->w = cw->h = -1;
2262    evas_object_smart_data_set(obj, cw);
2263    cw->opacity = 255.0;
2264    evas_object_data_set(obj, "comp_obj", cw);
2265    evas_object_move(obj, -1, -1);
2266    /* intercept ALL the callbacks! */
2267    evas_object_intercept_stack_above_callback_add(obj, _e_comp_intercept_stack_above, cw);
2268    evas_object_intercept_stack_below_callback_add(obj, _e_comp_intercept_stack_below, cw);
2269    evas_object_intercept_raise_callback_add(obj, _e_comp_intercept_raise, cw);
2270    evas_object_intercept_lower_callback_add(obj, _e_comp_intercept_lower, cw);
2271    evas_object_intercept_layer_set_callback_add(obj, _e_comp_intercept_layer_set, cw);
2272    evas_object_intercept_move_callback_add(obj, _e_comp_intercept_move, cw);
2273    evas_object_intercept_resize_callback_add(obj, _e_comp_intercept_resize, cw);
2274    evas_object_intercept_show_callback_add(obj, _e_comp_intercept_show, cw);
2275    evas_object_intercept_hide_callback_add(obj, _e_comp_intercept_hide, cw);
2276    evas_object_intercept_focus_set_callback_add(obj, _e_comp_intercept_focus, cw);
2277 
2278    evas_object_smart_callback_add(obj, "shading", _e_comp_smart_cb_shading, cw);
2279    evas_object_smart_callback_add(obj, "shaded", _e_comp_smart_cb_shaded, cw);
2280    evas_object_smart_callback_add(obj, "unshading", _e_comp_smart_cb_unshading, cw);
2281    evas_object_smart_callback_add(obj, "unshaded", _e_comp_smart_cb_unshaded, cw);
2282 
2283    evas_object_smart_callback_add(obj, "maximize", _e_comp_smart_cb_maximize, cw);
2284    evas_object_smart_callback_add(obj, "fullscreen", _e_comp_smart_cb_fullscreen, cw);
2285    evas_object_smart_callback_add(obj, "unmaximize", _e_comp_smart_cb_unmaximize, cw);
2286    evas_object_smart_callback_add(obj, "unfullscreen", _e_comp_smart_cb_unfullscreen, cw);
2287 
2288    evas_object_smart_callback_add(obj, "stick", _e_comp_smart_cb_sticky, cw);
2289    evas_object_smart_callback_add(obj, "unstick", _e_comp_smart_cb_unsticky, cw);
2290 
2291    evas_object_smart_callback_add(obj, "hung", _e_comp_smart_cb_hung, cw);
2292    evas_object_smart_callback_add(obj, "unhung", _e_comp_smart_cb_unhung, cw);
2293 
2294    evas_object_smart_callback_add(obj, "frame_recalc", _e_comp_smart_cb_frame_recalc, cw);
2295 
2296    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_comp_smart_focus_in, cw);
2297    evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _e_comp_smart_focus_out, cw);
2298 }
2299 
2300 static void
_e_comp_smart_color_set(Evas_Object * obj,int r,int g,int b,int a)2301 _e_comp_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
2302 {
2303    INTERNAL_ENTRY;
2304    evas_object_color_set(cw->clip, r, g, b, a);
2305    cw->ec->netwm.opacity = a;
2306    if (cw->ec->remember && (cw->ec->remember->apply & E_REMEMBER_APPLY_OPACITY))
2307      e_remember_update(cw->ec);
2308    evas_object_smart_callback_call(obj, "color_set", NULL);
2309 }
2310 
2311 
2312 static void
_e_comp_smart_clip_set(Evas_Object * obj,Evas_Object * clip)2313 _e_comp_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
2314 {
2315    INTERNAL_ENTRY;
2316    evas_object_clip_set(cw->clip, clip);
2317 }
2318 
2319 static void
_e_comp_smart_clip_unset(Evas_Object * obj)2320 _e_comp_smart_clip_unset(Evas_Object *obj)
2321 {
2322    INTERNAL_ENTRY;
2323    evas_object_clip_unset(cw->clip);
2324 }
2325 
2326 static void
_e_comp_smart_hide(Evas_Object * obj)2327 _e_comp_smart_hide(Evas_Object *obj)
2328 {
2329    INTERNAL_ENTRY;
2330    cw->visible = 0;
2331    cw->deleted |= cw->ec->delete_requested || e_object_is_del(E_OBJECT(cw->ec));
2332    evas_object_hide(cw->clip);
2333    evas_object_hide(cw->effect_obj);
2334    if (stopping) return;
2335    if (!cw->ec->input_only)
2336      {
2337         edje_object_freeze(cw->effect_obj);
2338         edje_object_freeze(cw->shobj);
2339         edje_object_play_set(cw->shobj, 0);
2340         if (cw->frame_object)
2341           edje_object_play_set(cw->frame_object, 0);
2342      }
2343    /* ensure focus-out */
2344    if (cw->ec->focused)
2345      evas_object_focus_set(cw->ec->frame, 0);
2346    e_comp_render_queue(); //force nocomp recheck
2347    e_comp_shape_queue();
2348 }
2349 
2350 static void
_e_comp_smart_show(Evas_Object * obj)2351 _e_comp_smart_show(Evas_Object *obj)
2352 {
2353    E_Client *tmp;
2354    Eina_List *l;
2355 
2356    INTERNAL_ENTRY;
2357    cw->defer_hide = 0;
2358    cw->visible = 1;
2359    if ((cw->w < 0) || (cw->h < 0))
2360      CRI("ACK!");
2361 
2362    //INF("SMART SHOW: %p EC(%dx%d) CW(%dx%d)", cw->ec, cw->ec->w, cw->ec->h, cw->w, cw->h);
2363 
2364    EINA_LIST_FOREACH(cw->ec->e.state.video_child, l, tmp)
2365      evas_object_show(tmp->frame);
2366 
2367    evas_object_show(cw->clip);
2368    if (!cw->ec->input_only)
2369      {
2370         edje_object_thaw(cw->effect_obj);
2371         edje_object_thaw(cw->shobj);
2372         edje_object_play_set(cw->shobj, 1);
2373         if (cw->frame_object)
2374           edje_object_play_set(cw->frame_object, 1);
2375      }
2376    evas_object_show(cw->effect_obj);
2377    if (cw->ec->internal_elm_win && (!evas_object_visible_get(cw->ec->internal_elm_win)))
2378      evas_object_show(cw->ec->internal_elm_win);
2379    e_comp_render_queue();
2380    if (cw->ec->input_only)
2381      {
2382         e_comp_shape_queue();
2383         return;
2384      }
2385    if (cw->ec->iconic && (!cw->ec->new_client))
2386      e_comp_object_signal_emit(cw->smart_obj, "e,action,uniconify", "e");
2387    if (cw->updates_exist)
2388      e_comp_object_render_update_add(obj);
2389    if ((!cw->showing) && ((!cw->ec->iconic) || cw->ec->new_client || (!cw->animating)))
2390      {
2391         /* if cw->showing set, client was ec->hidden during show animation */
2392         e_comp_object_signal_emit(cw->smart_obj, "e,state,visible", "e");
2393         _e_comp_object_animating_begin(cw);
2394         cw->showing = 1;
2395         if (!_e_comp_object_effect_visibility_start(cw, 1)) return;
2396      }
2397    /* ensure some random effect doesn't lock the client offscreen */
2398    if (!cw->animating)
2399      {
2400         cw->showing = 0;
2401         e_comp_object_effect_set(obj, NULL);
2402         e_comp_shape_queue();
2403      }
2404 }
2405 
2406 static void
_e_comp_object_client_del(void * d,void * obj EINA_UNUSED)2407 _e_comp_object_client_del(void *d, void *obj EINA_UNUSED)
2408 {
2409    E_Comp_Object *cw = d;
2410    cw->deleted = 1;
2411    e_comp_object_render_update_del(cw->smart_obj);
2412    _e_comp_object_layers_remove(cw);
2413 }
2414 
2415 static void
_e_comp_input_objs_free(E_Comp_Object * cw)2416 _e_comp_input_objs_free(E_Comp_Object *cw)
2417 {
2418    Evas_Object *rect;
2419    if (!cw->input_objs) return;
2420    while ((rect = eina_array_pop(cw->input_objs)))
2421      {
2422         evas_object_smart_member_del(rect);
2423         evas_object_freeze_events_set(rect, 1);
2424         evas_object_del(rect);
2425      }
2426 }
2427 
2428 static void
_e_comp_smart_del(Evas_Object * obj)2429 _e_comp_smart_del(Evas_Object *obj)
2430 {
2431    Eina_List *l;
2432    Evas_Object *o;
2433 
2434    INTERNAL_ENTRY;
2435 
2436    E_FREE_FUNC(cw->updates, eina_tiler_free);
2437    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
2438    free(cw->ns);
2439 
2440    EINA_LIST_FREE(cw->obj_mirror, o)
2441      {
2442         evas_object_image_data_set(o, NULL);
2443         evas_object_freeze_events_set(o, 1);
2444         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
2445         evas_object_event_callback_del_full(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
2446         evas_object_event_callback_del_full(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
2447         evas_object_del(o);
2448      }
2449    EINA_LIST_FREE(cw->obj_agent, o)
2450      {
2451         evas_object_freeze_events_set(o, 1);
2452         evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_agent_del, cw);
2453         evas_object_del(o);
2454      }
2455    if (!cw->deleted)
2456      _e_comp_object_layers_remove(cw);
2457    l = evas_object_data_get(obj, "comp_object-to_del");
2458    E_FREE_LIST(l, evas_object_del);
2459    evas_object_del(cw->clip);
2460    evas_object_del(cw->effect_obj);
2461    evas_object_del(cw->shobj);
2462    evas_object_del(cw->frame_icon);
2463    evas_object_del(cw->frame_volume);
2464    evas_object_del(cw->frame_object);
2465    evas_object_del(cw->zoomobj);
2466    _e_comp_input_objs_free(cw);
2467    eina_array_free(cw->input_objs);
2468    eina_tiler_free(cw->input_area);
2469    evas_object_del(cw->obj);
2470    e_comp_shape_queue();
2471    eina_stringshare_del(cw->frame_theme);
2472    eina_stringshare_del(cw->frame_name);
2473    if (cw->animating)
2474      {
2475         cw->animating = 0;
2476         e_comp->animating--;
2477         UNREFD(cw->ec, 2);
2478         e_object_unref(E_OBJECT(cw->ec));
2479      }
2480 //   UNREFD(cw->ec, 9);
2481 //   e_object_unref(E_OBJECT(cw->ec));
2482    free(cw);
2483 }
2484 
2485 static void
_e_comp_object_input_rect_update(E_Comp_Object * cw)2486 _e_comp_object_input_rect_update(E_Comp_Object *cw)
2487 {
2488    int x, y, w, h;
2489    Eina_Iterator *it;
2490    Eina_Rectangle *rect;
2491    Evas_Object *o;
2492    int i = 0;
2493 
2494    if (!cw->input_area) return;
2495    it = eina_tiler_iterator_new(cw->input_area);
2496    EINA_ITERATOR_FOREACH(it, rect)
2497      {
2498         o = eina_array_data_get(cw->input_objs, i++);
2499         x = rect->x, y = rect->y, w = rect->w, h = rect->h;
2500 
2501         E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0,
2502                              cw->ec->client.w, cw->ec->client.h);
2503         evas_object_geometry_set
2504           (o, cw->x + x + (!!cw->frame_object * cw->client_inset.l),
2505               cw->y + y + (!!cw->frame_object * cw->client_inset.t),
2506               w, h);
2507      }
2508    eina_iterator_free(it);
2509 }
2510 
2511 static void
_e_comp_smart_move(Evas_Object * obj,int x,int y)2512 _e_comp_smart_move(Evas_Object *obj, int x, int y)
2513 {
2514    Eina_List *l;
2515    Evas_Object *o;
2516 
2517    INTERNAL_ENTRY;
2518 
2519    cw->x = x, cw->y = y;
2520    cw->agent_updating = 1;
2521    EINA_LIST_FOREACH(cw->obj_agent, l, o)
2522      evas_object_move(o, cw->ec->x, cw->ec->x);
2523    cw->agent_updating = 0;
2524    if (cw->clip) evas_object_move(cw->clip, 0, 0);
2525    if (cw->effect_obj) evas_object_move(cw->effect_obj, x, y);
2526    if (cw->input_area)
2527      _e_comp_object_input_rect_update(cw);
2528    /* this gets called once during setup to init coords offscreen and guarantee first move */
2529    if (e_comp && cw->visible)
2530      e_comp_shape_queue();
2531 }
2532 
2533 static void
_e_comp_smart_resize(Evas_Object * obj,int w,int h)2534 _e_comp_smart_resize(Evas_Object *obj, int w, int h)
2535 {
2536    Eina_Bool first = EINA_FALSE;
2537    Eina_List *l;
2538    Evas_Object *o;
2539 
2540    INTERNAL_ENTRY;
2541 
2542    //INF("RSZ(%p): %dx%d -> %dx%d", cw->ec, cw->w, cw->h, w, h);
2543    if (!cw->effect_obj) CRI("ACK!");
2544    first = ((cw->w < 1) || (cw->h < 1));
2545    cw->w = w, cw->h = h;
2546    if ((!cw->ec->shading) && (!cw->ec->shaded))
2547      {
2548         int ww = 0, hh = 0, pw = 0, ph = 0;
2549 
2550         if (cw->frame_object)
2551           e_comp_object_frame_wh_unadjust(obj, w, h, &ww, &hh);
2552         else
2553           {
2554              ww = w;
2555              hh = h;
2556           }
2557         /* verify pixmap:object size */
2558         if (e_pixmap_size_get(cw->ec->pixmap, &pw, &ph) && (!cw->ec->override))
2559           {
2560              //INF("CW RSZ: %dx%d PIX(%dx%d)", w, h, pw, ph);
2561              //if (cw->obj)
2562                //{
2563                   //evas_object_size_hint_max_set(cw->obj, pw, ph);
2564                   //evas_object_size_hint_min_set(cw->obj, pw, ph);
2565                //}
2566              if ((ww != pw) || (hh != ph))
2567                CRI("CW RSZ: %dx%d || PX: %dx%d", ww, hh, pw, ph);
2568           }
2569         evas_object_resize(cw->effect_obj, w, h);
2570         if (cw->zoomobj) e_zoomap_child_resize(cw->zoomobj, pw, ph);
2571         if (cw->input_area)
2572           _e_comp_object_input_rect_update(cw);
2573         /* resize render update tiler */
2574         if (!first)
2575           {
2576              if (cw->updates)
2577                {
2578                   int tw, th;
2579 
2580                   eina_tiler_area_size_get(cw->updates, &tw, &th);
2581                   if ((tw != pw) || (th != ph))
2582                     {
2583                        RENDER_DEBUG("DAMAGE UNFULL: %p", cw->ec);
2584                        cw->updates_full = 0;
2585                        eina_tiler_clear(cw->updates);
2586                     }
2587                }
2588           }
2589         else
2590           {
2591              RENDER_DEBUG("DAMAGE RESIZE(%p): %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
2592              if (cw->updates) eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
2593           }
2594      }
2595    else
2596      {
2597         evas_object_resize(cw->effect_obj, w, h);
2598      }
2599    cw->agent_updating = 1;
2600    EINA_LIST_FOREACH(cw->obj_agent, l, o)
2601      evas_object_resize(o, cw->ec->w, cw->ec->h);
2602    cw->agent_updating = 0;
2603    if (!cw->visible) return;
2604    e_comp_render_queue();
2605    if (!cw->animating)
2606      e_comp_shape_queue();
2607 }
2608 
2609 static void
_e_comp_object_move_end(void * d EINA_UNUSED,E_Client * ec)2610 _e_comp_object_move_end(void *d EINA_UNUSED, E_Client *ec)
2611 {
2612    E_Comp_Object *cw = evas_object_smart_data_get(ec->frame);
2613    unsigned int i;
2614    Evas_Object *rect;
2615    Eina_Array_Iterator it;
2616 
2617    if (!cw) return;
2618    if (!cw->input_objs) return;
2619 
2620    EINA_ARRAY_ITER_NEXT(cw->input_objs, i, rect, it)
2621      evas_object_pointer_mode_set(rect, EVAS_OBJECT_POINTER_MODE_AUTOGRAB);
2622 }
2623 
2624 static void
_e_comp_object_move_begin(void * d EINA_UNUSED,E_Client * ec)2625 _e_comp_object_move_begin(void *d EINA_UNUSED, E_Client *ec)
2626 {
2627    E_Comp_Object *cw = evas_object_smart_data_get(ec->frame);
2628    unsigned int i;
2629    Evas_Object *rect;
2630    Eina_Array_Iterator it;
2631 
2632    if (!cw) return;
2633    if (!cw->input_objs) return;
2634 
2635    EINA_ARRAY_ITER_NEXT(cw->input_objs, i, rect, it)
2636      evas_object_pointer_mode_set(rect, EVAS_OBJECT_POINTER_MODE_NOGRAB);
2637 }
2638 
2639 static void
_e_comp_smart_init(void)2640 _e_comp_smart_init(void)
2641 {
2642    const char *env;
2643    if (_e_comp_smart) return;
2644 
2645    env = getenv("E_RENDER_DEBUG");
2646    if (eina_streq(env, "focus"))
2647      render_debug_enabled = -1;
2648    else if (env)
2649      render_debug_enabled = 1;
2650    e_client_hook_add(E_CLIENT_HOOK_MOVE_BEGIN, _e_comp_object_move_begin, NULL);
2651    e_client_hook_add(E_CLIENT_HOOK_MOVE_END, _e_comp_object_move_end, NULL);
2652    {
2653       static const Evas_Smart_Class sc =
2654       {
2655          SMART_NAME,
2656          EVAS_SMART_CLASS_VERSION,
2657          _e_comp_smart_add,
2658          _e_comp_smart_del,
2659          _e_comp_smart_move,
2660          _e_comp_smart_resize,
2661          _e_comp_smart_show,
2662          _e_comp_smart_hide,
2663          _e_comp_smart_color_set,
2664          _e_comp_smart_clip_set,
2665          _e_comp_smart_clip_unset,
2666          NULL,
2667          NULL,
2668          NULL,
2669 
2670          NULL,
2671          NULL,
2672          NULL,
2673          NULL
2674       };
2675       _e_comp_smart = evas_smart_class_new(&sc);
2676    }
2677 }
2678 
2679 E_API void
e_comp_object_zoomap_set(Evas_Object * obj,Eina_Bool enabled)2680 e_comp_object_zoomap_set(Evas_Object *obj, Eina_Bool enabled)
2681 {
2682    API_ENTRY;
2683 
2684    enabled = !enabled;
2685    if (cw->zoomap_disabled == enabled) return;
2686    if (enabled)
2687      {
2688         cw->zoomobj = e_zoomap_add(e_comp->evas);
2689         e_zoomap_smooth_set(cw->zoomobj, e_comp_config_get()->smooth_windows);
2690         e_zoomap_child_set(cw->zoomobj, cw->ec ? cw->frame_object : cw->obj);
2691         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->zoomobj);
2692         e_zoomap_child_edje_solid_setup(cw->zoomobj);
2693         if (cw->ec->override)
2694           evas_object_name_set(cw->zoomobj, "cw->zoomobj::WINDOW");
2695         else if (!cw->ec->input_only)
2696           evas_object_name_set(cw->zoomobj, "cw->zoomobj::CLIENT");
2697      }
2698    else
2699      {
2700         edje_object_part_unswallow(cw->shobj, cw->zoomobj);
2701         E_FREE_FUNC(cw->zoomobj, evas_object_del);
2702         edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->ec ? cw->frame_object : cw->obj);
2703      }
2704    cw->zoomap_disabled = enabled;
2705 }
2706 
2707 E_API Eina_Bool
e_comp_object_mirror_visibility_check(Evas_Object * obj)2708 e_comp_object_mirror_visibility_check(Evas_Object *obj)
2709 {
2710    API_ENTRY EINA_FALSE;
2711    return !!cw->force_visible;
2712 }
2713 /////////////////////////////////////////////////////////
2714 
2715 static void
_e_comp_object_util_del(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2716 _e_comp_object_util_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2717 {
2718    Eina_List *l;
2719    Eina_Bool comp_object;
2720 
2721    comp_object = !!evas_object_data_get(obj, "comp_object");
2722    if (comp_object)
2723      {
2724         Evas_Object *o;
2725 
2726         o = edje_object_part_swallow_get(obj, "e.swallow.content");
2727         evas_object_del(o);
2728         e_comp_render_queue();
2729         e_comp_shape_queue();
2730      }
2731    l = evas_object_data_get(obj, "comp_object-to_del");
2732    E_FREE_LIST(l, evas_object_del);
2733 }
2734 
2735 static void
_e_comp_object_util_restack(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2736 _e_comp_object_util_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2737 {
2738    if (e_comp_util_object_is_above_nocomp(obj) &&
2739        (!evas_object_data_get(obj, "comp_override")))
2740      {
2741         evas_object_data_set(obj, "comp_override", (void*)1);
2742         e_comp_override_add();
2743      }
2744 }
2745 
2746 static void
_e_comp_object_util_show(void * data EINA_UNUSED,Evas_Object * obj)2747 _e_comp_object_util_show(void *data EINA_UNUSED, Evas_Object *obj)
2748 {
2749    Eina_Bool ref = EINA_TRUE;
2750    if (evas_object_visible_get(obj))
2751      {
2752         void *d;
2753 
2754         d = evas_object_data_del(obj, "comp_hiding");
2755         if (d)
2756           /* currently trying to hide */
2757           ref = EINA_FALSE;
2758         else
2759           /* already visible */
2760           return;
2761      }
2762    else
2763      e_comp_shape_queue();
2764 
2765    evas_object_show(obj);
2766    if (ref && (!stopping))
2767      {
2768         evas_object_ref(obj);
2769         evas_object_data_set(obj, "comp_ref", (void*)1);
2770      }
2771    edje_object_signal_emit(obj, "e,state,visible", "e");
2772    edje_object_message_signal_process(obj);
2773    evas_object_data_set(obj, "comp_showing", (void*)1);
2774    if (e_comp_util_object_is_above_nocomp(obj))
2775      {
2776         evas_object_data_set(obj, "comp_override", (void*)1);
2777         e_comp_override_add();
2778      }
2779 }
2780 
2781 static void
_e_comp_object_util_hide(void * data EINA_UNUSED,Evas_Object * obj)2782 _e_comp_object_util_hide(void *data EINA_UNUSED, Evas_Object *obj)
2783 {
2784    if (!evas_object_visible_get(obj)) return;
2785    /* already hiding */
2786    if (evas_object_data_get(obj, "comp_hiding"))
2787      {
2788         evas_object_data_del(obj, "comp_hiding");
2789         evas_object_hide(obj);
2790         e_comp_shape_queue();
2791         if (evas_object_data_del(obj, "comp_ref"))
2792           evas_object_unref(obj);
2793         return;
2794      }
2795    if ((!stopping) && (!evas_object_data_del(obj, "comp_showing")))
2796      {
2797         evas_object_ref(obj);
2798         evas_object_data_set(obj, "comp_ref", (void*)1);
2799      }
2800    edje_object_signal_emit(obj, "e,state,hidden", "e");
2801    edje_object_message_signal_process(obj);
2802    evas_object_data_set(obj, "comp_hiding", (void*)1);
2803 
2804    if (evas_object_data_del(obj, "comp_override"))
2805      e_comp_override_timed_pop();
2806 }
2807 
2808 static void
_e_comp_object_util_done_defer(void * data,Evas_Object * obj,const char * emission,const char * source EINA_UNUSED)2809 _e_comp_object_util_done_defer(void *data, Evas_Object *obj, const char *emission, const char *source EINA_UNUSED)
2810 {
2811    if (!e_util_strcmp(emission, "e,action,hide,done"))
2812      {
2813         if (!evas_object_data_del(obj, "comp_hiding")) return;
2814         evas_object_intercept_hide_callback_del(obj, _e_comp_object_util_hide);
2815         evas_object_hide(obj);
2816         e_comp_shape_queue();
2817         evas_object_intercept_hide_callback_add(obj, _e_comp_object_util_hide, data);
2818      }
2819    else
2820      evas_object_data_del(obj, "comp_showing");
2821    if (evas_object_data_del(obj, "comp_ref"))
2822      evas_object_unref(obj);
2823 }
2824 
2825 static void
_e_comp_object_util_moveresize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)2826 _e_comp_object_util_moveresize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
2827 {
2828    if (data)
2829      {
2830         int w, h;
2831 
2832         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2833         e_zoomap_child_resize(data, w, h);
2834      }
2835    if (evas_object_visible_get(obj))
2836      e_comp_shape_queue();
2837 }
2838 
2839 E_API void
e_comp_object_util_type_set(Evas_Object * obj,E_Comp_Object_Type type)2840 e_comp_object_util_type_set(Evas_Object *obj, E_Comp_Object_Type type)
2841 {
2842    Evas_Object *content;
2843    const char *name = NULL;
2844    Eina_List *l, *list = NULL;
2845    E_Comp_Config *conf = e_comp_config_get();
2846    Eina_Bool skip = EINA_FALSE, shadow = EINA_FALSE;
2847    E_Comp_Match *m;
2848    const char *grp;
2849    char buf[1024];
2850    int ok = 0;
2851 
2852    EINA_SAFETY_ON_NULL_RETURN(obj);
2853 
2854    edje_object_file_get(obj, NULL, &grp);
2855    switch (type)
2856      {
2857       case E_COMP_OBJECT_TYPE_MENU:
2858         list = conf->match.menus;
2859         shadow = EINA_TRUE;
2860         break;
2861       case E_COMP_OBJECT_TYPE_POPUP:
2862         list = conf->match.popups;
2863         break;
2864       default:
2865         list = conf->match.objects;
2866      }
2867    content = edje_object_part_swallow_get(obj, "e.swallow.content");
2868    if (content)
2869      {
2870         if (eina_streq(evas_object_type_get(content), "e_zoomap"))
2871           name = evas_object_name_get(e_zoomap_child_get(content));
2872         else
2873           name = evas_object_name_get(content);
2874      }
2875    if (name && (!skip))
2876      skip = (!strncmp(name, "noshadow", 8));
2877    if (skip)
2878      evas_object_data_set(obj, "comp_object_skip", (void*)1);
2879    else
2880      evas_object_data_del(obj, "comp_object_skip");
2881    if (list && (!skip))
2882      {
2883         EINA_LIST_FOREACH(list, l, m)
2884           {
2885              if (((m->name) && (!name)) ||
2886                  ((name) && (m->name) && (!e_util_glob_match(name, m->name))))
2887                continue;
2888              if (!m->shadow_style) continue;
2889              snprintf(buf, sizeof(buf), "e/comp/frame/%s", m->shadow_style);
2890              if (eina_streq(buf, grp)) return;
2891              ok = e_theme_edje_object_set(obj, "base/theme/comp", buf);
2892              if (ok)
2893                {
2894                   shadow = !m->no_shadow;
2895                   break;
2896                }
2897           }
2898      }
2899    else
2900      skip = EINA_TRUE;
2901    while (!ok)
2902      {
2903         if (skip)
2904           {
2905              if (eina_streq("e/comp/frame/none", grp)) return;
2906              ok = e_theme_edje_object_set(obj, "base/theme/comp", "e/comp/frame/none");
2907           }
2908         if (ok) break;
2909         if (conf->shadow_style)
2910           {
2911              snprintf(buf, sizeof(buf), "e/comp/frame/%s", conf->shadow_style);
2912              if (eina_streq(buf, grp)) return;
2913              ok = e_theme_edje_object_set(obj, "base/theme/comp", buf);
2914              if (ok) break;
2915           }
2916         if (eina_streq("e/comp/frame/default", grp)) return;
2917         ok = e_theme_edje_object_set(obj, "base/theme/comp", "e/comp/frame/default");
2918         break;
2919      }
2920    if (shadow && (e_util_strcmp(evas_object_type_get(obj), "edje") || (!edje_object_data_get(obj, "noshadow"))))
2921      edje_object_signal_emit(obj, "e,state,shadow,on", "e");
2922    else
2923      edje_object_signal_emit(obj, "e,state,shadow,off", "e");
2924    if (evas_object_visible_get(obj))
2925      edje_object_signal_emit(obj, "e,state,visible", "e");
2926    if (content)
2927      edje_object_part_swallow(obj, "e.swallow.content", content);
2928 }
2929 
2930 E_API Evas_Object *
e_comp_object_util_add(Evas_Object * obj,E_Comp_Object_Type type)2931 e_comp_object_util_add(Evas_Object *obj, E_Comp_Object_Type type)
2932 {
2933    Evas_Object *o, *z = NULL;
2934    E_Comp_Config *conf = e_comp_config_get();
2935    int x, y, w, h;
2936    Eina_Bool vis;
2937 
2938    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
2939    vis = evas_object_visible_get(obj);
2940    o = edje_object_add(e_comp->evas);
2941    evas_object_data_set(o, "comp_object", (void*)1);
2942    e_comp_object_util_type_set(o, type);
2943 
2944    evas_object_geometry_get(obj, &x, &y, &w, &h);
2945    evas_object_geometry_set(o, x, y, w, h);
2946    evas_object_pass_events_set(o, evas_object_pass_events_get(obj));
2947 
2948    z = e_zoomap_add(e_comp->evas);
2949    evas_object_show(z);
2950    evas_object_geometry_set(z, x, y, w, h);
2951    e_zoomap_child_edje_solid_setup(z);
2952    e_zoomap_smooth_set(z, conf->smooth_windows);
2953    e_zoomap_child_set(z, obj);
2954    edje_object_signal_callback_add(o, "e,action,*,done", "e", _e_comp_object_util_done_defer, z);
2955 
2956    evas_object_intercept_show_callback_add(o, _e_comp_object_util_show, z);
2957    evas_object_intercept_hide_callback_add(o, _e_comp_object_util_hide, z);
2958    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_util_moveresize, z);
2959    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_util_del, z);
2960    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_util_moveresize, z);
2961    evas_object_event_callback_add(o, EVAS_CALLBACK_RESTACK, _e_comp_object_util_restack, z);
2962 
2963    e_comp_object_signal_emit(o, "e,state,hidden", "e");
2964 
2965    edje_object_part_swallow(o, "e.swallow.content", z ?: obj);
2966 
2967    _e_comp_object_event_add(o);
2968 
2969    if (vis)
2970      evas_object_show(o);
2971 
2972    return o;
2973 }
2974 
2975 E_API Evas_Object *
e_comp_object_util_get(Evas_Object * obj)2976 e_comp_object_util_get(Evas_Object *obj)
2977 {
2978    Evas_Object *z;
2979    SOFT_ENTRY(NULL);
2980    if (cw) return NULL;
2981    z = edje_object_part_swallow_get(obj, "e.swallow.content");
2982    EINA_SAFETY_ON_NULL_RETURN_VAL(z, NULL);
2983    return e_zoomap_child_get(z);
2984 }
2985 
2986 /* utility functions for deleting objects when their "owner" is deleted */
2987 E_API void
e_comp_object_util_del_list_append(Evas_Object * obj,Evas_Object * to_del)2988 e_comp_object_util_del_list_append(Evas_Object *obj, Evas_Object *to_del)
2989 {
2990    Eina_List *l;
2991 
2992    EINA_SAFETY_ON_NULL_RETURN(to_del);
2993    l = evas_object_data_get(obj, "comp_object-to_del");
2994    evas_object_data_set(obj, "comp_object-to_del", eina_list_append(l, to_del));
2995    evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del);
2996    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_util_del, NULL);
2997 }
2998 
2999 E_API void
e_comp_object_util_del_list_remove(Evas_Object * obj,Evas_Object * to_del)3000 e_comp_object_util_del_list_remove(Evas_Object *obj, Evas_Object *to_del)
3001 {
3002    Eina_List *l;
3003 
3004    SOFT_ENTRY();
3005    EINA_SAFETY_ON_NULL_RETURN(to_del);
3006    l = evas_object_data_get(obj, "comp_object-to_del");
3007    if (l)
3008      evas_object_data_set(obj, "comp_object-to_del", eina_list_remove(l, to_del));
3009 }
3010 
3011 /////////////////////////////////////////////////////////
3012 
3013 E_API Evas_Object *
e_comp_object_client_add(E_Client * ec)3014 e_comp_object_client_add(E_Client *ec)
3015 {
3016    Evas_Object *o;
3017    E_Comp_Object *cw;
3018 
3019    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3020    if (ec->frame) return NULL;
3021    _e_comp_smart_init();
3022    o = evas_object_smart_add(e_comp->evas, _e_comp_smart);
3023    cw = evas_object_smart_data_get(o);
3024    if (!cw)
3025      {
3026         evas_object_del(o);
3027         return NULL;
3028      }
3029    evas_object_data_set(o, "E_Client", ec);
3030 //   REFD(ec, 9);
3031 //   e_object_ref(E_OBJECT(ec));
3032    cw->ec = ec;
3033    ec->frame = o;
3034    evas_object_data_set(o, "comp_object", (void*)1);
3035    e_object_delfn_add(E_OBJECT(ec), _e_comp_object_client_del, cw);
3036 
3037    _e_comp_object_event_add(o);
3038 
3039    return o;
3040 }
3041 
3042 /* utility functions for getting client inset */
3043 E_API void
e_comp_object_frame_xy_adjust(Evas_Object * obj,int x,int y,int * ax,int * ay)3044 e_comp_object_frame_xy_adjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3045 {
3046    API_ENTRY;
3047    if (!cw->client_inset.calc)
3048      {
3049         if (ax) *ax = x;
3050         if (ay) *ay = y;
3051         return;
3052      }
3053    if (ax) *ax = x - cw->client_inset.l;
3054    if (ay) *ay = y - cw->client_inset.t;
3055 }
3056 
3057 E_API void
e_comp_object_frame_xy_unadjust(Evas_Object * obj,int x,int y,int * ax,int * ay)3058 e_comp_object_frame_xy_unadjust(Evas_Object *obj, int x, int y, int *ax, int *ay)
3059 {
3060    API_ENTRY;
3061    if (!cw->client_inset.calc)
3062      {
3063         if (ax) *ax = x;
3064         if (ay) *ay = y;
3065         return;
3066      }
3067    if (ax) *ax = x + cw->client_inset.l;
3068    if (ay) *ay = y + cw->client_inset.t;
3069 }
3070 
3071 E_API void
e_comp_object_frame_wh_adjust(Evas_Object * obj,int w,int h,int * aw,int * ah)3072 e_comp_object_frame_wh_adjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3073 {
3074    API_ENTRY;
3075    if (!cw->client_inset.calc)
3076      {
3077         if (aw) *aw = w;
3078         if (ah) *ah = h;
3079         return;
3080      }
3081    if (aw) *aw = w + cw->client_inset.l + cw->client_inset.r;
3082    if (ah) *ah = h + cw->client_inset.t + cw->client_inset.b;
3083 }
3084 
3085 E_API void
e_comp_object_frame_wh_unadjust(Evas_Object * obj,int w,int h,int * aw,int * ah)3086 e_comp_object_frame_wh_unadjust(Evas_Object *obj, int w, int h, int *aw, int *ah)
3087 {
3088    API_ENTRY;
3089    if (!cw->client_inset.calc)
3090      {
3091         if (aw) *aw = w;
3092         if (ah) *ah = h;
3093         return;
3094      }
3095    if (aw) *aw = w - cw->client_inset.l - cw->client_inset.r;
3096    if (ah) *ah = h - cw->client_inset.t - cw->client_inset.b;
3097 }
3098 
3099 E_API E_Client *
e_comp_object_client_get(Evas_Object * obj)3100 e_comp_object_client_get(Evas_Object *obj)
3101 {
3102    Evas_Object *o;
3103 
3104    SOFT_ENTRY(NULL);
3105    /* FIXME: remove this when eo is used */
3106    o = evas_object_data_get(obj, "comp_smart_obj");
3107    if (o)
3108      return e_comp_object_client_get(o);
3109    return cw ? cw->ec : NULL;
3110 }
3111 
3112 E_API void
e_comp_object_frame_extends_get(Evas_Object * obj,int * x,int * y,int * w,int * h)3113 e_comp_object_frame_extends_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3114 {
3115    API_ENTRY;
3116    if (cw->frame_extends)
3117      edje_object_parts_extends_calc(cw->frame_object, x, y, w, h);
3118    else
3119      {
3120         if (x) *x = 0;
3121         if (y) *y = 0;
3122         if (w) *w  = cw->ec->w;
3123         if (h) *h  = cw->ec->h;
3124      }
3125 }
3126 
3127 E_API E_Zone *
e_comp_object_util_zone_get(Evas_Object * obj)3128 e_comp_object_util_zone_get(Evas_Object *obj)
3129 {
3130    E_Zone *zone = NULL;
3131 
3132    SOFT_ENTRY(NULL);
3133    if (cw)
3134      zone = cw->ec->zone;
3135    if (!zone)
3136      {
3137         int x, y, w, h;
3138 
3139         if (e_win_client_get(obj))
3140           return e_win_client_get(obj)->zone;
3141         evas_object_geometry_get(obj, &x, &y, &w, &h);
3142         zone = e_comp_zone_xy_get(x, y);
3143         if (zone) return zone;
3144         zone = e_comp_zone_xy_get(x + w, y + h);
3145         if (zone) return zone;
3146         zone = e_comp_zone_xy_get(x + w, y);
3147         if (zone) return zone;
3148         zone = e_comp_zone_xy_get(x, y + h);
3149      }
3150    return zone;
3151 }
3152 
3153 E_API void
e_comp_object_util_center_on_zone(Evas_Object * obj,E_Zone * zone)3154 e_comp_object_util_center_on_zone(Evas_Object *obj, E_Zone *zone)
3155 {
3156    int x, y, w, h, ow, oh;
3157 
3158    SOFT_ENTRY();
3159 
3160    EINA_SAFETY_ON_NULL_RETURN(zone);
3161    e_zone_useful_geometry_get(zone, &x, &y, &w, &h);
3162    if (cw)
3163      ow = cw->ec->w, oh = cw->ec->h;
3164    else
3165      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3166    x = x + (w - ow) / 2;
3167    y = y + (h - oh) / 2;
3168    evas_object_move(obj, x, y);
3169 }
3170 
3171 E_API void
e_comp_object_util_center(Evas_Object * obj)3172 e_comp_object_util_center(Evas_Object *obj)
3173 {
3174    E_Zone *zone;
3175 
3176    zone = e_comp_object_util_zone_get(obj);
3177 
3178    e_comp_object_util_center_on_zone(obj, zone);
3179 }
3180 
3181 E_API void
e_comp_object_util_center_on(Evas_Object * obj,Evas_Object * on)3182 e_comp_object_util_center_on(Evas_Object *obj, Evas_Object *on)
3183 {
3184    int x, y, w, h, ow, oh;
3185    E_Comp_Object *cw2 = NULL;
3186    const char *type;
3187 
3188    SOFT_ENTRY();
3189    EINA_SAFETY_ON_NULL_RETURN(on);
3190 
3191    type = evas_object_type_get(on);
3192    if ((type) && (!strcmp(type, "e_comp_object")))
3193      cw2 = evas_object_smart_data_get(on);
3194    if (cw2 && eina_streq(evas_object_type_get(on), SMART_NAME))
3195      x = cw2->ec->x, y = cw2->ec->y, w = cw2->ec->w, h = cw2->ec->h;
3196    else
3197      evas_object_geometry_get(on, &x, &y, &w, &h);
3198    if (cw)
3199      ow = cw->ec->w, oh = cw->ec->h;
3200    else
3201      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3202    evas_object_move(obj, x + (w / 2) - (ow / 2), y + (h / 2) - (oh / 2));
3203 }
3204 
3205 E_API void
e_comp_object_util_fullscreen(Evas_Object * obj)3206 e_comp_object_util_fullscreen(Evas_Object *obj)
3207 {
3208    SOFT_ENTRY();
3209 
3210    if (cw)
3211      e_client_fullscreen(cw->ec, E_FULLSCREEN_RESIZE);
3212    else
3213      {
3214         evas_object_move(obj, 0, 0);
3215         evas_object_resize(obj, e_comp->w, e_comp->h);
3216      }
3217 }
3218 
3219 E_API void
e_comp_object_util_center_pos_get(Evas_Object * obj,int * x,int * y)3220 e_comp_object_util_center_pos_get(Evas_Object *obj, int *x, int *y)
3221 {
3222    E_Zone *zone;
3223    int zx, zy, zw, zh;
3224    int ow, oh;
3225    SOFT_ENTRY();
3226 
3227    if (cw)
3228      ow = cw->w, oh = cw->h;
3229    else
3230      evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3231    zone = e_comp_object_util_zone_get(obj);
3232    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
3233    if (x) *x = zx + (zw - ow) / 2;
3234    if (y) *y = zy + (zh - oh) / 2;
3235 }
3236 
3237 E_API void
e_comp_object_input_area_set(Evas_Object * obj,const Eina_Tiler * area)3238 e_comp_object_input_area_set(Evas_Object *obj, const Eina_Tiler *area)
3239 {
3240    Eina_Rectangle *rect;
3241    Eina_Iterator *it;
3242 
3243    API_ENTRY;
3244 
3245    if ((!area) && (!cw->input_area)) return;
3246    if (area && cw->input_area && eina_tiler_equal(area, cw->input_area)) return;
3247    _e_comp_input_objs_free(cw);
3248    if (cw->obj) evas_object_pass_events_set(cw->obj, 1);
3249    if ((!area) || eina_tiler_empty(area))
3250      {
3251         E_FREE_FUNC(cw->input_area, eina_tiler_free);
3252         E_FREE_FUNC(cw->input_objs, eina_array_free);
3253         return;
3254      }
3255    if (cw->input_area)
3256      eina_tiler_clear(cw->input_area);
3257    else
3258      {
3259         cw->input_area = eina_tiler_new(99999, 99999);
3260         eina_tiler_tile_size_set(cw->input_area, 1, 1);
3261      }
3262    if (!cw->input_objs)
3263      cw->input_objs = eina_array_new(1);
3264    it = eina_tiler_iterator_new(area);
3265    EINA_ITERATOR_FOREACH(it, rect)
3266      {
3267         Evas_Object *o = evas_object_rectangle_add(e_comp->evas);
3268         //e_util_size_debug_set(o, 1);
3269         evas_object_name_set(o, "cw->input_rect");
3270         evas_object_color_set(o, 0, 0, 0, 0);
3271         evas_object_clip_set(o, cw->clip);
3272         evas_object_smart_member_add(o, obj);
3273         evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_ssd_mouse_in, cw);
3274         evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_ssd_mouse_out, cw);
3275         if (cw->ec->moving)
3276           evas_object_pointer_mode_set(o, EVAS_OBJECT_POINTER_MODE_NOGRAB);
3277         evas_object_show(o);
3278         eina_array_push(cw->input_objs, o);
3279         eina_tiler_rect_add(cw->input_area, rect);
3280      }
3281    eina_iterator_free(it);
3282    _e_comp_object_input_rect_update(cw);
3283 }
3284 
3285 E_API Eina_Bool
e_comp_object_coords_inside_input_area(Evas_Object * obj,int x,int y)3286 e_comp_object_coords_inside_input_area(Evas_Object *obj, int x, int y)
3287 {
3288    API_ENTRY EINA_FALSE;
3289 
3290    if (cw->input_area)
3291      {
3292         unsigned int i;
3293         Evas_Object *rect;
3294         Eina_Array_Iterator it;
3295 
3296         EINA_ARRAY_ITER_NEXT(cw->input_objs, i, rect, it)
3297           if (evas_object_pointer_coords_inside_get(rect, x, y)) return EINA_TRUE;
3298 
3299         return EINA_FALSE;
3300      }
3301    if (evas_object_pass_events_get(obj)) return EINA_FALSE;
3302    return E_INSIDE(x, y, cw->ec->x, cw->ec->y, cw->ec->w, cw->ec->h);
3303 }
3304 
3305 E_API void
e_comp_object_frame_geometry_get(Evas_Object * obj,int * l,int * r,int * t,int * b)3306 e_comp_object_frame_geometry_get(Evas_Object *obj, int *l, int *r, int *t, int *b)
3307 {
3308    API_ENTRY;
3309    if (l) *l = cw->client_inset.l;
3310    if (r) *r = cw->client_inset.r;
3311    if (t) *t = cw->client_inset.t;
3312    if (b) *b = cw->client_inset.b;
3313 }
3314 
3315 /* set geometry for CSD */
3316 E_API void
e_comp_object_frame_geometry_set(Evas_Object * obj,int l,int r,int t,int b)3317 e_comp_object_frame_geometry_set(Evas_Object *obj, int l, int r, int t, int b)
3318 {
3319    Eina_Bool calc;
3320 
3321    API_ENTRY;
3322    if (cw->frame_object)
3323      CRI("ACK!");
3324    if ((cw->client_inset.l == l) && (cw->client_inset.r == r) &&
3325        (cw->client_inset.t == t) && (cw->client_inset.b == b)) return;
3326    calc = cw->client_inset.calc;
3327    cw->client_inset.calc = l || r || t || b;
3328    eina_stringshare_replace(&cw->frame_theme, "borderless");
3329    if (cw->client_inset.calc)
3330      {
3331         cw->ec->w += (l + r) - (cw->client_inset.l + cw->client_inset.r);
3332         cw->ec->h += (t + b) - (cw->client_inset.t + cw->client_inset.b);
3333         if (cw->ec->maximized || cw->ec->fullscreen)
3334           cw->ec->saved.frame = 0;
3335      }
3336    else if (cw->ec->maximized || cw->ec->fullscreen)
3337      {
3338         cw->ec->saved.x += l - cw->client_inset.l;
3339         cw->ec->saved.y += t - cw->client_inset.t;
3340         if (!e_client_has_xwindow(cw->ec))
3341           {
3342              cw->ec->saved.w -= ((l + r) - (cw->client_inset.l + cw->client_inset.r));
3343              cw->ec->saved.h -= ((t + b) - (cw->client_inset.t + cw->client_inset.b));
3344           }
3345      }
3346    if (!cw->ec->new_client)
3347      {
3348         if (calc && cw->client_inset.calc)
3349           {
3350              E_Zone *zone = e_comp_object_util_zone_get(obj);
3351 
3352              if (cw->ec->x != zone->x)
3353                cw->ec->x -= l - cw->client_inset.l;
3354              if (cw->ec->y != zone->y)
3355                cw->ec->y -= t - cw->client_inset.t;
3356           }
3357         cw->ec->changes.pos = cw->ec->changes.size = 1;
3358         EC_CHANGED(cw->ec);
3359      }
3360    cw->client_inset.l = l;
3361    cw->client_inset.r = r;
3362    cw->client_inset.t = t;
3363    cw->client_inset.b = b;
3364    if (!cw->shobj) return;
3365    if (cw->client_inset.calc)
3366      e_comp_object_signal_emit(obj, "e,state,focus,disabled", "e");
3367    else
3368      e_comp_object_signal_emit(obj, "e,state,focus,enabled", "e");
3369 }
3370 
3371 E_API Eina_Bool
e_comp_object_frame_allowed(Evas_Object * obj)3372 e_comp_object_frame_allowed(Evas_Object *obj)
3373 {
3374    API_ENTRY EINA_FALSE;
3375    return (!e_client_util_ignored_get(cw->ec)) && (!cw->ec->mwm.borderless) &&
3376      (cw->frame_object || (!cw->client_inset.calc));
3377 }
3378 
3379 E_API void
e_comp_object_frame_icon_geometry_get(Evas_Object * obj,int * x,int * y,int * w,int * h)3380 e_comp_object_frame_icon_geometry_get(Evas_Object *obj, int *x, int *y, int *w, int *h)
3381 {
3382    API_ENTRY;
3383 
3384    if (x) *x = 0;
3385    if (y) *y = 0;
3386    if (w) *w = 0;
3387    if (h) *h = 0;
3388    if (!cw->frame_icon) return;
3389    evas_object_geometry_get(cw->frame_icon, x, y, w, h);
3390 }
3391 
3392 E_API Eina_Bool
e_comp_object_frame_title_set(Evas_Object * obj,const char * name)3393 e_comp_object_frame_title_set(Evas_Object *obj, const char *name)
3394 {
3395    API_ENTRY EINA_FALSE;
3396    if (!e_util_strcmp(cw->frame_name, name)) return EINA_FALSE;
3397    eina_stringshare_replace(&cw->frame_name, name);
3398    if (cw->frame_object)
3399      edje_object_part_text_set(cw->frame_object, "e.text.title", cw->frame_name);
3400    return EINA_TRUE;
3401 }
3402 
3403 E_API Eina_Bool
e_comp_object_frame_exists(Evas_Object * obj)3404 e_comp_object_frame_exists(Evas_Object *obj)
3405 {
3406    API_ENTRY EINA_FALSE;
3407    return !!cw->frame_object;
3408 }
3409 
3410 E_API Eina_Bool
e_comp_object_frame_icon_update(Evas_Object * obj)3411 e_comp_object_frame_icon_update(Evas_Object *obj)
3412 {
3413    API_ENTRY EINA_FALSE;
3414 
3415    E_FREE_FUNC(cw->frame_icon, evas_object_del);
3416    if (!cw->frame_object) return EINA_FALSE;
3417    if (!edje_object_part_exists(cw->frame_object, "e.swallow.icon"))
3418      return EINA_TRUE;
3419    cw->frame_icon = e_client_icon_add(cw->ec, e_comp->evas);
3420    if (!cw->frame_icon) return EINA_TRUE;
3421    if (!edje_object_part_swallow(cw->frame_object, "e.swallow.icon", cw->frame_icon))
3422      E_FREE_FUNC(cw->frame_icon, evas_object_del);
3423    return EINA_TRUE;
3424 }
3425 
3426 static void
_e_comp_object_volume_update(Evas_Object * obj)3427 _e_comp_object_volume_update(Evas_Object *obj)
3428 {
3429    API_ENTRY;
3430 
3431    if (cw->ec->focused)
3432      e_client_volume_object_emit(cw->ec, "e,state,focused", "e");
3433    else
3434      e_client_volume_object_emit(cw->ec, "e,state,unfocused", "e");
3435    if (cw->ec->urgent)
3436      e_client_volume_object_emit(cw->ec, "e,state,urgent", "e");
3437    else
3438      e_client_volume_object_emit(cw->ec, "e,state,not_urgent", "e");
3439    if (cw->ec->shaded)
3440      e_client_volume_object_emit(cw->ec, "e,state,shaded", "e");
3441    if (cw->ec->sticky)
3442      e_client_volume_object_emit(cw->ec, "e,state,sticky", "e");
3443    if (cw->ec->hung)
3444      e_client_volume_object_emit(cw->ec, "e,state,hung", "e");
3445    /* visibility must always be enabled for re_manage clients to prevent
3446     * pop-in animations every time the user sees a persistent client again;
3447     * applying visibility for iconic clients prevents the client from getting
3448     * stuck as hidden
3449     */
3450    if (cw->visible || cw->ec->iconic || cw->ec->re_manage)
3451      {
3452         if ((cw->w > 0) && (cw->h > 0))
3453           e_client_volume_object_emit(cw->ec, "e,state,visible", "e");
3454      }
3455    else
3456      e_client_volume_object_emit(cw->ec, "e,state,hidden", "e");
3457    if (e_comp_object_frame_allowed(cw->smart_obj))
3458      e_client_volume_object_emit(cw->ec, "e,state,focus,enabled", "e");
3459    else
3460      e_client_volume_object_emit(cw->ec, "e,state,focus,disabled", "e");
3461 }
3462 
3463 E_API void
e_comp_object_frame_volume_update(Evas_Object * obj)3464 e_comp_object_frame_volume_update(Evas_Object *obj)
3465 {
3466    API_ENTRY;
3467 
3468    if (!cw->frame_object) return;
3469    if (edje_object_part_exists(cw->frame_object, "e.swallow.volume"))
3470      {
3471         if (cw->ec->sinks)
3472           {
3473              if (!cw->frame_volume)
3474                {
3475                   cw->frame_volume = e_client_volume_object_add(cw->ec, e_comp->evas);
3476                   edje_object_part_swallow(cw->frame_object,
3477                                            "e.swallow.volume", cw->frame_volume);
3478                   _e_comp_object_volume_update(obj);
3479                   evas_object_show(cw->frame_volume);
3480                }
3481           }
3482         else
3483           {
3484              E_FREE_FUNC(cw->frame_volume, evas_object_del);
3485           }
3486      }
3487 }
3488 
3489 E_API Eina_Bool
e_comp_object_frame_theme_set(Evas_Object * obj,const char * name)3490 e_comp_object_frame_theme_set(Evas_Object *obj, const char *name)
3491 {
3492    Evas_Object *o, *pbg;
3493    char buf[4096];
3494    int ok;
3495    Eina_Stringshare *theme;
3496 
3497    API_ENTRY EINA_FALSE;
3498 
3499    if (!e_util_strcmp(cw->frame_theme, name))
3500     return edje_object_part_swallow(cw->shobj, "e.swallow.content", cw->frame_object ?: cw->obj);
3501    if (!e_util_strcmp(name, "COMP_RESHADOW"))
3502      return _e_comp_object_shadow_setup(cw);
3503    if (eina_streq(name, "borderless") && (!cw->frame_object)) return EINA_TRUE;
3504    pbg = cw->frame_object;
3505    theme = eina_stringshare_add(name);
3506 
3507    if (cw->frame_object)
3508      {
3509         int w, h;
3510 
3511         w = cw->ec->w, h = cw->ec->h;
3512         e_comp_object_frame_wh_unadjust(obj, w, h, &cw->ec->w, &cw->ec->h);
3513         if ((cw->ec->w != w) || (cw->ec->h != h))
3514           {
3515              cw->ec->changes.size = 1;
3516              EC_CHANGED(cw->ec);
3517           }
3518         E_FREE_FUNC(cw->frame_object, evas_object_del);
3519         if (!name) goto reshadow;
3520      }
3521    o = edje_object_add(e_comp->evas);
3522    snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", name);
3523    ok = e_theme_edje_object_set(o, "base/theme/border", buf);
3524    if ((!ok) && (!e_util_strcmp(name, "borderless")))
3525      {
3526         cw->frame_object = NULL;
3527         E_FREE_FUNC(cw->frame_icon, evas_object_del);
3528         E_FREE_FUNC(cw->frame_volume, evas_object_del);
3529         evas_object_del(o);
3530         eina_stringshare_del(cw->frame_theme);
3531         cw->frame_theme = theme;
3532         goto reshadow;
3533      }
3534    if (!ok)
3535      {
3536         if (theme != e_config->theme_default_border_style)
3537           {
3538              snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
3539              ok = e_theme_edje_object_set(o, "base/theme/border", buf);
3540           }
3541         if (!ok)
3542           {
3543              ok = e_theme_edje_object_set(o, "base/theme/border",
3544                                           "e/widgets/border/default/border");
3545              if (ok && (theme == e_config->theme_default_border_style))
3546                {
3547                   /* Reset default border style to default */
3548                   eina_stringshare_replace(&e_config->theme_default_border_style, "default");
3549                   e_config_save_queue();
3550                }
3551           }
3552      }
3553 
3554    if (ok)
3555      {
3556         cw->frame_object = o;
3557         edje_object_signal_emit(o, "e,version,22", "e");
3558         eina_stringshare_del(cw->frame_theme);
3559         cw->frame_theme = theme;
3560         evas_object_name_set(o, "cw->frame_object");
3561 
3562         if (cw->frame_name)
3563           edje_object_part_text_set(o, "e.text.title", cw->frame_name);
3564 
3565         if (pbg)
3566           {
3567              if (cw->frame_icon)
3568                {
3569                   if (!edje_object_part_swallow(cw->frame_object,
3570                                                 "e.swallow.icon",
3571                                                 cw->frame_icon))
3572                     E_FREE_FUNC(cw->frame_icon, evas_object_del);
3573                }
3574              if (cw->frame_volume)
3575                {
3576                   if (!edje_object_part_swallow(cw->frame_object,
3577                                                 "e.swallow.volume",
3578                                                 cw->frame_volume))
3579                     E_FREE_FUNC(cw->frame_volume, evas_object_del);
3580                }
3581           }
3582         else
3583           {
3584              cw->ec->changes.icon = 1;
3585              EC_CHANGED(cw->ec);
3586           }
3587 
3588         if (cw->ec->volume_control_enabled)
3589           {
3590              e_comp_object_frame_volume_update(obj);
3591           }
3592      }
3593    else
3594      {
3595         CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
3596         evas_object_del(o);
3597         E_FREE_FUNC(cw->frame_icon, evas_object_del);
3598         E_FREE_FUNC(cw->frame_volume, evas_object_del);
3599      }
3600 reshadow:
3601    if (cw->shobj)
3602      _e_comp_object_shadow_setup(cw);
3603    do
3604      {
3605         _e_comp_smart_cb_frame_recalc(cw, cw->smart_obj, NULL);
3606         if ((cw->x == -1) && (cw->y == -1) && cw->ec->new_client &&
3607             (!cw->ec->placed) && (!cw->ec->re_manage))
3608           {
3609              cw->ec->x = MAX(cw->ec->zone->x, cw->ec->client.x - cw->client_inset.l);
3610              cw->ec->y = MAX(cw->ec->zone->y, cw->ec->client.y - cw->client_inset.t);
3611           }
3612         /* this guarantees that we won't get blocked by the NOP check in the interceptor */
3613         cw->y = cw->x = -99999;
3614         if (pbg)
3615           evas_object_move(obj, cw->ec->x, cw->ec->y);
3616         else if (cw->ec->placed || (!cw->ec->new_client))
3617           {
3618              /* if no previous frame:
3619               * - reapply client_inset
3620               * - clamp to zone
3621               */
3622              int x, y;
3623 
3624              if (cw->ec->changes.size)
3625                {
3626                   x = cw->ec->x;
3627                   y = cw->ec->y;
3628                }
3629              else
3630                {
3631                   x = cw->ec->client.x, y = cw->ec->client.y;
3632                   x = MAX(cw->ec->zone->x, cw->ec->client.x - cw->client_inset.l);
3633                   y = MAX(cw->ec->zone->y, cw->ec->client.y - cw->client_inset.t);
3634                }
3635              evas_object_move(obj, x, y);
3636           }
3637      } while (0);
3638 
3639    if (cw->ec->maximized)
3640      {
3641         cw->ec->changes.need_maximize = 1;
3642         EC_CHANGED(cw->ec);
3643      }
3644    evas_object_smart_callback_call(cw->smart_obj, "frame_changed", NULL);
3645    if (cw->frame_object)
3646      {
3647         cw->frame_extends = !!edje_object_data_get(cw->frame_object, "frame_extends");
3648         edje_object_signal_callback_add(cw->frame_object, "*", "*",
3649                                         _e_comp_object_cb_signal_bind, cw);
3650      }
3651    else
3652      cw->frame_extends = 0;
3653    if (pbg && (!cw->frame_object))
3654      {
3655         evas_object_event_callback_del(cw->obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_ssd_mouse_in);
3656         evas_object_event_callback_del(cw->obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_ssd_mouse_out);
3657      }
3658    else if (cw->obj)
3659      {
3660         evas_object_event_callback_add(cw->obj, EVAS_CALLBACK_MOUSE_IN, _e_comp_object_ssd_mouse_in, cw);
3661         evas_object_event_callback_add(cw->obj, EVAS_CALLBACK_MOUSE_OUT, _e_comp_object_ssd_mouse_out, cw);
3662      }
3663    evas_object_del(pbg);
3664    return EINA_TRUE;
3665 }
3666 
3667 E_API void
e_comp_object_signal_emit(Evas_Object * obj,const char * sig,const char * src)3668 e_comp_object_signal_emit(Evas_Object *obj, const char *sig, const char *src)
3669 {
3670    E_Comp_Object_Mover *prov;
3671 
3672    API_ENTRY;
3673    //INF("EMIT %p: %s %s", cw->ec, sig, src);
3674    edje_object_signal_emit(cw->shobj, sig, src);
3675    e_client_volume_object_emit(cw->ec, sig, src);
3676    if (cw->frame_object) edje_object_signal_emit(cw->frame_object, sig, src);
3677    if (cw->frame_icon && e_icon_edje_get(cw->frame_icon))
3678      edje_object_signal_emit(e_icon_edje_get(cw->frame_icon), sig, src);
3679    /* start with highest priority callback first */
3680    EINA_INLIST_REVERSE_FOREACH(_e_comp_object_movers, prov)
3681      {
3682         if (!e_util_glob_match(sig, prov->sig)) continue;
3683         if (prov->func(prov->data, obj, sig)) break;
3684      }
3685 }
3686 
3687 E_API void
e_comp_object_signal_callback_add(Evas_Object * obj,const char * sig,const char * src,Edje_Signal_Cb cb,const void * data)3688 e_comp_object_signal_callback_add(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
3689 {
3690    /* FIXME: at some point I guess this should use eo to inherit
3691     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_ADD
3692     * -EDJE_OBJ_SUB_ID_SIGNAL_CALLBACK_DEL
3693     */
3694    API_ENTRY;
3695    edje_object_signal_callback_add(cw->shobj, sig, src, cb, (void*)data);
3696 }
3697 
3698 E_API void
e_comp_object_signal_callback_del(Evas_Object * obj,const char * sig,const char * src,Edje_Signal_Cb cb)3699 e_comp_object_signal_callback_del(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb)
3700 {
3701    API_ENTRY;
3702    edje_object_signal_callback_del(cw->shobj, sig, src, cb);
3703 }
3704 
3705 E_API void
e_comp_object_signal_callback_del_full(Evas_Object * obj,const char * sig,const char * src,Edje_Signal_Cb cb,const void * data)3706 e_comp_object_signal_callback_del_full(Evas_Object *obj, const char *sig, const char *src, Edje_Signal_Cb cb, const void *data)
3707 {
3708    API_ENTRY;
3709    edje_object_signal_callback_del_full(cw->shobj, sig, src, cb, (void*)data);
3710 }
3711 
3712 E_API void
e_comp_object_damage(Evas_Object * obj,int x,int y,int w,int h)3713 e_comp_object_damage(Evas_Object *obj, int x, int y, int w, int h)
3714 {
3715    int tw, th;
3716    Eina_Rectangle rect;
3717    API_ENTRY;
3718 
3719    if (cw->ec->input_only) return;
3720    if (cw->nocomp) return;
3721    _e_comp_object_updates_init(cw);
3722    EINA_SAFETY_ON_NULL_RETURN(cw->updates);
3723    rect.x = x, rect.y = y;
3724    rect.w = w, rect.h = h;
3725    evas_object_smart_callback_call(obj, "damage", &rect);
3726    if (e_comp->nocomp)
3727      {
3728         cw->nocomp_need_update = EINA_TRUE;
3729         return;
3730      }
3731    /* ignore overdraw */
3732    if (cw->updates_full)
3733      {
3734         RENDER_DEBUG("IGNORED %p: %d,%d %dx%d", cw->ec, x, y, w, h);
3735         if (!e_object_is_del(E_OBJECT(cw->ec)))
3736           e_comp_object_render_update_add(obj);
3737         return;
3738      }
3739    /* clip rect to client surface */
3740    RENDER_DEBUG("DAMAGE(%d,%d %dx%d) CLIP(%dx%d)", x, y, w, h, cw->ec->client.w, cw->ec->client.h);
3741    E_RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, cw->ec->client.w, cw->ec->client.h);
3742    /* if rect is the total size of the client after clip, clear the updates
3743     * since this is guaranteed to be the whole region anyway
3744     */
3745    eina_tiler_area_size_get(cw->updates, &tw, &th);
3746    if ((w > tw) || (h > th))
3747      {
3748         RENDER_DEBUG("DAMAGE RESIZE %p: %dx%d", cw->ec, cw->ec->client.w, cw->ec->client.h);
3749         eina_tiler_clear(cw->updates);
3750         eina_tiler_area_size_set(cw->updates, cw->ec->client.w, cw->ec->client.h);
3751         x = 0, y = 0;
3752         tw = cw->ec->client.w, th = cw->ec->client.h;
3753      }
3754    if ((!x) && (!y) && (w == tw) && (h == th))
3755      {
3756         eina_tiler_clear(cw->updates);
3757         RENDER_DEBUG("DAMAGE FULL: %p", cw->ec);
3758         cw->updates_full = 1;
3759         cw->update_count = 0;
3760      }
3761    cw->update_count++;
3762    if (cw->update_count > UPDATE_MAX)
3763      {
3764         /* this is going to get really dumb, so just update the whole thing */
3765         eina_tiler_clear(cw->updates);
3766         cw->update_count = cw->updates_full = 1;
3767         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){0, 0, tw, th});
3768         RENDER_DEBUG("DAMAGE MAX: %dx%d", tw, th);
3769      }
3770    else
3771      {
3772         eina_tiler_rect_add(cw->updates, &(Eina_Rectangle){x, y, w, h});
3773         RENDER_DEBUG("DAMAGE: %d,%d %dx%d", x, y, w, h);
3774      }
3775    cw->updates_exist = 1;
3776    if (!e_object_is_del(E_OBJECT(cw->ec)))
3777      e_comp_object_render_update_add(obj);
3778 }
3779 
3780 E_API Eina_Bool
e_comp_object_damage_exists(Evas_Object * obj)3781 e_comp_object_damage_exists(Evas_Object *obj)
3782 {
3783    API_ENTRY EINA_FALSE;
3784    return cw->updates_exist || cw->updates_full;
3785 }
3786 
3787 E_API void
e_comp_object_render_update_add(Evas_Object * obj)3788 e_comp_object_render_update_add(Evas_Object *obj)
3789 {
3790    API_ENTRY;
3791 
3792    if (cw->ec->input_only || (!cw->updates) || (!cw->redirected)) return;
3793    if (e_object_is_del(E_OBJECT(cw->ec)))
3794      CRI("CAN'T RENDER A DELETED CLIENT!");
3795    if (!e_pixmap_usable_get(cw->ec->pixmap)) return;
3796    //if (e_client_util_resizing_get(cw->ec) && (e_pixmap_type_get(cw->ec->pixmap) == E_PIXMAP_TYPE_WL))
3797      //INF("WL RENDER UPDATE");
3798    if (!cw->update)
3799      {
3800         cw->update = 1;
3801         e_comp->updates = eina_list_append(e_comp->updates, cw->ec);
3802      }
3803    e_comp_render_queue();
3804 }
3805 
3806 E_API void
e_comp_object_render_update_del(Evas_Object * obj)3807 e_comp_object_render_update_del(Evas_Object *obj)
3808 {
3809    API_ENTRY;
3810 
3811    if (cw->ec->input_only || (!cw->updates)) return;
3812    if (!cw->update) return;
3813    cw->update = 0;
3814    /* this gets called during comp animating to clear the update flag */
3815    if (e_comp->grabbed) return;
3816    e_comp->updates = eina_list_remove(e_comp->updates, cw->ec);
3817 }
3818 
3819 E_API void
e_comp_object_shape_apply(Evas_Object * obj)3820 e_comp_object_shape_apply(Evas_Object *obj)
3821 {
3822    Eina_List *l;
3823    Evas_Object *o;
3824    unsigned int i, *pix, *p;
3825    int w, h, px, py;
3826 
3827    API_ENTRY;
3828    if (!cw->ec) return; //NYI
3829    if (cw->ec->shaped)
3830      {
3831         if ((cw->ec->shape_rects_num >= 1) &&
3832             (!_e_comp_shaped_check(cw->ec->client.w, cw->ec->client.h, cw->ec->shape_rects, cw->ec->shape_rects_num)))
3833            return;
3834      }
3835    if (cw->native)
3836      {
3837         ERR("BUGGER: shape with native surface? cw=%p", cw);
3838         return;
3839      }
3840    evas_object_image_size_get(cw->obj, &w, &h);
3841    if ((w < 1) || (h < 1)) return;
3842 
3843    //INF("SHAPE RENDER %p", cw->ec);
3844 
3845    p = pix = evas_object_image_data_get(cw->obj, 1);
3846    if (!pix)
3847      {
3848         evas_object_image_data_set(cw->obj, pix);
3849         _e_comp_object_alpha_set(cw);
3850         return;
3851      }
3852    if ((cw->ec->shaped) && (cw->ec->shape_rects))
3853      {
3854         unsigned char *spix, *sp;
3855 
3856         spix = calloc(w * h, sizeof(unsigned char));
3857         RENDER_DEBUG("SHAPE [%p] rects %i", cw->ec, cw->ec->shape_rects_num);
3858         for (i = 0; i < cw->ec->shape_rects_num; i++)
3859           {
3860              int rx, ry, rw, rh;
3861 
3862              rx = cw->ec->shape_rects[i].x; ry = cw->ec->shape_rects[i].y;
3863              rw = cw->ec->shape_rects[i].w; rh = cw->ec->shape_rects[i].h;
3864              E_RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, w, h);
3865              sp = spix + (w * ry) + rx;
3866              for (py = 0; py < rh; py++)
3867                {
3868                   for (px = 0; px < rw; px++)
3869                     {
3870                        *sp = 0xff; sp++;
3871                     }
3872                   sp += w - rw;
3873                }
3874           }
3875         sp = spix;
3876         for (py = 0; py < h; py++)
3877           {
3878              for (px = 0; px < w; px++)
3879                {
3880                   unsigned int mask, imask;
3881 
3882                   mask = ((unsigned int)(*sp)) << 24;
3883                   imask = mask >> 8;
3884                   imask |= imask >> 8;
3885                   imask |= imask >> 8;
3886                   *p = mask | (*p & imask);
3887                   //if (*sp) *p = 0xff000000 | *p;
3888                   //else *p = 0x00000000;
3889                   sp++;
3890                   p++;
3891                }
3892           }
3893         free(spix);
3894      }
3895    else
3896       {
3897          for (py = 0; py < h; py++)
3898            {
3899               for (px = 0; px < w; px++)
3900                 *p |= 0xff000000;
3901            }
3902       }
3903    evas_object_image_data_set(cw->obj, pix);
3904    _e_comp_object_alpha_set(cw);
3905    evas_object_image_data_update_add(cw->obj, 0, 0, w, h);
3906    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
3907      {
3908         evas_object_image_data_set(o, pix);
3909         evas_object_image_data_update_add(o, 0, 0, w, h);
3910         evas_object_image_alpha_set(o, 1);
3911      }
3912 // don't need to fix alpha chanel as blending
3913 // should be totally off here regardless of
3914 // alpha channel content
3915 }
3916 
3917 /* helper function to simplify toggling of redirection for display servers which support it */
3918 E_API void
e_comp_object_redirected_set(Evas_Object * obj,Eina_Bool set)3919 e_comp_object_redirected_set(Evas_Object *obj, Eina_Bool set)
3920 {
3921    API_ENTRY;
3922 
3923    set = !!set;
3924    if (cw->redirected == set) return;
3925    cw->redirected = set;
3926    if (set)
3927      {
3928         if (cw->updates_exist)
3929           e_comp_object_render_update_add(obj);
3930         else
3931           e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
3932         evas_object_smart_callback_call(obj, "redirected", NULL);
3933      }
3934    else
3935      {
3936         Eina_List *l;
3937         Evas_Object *o;
3938 
3939         if (cw->ec->pixmap)
3940           e_pixmap_clear(cw->ec->pixmap);
3941         if (cw->native)
3942           evas_object_image_native_surface_set(cw->obj, NULL);
3943         evas_object_image_size_set(cw->obj, 1, 1);
3944         evas_object_image_data_set(cw->obj, NULL);
3945         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
3946           {
3947              evas_object_image_size_set(o, 1, 1);
3948              evas_object_image_data_set(o, NULL);
3949              if (cw->native)
3950                evas_object_image_native_surface_set(o, NULL);
3951           }
3952         cw->native = 0;
3953         e_comp_object_render_update_del(obj);
3954         evas_object_smart_callback_call(obj, "unredirected", NULL);
3955      }
3956 }
3957 
3958 E_API void
e_comp_object_native_surface_set(Evas_Object * obj,Eina_Bool set)3959 e_comp_object_native_surface_set(Evas_Object *obj, Eina_Bool set)
3960 {
3961    Evas_Native_Surface ns;
3962    Eina_List *l;
3963    Evas_Object *o;
3964 
3965    API_ENTRY;
3966    EINA_SAFETY_ON_NULL_RETURN(cw->ec);
3967    if (cw->ec->input_only) return;
3968    set = !!set;
3969 
3970    if (set)
3971      {
3972         switch (e_comp->comp_type)
3973           {
3974            case E_PIXMAP_TYPE_X:
3975              /* native requires gl enabled, texture from pixmap enabled, and a non-shaped client */
3976              set = e_comp->gl &&
3977                    e_comp_config_get()->texture_from_pixmap &&
3978                    !cw->ec->shaped;
3979              break;
3980            case E_PIXMAP_TYPE_WL:
3981              set = !e_pixmap_is_pixels(cw->ec->pixmap);
3982              break;
3983            default:
3984              set = 0;
3985           }
3986         if (set)
3987           set = (!!cw->ns) || e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
3988      }
3989    if ((!set) && (!cw->native)) return;
3990 
3991    cw->native = set;
3992    evas_object_image_native_surface_set(cw->obj, set && (!cw->blanked) ? (cw->ns ?: &ns) : NULL);
3993    _e_comp_object_alpha_set(cw);
3994    EINA_LIST_FOREACH(cw->obj_mirror, l, o)
3995      {
3996         evas_object_image_native_surface_set(o, set ? (cw->ns ?: &ns) : NULL);
3997         evas_object_image_alpha_set(o, !!cw->ns ? 1 : cw->ec->argb);
3998      }
3999 }
4000 
4001 E_API void
e_comp_object_native_surface_override(Evas_Object * obj,Evas_Native_Surface * ns)4002 e_comp_object_native_surface_override(Evas_Object *obj, Evas_Native_Surface *ns)
4003 {
4004    API_ENTRY;
4005    if (cw->ec->input_only) return;
4006    E_FREE(cw->ns);
4007    if (ns)
4008      cw->ns = (void *)eina_memdup((unsigned char *)ns, sizeof(Evas_Native_Surface), 0);
4009    _e_comp_object_alpha_set(cw);
4010    if (cw->native)
4011      e_comp_object_native_surface_set(obj, cw->native);
4012    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4013 }
4014 
4015 E_API void
e_comp_object_blank(Evas_Object * obj,Eina_Bool set)4016 e_comp_object_blank(Evas_Object *obj, Eina_Bool set)
4017 {
4018    API_ENTRY;
4019 
4020    set = !!set;
4021 
4022    if (cw->blanked == set) return;
4023    cw->blanked = set;
4024    _e_comp_object_alpha_set(cw);
4025    if (set)
4026      {
4027         evas_object_image_native_surface_set(cw->obj, NULL);
4028         evas_object_image_data_set(cw->obj, NULL);
4029         return;
4030      }
4031    if (cw->native)
4032      e_comp_object_native_surface_set(obj, 1);
4033    e_comp_object_damage(obj, 0, 0, cw->w, cw->h);
4034 }
4035 
4036 /* mark an object as dirty and setup damages */
4037 E_API void
e_comp_object_dirty(Evas_Object * obj)4038 e_comp_object_dirty(Evas_Object *obj)
4039 {
4040    Eina_Iterator *it;
4041    Eina_Rectangle *rect;
4042    Eina_List *ll;
4043    Evas_Object *o;
4044    int w, h;
4045    Eina_Bool dirty, visible, alpha;
4046    int bx, by, bxx, byy;
4047 
4048    API_ENTRY;
4049    /* only actually dirty if pixmap is available */
4050    dirty = e_pixmap_size_get(cw->ec->pixmap, &w, &h);
4051    visible = cw->visible;
4052    if (!dirty) w = h = 1;
4053    evas_object_image_pixels_dirty_set(cw->obj, cw->blanked ? 0 : dirty);
4054    if (!dirty)
4055      evas_object_image_data_set(cw->obj, e_pixmap_image_data_get(cw->ec->pixmap));
4056    evas_object_image_size_set(cw->obj, w, h);
4057 
4058    RENDER_DEBUG("SIZE [%p]: %dx%d", cw->ec, w, h);
4059    if (cw->pending_updates)
4060      eina_tiler_area_size_set(cw->pending_updates, w, h);
4061 
4062    alpha = evas_object_image_alpha_get(cw->obj);
4063    EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4064      {
4065         //evas_object_image_border_set(o, bx, by, bxx, byy);
4066         //evas_object_image_border_center_fill_set(o, EVAS_BORDER_FILL_SOLID);
4067         if (!dirty)
4068           evas_object_image_data_set(o, NULL);
4069         evas_object_image_size_set(o, w, h);
4070         evas_object_image_pixels_dirty_set(o, dirty);
4071         evas_object_image_alpha_set(o, alpha);
4072         visible |= evas_object_visible_get(o);
4073      }
4074    if (!dirty)
4075      {
4076         if (!e_object_is_del(E_OBJECT(cw->ec)))
4077           ERR("ERROR FETCHING PIXMAP FOR %p", cw->ec);
4078         return;
4079      }
4080 
4081    e_pixmap_image_opaque_get(cw->ec->pixmap, &bx, &by, &bxx, &byy);
4082    if (bxx && byy)
4083      {
4084         bxx = w - (bx + bxx), byy = h - (by + byy);
4085         // XXX: FIXME: - keep at least ONE border > 0 to allow cutouts to work
4086         // evas doesn't have a good fix for this right now.... also
4087         // we still BLEND the center bit anyway as we dont switch to non
4088         // blend ... so ugh. evas issue tho.
4089         if (byy < 1) byy = 1;
4090         evas_object_image_border_set(cw->obj, bx, bxx, by, byy);
4091      }
4092    else
4093      {
4094         bx = by = bxx = byy = 0;
4095         evas_object_image_border_set(cw->obj, bx, bxx, by, byy);
4096         if (cw->client_inset.calc && (!cw->frame_object)) //CSD
4097           {
4098              bx = -cw->client_inset.l + 4, by = -cw->client_inset.t + 4;
4099              bxx = -cw->client_inset.r, byy = -cw->client_inset.b;
4100           }
4101      }
4102    if ((cw->border.bx != bx) || (cw->border.by != by) ||
4103        (cw->border.bxx != bxx) || (cw->border.byy != byy) ||
4104        (cw->border.w != w) || (cw->border.h != h))
4105    {
4106       Edje_Message_Int_Set *msg;
4107       Edje_Message_Int msg2;
4108       Eina_Bool id = (bx || by || bxx || byy);
4109 
4110       cw->border.bx = bx;
4111       cw->border.by = by;
4112       cw->border.bxx = bxx;
4113       cw->border.byy = byy;
4114       cw->border.w = w;
4115       cw->border.h = h;
4116       msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int) * 3));
4117       msg->count = 4;
4118       msg->val[0] = bx;
4119       msg->val[1] = by;
4120       msg->val[2] = bxx;
4121       msg->val[3] = byy;
4122       edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT_SET, 1, msg);
4123       msg2.val = id;
4124       edje_object_message_send(cw->shobj, EDJE_MESSAGE_INT, 0, &msg2);
4125    }
4126 
4127    e_comp_object_native_surface_set(obj, 1);
4128    it = eina_tiler_iterator_new(cw->updates);
4129    EINA_ITERATOR_FOREACH(it, rect)
4130      {
4131         RENDER_DEBUG("UPDATE ADD [%p]: %d %d %dx%d", cw->ec, rect->x, rect->y, rect->w, rect->h);
4132         evas_object_image_data_update_add(cw->obj, rect->x, rect->y, rect->w, rect->h);
4133         EINA_LIST_FOREACH(cw->obj_mirror, ll, o)
4134           evas_object_image_data_update_add(o, rect->x, rect->y, rect->w, rect->h);
4135         if (cw->pending_updates)
4136           eina_tiler_rect_add(cw->pending_updates, rect);
4137      }
4138    eina_iterator_free(it);
4139    if (cw->pending_updates)
4140      eina_tiler_clear(cw->updates);
4141    else
4142      {
4143         cw->pending_updates = cw->updates;
4144         cw->updates = eina_tiler_new(w, h);
4145         eina_tiler_tile_size_set(cw->updates, 1, 1);
4146      }
4147    cw->update_count = cw->updates_full = cw->updates_exist = 0;
4148    evas_object_smart_callback_call(obj, "dirty", NULL);
4149    if (cw->real_hid || cw->visible || (!visible) || (!cw->pending_updates) || cw->native) return;
4150    /* force render if main object is hidden but mirrors are visible */
4151    RENDER_DEBUG("FORCING RENDER %p", cw->ec);
4152    e_comp_object_render(obj);
4153 }
4154 
4155 E_API Eina_Bool
e_comp_object_render(Evas_Object * obj)4156 e_comp_object_render(Evas_Object *obj)
4157 {
4158    Eina_Iterator *it = NULL;
4159    Eina_Rectangle *r;
4160    Eina_List *l;
4161    Evas_Object *o;
4162    int stride, pw, ph;
4163    unsigned int *pix, *srcpix;
4164    Eina_Bool ret = EINA_FALSE;
4165 
4166    API_ENTRY EINA_FALSE;
4167 
4168    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE);
4169    if (cw->ec->input_only) return EINA_TRUE;
4170    e_comp_object_render_update_del(obj);
4171    if (!e_pixmap_size_get(cw->ec->pixmap, &pw, &ph)) return EINA_FALSE;
4172    //if (e_pixmap_type_get(cw->ec->pixmap) == E_PIXMAP_TYPE_WL)
4173      //INF("WL RENDER!");
4174 
4175    if (!cw->pending_updates)
4176      {
4177         WRN("RENDER [%p]: NO RECTS!", cw->ec);
4178         evas_object_image_data_set(cw->obj, NULL);
4179         EINA_LIST_FOREACH(cw->obj_mirror, l, o)
4180           evas_object_image_data_set(o, NULL);
4181         return EINA_FALSE;
4182      }
4183 
4184    evas_object_image_pixels_dirty_set(cw->obj, EINA_FALSE);
4185 
4186    RENDER_DEBUG("RENDER SIZE: %dx%d", pw, ph);
4187 
4188    if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
4189      {
4190         pix = e_pixmap_image_data_get(cw->ec->pixmap);
4191         ret = EINA_TRUE;
4192         goto end;
4193      }
4194 
4195    it = eina_tiler_iterator_new(cw->pending_updates);
4196    if (e_pixmap_image_is_argb(cw->ec->pixmap))
4197      {
4198         pix = e_pixmap_image_data_get(cw->ec->pixmap);
4199         EINA_ITERATOR_FOREACH(it, r)
4200           {
4201              E_RECTS_CLIP_TO_RECT(r->x, r->y, r->w, r->h, 0, 0, pw, ph);
4202              /* get pixmap data from rect region on display server into memory */
4203              ret = e_pixmap_image_draw(cw->ec->pixmap, r);
4204              if (!ret)
4205                {
4206                   WRN("UPDATE [%p]: %i %i %ix%i FAIL(%u)!!!!!!!!!!!!!!!!!", cw->ec, r->x, r->y, r->w, r->h, cw->failures);
4207                   if (++cw->failures < FAILURE_MAX)
4208                     e_comp_object_damage(obj, 0, 0, pw, ph);
4209                   else
4210                     {
4211                        DELD(cw->ec, 2);
4212                        e_object_del(E_OBJECT(cw->ec));
4213                        return EINA_FALSE;
4214                     }
4215                   break;
4216                }
4217              RENDER_DEBUG("UPDATE [%p] %i %i %ix%i", cw->ec, r->x, r->y, r->w, r->h);
4218           }
4219         if (!it) pix = NULL;
4220         goto end;
4221      }
4222 
4223    pix = evas_object_image_data_get(cw->obj, EINA_TRUE);
4224    stride = evas_object_image_stride_get(cw->obj);
4225    srcpix = e_pixmap_image_data_get(cw->ec->pixmap);
4226    EINA_ITERATOR_FOREACH(it, r)
4227      {
4228         E_RECTS_CLIP_TO_RECT(r->x, r->y, r->w, r->h, 0, 0, pw, ph);
4229         ret = e_pixmap_image_draw(cw->ec->pixmap, r);
4230         if (!ret)
4231           {
4232              WRN("UPDATE [%p]: %i %i %ix%i FAIL(%u)!!!!!!!!!!!!!!!!!", cw->ec, r->x, r->y, r->w, r->h, cw->failures);
4233              if (++cw->failures < FAILURE_MAX)
4234                e_comp_object_damage(obj, 0, 0, pw, ph);
4235              else
4236                {
4237                   DELD(cw->ec, 3);
4238                   e_object_del(E_OBJECT(cw->ec));
4239                   return EINA_FALSE;
4240                }
4241              break;
4242           }
4243         e_pixmap_image_data_argb_convert(cw->ec->pixmap, pix, srcpix, r, stride);
4244         RENDER_DEBUG("UPDATE [%p]: %d %d %dx%d -- pix = %p", cw->ec, r->x, r->y, r->w, r->h, pix);
4245      }
4246    if (!it) pix = NULL;
4247 end:
4248    eina_iterator_free(it);
4249    evas_object_image_data_set(cw->obj, cw->blanked ? NULL : pix);
4250    _e_comp_object_alpha_set(cw);
4251 
4252    E_FREE_FUNC(cw->pending_updates, eina_tiler_free);
4253    if (ret)
4254      e_comp_client_post_update_add(cw->ec);
4255    return ret;
4256 }
4257 
4258 E_API Evas_Object *
e_comp_object_agent_add(Evas_Object * obj)4259 e_comp_object_agent_add(Evas_Object *obj)
4260 {
4261    Evas_Object *o;
4262 
4263    API_ENTRY NULL;
4264 
4265    o = evas_object_rectangle_add(e_comp->evas);
4266    evas_object_color_set(o, 0, 0, 0, 0);
4267    evas_object_pass_events_set(o, 1);
4268    evas_object_geometry_set(o, cw->ec->x, cw->ec->y, cw->ec->w, cw->ec->h);
4269 
4270    cw->obj_agent = eina_list_append(cw->obj_agent, o);
4271    evas_object_event_callback_add(o, EVAS_CALLBACK_RESIZE, _e_comp_object_cb_agent_resize, cw);
4272    evas_object_event_callback_add(o, EVAS_CALLBACK_MOVE, _e_comp_object_cb_agent_move, cw);
4273    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_agent_del, cw);
4274    return o;
4275 }
4276 
4277 /* create a duplicate of an evas object */
4278 E_API Evas_Object *
e_comp_object_util_mirror_add(Evas_Object * obj)4279 e_comp_object_util_mirror_add(Evas_Object *obj)
4280 {
4281    Evas_Object *o;
4282    int w, h;
4283    unsigned int *pix = NULL;
4284 
4285    SOFT_ENTRY(NULL);
4286 
4287    if (!cw)
4288      cw = evas_object_data_get(obj, "comp_mirror");
4289    if (!cw)
4290      {
4291         o = evas_object_image_filled_add(evas_object_evas_get(obj));
4292         evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
4293         evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
4294         evas_object_image_alpha_set(o, 1);
4295         evas_object_image_source_set(o, obj);
4296         return o;
4297      }
4298    if ((!cw->ec) || (!e_pixmap_size_get(cw->ec->pixmap, &w, &h))) return NULL;
4299    o = evas_object_image_filled_add(evas_object_evas_get(obj));
4300    evas_object_image_colorspace_set(o, EVAS_COLORSPACE_ARGB8888);
4301    evas_object_image_smooth_scale_set(o, e_comp_config_get()->smooth_windows);
4302    cw->obj_mirror = eina_list_append(cw->obj_mirror, o);
4303    evas_object_event_callback_add(o, EVAS_CALLBACK_DEL, _e_comp_object_cb_mirror_del, cw);
4304    evas_object_event_callback_add(o, EVAS_CALLBACK_SHOW, _e_comp_object_cb_mirror_show, cw);
4305    evas_object_event_callback_add(o, EVAS_CALLBACK_HIDE, _e_comp_object_cb_mirror_hide, cw);
4306    evas_object_data_set(o, "E_Client", cw->ec);
4307    evas_object_data_set(o, "comp_mirror", cw);
4308 
4309    evas_object_image_size_set(o, w, h);
4310    evas_object_image_alpha_set(o, evas_object_image_alpha_get(cw->obj));
4311 
4312    if (cw->ec->shaped)
4313      {
4314         if (e_pixmap_image_data_get(cw->ec->pixmap))
4315           pix = evas_object_image_data_get(cw->obj, 0);
4316      }
4317    else
4318      {
4319         if (cw->native)
4320           {
4321              if (cw->ns)
4322                evas_object_image_native_surface_set(o, cw->ns);
4323              else
4324                {
4325                   Evas_Native_Surface ns;
4326 
4327                   e_pixmap_native_surface_init(cw->ec->pixmap, &ns);
4328                   evas_object_image_native_surface_set(o, &ns);
4329                }
4330           }
4331         else
4332           pix = e_pixmap_image_data_get(cw->ec->pixmap);
4333      }
4334    if (pix)
4335      {
4336       Eina_Bool dirty;
4337       //int bx, by, bxx, byy;
4338 
4339       dirty = evas_object_image_pixels_dirty_get(cw->obj);
4340       evas_object_image_pixels_dirty_set(o, dirty);
4341       //e_pixmap_image_opaque_get(cw->ec->pixmap, &bx, &by, &bxx, &byy);
4342       //if (bxx && byy)
4343         //bxx = cw->ec->client.w - (bx + bxx), byy = cw->ec->client.h - (by + byy);
4344       //else
4345         //bx = by = bxx = byy = 0;
4346       //evas_object_image_border_set(o, bx, by, bxx, byy);
4347       //evas_object_image_border_center_fill_set(o, EVAS_BORDER_FILL_SOLID);
4348       evas_object_image_data_set(o, pix);
4349       if (cw->ec->shaped)
4350         evas_object_image_data_set(cw->obj, pix);
4351       if (dirty)
4352         evas_object_image_data_update_add(o, 0, 0, w, h);
4353    }
4354    evas_object_image_pixels_get_callback_set(o, _e_comp_object_mirror_pixels_get, cw);
4355    return o;
4356 }
4357 
4358 //////////////////////////////////////////////////////
4359 
4360 E_API Eina_Bool
e_comp_object_effect_allowed_get(Evas_Object * obj)4361 e_comp_object_effect_allowed_get(Evas_Object *obj)
4362 {
4363    API_ENTRY EINA_FALSE;
4364 
4365    if (!cw->shobj) return EINA_FALSE;
4366    return EINA_TRUE;
4367 }
4368 
4369 /* setup an api effect for a client */
4370 E_API Eina_Bool
e_comp_object_effect_set(Evas_Object * obj,const char * effect)4371 e_comp_object_effect_set(Evas_Object *obj, const char *effect)
4372 {
4373    char buf[4096];
4374    Eina_Stringshare *grp;
4375 
4376    API_ENTRY EINA_FALSE;
4377    if (!cw->shobj) return EINA_FALSE; //input window
4378 
4379    if (!effect) effect = "none";
4380    snprintf(buf, sizeof(buf), "e/comp/effects/%s", effect);
4381    edje_object_file_get(cw->effect_obj, NULL, &grp);
4382    cw->effect_set = !eina_streq(effect, "none");
4383    if (!e_util_strcmp(buf, grp)) return cw->effect_set;
4384    if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
4385      {
4386         snprintf(buf, sizeof(buf), "e/comp/effects/auto/%s", effect);
4387         if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", buf))
4388           if (!e_theme_edje_object_set(cw->effect_obj, "base/theme/comp", "e/comp/effects/none"))
4389             {
4390                if (cw->effect_running)
4391                  {
4392                     if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
4393                       return EINA_FALSE;
4394                  }
4395                cw->effect_set = EINA_FALSE;
4396                return cw->effect_set;
4397             }
4398      }
4399    if (cw->effect_running)
4400      {
4401         if (!e_comp_object_effect_stop(obj, evas_object_data_get(cw->effect_obj, "_e_comp.end_cb")))
4402           return EINA_FALSE;
4403      }
4404    edje_object_part_swallow(cw->effect_obj, "e.swallow.content", cw->shobj);
4405    if (cw->effect_clip)
4406      {
4407         evas_object_clip_unset(cw->clip);
4408         cw->effect_clip = 0;
4409      }
4410    cw->effect_clip_able = !edje_object_data_get(cw->effect_obj, "noclip");
4411    return cw->effect_set;
4412 }
4413 
4414 /* set params for embryo scripts in effect */
4415 E_API void
e_comp_object_effect_params_set(Evas_Object * obj,int id,int * params,unsigned int count)4416 e_comp_object_effect_params_set(Evas_Object *obj, int id, int *params, unsigned int count)
4417 {
4418    Edje_Message_Int_Set *msg;
4419    unsigned int x;
4420 
4421    API_ENTRY;
4422    EINA_SAFETY_ON_NULL_RETURN(params);
4423    EINA_SAFETY_ON_FALSE_RETURN(count);
4424    if (!cw->effect_set) return;
4425 
4426    msg = alloca(sizeof(Edje_Message_Int_Set) + ((count - 1) * sizeof(int)));
4427    msg->count = (int)count;
4428    for (x = 0; x < count; x++)
4429       msg->val[x] = params[x];
4430    edje_object_message_send(cw->effect_obj, EDJE_MESSAGE_INT_SET, id, msg);
4431    edje_object_message_signal_process(cw->effect_obj);
4432 }
4433 
4434 static void
_e_comp_object_effect_end_cb(void * data,Evas_Object * obj,const char * emission,const char * source)4435 _e_comp_object_effect_end_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
4436 {
4437    Edje_Signal_Cb end_cb;
4438    void *end_data;
4439    E_Comp_Object *cw = data;
4440 
4441    edje_object_signal_callback_del_full(obj, "e,action,done", "e", _e_comp_object_effect_end_cb, NULL);
4442    cw->effect_running = 0;
4443    if (!_e_comp_object_animating_end(cw)) return;
4444    e_comp_shape_queue();
4445    end_cb = evas_object_data_get(obj, "_e_comp.end_cb");
4446    if (!end_cb) return;
4447    end_data = evas_object_data_get(obj, "_e_comp.end_data");
4448    end_cb(end_data, cw->smart_obj, emission, source);
4449 
4450 }
4451 
4452 /* clip effect to client's zone */
4453 E_API void
e_comp_object_effect_clip(Evas_Object * obj)4454 e_comp_object_effect_clip(Evas_Object *obj)
4455 {
4456    API_ENTRY;
4457    if (!cw->ec->zone) return;
4458    if (cw->effect_clip) e_comp_object_effect_unclip(cw->smart_obj);
4459    if (!cw->effect_clip_able) return;
4460    evas_object_clip_set(cw->smart_obj, cw->ec->zone->bg_clip_object);
4461    cw->effect_clip = 1;
4462 }
4463 
4464 /* unclip effect from client's zone */
4465 E_API void
e_comp_object_effect_unclip(Evas_Object * obj)4466 e_comp_object_effect_unclip(Evas_Object *obj)
4467 {
4468    API_ENTRY;
4469    if (!cw->effect_clip) return;
4470    evas_object_clip_unset(cw->smart_obj);
4471    cw->effect_clip = 0;
4472 }
4473 
4474 /* start effect, running end_cb after */
4475 E_API Eina_Bool
e_comp_object_effect_start(Evas_Object * obj,Edje_Signal_Cb end_cb,const void * end_data)4476 e_comp_object_effect_start(Evas_Object *obj, Edje_Signal_Cb end_cb, const void *end_data)
4477 {
4478    API_ENTRY EINA_FALSE;
4479    EINA_SAFETY_ON_NULL_RETURN_VAL(cw->ec, EINA_FALSE); //NYI
4480    if (!cw->effect_set) return EINA_FALSE;
4481    e_comp_object_effect_clip(obj);
4482    edje_object_signal_callback_del(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb);
4483 
4484    edje_object_signal_callback_add(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
4485    evas_object_data_set(cw->effect_obj, "_e_comp.end_cb", end_cb);
4486    evas_object_data_set(cw->effect_obj, "_e_comp.end_data", end_data);
4487 
4488    edje_object_signal_emit(cw->effect_obj, "e,action,go", "e");
4489    _e_comp_object_animating_begin(cw);
4490    cw->effect_running = 1;
4491    return EINA_TRUE;
4492 }
4493 
4494 /* stop a currently-running effect immediately */
4495 E_API Eina_Bool
e_comp_object_effect_stop(Evas_Object * obj,Edje_Signal_Cb end_cb)4496 e_comp_object_effect_stop(Evas_Object *obj, Edje_Signal_Cb end_cb)
4497 {
4498    API_ENTRY EINA_FALSE;
4499    if (evas_object_data_get(cw->effect_obj, "_e_comp.end_cb") != end_cb) return EINA_TRUE;
4500    e_comp_object_effect_unclip(obj);
4501    if (cw->effect_clip)
4502      {
4503         evas_object_clip_unset(cw->effect_obj);
4504         cw->effect_clip = 0;
4505      }
4506    edje_object_signal_emit(cw->effect_obj, "e,action,stop", "e");
4507    edje_object_signal_callback_del_full(cw->effect_obj, "e,action,done", "e", _e_comp_object_effect_end_cb, cw);
4508    cw->effect_running = 0;
4509    return _e_comp_object_animating_end(cw);
4510 }
4511 
4512 static int
_e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover * a,E_Comp_Object_Mover * b)4513 _e_comp_object_effect_mover_sort_cb(E_Comp_Object_Mover *a, E_Comp_Object_Mover *b)
4514 {
4515    return a->pri - b->pri;
4516 }
4517 
4518 /* add a function to trigger based on signal emissions for the purpose of modifying effects */
4519 E_API E_Comp_Object_Mover *
e_comp_object_effect_mover_add(int pri,const char * sig,E_Comp_Object_Mover_Cb provider,const void * data)4520 e_comp_object_effect_mover_add(int pri, const char *sig, E_Comp_Object_Mover_Cb provider, const void *data)
4521 {
4522    E_Comp_Object_Mover *prov;
4523 
4524    prov = E_NEW(E_Comp_Object_Mover, 1);
4525    EINA_SAFETY_ON_NULL_RETURN_VAL(prov, NULL);
4526    prov->func = provider;
4527    prov->data = (void*)data;
4528    prov->pri = pri;
4529    prov->sig = sig;
4530    _e_comp_object_movers = eina_inlist_sorted_insert(_e_comp_object_movers, EINA_INLIST_GET(prov),
4531      (Eina_Compare_Cb)_e_comp_object_effect_mover_sort_cb);
4532    return prov;
4533 }
4534 
4535 E_API void
e_comp_object_effect_mover_del(E_Comp_Object_Mover * prov)4536 e_comp_object_effect_mover_del(E_Comp_Object_Mover *prov)
4537 {
4538    EINA_SAFETY_ON_NULL_RETURN(prov);
4539    _e_comp_object_movers = eina_inlist_remove(_e_comp_object_movers, EINA_INLIST_GET(prov));
4540    free(prov);
4541 }
4542 ////////////////////////////////////
4543 
4544 static void
_e_comp_object_autoclose_cleanup(Eina_Bool already_del)4545 _e_comp_object_autoclose_cleanup(Eina_Bool already_del)
4546 {
4547    if (e_comp->autoclose.obj)
4548      {
4549         e_comp_ungrab_input(0, 1);
4550         if (e_comp->autoclose.del_cb)
4551           e_comp->autoclose.del_cb(e_comp->autoclose.data, e_comp->autoclose.obj);
4552         else if (!already_del)
4553           {
4554              evas_object_hide(e_comp->autoclose.obj);
4555              E_FREE_FUNC(e_comp->autoclose.obj, evas_object_del);
4556           }
4557         E_FREE_FUNC(e_comp->autoclose.rect, evas_object_del);
4558      }
4559    e_comp->autoclose.obj = NULL;
4560    e_comp->autoclose.data = NULL;
4561    e_comp->autoclose.del_cb = NULL;
4562    e_comp->autoclose.key_cb = NULL;
4563    E_FREE_FUNC(e_comp->autoclose.key_handler, ecore_event_handler_del);
4564    e_comp_shape_queue();
4565 }
4566 
4567 static Eina_Bool
_e_comp_object_autoclose_key_down_cb(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)4568 _e_comp_object_autoclose_key_down_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
4569 {
4570    Ecore_Event_Key *ev = event;
4571    Eina_Bool del = EINA_TRUE;
4572 
4573    /* returning false in key_cb means delete the object */
4574    if (e_comp->autoclose.key_cb)
4575      del = !e_comp->autoclose.key_cb(e_comp->autoclose.data, ev);
4576    if (del) _e_comp_object_autoclose_cleanup(0);
4577    return ECORE_CALLBACK_DONE;
4578 }
4579 
4580 static void
_e_comp_object_autoclose_mouse_up_cb(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)4581 _e_comp_object_autoclose_mouse_up_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
4582 {
4583    _e_comp_object_autoclose_cleanup(0);
4584 }
4585 
4586 static void
_e_comp_object_autoclose_setup(Evas_Object * obj)4587 _e_comp_object_autoclose_setup(Evas_Object *obj)
4588 {
4589    if (!e_comp->autoclose.rect)
4590      {
4591         /* create rect just below autoclose object to catch mouse events */
4592         e_comp->autoclose.rect = evas_object_rectangle_add(e_comp->evas);
4593         evas_object_move(e_comp->autoclose.rect, 0, 0);
4594         evas_object_resize(e_comp->autoclose.rect, e_comp->w, e_comp->h);
4595         evas_object_show(e_comp->autoclose.rect);
4596         evas_object_name_set(e_comp->autoclose.rect, "e_comp->autoclose.rect");
4597         evas_object_color_set(e_comp->autoclose.rect, 0, 0, 0, 0);
4598         evas_object_event_callback_add(e_comp->autoclose.rect, EVAS_CALLBACK_MOUSE_UP, _e_comp_object_autoclose_mouse_up_cb, e_comp);
4599         e_comp_grab_input(0, 1);
4600      }
4601    evas_object_layer_set(e_comp->autoclose.rect, evas_object_layer_get(obj) - 1);
4602    evas_object_focus_set(obj, 1);
4603    e_comp_shape_queue();
4604    if (!e_comp->autoclose.key_handler)
4605      e_comp->autoclose.key_handler = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_comp_object_autoclose_key_down_cb, e_comp);
4606 }
4607 
4608 static void
_e_comp_object_autoclose_show(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)4609 _e_comp_object_autoclose_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
4610 {
4611    _e_comp_object_autoclose_setup(obj);
4612    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
4613 }
4614 
4615 static void
_e_comp_object_autoclose_del(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)4616 _e_comp_object_autoclose_del(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
4617 {
4618    evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show);
4619    _e_comp_object_autoclose_cleanup(1);
4620    if (e_client_focused_get()) return;
4621    if (e_config->focus_policy != E_FOCUS_MOUSE)
4622      e_client_refocus();
4623 }
4624 
4625 
4626 E_API Eina_Bool
e_comp_object_util_autoclose_on_escape(void * d EINA_UNUSED,Ecore_Event_Key * ev)4627 e_comp_object_util_autoclose_on_escape(void *d EINA_UNUSED, Ecore_Event_Key *ev)
4628 {
4629    return !!strcmp(ev->key, "Escape");
4630 }
4631 
4632 E_API void
e_comp_object_util_autoclose(Evas_Object * obj,E_Comp_Object_Autoclose_Cb del_cb,E_Comp_Object_Key_Cb cb,const void * data)4633 e_comp_object_util_autoclose(Evas_Object *obj, E_Comp_Object_Autoclose_Cb del_cb, E_Comp_Object_Key_Cb cb, const void *data)
4634 {
4635    if (e_comp->autoclose.obj)
4636      {
4637         if (e_comp->autoclose.obj == obj) return;
4638         evas_object_event_callback_del_full(e_comp->autoclose.obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
4639         _e_comp_object_autoclose_cleanup(0);
4640      }
4641    if (!obj) return;
4642    e_comp->autoclose.obj = obj;
4643    e_comp->autoclose.del_cb = del_cb;
4644    e_comp->autoclose.key_cb = cb;
4645    e_comp->autoclose.data = (void*)data;
4646    if (evas_object_visible_get(obj))
4647      _e_comp_object_autoclose_setup(obj);
4648    else
4649      evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _e_comp_object_autoclose_show, e_comp);
4650    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _e_comp_object_autoclose_del, e_comp);
4651 }
4652 
4653 E_API Evas_Object *
e_comp_object_frame_icon_get(Evas_Object * obj)4654 e_comp_object_frame_icon_get(Evas_Object *obj)
4655 {
4656    API_ENTRY NULL;
4657    return cw->frame_icon;
4658 }
4659 
4660 E_API Evas_Object *
e_comp_object_frame_volume_get(Evas_Object * obj)4661 e_comp_object_frame_volume_get(Evas_Object *obj)
4662 {
4663    API_ENTRY NULL;
4664    return cw->frame_volume;
4665 }
4666