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