3 static int _e_client_hooks_delete = 0;
4 static int _e_client_hooks_walking = 0;
6 static int _e_client_intercept_hooks_delete = 0;
7 static int _e_client_intercept_hooks_walking = 0;
9 E_API int E_EVENT_CLIENT_ADD = -1;
10 E_API int E_EVENT_CLIENT_REMOVE = -1;
11 E_API int E_EVENT_CLIENT_ZONE_SET = -1;
12 E_API int E_EVENT_CLIENT_DESK_SET = -1;
13 E_API int E_EVENT_CLIENT_RESIZE = -1;
14 E_API int E_EVENT_CLIENT_MOVE = -1;
15 E_API int E_EVENT_CLIENT_SHOW = -1;
16 E_API int E_EVENT_CLIENT_HIDE = -1;
17 E_API int E_EVENT_CLIENT_ICONIFY = -1;
18 E_API int E_EVENT_CLIENT_UNICONIFY = -1;
19 E_API int E_EVENT_CLIENT_STACK = -1;
20 E_API int E_EVENT_CLIENT_FOCUS_IN = -1;
21 E_API int E_EVENT_CLIENT_FOCUS_OUT = -1;
22 E_API int E_EVENT_CLIENT_PROPERTY = -1;
23 E_API int E_EVENT_CLIENT_FULLSCREEN = -1;
24 E_API int E_EVENT_CLIENT_UNFULLSCREEN = -1;
25 #ifdef _F_ZONE_WINDOW_ROTATION_
26 E_API int E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN = -1;
27 E_API int E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL = -1;
28 E_API int E_EVENT_CLIENT_ROTATION_CHANGE_END = -1;
29 E_API int E_EVENT_CLIENT_ROTATION_GEOMETRY_SET = -1;
31 E_API int E_EVENT_CLIENT_VISIBILITY_CHANGE = -1;
32 E_API int E_EVENT_CLIENT_BUFFER_CHANGE = -1;
33 E_API int E_EVENT_CLIENT_FOCUS_SKIP_SET = -1;
34 E_API int E_EVENT_CLIENT_FOCUS_SKIP_UNSET = -1;
36 static Eina_Hash *clients_hash[E_PIXMAP_TYPE_MAX] = {NULL}; // pixmap->client
38 static unsigned int focus_track_frozen = 0;
40 static int warp_to = 0;
41 static int warp_to_x = 0;
42 static int warp_to_y = 0;
43 static int warp_x[2] = {0}; //{cur,prev}
44 static int warp_y[2] = {0}; //{cur,prev}
45 static Ecore_Timer *warp_timer = NULL;
47 static E_Client *focused = NULL;
48 static E_Client *warp_client = NULL;
49 static E_Client *ecmove = NULL;
50 static E_Client *ecresize = NULL;
51 static E_Client *action_client = NULL;
52 static E_Drag *client_drag = NULL;
54 static Eina_List *focus_stack = NULL;
55 static Eina_List *defer_focus_stack = NULL;
57 static Eina_Bool comp_grabbed = EINA_FALSE;
59 static Eina_List *handlers = NULL;
60 static Eina_List *hooks = NULL;
62 static Ecore_Event_Handler *action_handler_mouse = NULL;
63 static Ecore_Timer *action_timer = NULL;
64 static Eina_Rectangle action_orig = {0, 0, 0, 0};
66 static E_Client_Layout_Cb _e_client_layout_cb = NULL;
67 static E_Client_Resize_Object_Create_Cb _e_client_resize_object_create_cb = NULL;
69 static Eina_Bool _e_calc_visibility = EINA_FALSE;
70 static Eina_Bool _e_visibility_changed = EINA_FALSE;
72 EINTERN void e_client_focused_set(E_Client *ec);
73 static void _e_client_transient_for_group_make(E_Client *ec, Eina_List **list);
74 static Evas_Object *_e_client_resize_object_create(E_Client *ec);
75 static void _e_client_resize_object_del(E_Client *ec);
76 static void _e_client_stay_within_canvas(E_Client *ec, int x, int y, int *new_x, int *new_y);
77 static void _e_client_stay_within_canvas_margin(E_Client *ec, int x, int y, int *new_x, int *new_y);
79 static Eina_Inlist *_e_client_hooks[] =
81 [E_CLIENT_HOOK_EVAL_PRE_FETCH] = NULL,
82 [E_CLIENT_HOOK_EVAL_FETCH] = NULL,
83 [E_CLIENT_HOOK_EVAL_PRE_POST_FETCH] = NULL,
84 [E_CLIENT_HOOK_EVAL_POST_FETCH] = NULL,
85 [E_CLIENT_HOOK_EVAL_PRE_FRAME_ASSIGN] = NULL,
86 [E_CLIENT_HOOK_EVAL_POST_FRAME_ASSIGN] = NULL,
87 [E_CLIENT_HOOK_EVAL_PRE_NEW_CLIENT] = NULL,
88 [E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT] = NULL,
89 [E_CLIENT_HOOK_EVAL_END] = NULL,
90 [E_CLIENT_HOOK_FOCUS_SET] = NULL,
91 [E_CLIENT_HOOK_FOCUS_UNSET] = NULL,
92 [E_CLIENT_HOOK_NEW_CLIENT] = NULL,
93 [E_CLIENT_HOOK_DESK_SET] = NULL,
94 [E_CLIENT_HOOK_MOVE_BEGIN] = NULL,
95 [E_CLIENT_HOOK_MOVE_UPDATE] = NULL,
96 [E_CLIENT_HOOK_MOVE_END] = NULL,
97 [E_CLIENT_HOOK_RESIZE_BEGIN] = NULL,
98 [E_CLIENT_HOOK_RESIZE_UPDATE] = NULL,
99 [E_CLIENT_HOOK_RESIZE_END] = NULL,
100 [E_CLIENT_HOOK_FULLSCREEN_PRE] = NULL,
101 [E_CLIENT_HOOK_DEL] = NULL,
102 [E_CLIENT_HOOK_UNREDIRECT] = NULL,
103 [E_CLIENT_HOOK_REDIRECT] = NULL,
104 #ifdef _F_E_CLIENT_NEW_CLIENT_POST_HOOK_
105 [E_CLIENT_HOOK_NEW_CLIENT_POST] = NULL,
107 [E_CLIENT_HOOK_EVAL_VISIBILITY] = NULL,
108 [E_CLIENT_HOOK_ICONIFY] = NULL,
109 [E_CLIENT_HOOK_UNICONIFY] = NULL,
110 [E_CLIENT_HOOK_AUX_HINT_CHANGE] = NULL,
111 [E_CLIENT_HOOK_WINDOW_ROLE_CHANGE] = NULL,
112 [E_CLIENT_HOOK_CAL_VISIBILITY_DISPLAY_OFF] = NULL,
113 [E_CLIENT_HOOK_TRANSFORM_CHANGE] = NULL,
114 [E_CLIENT_HOOK_ACTIVATE_DONE] = NULL,
115 [E_CLIENT_HOOK_EVAL_VISIBILITY_END] = NULL,
118 static Eina_Inlist *_e_client_intercept_hooks[] =
120 [E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT] = NULL,
121 [E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT] = NULL,
124 ///////////////////////////////////////////
127 _e_client_cb_desk_window_profile_change(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Desk_Window_Profile_Change *ev EINA_UNUSED)
132 EINA_LIST_FOREACH(e_comp->clients, l, ec)
134 if (e_object_is_del(E_OBJECT(ec))) continue;
135 ec->e.fetch.profile = 1;
138 return ECORE_CALLBACK_RENEW;
142 _e_client_cb_drag_finished(E_Drag *drag, int dropped EINA_UNUSED)
148 e_object_unref(E_OBJECT(ec));
153 _e_client_desk_window_profile_wait_desk_delfn(void *data, void *obj)
156 E_Desk *desk = obj, *new_desk;
160 if (e_object_is_del(E_OBJECT(ec))) return;
162 ec->e.state.profile.wait_desk_delfn = NULL;
163 eina_stringshare_replace(&ec->e.state.profile.wait, NULL);
164 if (ec->e.state.profile.wait_desk)
165 e_object_unref(E_OBJECT(ec->e.state.profile.wait_desk));
166 ec->e.state.profile.wait_desk = NULL;
167 ec->e.state.profile.wait_for_done = 0;
169 if (!ec->e.state.profile.use) return;
171 new_desk = e_comp_desk_window_profile_get(desk->window_profile);
173 e_client_desk_set(ec, new_desk);
176 for (i = 0; i < ec->e.state.profile.num; i++)
178 p = ec->e.state.profile.available_list[i];
179 new_desk = e_comp_desk_window_profile_get(p);
182 e_client_desk_set(ec, new_desk);
188 ////////////////////////////////////////////////
192 _e_client_pointer_warp_to_center_timer(void *data EINA_UNUSED)
194 if (warp_to && warp_client)
199 e_input_device_pointer_xy_get(NULL, &x, &y);
200 /* move hasn't happened yet */
201 if ((x == warp_x[1]) && (y == warp_y[1]))
203 if ((abs(x - warp_x[0]) > 5) || (abs(y - warp_y[0]) > 5))
205 /* User moved the mouse, so stop warping */
211 warp_x[1] = x = warp_x[0];
212 warp_y[1] = y = warp_y[0];
213 warp_x[0] = (x * (1.0 - spd)) + (warp_to_x * spd);
214 warp_y[0] = (y * (1.0 - spd)) + (warp_to_y * spd);
215 if ((warp_x[0] == x) && (warp_y[0] == y))
217 warp_x[0] = warp_to_x;
218 warp_y[0] = warp_to_y;
222 e_input_device_pointer_warp(NULL, warp_x[0], warp_y[0]);
223 return ECORE_CALLBACK_RENEW;
226 E_FREE_FUNC(warp_timer, ecore_timer_del);
229 warp_x[0] = warp_x[1] = warp_y[0] = warp_y[1] = -1;
230 e_focus_event_mouse_in(warp_client);
231 if (warp_client->iconic)
233 if (!warp_client->lock_user_iconify)
234 e_client_uniconify(warp_client);
236 if (warp_client->shaded)
238 if (!warp_client->lock_user_shade)
239 e_client_unshade(warp_client, warp_client->shade_dir);
242 if (!warp_client->lock_focus_out)
244 if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
246 ELOGF("FOCUS", "focus set | pointer_warp_to_center", warp_client);
247 e_client_frame_focus_set(warp_client, EINA_TRUE);
248 e_client_focus_latest_set(warp_client);
253 return ECORE_CALLBACK_CANCEL;
256 ////////////////////////////////////////////////
259 _e_client_hooks_clean(void)
265 for (x = 0; x < E_CLIENT_HOOK_LAST; x++)
266 EINA_INLIST_FOREACH_SAFE(_e_client_hooks[x], l, ch)
268 if (!ch->delete_me) continue;
269 _e_client_hooks[x] = eina_inlist_remove(_e_client_hooks[x], EINA_INLIST_GET(ch));
275 _e_client_hook_call(E_Client_Hook_Point hookpoint, E_Client *ec)
279 e_object_ref(E_OBJECT(ec));
280 _e_client_hooks_walking++;
281 EINA_INLIST_FOREACH(_e_client_hooks[hookpoint], ch)
283 if (ch->delete_me) continue;
284 ch->func(ch->data, ec);
285 if ((hookpoint != E_CLIENT_HOOK_DEL) &&
286 (hookpoint != E_CLIENT_HOOK_MOVE_END) &&
287 (hookpoint != E_CLIENT_HOOK_RESIZE_END) &&
288 (hookpoint != E_CLIENT_HOOK_FOCUS_UNSET) &&
289 e_object_is_del(E_OBJECT(ec)))
292 _e_client_hooks_walking--;
293 if ((_e_client_hooks_walking == 0) && (_e_client_hooks_delete > 0))
294 _e_client_hooks_clean();
295 return !!e_object_unref(E_OBJECT(ec));
298 ///////////////////////////////////////////
301 _e_client_intercept_hooks_clean(void)
304 E_Client_Intercept_Hook *ch;
307 for (x = 0; x < E_CLIENT_INTERCEPT_HOOK_LAST; x++)
308 EINA_INLIST_FOREACH_SAFE(_e_client_intercept_hooks[x], l, ch)
310 if (!ch->delete_me) continue;
311 _e_client_intercept_hooks[x] =
312 eina_inlist_remove(_e_client_intercept_hooks[x], EINA_INLIST_GET(ch));
318 _e_client_intercept_hook_call(E_Client_Intercept_Hook_Point hookpoint, E_Client *ec)
320 E_Client_Intercept_Hook *ch;
321 Eina_Bool ret = EINA_TRUE;
323 if (e_object_is_del(E_OBJECT(ec)))
325 if (hookpoint != E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT)
331 e_object_ref(E_OBJECT(ec));
332 _e_client_intercept_hooks_walking++;
333 EINA_INLIST_FOREACH(_e_client_intercept_hooks[hookpoint], ch)
335 if (ch->delete_me) continue;
336 if (!(ch->func(ch->data, ec)))
342 _e_client_intercept_hooks_walking--;
343 if ((_e_client_intercept_hooks_walking == 0) &&
344 (_e_client_intercept_hooks_delete > 0))
345 _e_client_intercept_hooks_clean();
347 e_object_unref(E_OBJECT(ec));
352 _e_client_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
355 e_object_unref(E_OBJECT(ev->ec));
360 _e_client_event_simple(E_Client *ec, int type)
364 ev = E_NEW(E_Event_Client, 1);
368 e_object_ref(E_OBJECT(ec));
369 ecore_event_add(type, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
373 _e_client_event_add(E_Client *ec)
378 ec->reg_ev.add = EINA_TRUE;
379 ELOGF("COMP", "SEND E_EVENT_CLIENT_ADD event", ec);
380 _e_client_event_simple(ec, E_EVENT_CLIENT_ADD);
384 _e_client_event_remove(E_Client *ec)
389 ec->reg_ev.add = EINA_FALSE;
390 ELOGF("COMP", "SEND E_EVENT_CLIENT_REMOVE event", ec);
391 _e_client_event_simple(ec, E_EVENT_CLIENT_REMOVE);
395 _e_client_event_show(E_Client *ec)
400 ec->reg_ev.show = EINA_TRUE;
401 _e_client_event_simple(ec, E_EVENT_CLIENT_SHOW);
405 _e_client_event_hide(E_Client *ec)
407 if (!ec->reg_ev.show)
410 ec->reg_ev.show = EINA_FALSE;
411 _e_client_event_simple(ec, E_EVENT_CLIENT_HIDE);
415 _e_client_event_property(E_Client *ec, int prop)
417 E_Event_Client_Property *ev;
419 ev = E_NEW(E_Event_Client_Property, 1);
424 e_object_ref(E_OBJECT(ec));
425 ecore_event_add(E_EVENT_CLIENT_PROPERTY, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
429 _e_client_event_desk_set_free(void *d EINA_UNUSED, E_Event_Client_Desk_Set *ev)
432 e_object_unref(E_OBJECT(ev->ec));
433 e_object_unref(E_OBJECT(ev->desk));
438 _e_client_event_zone_set_free(void *d EINA_UNUSED, E_Event_Client_Zone_Set *ev)
441 e_object_unref(E_OBJECT(ev->ec));
442 e_object_unref(E_OBJECT(ev->zone));
445 ////////////////////////////////////////////////
448 _e_client_action_input_win_del(void)
450 if (!comp_grabbed) return 0;
452 e_comp_ungrab_input(1, 1);
458 _e_client_action_finish(void)
461 _e_client_action_input_win_del();
463 E_FREE_FUNC(action_timer, ecore_timer_del);
464 E_FREE_FUNC(action_handler_mouse, ecore_event_handler_del);
467 action_client->keyboard_resizing = 0;
469 action_client = NULL;
473 _e_client_transform_point_transform(int cx, int cy, double angle, int x, int y, int *tx, int *ty)
475 double s = sin(angle * M_PI / 180);
476 double c = cos(angle * M_PI / 180);
483 ry = - x * s + y * c;
493 _e_client_transform_geometry_save(E_Client *ec, E_Map *map)
499 for (i = 0; i < 4; i ++)
501 e_map_point_precise_coord_get(map, i,
502 &ec->transform.saved[i].x,
503 &ec->transform.saved[i].y,
504 &ec->transform.saved[i].z);
509 _e_client_transform_resize(E_Client *ec)
513 double dx = 0, dy = 0;
518 if (!ec->transformed) return;
520 if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
526 cx = ec->client.x + pw / 2;
527 cy = ec->client.y + ph / 2;
529 /* step 1: Rotate resized object and get map points */
530 map = e_map_new_with_direct_render(ec->transform_core.direct_render);
531 e_map_util_points_populate_from_geometry(map,
532 ec->client.x, ec->client.y,
535 e_map_util_rotate(map, ec->transform.angle, cx, cy);
536 e_map_util_zoom(map, ec->transform.zoom, ec->transform.zoom, cx, cy);
538 for (i = 0; i < 4; i++)
539 e_map_point_precise_coord_get(map, i, &px[i], &py[i], NULL);
543 /* step 2: get adjusted values to keep up fixed position according
545 switch (ec->resize_mode)
547 case E_POINTER_RESIZE_R:
548 case E_POINTER_RESIZE_BR:
549 dx = ec->transform.saved[0].x - px[0];
550 dy = ec->transform.saved[0].y - py[0];
552 case E_POINTER_RESIZE_BL:
553 case E_POINTER_RESIZE_B:
554 dx = ec->transform.saved[1].x - px[1];
555 dy = ec->transform.saved[1].y - py[1];
557 case E_POINTER_RESIZE_TL:
558 case E_POINTER_RESIZE_L:
559 dx = ec->transform.saved[2].x - px[2];
560 dy = ec->transform.saved[2].y - py[2];
562 case E_POINTER_RESIZE_T:
563 case E_POINTER_RESIZE_TR:
564 dx = ec->transform.saved[3].x - px[3];
565 dy = ec->transform.saved[3].y - py[3];
571 ec->transform.adjusted.x = dx;
572 ec->transform.adjusted.y = dy;
574 /* step 3: set each points of the quadrangle */
575 map = e_map_new_with_direct_render(ec->transform_core.direct_render);
576 e_map_util_points_populate_from_object_full(map, ec->frame, 0);
578 for (i = 0; i < 4; i++)
579 e_map_point_precise_coord_set(map, i, px[i] + dx, py[i] + dy, 0);
581 e_client_map_set(ec, map);
582 e_client_map_enable_set(ec, EINA_TRUE);
587 _e_client_transform_resize_handle(E_Client *ec)
590 int new_x, new_y, new_w, new_h;
594 Evas_Point current, moveinfo;
596 if (e_object_is_del(E_OBJECT(ec))) return;
597 if (e_client_util_ignored_get(ec)) return;
598 if (!ec->transformed) return;
600 button_id = ec->moveinfo.down.button;
602 org_w = ec->mouse.last_down[button_id - 1].w;
603 org_h = ec->mouse.last_down[button_id - 1].h;
605 new_w = ec->client.w;
606 new_h = ec->client.h;
607 new_x = ec->client.x;
608 new_y = ec->client.y;
610 /* step 1: get center coordinate its' based on original object geometry*/
611 cx = ec->client.x + org_w / 2;
612 cy = ec->client.y + org_h / 2;
614 /* step 2: transform coordinates of mouse position
615 * subtract adjusted value from mouse position is needed */
616 current.x = ec->mouse.current.mx - ec->transform.adjusted.x;
617 current.y = ec->mouse.current.my - ec->transform.adjusted.y;
618 moveinfo.x = ec->moveinfo.down.mx - ec->transform.adjusted.x;
619 moveinfo.y = ec->moveinfo.down.my - ec->transform.adjusted.y;
621 _e_client_transform_point_transform(cx, cy, ec->transform.angle,
622 current.x, current.y,
623 ¤t.x, ¤t.y);
624 _e_client_transform_point_transform(cx, cy, ec->transform.angle,
625 moveinfo.x, moveinfo.y,
626 &moveinfo.x, &moveinfo.y);
628 /* step 3: calculate new size */
629 if ((ec->resize_mode == E_POINTER_RESIZE_TR) ||
630 (ec->resize_mode == E_POINTER_RESIZE_R) ||
631 (ec->resize_mode == E_POINTER_RESIZE_BR))
633 if ((button_id >= 1) && (button_id <= 3))
634 new_w = org_w + (current.x - moveinfo.x);
636 new_w = ec->moveinfo.down.w + (current.x - moveinfo.x);
638 else if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
639 (ec->resize_mode == E_POINTER_RESIZE_L) ||
640 (ec->resize_mode == E_POINTER_RESIZE_BL))
642 if ((button_id >= 1) && (button_id <= 3))
643 new_w = org_w - (current.x - moveinfo.x);
645 new_w = ec->moveinfo.down.w - (current.x - moveinfo.x);
648 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
649 (ec->resize_mode == E_POINTER_RESIZE_T) ||
650 (ec->resize_mode == E_POINTER_RESIZE_TR))
652 if ((button_id >= 1) && (button_id <= 3))
653 new_h = org_h - (current.y - moveinfo.y);
655 new_h = ec->moveinfo.down.h - (current.y - moveinfo.y);
657 else if ((ec->resize_mode == E_POINTER_RESIZE_BL) ||
658 (ec->resize_mode == E_POINTER_RESIZE_B) ||
659 (ec->resize_mode == E_POINTER_RESIZE_BR))
661 if ((button_id >= 1) && (button_id <= 3))
662 new_h = org_h + (current.y - moveinfo.y);
664 new_h = ec->moveinfo.down.h + (current.y - moveinfo.y);
667 new_w = MIN(new_w, ec->zone->w);
668 new_h = MIN(new_h, ec->zone->h);
670 /* step 4: move to new position */
671 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
672 (ec->resize_mode == E_POINTER_RESIZE_L) ||
673 (ec->resize_mode == E_POINTER_RESIZE_BL))
674 new_x += (new_w - org_w);
675 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
676 (ec->resize_mode == E_POINTER_RESIZE_T) ||
677 (ec->resize_mode == E_POINTER_RESIZE_TR))
678 new_y += (new_h - org_h);
680 /* step 5: set geometry to new value */
681 evas_object_geometry_set(ec->frame, new_x, new_y, new_w, new_h);
685 _e_client_transform_resize_begin(E_Client *ec)
688 if (!ec->transformed) return;
690 map = e_client_map_get(ec);
691 _e_client_transform_geometry_save(ec, map);
696 _e_client_transform_resize_end(E_Client *ec)
699 int new_x = 0, new_y = 0;
702 if (!ec->transformed) return;
704 map = e_client_map_get(ec);
707 if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
713 cx = ec->client.x + pw / 2 + ec->transform.adjusted.x;
714 cy = ec->client.y + ph / 2 + ec->transform.adjusted.y;
716 if (ec->transform.zoom != 1.0)
720 tmp_map = e_map_dup(map);
721 e_map_util_zoom(tmp_map,
722 1 / ec->transform.zoom,
723 1 / ec->transform.zoom,
726 _e_client_transform_geometry_save(ec, tmp_map);
731 _e_client_transform_geometry_save(ec, map);
734 /* move original object to adjusted position after resizing */
735 _e_client_transform_point_transform(cx, cy,
737 ec->transform.saved[0].x,
738 ec->transform.saved[0].y,
740 e_client_util_move_without_frame(ec, new_x, new_y);
741 e_map_util_object_move_sync_set(map, EINA_TRUE);
746 _e_client_transform_move_end(E_Client *ec)
750 double dx, dy, px, py;
753 if (!ec->transformed) return;
755 map = e_client_map_get(ec);
758 if (ec->transform.zoom != 1.0)
760 e_map_point_precise_coord_get(map, 0, &px, &py, NULL);
762 dx = px - ec->transform.saved[0].x;
763 dy = py - ec->transform.saved[0].y;
765 for (i = 0; i < 4; i++)
767 ec->transform.saved[i].x += dx;
768 ec->transform.saved[i].y += dy;
772 _e_client_transform_geometry_save(ec, map);
777 _e_client_check_fully_contain_by_above(E_Client *ec, Eina_Bool check_layer)
779 E_Client *above = NULL;
781 int x = 0, y = 0, w = 0, h = 0;
782 int ax = 0, ay = 0, aw = 0, ah = 0;
784 if (!ec) return NULL;
786 e_client_geometry_get(ec, &x, &y, &w, &h);
791 E_RECTS_CLIP_TO_RECT(x, y, w, h, _z->x, _z->y, _z->w, _z->h);
794 above = e_client_above_get(ec);
798 (above->layer <= ec->layer))
800 above = e_client_above_get(above);
804 if ((!e_object_is_del(E_OBJECT(above))) &&
805 (!e_client_util_ignored_get(above)) &&
807 (!above->iconic || e_policy_visibility_client_is_uniconic(above)) &&
808 (!above->bg_state) &&
810 (!above->visibility.force_obscured) &&
813 e_client_geometry_get(above, &ax, &ay, &aw, &ah);
814 if (E_CONTAINS(ax, ay, aw, ah, x, y, w, h))
817 above = e_client_above_get(above);
824 _e_client_check_obscured_by_children_group(E_Client *ec)
826 E_Client *cec = NULL;
827 Eina_List *transients = NULL, *l = NULL;
829 _e_client_transient_for_group_make(ec, &transients);
831 EINA_LIST_FOREACH(transients, l, cec)
833 if (e_client_transient_policy_get(cec) == E_TRANSIENT_BELOW)
836 if (!E_CONTAINS(cec->x, cec->y, cec->w, cec->h, ec->x, ec->y, ec->w, ec->h))
839 if (!cec->argb) goto finish;
840 else if (cec->visibility.opaque > 0) goto finish;
845 eina_list_free(transients);
851 _e_client_check_really_iconified(E_Client *ec)
853 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
857 if (!(e_policy_visibility_client_is_uniconic(ec) ||
858 e_policy_visibility_client_is_uniconify_render_running(ec)))
860 else if (e_client_is_iconified_by_client(ec))
868 _e_client_focus_can_take(E_Client *ec)
871 E_Client *child_ec = NULL;
872 E_Client *above_ec = NULL;
873 int x = 0, y = 0, w = 0, h = 0;
875 if (!ec) return EINA_FALSE;
876 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
877 if (e_client_util_ignored_get(ec)) return EINA_FALSE;
878 if (!(ec->icccm.accepts_focus || ec->icccm.take_focus)) return EINA_FALSE;
879 if (ec->lock_focus_in || ec->lock_focus_out) return EINA_FALSE;
880 if (!ec->visible) return EINA_FALSE;
881 if (ec->bg_state) return EINA_FALSE;
882 if (ec->visibility.force_obscured) return EINA_FALSE;
883 if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)
885 if (_e_client_check_really_iconified(ec))
888 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK)
890 if ((ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED) &&
891 !evas_object_visible_get(ec->frame))
893 ELOGF("FOCUS", "client is hidden, skip focus", ec);
898 if (ec->visibility.obscured == E_VISIBILITY_UNKNOWN)
900 if (!evas_object_visible_get(ec->frame) &&
901 !eina_list_data_find(defer_focus_stack, ec))
908 e_client_geometry_get(ec, &x, &y, &w, &h);
909 if (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h, x, y, w, h))
915 above_ec = _e_client_check_fully_contain_by_above(ec, EINA_FALSE);
916 if (!above_ec) return EINA_TRUE;
918 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK)
920 if (!evas_object_visible_get(above_ec->frame))
924 child_ec = _e_client_check_obscured_by_children_group(ec);
925 if (!child_ec) return EINA_FALSE;
927 if (above_ec != child_ec)
930 if (_e_client_focus_can_take(child_ec))
934 else if (_e_client_check_fully_contain_by_above(child_ec, EINA_FALSE))
943 e_client_focus_can_take(E_Client *ec)
945 return _e_client_focus_can_take(ec);
949 _e_client_focus_topmost_focusable_get(void)
953 E_CLIENT_REVERSE_FOREACH(ec)
955 if (_e_client_focus_can_take(ec))
962 _e_client_find_next_focus(E_Client *ec)
965 E_Client *temp_ec = NULL;
967 // intercept revert focus policy
968 if (ec && !_e_client_intercept_hook_call(E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT, ec))
971 EINA_LIST_FOREACH(focus_stack, l, temp_ec)
973 if (_e_client_focus_can_take(temp_ec))
981 _e_client_revert_focus_get(E_Client *ec)
983 E_Client *pec = NULL, *focus_ec = NULL;
986 if (stopping) return NULL;
988 return _e_client_find_next_focus(NULL);
990 if (!ec->zone) return NULL;
991 desk = e_desk_current_get(ec->zone);
992 if (!desk) return NULL;
993 if (ec->zone->display_state == E_ZONE_DISPLAY_STATE_OFF) return NULL;
995 if (e_config->focus_policy == E_FOCUS_MOUSE)
997 // set mouse over focus
998 pec = e_client_under_pointer_get(desk, ec);
1001 /* no autoraise/revert here because it's probably annoying */
1004 focus_ec = _e_client_find_next_focus(ec);
1010 _e_client_event_focus_skip_set(E_Client *ec, Eina_Bool by_client)
1012 E_Event_Client_Focus_Skip_Set *ev;
1014 ev = E_NEW(E_Event_Client_Focus_Skip_Set, 1);
1018 ev->by_client = by_client;
1019 e_object_ref(E_OBJECT(ec));
1021 ecore_event_add(E_EVENT_CLIENT_FOCUS_SKIP_SET, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
1025 _e_client_event_focus_skip_unset(E_Client *ec, Eina_Bool by_client)
1027 E_Event_Client_Focus_Skip_Unset *ev;
1029 ev = E_NEW(E_Event_Client_Focus_Skip_Unset, 1);
1033 ev->by_client = by_client;
1034 e_object_ref(E_OBJECT(ec));
1036 ecore_event_add(E_EVENT_CLIENT_FOCUS_SKIP_UNSET, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
1040 e_client_focus_skip_set(E_Client *ec, Eina_Bool skip, Eina_Bool by_client)
1046 if (ec->icccm.accepts_focus)
1048 ELOGF("TZPOL", "FOCUS|SKIP SET (by_client:%d)", ec, by_client);
1049 ec->icccm.accepts_focus = ec->icccm.take_focus = 0;
1050 ec->changes.accepts_focus = 1;
1053 _e_client_event_focus_skip_set(ec, by_client);
1058 if (!ec->icccm.accepts_focus)
1060 ELOGF("TZPOL", "FOCUS|SKIP UNSET (by_client:%d)", ec, by_client);
1061 ec->icccm.accepts_focus = ec->icccm.take_focus = 1;
1062 ec->changes.accepts_focus = 1;
1065 _e_client_event_focus_skip_unset(ec, by_client);
1071 e_client_revert_focus(E_Client *ec)
1073 E_Client *focus_ec = NULL;
1075 // check topmost focus policy
1076 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK)
1078 focus_ec = _e_client_focus_topmost_focusable_get();
1079 if (focus_ec && (focus_ec != focused) &&
1080 (!focus_ec->iconic || focus_ec->exp_iconify.buffer_flush))
1082 ELOGF("FOCUS", "focus set | topmost_focus", focus_ec);
1083 if (focused) e_client_frame_focus_set(focused, EINA_FALSE);
1084 e_client_frame_focus_set(focus_ec, EINA_TRUE);
1086 else if (focused && (focus_ec == NULL))
1088 ELOGF("FOCUS", "focus unset | No focusable ec", focused);
1089 e_client_frame_focus_set(focused, EINA_FALSE);
1094 focus_ec = _e_client_revert_focus_get(ec);
1100 e_client_focus_defer_unset(ec);
1101 ELOGF("FOCUS", "focus unset | revert_focus", ec);
1102 e_client_frame_focus_set(ec, EINA_FALSE);
1104 if (!focus_ec->iconic || focus_ec->exp_iconify.buffer_flush)
1106 ELOGF("FOCUS", "focus set | revert_focus", focus_ec);
1107 e_client_frame_focus_set(focus_ec, EINA_TRUE);
1113 e_client_check_above_focused(E_Client *ec)
1115 E_Client *focus = NULL;
1116 E_Client *above = NULL;
1118 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1120 focus = e_client_focused_get();
1121 if (!focus) return EINA_FALSE;
1123 above = e_client_above_get(ec);
1129 above = e_client_above_get(above);
1136 _e_client_free(E_Client *ec)
1138 e_comp_object_redirected_set(ec->frame, 0);
1139 e_comp_object_render_update_del(ec->frame);
1141 E_OBJECT(ec)->references++;
1144 ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
1145 if (!ec->desk->fullscreen_clients)
1146 e_comp_render_queue();
1149 e_comp->new_clients--;
1150 if (ec->e.state.profile.use)
1152 e_client_desk_window_profile_wait_desk_set(ec, NULL);
1154 if (ec->e.state.profile.available_list)
1157 for (i = 0; i < ec->e.state.profile.num; i++)
1158 eina_stringshare_replace(&ec->e.state.profile.available_list[i], NULL);
1159 E_FREE(ec->e.state.profile.available_list);
1162 ec->e.state.profile.num = 0;
1164 eina_stringshare_replace(&ec->e.state.profile.set, NULL);
1165 eina_stringshare_replace(&ec->e.state.profile.wait, NULL);
1166 eina_stringshare_replace(&ec->e.state.profile.name, NULL);
1167 ec->e.state.profile.wait_for_done = 0;
1168 ec->e.state.profile.use = 0;
1171 if (ec->e.state.video_parent && ec->e.state.video_parent_client)
1173 ec->e.state.video_parent_client->e.state.video_child =
1174 eina_list_remove(ec->e.state.video_parent_client->e.state.video_child, ec);
1176 if (ec->e.state.video_child)
1180 EINA_LIST_FREE(ec->e.state.video_child, tmp)
1181 tmp->e.state.video_parent_client = NULL;
1183 E_FREE_FUNC(ec->kill_timer, ecore_timer_del);
1184 E_FREE_LIST(ec->pending_resize, free);
1186 E_FREE_FUNC(ec->map_timer, ecore_timer_del);
1188 ec->transients = eina_list_free(ec->transients);
1189 ec->stick_desks = eina_list_free(ec->stick_desks);
1190 if (ec->netwm.icons)
1193 for (i = 0; i < ec->netwm.num_icons; i++)
1194 free(ec->netwm.icons[i].data);
1195 E_FREE(ec->netwm.icons);
1197 E_FREE(ec->netwm.extra_types);
1198 eina_stringshare_replace(&ec->border.name, NULL);
1199 eina_stringshare_replace(&ec->bordername, NULL);
1200 eina_stringshare_replace(&ec->icccm.name, NULL);
1201 #if defined(__cplusplus) || defined(c_plusplus)
1202 eina_stringshare_replace(&ec->icccm.cpp_class, NULL);
1204 eina_stringshare_replace(&ec->icccm.class, NULL);
1206 eina_stringshare_replace(&ec->icccm.title, NULL);
1207 eina_stringshare_replace(&ec->icccm.icon_name, NULL);
1208 eina_stringshare_replace(&ec->icccm.machine, NULL);
1209 eina_stringshare_replace(&ec->icccm.window_role, NULL);
1210 if ((ec->icccm.command.argc > 0) && (ec->icccm.command.argv))
1214 for (i = 0; i < ec->icccm.command.argc; i++)
1215 free(ec->icccm.command.argv[i]);
1216 E_FREE(ec->icccm.command.argv);
1218 eina_stringshare_replace(&ec->netwm.name, NULL);
1219 eina_stringshare_replace(&ec->netwm.icon_name, NULL);
1220 eina_stringshare_replace(&ec->internal_icon, NULL);
1221 eina_stringshare_replace(&ec->internal_icon_key, NULL);
1223 focus_stack = eina_list_remove(focus_stack, ec);
1224 e_client_focus_defer_unset(ec);
1226 if (ec->e.state.profile.wait_desk)
1228 e_object_delfn_del(E_OBJECT(ec->e.state.profile.wait_desk),
1229 ec->e.state.profile.wait_desk_delfn);
1230 ec->e.state.profile.wait_desk_delfn = NULL;
1231 e_object_unref(E_OBJECT(ec->e.state.profile.wait_desk));
1233 ec->e.state.profile.wait_desk = NULL;
1234 E_FREE_FUNC(ec->frame, evas_object_del);
1238 ELOGF("COMP", "CRITICAL. focused is deleted ec.", ec);
1239 ELOGF("FOCUS", "CLIENT FOCUS_SET", NULL);
1243 E_OBJECT(ec)->references--;
1244 ELOGF("COMP", "CLIENT FREE", ec);
1246 e_uuid_store_entry_del(ec->uuid);
1248 e_desk_client_del(ec->desk, ec);
1254 _e_client_del(E_Client *ec)
1260 focus_stack = eina_list_remove(focus_stack, ec);
1261 e_client_focus_defer_unset(ec);
1263 e_desk_visible_client_iconified_list_remove(ec->desk, ec);
1265 if (ec == e_comp_object_dim_client_get())
1267 INF("[DIM] client deleted\n");
1268 e_comp_object_dim_client_set(NULL);
1271 if (ec->cur_mouse_action)
1273 if (ec->cur_mouse_action->func.end)
1274 ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
1276 if (action_client == ec) _e_client_action_finish();
1278 if (warp_client == ec)
1280 E_FREE_FUNC(warp_timer, ecore_timer_del);
1284 if ((client_drag) && (client_drag->data == ec))
1286 e_object_del(E_OBJECT(client_drag));
1291 e_client_comp_hidden_set(ec, 1);
1292 evas_object_pass_events_set(ec->frame, 1);
1295 E_FREE_FUNC(ec->color_editor, evas_object_del);
1298 e_client_revert_focus(ec);
1300 E_FREE_FUNC(ec->ping_poller, ecore_poller_del);
1301 /* must be called before parent/child clear */
1302 _e_client_hook_call(E_CLIENT_HOOK_DEL, ec);
1304 _e_client_event_remove(ec);
1306 ELOGF("COMP", "CLIENT DEL", ec);
1310 ec->parent->transients = eina_list_remove(ec->parent->transients, ec);
1313 EINA_LIST_FREE(ec->transients, child)
1314 child->parent = NULL;
1316 type = e_pixmap_type_get(ec->pixmap);
1317 if (type < E_PIXMAP_TYPE_MAX)
1318 eina_hash_del_by_key(clients_hash[type], &ec->pixmap);
1319 e_comp->clients = eina_list_remove(e_comp->clients, ec);
1320 e_comp_object_render_update_del(ec->frame);
1321 e_comp_post_update_purge(ec);
1322 if (e_pixmap_free(ec->pixmap))
1323 e_pixmap_client_set(ec->pixmap, NULL);
1326 // base_output_resolution
1327 e_client_transform_core_remove(ec, ec->base_output_resolution.transform);
1328 e_util_transform_del(ec->base_output_resolution.transform);
1329 ec->base_output_resolution.transform = NULL;
1330 E_FREE_FUNC(ec->base_output_resolution.hook_subsurf_create, e_comp_wl_hook_del);
1333 e_client_transform_core_remove(ec, ec->desk_zoom.transform);
1334 e_util_transform_del(ec->desk_zoom.transform);
1335 ec->desk_zoom.transform = NULL;
1336 E_FREE_FUNC(ec->desk_zoom.hook_subsurf_create, e_comp_wl_hook_del);
1338 if (ec->transform_core.transform_list)
1340 E_Util_Transform *transform;
1342 EINA_LIST_FREE(ec->transform_core.transform_list, transform)
1344 e_util_transform_unref(transform);
1348 ec->transform_core.result.enable = EINA_FALSE;
1350 e_client_desk_area_set(ec, NULL);
1351 e_util_transform_del(ec->desk_area.transform);
1352 ec->desk_area.transform = NULL;
1354 _e_client_resize_object_del(ec);
1356 e_client_visibility_calculate();
1359 ///////////////////////////////////////////
1362 _e_client_cb_kill_timer(void *data)
1364 E_Client *ec = data;
1366 // dont wait until it's hung -
1369 if (ec->netwm.pid > 1)
1370 kill(ec->netwm.pid, SIGKILL);
1372 ec->kill_timer = NULL;
1373 return ECORE_CALLBACK_CANCEL;
1377 _e_client_cb_ping_poller(void *data)
1382 if (e_object_is_del(E_OBJECT(ec)))
1384 ec->ping_poller = NULL;
1385 return ECORE_CALLBACK_CANCEL;
1393 evas_object_smart_callback_call(ec->frame, "unhung", NULL);
1394 E_FREE_FUNC(ec->kill_timer, ecore_timer_del);
1399 /* if time between last ping and now is greater
1400 * than half the ping interval... */
1401 if ((ecore_loop_time_get() - ec->ping) >
1402 ((e_config->ping_clients_interval *
1403 ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
1408 evas_object_smart_callback_call(ec->frame, "hung", NULL);
1409 /* FIXME: if below dialog is up - hide it now */
1411 if (ec->delete_requested)
1413 /* FIXME: pop up dialog saying app is hung - kill client, or pid */
1414 e_client_act_kill_begin(ec);
1418 ec->ping_poller = NULL;
1420 return ECORE_CALLBACK_CANCEL;
1423 ///////////////////////////////////////////
1426 _e_client_action_input_win_new(void)
1430 CRI("DOUBLE COMP GRAB! ACK!!!!");
1433 comp_grabbed = e_comp_grab_input(1, 1);
1434 if (!comp_grabbed) _e_client_action_input_win_del();
1435 return comp_grabbed;
1439 _e_client_action_init(E_Client *ec)
1441 action_orig.x = ec->x;
1442 action_orig.y = ec->y;
1443 action_orig.w = ec->w;
1444 action_orig.h = ec->h;
1448 action_client->keyboard_resizing = 0;
1454 _e_client_move_begin(E_Client *ec)
1456 if ((ec->fullscreen) || (ec->lock_user_location))
1459 if (!_e_client_action_input_win_new()) return 0;
1462 _e_client_hook_call(E_CLIENT_HOOK_MOVE_BEGIN, ec);
1465 if (ecmove == ec) ecmove = NULL;
1466 _e_client_action_input_win_del();
1469 if (!ec->lock_user_stacking)
1471 if (e_config->border_raise_on_mouse_action)
1476 e_comp_client_override_add(ec);
1482 _e_client_move_end(E_Client *ec)
1485 _e_client_action_input_win_del();
1486 _e_client_hook_call(E_CLIENT_HOOK_MOVE_END, ec);
1488 if (ec->transformed)
1489 _e_client_transform_move_end(ec);
1492 e_comp_client_override_del(ec);
1499 _e_client_action_move_timeout(void *data EINA_UNUSED)
1501 _e_client_move_end(action_client);
1502 _e_client_action_finish();
1503 return ECORE_CALLBACK_CANCEL;
1507 _e_client_action_move_timeout_add(void)
1509 E_FREE_FUNC(action_timer, ecore_timer_del);
1510 if (e_config->border_keyboard.timeout)
1511 action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_client_action_move_timeout, NULL);
1515 _e_client_move_mouse_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1517 if (!comp_grabbed) return ECORE_CALLBACK_RENEW;
1520 ERR("no action_client!");
1522 if (action_client) _e_client_move_end(action_client);
1523 _e_client_action_finish();
1524 return ECORE_CALLBACK_DONE;
1528 _e_client_moveinfo_gather(E_Client *ec, const char *source)
1530 if (e_util_glob_match(source, "mouse,*,1"))
1531 ec->moveinfo.down.button = 1;
1532 else if (e_util_glob_match(source, "mouse,*,2"))
1533 ec->moveinfo.down.button = 2;
1534 else if (e_util_glob_match(source, "mouse,*,3"))
1535 ec->moveinfo.down.button = 3;
1537 ec->moveinfo.down.button = 0;
1538 if ((ec->moveinfo.down.button >= 1) && (ec->moveinfo.down.button <= 3))
1540 ec->moveinfo.down.mx = ec->mouse.last_down[ec->moveinfo.down.button - 1].mx;
1541 ec->moveinfo.down.my = ec->mouse.last_down[ec->moveinfo.down.button - 1].my;
1545 ec->moveinfo.down.mx = ec->mouse.current.mx;
1546 ec->moveinfo.down.my = ec->mouse.current.my;
1551 _e_client_move_handle(E_Client *ec)
1554 Eina_List *skiplist = NULL;
1556 if ((ec->moveinfo.down.button >= 1) && (ec->moveinfo.down.button <= 3))
1558 x = ec->mouse.last_down[ec->moveinfo.down.button - 1].x +
1559 (ec->mouse.current.mx - ec->moveinfo.down.mx);
1560 y = ec->mouse.last_down[ec->moveinfo.down.button - 1].y +
1561 (ec->mouse.current.my - ec->moveinfo.down.my);
1565 x = ec->moveinfo.down.x +
1566 (ec->mouse.current.mx - ec->moveinfo.down.mx);
1567 y = ec->moveinfo.down.y +
1568 (ec->mouse.current.my - ec->moveinfo.down.my);
1571 if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1572 _e_client_stay_within_canvas(ec, x, y, &x, &y);
1575 _e_client_stay_within_canvas_margin(ec, x, y, &x, &y);
1577 ec->shelf_fix.x = 0;
1578 ec->shelf_fix.y = 0;
1579 ec->shelf_fix.modified = 0;
1580 evas_object_move(ec->frame, x, y);
1582 if (e_client_transform_core_enable_get(ec))
1584 e_client_transform_core_update(ec);
1588 static Evas_Object *
1589 _e_client_resize_object_rectangle_get(E_Client *ec)
1591 Evas_Object *resize_obj = NULL;
1593 resize_obj = evas_object_rectangle_add(evas_object_evas_get(ec->frame));
1594 EINA_SAFETY_ON_NULL_RETURN_VAL(resize_obj, NULL);
1596 if (e_config->resize_object.customize)
1598 evas_object_color_set(resize_obj,
1599 e_config->resize_object.r,
1600 e_config->resize_object.g,
1601 e_config->resize_object.b,
1602 e_config->resize_object.a);
1605 evas_object_color_set(resize_obj, 128, 128, 128, 100);
1610 static Evas_Object *
1611 _e_client_resize_object_image_get(E_Client *ec)
1614 Evas_Object *resize_obj = NULL;
1616 if (!e_config->resize_object.image_path)
1618 ELOGF("COMP", "NO resize_object image! Make default resize_object", ec);
1622 resize_obj = evas_object_image_add(evas_object_evas_get(ec->frame));
1623 EINA_SAFETY_ON_NULL_RETURN_VAL(resize_obj, NULL);
1625 evas_object_image_file_set(resize_obj, e_config->resize_object.image_path, NULL);
1626 err = evas_object_image_load_error_get(resize_obj);
1627 if (err != EVAS_LOAD_ERROR_NONE)
1629 ELOGF("COMP", "Image load error. path:%s, errno:%d. Make default resize_object",
1630 ec, e_config->resize_object.image_path, err);
1631 evas_object_del(resize_obj);
1636 evas_object_image_fill_set(resize_obj, 0, 0, ec->w, ec->h);
1637 evas_object_image_filled_set(resize_obj, EINA_TRUE);
1639 evas_object_image_border_set(resize_obj,
1640 e_config->resize_object.border_width.l,
1641 e_config->resize_object.border_width.r,
1642 e_config->resize_object.border_width.t,
1643 e_config->resize_object.border_width.b);
1648 return _e_client_resize_object_rectangle_get(ec);
1651 static Evas_Object *
1652 _e_client_resize_object_create(E_Client *ec)
1654 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, NULL);
1656 Evas_Object *resize_obj = NULL;
1658 if (_e_client_resize_object_create_cb)
1659 resize_obj = _e_client_resize_object_create_cb(ec);
1662 if (e_config->resize_object.type == 1) // image object
1664 resize_obj = _e_client_resize_object_image_get(ec);
1668 resize_obj = _e_client_resize_object_rectangle_get(ec);
1671 EINA_SAFETY_ON_NULL_RETURN_VAL(resize_obj, NULL);
1673 evas_object_pass_events_set(resize_obj, EINA_TRUE);
1674 evas_object_layer_set(resize_obj, evas_object_layer_get(ec->frame));
1675 evas_object_stack_above(resize_obj, ec->frame);
1676 evas_object_name_set(resize_obj, "resize_object");
1682 _e_client_resize_object_del(E_Client *ec)
1684 if (ec == NULL) return;
1685 if (ec->manage_resize.resize_obj == NULL) return;
1687 evas_object_hide(ec->manage_resize.resize_obj);
1688 evas_object_del(ec->manage_resize.resize_obj);
1689 ec->manage_resize.resize_obj = NULL;
1693 _e_client_resize_handle(E_Client *ec)
1696 int new_x, new_y, new_w, new_h;
1698 int trans_x = 0, trans_y = 0;
1699 int trans_w = 0, trans_h = 0;
1701 if (ec->transformed)
1703 _e_client_transform_resize_handle(ec);
1712 if ((ec->resize_mode == E_POINTER_RESIZE_TR) ||
1713 (ec->resize_mode == E_POINTER_RESIZE_R) ||
1714 (ec->resize_mode == E_POINTER_RESIZE_BR))
1716 if ((ec->moveinfo.down.button >= 1) &&
1717 (ec->moveinfo.down.button <= 3))
1718 w = ec->mouse.last_down[ec->moveinfo.down.button - 1].w +
1719 (ec->mouse.current.mx - ec->moveinfo.down.mx);
1721 w = ec->moveinfo.down.w + (ec->mouse.current.mx - ec->moveinfo.down.mx);
1723 else if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
1724 (ec->resize_mode == E_POINTER_RESIZE_L) ||
1725 (ec->resize_mode == E_POINTER_RESIZE_BL))
1727 if ((ec->moveinfo.down.button >= 1) &&
1728 (ec->moveinfo.down.button <= 3))
1729 w = ec->mouse.last_down[ec->moveinfo.down.button - 1].w -
1730 (ec->mouse.current.mx - ec->moveinfo.down.mx);
1732 w = ec->moveinfo.down.w - (ec->mouse.current.mx - ec->moveinfo.down.mx);
1735 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
1736 (ec->resize_mode == E_POINTER_RESIZE_T) ||
1737 (ec->resize_mode == E_POINTER_RESIZE_TR))
1739 if ((ec->moveinfo.down.button >= 1) &&
1740 (ec->moveinfo.down.button <= 3))
1741 h = ec->mouse.last_down[ec->moveinfo.down.button - 1].h -
1742 (ec->mouse.current.my - ec->moveinfo.down.my);
1744 h = ec->moveinfo.down.h - (ec->mouse.current.my - ec->moveinfo.down.my);
1746 else if ((ec->resize_mode == E_POINTER_RESIZE_BL) ||
1747 (ec->resize_mode == E_POINTER_RESIZE_B) ||
1748 (ec->resize_mode == E_POINTER_RESIZE_BR))
1750 if ((ec->moveinfo.down.button >= 1) &&
1751 (ec->moveinfo.down.button <= 3))
1752 h = ec->mouse.last_down[ec->moveinfo.down.button - 1].h +
1753 (ec->mouse.current.my - ec->moveinfo.down.my);
1755 h = ec->moveinfo.down.h + (ec->mouse.current.my - ec->moveinfo.down.my);
1760 if ((ec->resize_mode == E_POINTER_RESIZE_T) ||
1761 (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1762 (ec->resize_mode == E_POINTER_RESIZE_L) ||
1763 (ec->resize_mode == E_POINTER_RESIZE_BL))
1765 if ((ec->resize_mode == E_POINTER_RESIZE_L) ||
1766 (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1767 (ec->resize_mode == E_POINTER_RESIZE_T) ||
1768 (ec->resize_mode == E_POINTER_RESIZE_TR))
1775 if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1779 w = MIN(w, ec->zone->w);
1780 h = MIN(h, ec->zone->h);
1783 e_client_resize_limit(ec, &new_w, &new_h);
1785 if (ec->manage_resize.enable_aspect_ratio)
1787 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
1788 (ec->resize_mode == E_POINTER_RESIZE_L) ||
1789 (ec->resize_mode == E_POINTER_RESIZE_BL) ||
1790 (ec->resize_mode == E_POINTER_RESIZE_TR) ||
1791 (ec->resize_mode == E_POINTER_RESIZE_R) ||
1792 (ec->resize_mode == E_POINTER_RESIZE_BR))
1794 new_h = (int) ec->manage_resize.ah / ec->manage_resize.aw * new_w;
1796 else if ((ec->resize_mode == E_POINTER_RESIZE_T) ||
1797 (ec->resize_mode == E_POINTER_RESIZE_B))
1799 new_w = (int) ec->manage_resize.aw / ec->manage_resize.ah * new_h;
1801 new_h += ec->manage_resize.header_h;
1802 new_h += ec->manage_resize.footer_h;
1805 if ((ec->resize_mode == E_POINTER_RESIZE_T) ||
1806 (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1807 (ec->resize_mode == E_POINTER_RESIZE_L) ||
1808 (ec->resize_mode == E_POINTER_RESIZE_BL))
1809 new_x += (w - new_w);
1810 if ((ec->resize_mode == E_POINTER_RESIZE_L) ||
1811 (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1812 (ec->resize_mode == E_POINTER_RESIZE_T) ||
1813 (ec->resize_mode == E_POINTER_RESIZE_TR))
1814 new_y += (h - new_h);
1816 if (e_config->interactive_resize)
1818 evas_object_geometry_set(ec->frame, new_x, new_y, new_w, new_h);
1822 if (ec->manage_resize.resize_obj == NULL)
1824 ec->manage_resize.resize_obj = _e_client_resize_object_create(ec);
1825 EINA_SAFETY_ON_NULL_RETURN(ec->manage_resize.resize_obj);
1828 if (e_client_transform_core_enable_get(ec))
1830 e_client_transform_core_input_inv_transform(ec, new_x, new_y, &trans_x, &trans_y);
1831 e_client_transform_core_input_inv_transform(ec, new_w, new_h, &trans_w, &trans_h);
1832 evas_object_geometry_set(ec->manage_resize.resize_obj, trans_x, trans_y, trans_w, trans_h);
1835 evas_object_geometry_set(ec->manage_resize.resize_obj, new_x, new_y, new_w, new_h);
1836 evas_object_show(ec->manage_resize.resize_obj);
1838 ec->manage_resize.x = new_x;
1839 ec->manage_resize.y = new_y;
1840 ec->manage_resize.w = new_w;
1841 ec->manage_resize.h = new_h;
1846 _e_client_adjust_size_by_ppu(int size, int start_size, unsigned int ppu)
1848 if (ppu <= 1) return size;
1850 unsigned int remainder = size % ppu;
1851 if (remainder == 0) return size;
1853 int gap = size - start_size;
1854 int new_size = size;
1856 new_size = size + (ppu - remainder);
1858 new_size = size - remainder;
1864 _e_client_adjust_position_by_ppu(int pos, int size, int prev_pos, int prev_size)
1868 if (prev_pos == pos)
1871 new_pos = (prev_pos + prev_size) - size;
1877 _e_client_adjust_geometry_by_resize_ppu(E_Client *ec)
1879 if (ec->manage_resize.unit_size <= 1) return;
1881 ec->manage_resize.w = _e_client_adjust_size_by_ppu(ec->manage_resize.w, ec->w, ec->manage_resize.unit_size);
1882 ec->manage_resize.h = _e_client_adjust_size_by_ppu(ec->manage_resize.h, ec->h, ec->manage_resize.unit_size);
1884 ec->manage_resize.x = _e_client_adjust_position_by_ppu(ec->manage_resize.x, ec->manage_resize.w, ec->x, ec->w);
1885 ec->manage_resize.y = _e_client_adjust_position_by_ppu(ec->manage_resize.y, ec->manage_resize.h, ec->y, ec->h);
1889 _e_client_resize_end(E_Client *ec)
1891 ec->resize_mode = E_POINTER_RESIZE_NONE;
1892 _e_client_action_input_win_del();
1894 _e_client_hook_call(E_CLIENT_HOOK_RESIZE_END, ec);
1896 if (ec->transformed)
1897 _e_client_transform_resize_end(ec);
1900 e_comp_client_override_del(ec);
1904 if (!e_config->interactive_resize)
1906 if (ec->manage_resize.resize_obj)
1908 if (ec->manage_resize.unit_size > 1)
1909 _e_client_adjust_geometry_by_resize_ppu(ec);
1911 e_client_frame_geometry_set(ec,
1912 ec->manage_resize.x,
1913 ec->manage_resize.y,
1914 ec->manage_resize.w,
1915 ec->manage_resize.h);
1916 _e_client_resize_object_del(ec);
1924 _e_client_action_resize_timeout(void *data EINA_UNUSED)
1926 _e_client_resize_end(action_client);
1927 _e_client_action_finish();
1928 return ECORE_CALLBACK_CANCEL;
1932 _e_client_action_resize_timeout_add(void)
1934 E_FREE_FUNC(action_timer, ecore_timer_del);
1935 if (e_config->border_keyboard.timeout)
1936 action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_client_action_resize_timeout, NULL);
1940 _e_client_resize_mouse_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1942 if (!comp_grabbed) return ECORE_CALLBACK_RENEW;
1945 ERR("no action_client!");
1947 if (action_client) _e_client_resize_end(action_client);
1948 _e_client_action_finish();
1949 return ECORE_CALLBACK_DONE;
1952 ////////////////////////////////////////////////
1955 _e_client_position_inside_input_rect(E_Client *ec, int tx, int ty)
1958 Eina_Bool res = EINA_FALSE;
1959 Eina_List *list = NULL, *l;
1960 Eina_Rectangle *data;
1962 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1964 e_comp_object_input_rect_get(ec->frame, &list);
1967 EINA_LIST_FOREACH(list, l, data)
1969 if ((tx >= data->x) && (tx <= data->x + data->w) &&
1970 (ty >= data->y) && (ty <= data->y + data->h))
1976 list = eina_list_free(list);
1980 e_client_geometry_get(ec, &x, &y, &w, &h);
1982 if ((tx >= x) && (tx <= x + w) &&
1983 (ty >= y) && (ty <= y + h))
1993 _e_client_under_pointer_helper(E_Desk *desk, E_Client *exclude, int x, int y)
1995 E_Client *ec = NULL, *cec;
1997 E_CLIENT_REVERSE_FOREACH(cec)
1999 /* If a border was specified which should be excluded from the list
2000 * (because it will be closed shortly for example), skip */
2001 if (e_client_util_ignored_get(cec) || (!e_client_util_desk_visible(cec, desk))) continue;
2002 if (!evas_object_visible_get(cec->frame)) continue;
2003 if (e_policy_client_is_cursor(cec)) continue;
2004 if ((exclude) && (cec == exclude)) continue;
2005 if (!E_INSIDE(x, y, cec->x, cec->y, cec->w, cec->h))
2007 /* If the layer is higher, the position of the window is higher
2008 * (always on top vs always below) */
2009 if (!ec || (cec->layer > ec->layer))
2016 _e_client_input_rect_under_pointer_helper(E_Desk *desk, E_Client *exclude, int x, int y)
2018 E_Client *ec = NULL, *cec;
2020 E_CLIENT_REVERSE_FOREACH(cec)
2022 /* If a border was specified which should be excluded from the list
2023 * (because it will be closed shortly for example), skip */
2024 if (e_client_util_ignored_get(cec) || (!e_client_util_desk_visible(cec, desk))) continue;
2025 if (!evas_object_visible_get(cec->frame)) continue;
2026 if (e_policy_client_is_cursor(cec)) continue;
2027 if ((exclude) && (cec == exclude)) continue;
2028 if (!E_INSIDE(x, y, cec->x, cec->y, cec->w, cec->h))
2030 /* If the layer is higher, the position of the window is higher
2031 * (always on top vs always below) */
2032 if (ec && (cec->layer <= ec->layer)) continue;
2033 if (_e_client_position_inside_input_rect(cec, x, y))
2039 ////////////////////////////////////////////////
2042 _e_client_zones_layout_calc(E_Client *ec, int *zx, int *zy, int *zw, int *zh)
2045 E_Zone *zone_above, *zone_below, *zone_left, *zone_right;
2047 if (!ec->zone) return;
2053 if (eina_list_count(e_comp->zones) == 1)
2062 zone_left = e_comp_zone_xy_get((x - w + 5), y);
2063 zone_right = e_comp_zone_xy_get((x + w + 5), y);
2064 zone_above = e_comp_zone_xy_get(x, (y - h + 5));
2065 zone_below = e_comp_zone_xy_get(x, (y + h + 5));
2067 if (!(zone_above) && (y))
2068 zone_above = e_comp_zone_xy_get(x, (h - 5));
2070 if (!(zone_left) && (x))
2071 zone_left = e_comp_zone_xy_get((x - 5), y);
2074 w = zone_right->x + zone_right->w;
2077 w = ec->zone->x + ec->zone->w;
2080 h = zone_below->y + zone_below->h;
2083 h = ec->zone->y + ec->zone->h;
2085 if ((zone_left) && (zone_right))
2086 w = ec->zone->w + zone_right->x;
2088 if ((zone_above) && (zone_below))
2089 h = ec->zone->h + zone_below->y;
2091 if (x) x -= ec->zone->w;
2092 if (y) y -= ec->zone->h;
2094 if (zx) *zx = x > 0 ? x : 0;
2095 if (zy) *zy = y > 0 ? y : 0;
2101 _e_client_stay_within_canvas(E_Client *ec, int x, int y, int *new_x, int *new_y)
2103 int new_x_max, new_y_max;
2109 if (new_x) *new_x = x;
2110 if (new_y) *new_y = y;
2114 _e_client_zones_layout_calc(ec, NULL, NULL, &zw, &zh);
2116 new_x_max = zw - ec->w;
2117 new_y_max = zh - ec->h;
2118 lw = ec->w > zw ? EINA_TRUE : EINA_FALSE;
2119 lh = ec->h > zh ? EINA_TRUE : EINA_FALSE;
2153 _e_client_stay_within_canvas_margin(E_Client *ec, int x, int y, int *new_x, int *new_y)
2155 int new_x_max, new_y_max, new_x_min, new_y_min;
2156 int margin_w, margin_h;
2162 if (new_x) *new_x = x;
2163 if (new_y) *new_y = y;
2170 _e_client_zones_layout_calc(ec, NULL, NULL, &zw, &zh);
2175 new_x_min = (margin_w > cw) ? 0 : -(cw - margin_w);
2176 new_x_max = (margin_w > cw) ? (zw - cw) : (zw - margin_w);
2177 new_y_min = (margin_h > ch) ? 0 : -(ch - margin_h);
2178 new_y_max = (margin_h > ch) ? (zh - ch) : (zh - margin_h);
2182 else if (x <= new_x_min)
2187 else if (y <= new_y_min)
2193 _e_client_reset_lost_window(E_Client *ec)
2197 if (ec->during_lost) return;
2198 ec->during_lost = EINA_TRUE;
2200 if (ec->iconic) e_client_uniconify(ec);
2201 if (!ec->moving) e_comp_object_util_center(ec->frame);
2204 if (!ec->lock_focus_out)
2206 if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
2208 ELOGF("FOCUS", "focus set | reset_lost_window", ec);
2209 e_client_frame_focus_set(ec, EINA_TRUE);
2213 e_client_pointer_warp_to_center(ec);
2214 ec->during_lost = EINA_FALSE;
2218 _e_client_move_lost_window_to_center(E_Client *ec)
2220 int loss_overlap = 5;
2223 if (ec->during_lost) return;
2224 if (!ec->zone) return;
2226 _e_client_zones_layout_calc(ec, &zx, &zy, &zw, &zh);
2228 if (!E_INTERSECTS(zx + loss_overlap,
2230 zw - (2 * loss_overlap),
2231 zh - (2 * loss_overlap),
2232 ec->x, ec->y, ec->w, ec->h))
2234 _e_client_reset_lost_window(ec);
2238 ////////////////////////////////////////////////
2240 _e_client_zone_update(E_Client *ec)
2245 /* still within old zone - leave it there */
2246 if (ec->zone && E_INTERSECTS(ec->x, ec->y, ec->w, ec->h,
2247 ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
2249 /* find a new zone */
2250 EINA_LIST_FOREACH(e_comp->zones, l, zone)
2252 if (E_INTERSECTS(ec->x, ec->y, ec->w, ec->h,
2253 zone->x, zone->y, zone->w, zone->h))
2255 e_client_zone_set(ec, zone);
2261 ////////////////////////////////////////////////
2264 _e_client_cb_evas_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2266 E_Client *ec = data;
2268 if (stopping) return; //ignore all of this if we're shutting down!
2269 if (e_object_is_del(data)) return; //client is about to die
2270 if (ec->cur_mouse_action)
2272 if (ec->cur_mouse_action->func.end_mouse)
2273 ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
2274 else if (ec->cur_mouse_action->func.end)
2275 ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
2276 E_FREE_FUNC(ec->cur_mouse_action, e_object_unref);
2278 if (action_client == ec) _e_client_action_finish();
2280 ec->want_focus = ec->take_focus = 0;
2284 if (ec->new_client) return;
2285 _e_client_event_hide(ec);
2291 _e_client_cb_evas_shade_done(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2293 E_Client *ec = data;
2295 if (e_object_is_del(data)) return;
2298 ec->shaded = !(ec->shaded);
2299 ec->changes.shaded = 1;
2300 ec->changes.shading = 1;
2301 e_client_comp_hidden_set(ec, ec->shaded);
2305 _e_client_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2307 E_Client *ec = data;
2311 if (e_object_is_del(data)) return;
2313 ec->pre_res_change.valid = 0;
2315 _e_client_event_simple(ec, E_EVENT_CLIENT_MOVE);
2317 _e_client_zone_update(ec);
2318 evas_object_geometry_get(ec->frame, &x, &y, NULL, NULL);
2319 if ((e_config->transient.move) && (ec->transients))
2321 Eina_List *list = eina_list_clone(ec->transients);
2324 EINA_LIST_FREE(list, child)
2326 if (child->vkbd.vkbd) continue;
2328 evas_object_move(child->frame,
2329 child->x + x - ec->pre_cb.x,
2330 child->y + y - ec->pre_cb.y);
2333 if (ec->moving || (ecmove == ec))
2334 _e_client_hook_call(E_CLIENT_HOOK_MOVE_UPDATE, ec);
2336 if ((!ec->moving) && (ec->transformed))
2338 map = e_client_map_get(ec);
2339 _e_client_transform_geometry_save(ec, map);
2343 ec->pre_cb.x = x; ec->pre_cb.y = y;
2347 if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h,
2348 ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
2350 e_client_revert_focus(ec);
2354 e_client_visibility_calculate();
2358 _e_client_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2360 E_Client *ec = data;
2361 Evas_Coord x, y, w, h;
2363 if (e_object_is_del(data)) return;
2365 ec->pre_res_change.valid = 0;
2367 _e_client_event_simple(ec, E_EVENT_CLIENT_RESIZE);
2369 _e_client_zone_update(ec);
2370 evas_object_geometry_get(ec->frame, &x, &y, &w, &h);
2371 if ((e_config->transient.resize) && (ec->transients))
2373 Eina_List *list = eina_list_clone(ec->transients);
2376 EINA_LIST_FREE(list, child)
2378 Evas_Coord nx, ny, nw, nh;
2380 if ((ec->pre_cb.w > 0) && (ec->pre_cb.h > 0))
2382 nx = x + (((child->x - x) * w) / ec->pre_cb.w);
2383 ny = y + (((child->y - y) * h) / ec->pre_cb.h);
2384 nw = (child->w * w) / ec->pre_cb.w;
2385 nh = (child->h * h) / ec->pre_cb.h;
2386 nx += ((nw - child->w) / 2);
2387 ny += ((nh - child->h) / 2);
2388 evas_object_move(child->frame, nx, ny);
2393 if (e_client_util_resizing_get(ec) || (ecresize == ec))
2394 _e_client_hook_call(E_CLIENT_HOOK_RESIZE_UPDATE, ec);
2395 ec->pre_cb.w = w; ec->pre_cb.h = h;
2397 e_client_transform_core_update(ec);
2398 e_client_visibility_calculate();
2402 _e_client_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2404 E_Client *ec = data;
2406 if (e_object_is_del(data)) return;
2408 _e_client_event_show(ec);
2413 _e_client_cb_evas_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2415 E_Client *ec = data;
2416 E_Comp_Wl_Client_Data *child_cdata = NULL;
2418 if (e_object_is_del(data)) return;
2419 if (ec->layer_block) return;
2420 if (ec->layer_pending) return;
2421 if (e_config->transient.raise && ec->transients)
2423 Eina_List *list = eina_list_clone(ec->transients);
2424 E_Client *child, *below = NULL, *above = NULL;
2425 E_Transient transient_policy;
2427 E_LIST_REVERSE_FREE(list, child)
2429 child_cdata = e_client_cdata_get(child);
2430 if (child_cdata && !child_cdata->mapped)
2432 ELOGF("COMP", "STACK CHANGE CHILD. BUT not mapped. skip. child(ec:%p, win:0x%08zx)", ec, child, e_client_util_win_get(child));
2436 /* Don't stack iconic transients. If the user wants these shown,
2437 * that's another option.
2439 if (child->iconic && e_client_is_iconified_by_client(child)) continue;
2441 transient_policy = e_client_transient_policy_get(child);
2442 if (transient_policy == E_TRANSIENT_ABOVE)
2445 e_client_stack_below(child, below);
2447 e_client_stack_above(child, ec);
2450 else if (transient_policy == E_TRANSIENT_BELOW)
2453 e_client_stack_below(child, above);
2455 e_client_stack_below(child, ec);
2461 if (ec->unredirected_single) return;
2462 _e_client_event_simple(ec, E_EVENT_CLIENT_STACK);
2464 e_client_visibility_calculate();
2467 ////////////////////////////////////////////////
2470 _e_client_maximize(E_Client *ec, E_Maximize max)
2472 int x1, yy1, x2, y2;
2475 int ecx, ecy, ecw, ech;
2476 int desk_x, desk_y, desk_w, desk_h;
2477 Eina_Bool override = ec->maximize_override;
2479 if (!ec->zone) return;
2480 zx = zy = zw = zh = 0;
2481 ec->maximize_override = 1;
2483 if (ec->desk_area.enable && ec->desk_area.desk_area)
2485 desk_x = ec->desk_area.desk_area->x;
2486 desk_y = ec->desk_area.desk_area->y;
2487 desk_w = ec->desk_area.desk_area->w;
2488 desk_h = ec->desk_area.desk_area->h;
2492 desk_x = ec->desk->geom.x;
2493 desk_y = ec->desk->geom.y;
2494 desk_w = ec->desk->geom.w;
2495 desk_h = ec->desk->geom.h;
2498 switch (max & E_MAXIMIZE_TYPE)
2500 case E_MAXIMIZE_NONE:
2504 case E_MAXIMIZE_FULLSCREEN:
2508 e_client_resize_limit(ec, &w, &h);
2509 /* center x-direction */
2510 x1 = desk_x + (desk_w - w) / 2;
2511 /* center y-direction */
2512 yy1 = desk_y + (desk_h - h) / 2;
2514 switch (max & E_MAXIMIZE_DIRECTION)
2516 case E_MAXIMIZE_BOTH:
2517 e_client_maximized_geometry_set(ec, x1, yy1, w, h);
2520 case E_MAXIMIZE_VERTICAL:
2521 e_client_maximized_geometry_set(ec, ec->x, yy1, ec->w, h);
2524 case E_MAXIMIZE_HORIZONTAL:
2525 e_client_maximized_geometry_set(ec, x1, ec->y, w, ec->h);
2528 case E_MAXIMIZE_LEFT:
2529 e_client_maximized_geometry_set(ec, desk_x, desk_y, w / 2, h);
2532 case E_MAXIMIZE_RIGHT:
2533 e_client_maximized_geometry_set(ec, x1, desk_y, w / 2, h);
2538 case E_MAXIMIZE_SMART:
2539 case E_MAXIMIZE_EXPAND:
2540 if (ec->desk->visible)
2542 // base_output_resolution
2543 if (ec->base_output_resolution.use)
2547 zw = ec->base_output_resolution.w;
2548 zh = ec->base_output_resolution.h;
2552 e_zone_desk_useful_geometry_get(ec->zone, ec->desk, &zx, &zy, &zw, &zh);
2559 x2 = desk_x + desk_w;
2560 y2 = desk_y + desk_h;
2561 e_maximize_client_shelf_fill(ec, &x1, &yy1, &x2, &y2, max);
2568 evas_object_smart_callback_call(ec->frame, "maximize", NULL);
2569 e_comp_object_frame_xy_unadjust(ec->frame, ec->x, ec->y, &ecx, &ecy);
2570 e_comp_object_frame_wh_unadjust(ec->frame, ec->w, ec->h, &ecw, &ech);
2578 if (ecx < zx) // window left not useful coordinates
2580 else if (ecx + ecw > zx + zw) // window right not useful coordinates
2582 else // window normal position
2585 if (ecy < zy) // window top not useful coordinates
2587 else if (ecy + ech > zy + zh) // window bottom not useful coordinates
2588 yy1 = zy + zh - ech;
2589 else // window normal position
2592 switch (max & E_MAXIMIZE_DIRECTION)
2594 case E_MAXIMIZE_BOTH:
2595 e_client_maximized_geometry_set(ec, zx, zy, zw, zh);
2598 case E_MAXIMIZE_VERTICAL:
2599 e_client_maximized_geometry_set(ec, ec->x, zy, ec->w, zh);
2602 case E_MAXIMIZE_HORIZONTAL:
2603 e_client_maximized_geometry_set(ec, zx, ec->y, zw, ec->h);
2606 case E_MAXIMIZE_LEFT:
2607 e_client_maximized_geometry_set(ec, zx, zy, zw / 2, zh);
2610 case E_MAXIMIZE_RIGHT:
2611 e_client_maximized_geometry_set(ec, zx + zw / 2, zy, zw / 2, zh);
2617 case E_MAXIMIZE_FILL:
2620 x2 = desk_x + desk_w;
2621 y2 = desk_y + desk_h;
2623 /* walk through all shelves */
2624 e_maximize_client_shelf_fill(ec, &x1, &yy1, &x2, &y2, max);
2626 /* walk through all windows */
2627 e_maximize_client_client_fill(ec, &x1, &yy1, &x2, &y2, max);
2633 e_client_resize_limit(ec, &w, &h);
2634 /* center x-direction */
2635 x1 = x1 + (pw - w) / 2;
2636 /* center y-direction */
2637 yy1 = yy1 + (ph - h) / 2;
2639 switch (max & E_MAXIMIZE_DIRECTION)
2641 case E_MAXIMIZE_BOTH:
2642 e_client_maximized_geometry_set(ec, x1, yy1, w, h);
2645 case E_MAXIMIZE_VERTICAL:
2646 e_client_maximized_geometry_set(ec, ec->x, yy1, ec->w, h);
2649 case E_MAXIMIZE_HORIZONTAL:
2650 e_client_maximized_geometry_set(ec, x1, ec->y, w, ec->h);
2653 case E_MAXIMIZE_LEFT:
2654 e_client_maximized_geometry_set(ec, desk_x, desk_y, w / 2, h);
2657 case E_MAXIMIZE_RIGHT:
2658 e_client_maximized_geometry_set(ec, x1, desk_y, w / 2, h);
2663 if (ec->maximize_override)
2664 ec->maximize_override = override;
2667 ////////////////////////////////////////////////
2669 _e_client_aux_hint_eval(E_Client *ec)
2673 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
2675 E_Comp_Wl_Aux_Hint *hint;
2677 if (cdata && cdata->aux_hint.changed)
2679 _e_client_hook_call(E_CLIENT_HOOK_AUX_HINT_CHANGE, ec);
2681 EINA_LIST_FOREACH_SAFE(cdata->aux_hint.hints, l, ll, hint)
2683 hint->changed = EINA_FALSE;
2686 ELOGF("COMP", "AUX_HINT |Del [%d:%s:%s]", ec, hint->id, hint->hint, hint->val);
2687 if (hint->hint) eina_stringshare_del(hint->hint);
2688 if (hint->val) eina_stringshare_del(hint->val);
2689 cdata->aux_hint.hints = eina_list_remove_list(cdata->aux_hint.hints, l);
2693 cdata->aux_hint.changed = 0;
2698 _e_client_apply_auto_placement(E_Client *ec)
2700 Eina_List *skiplist = NULL;
2701 int new_x, new_y, t = 0;
2703 E_Client *parent_ec;
2705 // intercept auto placement policy
2706 if (!_e_client_intercept_hook_call(E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT, ec))
2708 ELOGF("POL", "Intercepted auto_placement policy.", ec);
2712 int zx = 0, zy = 0, zw = 0, zh = 0;
2713 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
2715 unsigned int seed = (unsigned int)time(NULL);
2718 new_x = zx + (rand_r(&seed) % (zw - ec->w));
2722 new_y = zy + (rand_r(&seed) % (zh - ec->h));
2726 e_comp_object_frame_geometry_get(ec->frame, NULL, NULL, &t, NULL);
2728 parent_ec = ec->parent;
2732 new_x = parent_ec->x;
2733 new_y = parent_ec->y;
2735 else if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
2738 skiplist = eina_list_append(skiplist, ec);
2740 e_place_desk_region_smart(ec->desk, skiplist,
2741 ec->x, ec->y, ec->w, ec->h,
2744 e_place_zone_region_smart(ec->zone, skiplist,
2745 ec->x, ec->y, ec->w, ec->h,
2748 eina_list_free(skiplist);
2750 else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
2753 e_place_zone_manual(ec->zone, ec->w, t, &new_x, &new_y);
2758 e_place_zone_cursor(ec->zone, ec->x, ec->y, ec->w, ec->h,
2762 ELOGF("POL", "Apply auto placement (type:%d). (%d,%d) -> (%d,%d).", ec, type, ec->x, ec->y, new_x, new_y);
2763 e_client_pos_set(ec, new_x, new_y);
2764 ec->changes.pos = 1;
2766 ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
2770 _e_client_eval(E_Client *ec)
2773 unsigned int prop = 0;
2779 if (e_object_is_del(E_OBJECT(ec)))
2781 CRI("_e_client_eval(%p) with deleted border! - %d\n", ec, ec->new_client);
2786 TRACE_DS_BEGIN(CLIENT:EVAL);
2788 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_NEW_CLIENT, ec))
2794 if ((ec->new_client) && (!e_client_util_ignored_get(ec)) && (ec->zone))
2796 int zx = 0, zy = 0, zw = 0, zh = 0;
2798 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
2799 /* enforce wm size hints for initial sizing */
2800 if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
2802 tw = MIN(ec->w, ec->zone->w);
2803 th = MIN(ec->h, ec->zone->h);
2804 e_client_size_set(ec, tw, th);
2809 e_client_resize_limit(ec, &nw, &nh);
2810 e_client_size_set(ec, nw, nh);
2814 int x = ec->x, y = ec->y;
2815 if (ec->x) e_comp_object_frame_xy_adjust(ec->frame, ec->x, 0, &ec->x, NULL);
2816 if (ec->y) e_comp_object_frame_xy_adjust(ec->frame, 0, ec->y, NULL, &ec->y);
2817 if ((x != ec->x) || (y != ec->y)) ec->changes.pos = 1;
2819 ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
2825 if (ec->parent->zone != e_zone_current_get())
2827 e_client_zone_set(ec, ec->parent->zone);
2828 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
2831 if (evas_object_visible_get(ec->parent->frame))
2833 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
2834 e_client_geometry_get(ec->parent, &px, &py, &pw, &ph);
2836 if ((!E_CONTAINS(ex, ey, ew, eh, zx, zy, zw, zh)) ||
2837 (!E_CONTAINS(ex, ey, ew, eh, px, py, pw, ph)))
2841 e_comp_object_util_center_pos_get(ec->parent->frame, &x, &y);
2842 if (E_CONTAINS(x, y, ew, eh, zx, zy, zw, zh))
2844 e_client_pos_set(ec, x, y);
2851 if (!E_CONTAINS(x, y, ew, eh, zx, zy, zw, zh))
2853 e_comp_object_util_center_on(ec->frame,
2857 ec->changes.pos = 1;
2862 e_comp_object_util_center_on(ec->frame,
2864 ec->changes.pos = 1;
2867 ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
2869 else if (ec->dialog)
2871 tx = zx + ((zw - ec->w) / 2);
2872 ty = zy + ((zh - ec->h) / 2);
2873 e_client_pos_set(ec, tx, ty);
2875 ec->changes.pos = 1;
2877 ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
2882 eai = e_appinfo_find_with_pid(ec->netwm.pid);
2886 _e_client_apply_auto_placement(ec);
2890 if (e_appinfo_auto_placement_get(eai))
2891 _e_client_apply_auto_placement(ec);
2894 /* Recreate state */
2895 if (ec->e.state.centered)
2897 tx = zx + (zw - ec->w) / 2;
2898 ty = zy + (zh - ec->h) / 2;
2899 e_client_pos_set(ec, tx, ty);
2900 ec->changes.pos = 1;
2903 /* if the explicit geometry request asks for the app to be
2904 * in another zone - well move it there */
2906 E_Zone *zone = NULL;
2911 if ((!ec->re_manage) && ((ec->x != x) || (ec->y != y)))
2912 zone = e_comp_zone_xy_get(x, y);
2916 zone = e_comp_zone_xy_get(ec->x + (ec->w / 2), ec->y + (ec->h / 2));
2919 E_Zone *z2 = e_comp_zone_xy_get(ec->x, ec->y);
2921 if (z2 && (z2 != zone))
2927 EINA_LIST_FOREACH(e_comp->zones, l, z2)
2931 x = ec->x, y = ec->y, w = ec->w, h = ec->h;
2932 E_RECTS_CLIP_TO_RECT(x, y, w, h, z2->x, z2->y, z2->w, z2->h);
2933 if (w * h == z2->w * z2->h)
2935 /* client fully covering zone */
2939 if ((unsigned)(w * h) > psz)
2950 zone = e_comp_zone_xy_get(ec->x, ec->y);
2952 zone = e_comp_zone_xy_get(ec->x + ec->w - 1, ec->y);
2954 zone = e_comp_zone_xy_get(ec->x + ec->w - 1, ec->y + ec->h - 1);
2956 zone = e_comp_zone_xy_get(ec->x, ec->y + ec->h - 1);
2957 if ((zone) && (zone != ec->zone))
2958 e_client_zone_set(ec, zone);
2962 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT, ec))
2968 /* effect changes to the window border itself */
2969 if ((ec->changes.shading))
2971 /* show at start of unshade (but don't hide until end of shade) */
2972 ec->changes.shading = 0;
2975 if (ec->changes.shaded) send_event = 0;
2976 if ((ec->changes.shaded) && (ec->changes.pos) && (ec->changes.size))
2978 ec->changes.shaded = 0;
2980 else if ((ec->changes.shaded) && (ec->changes.pos))
2982 ec->changes.size = 1;
2983 ec->changes.shaded = 0;
2985 else if ((ec->changes.shaded) && (ec->changes.size))
2987 ec->changes.shaded = 0;
2989 else if (ec->changes.shaded)
2991 ec->changes.shaded = 0;
2994 if (ec->changes.size)
2996 ec->changes.size = 0;
2997 if ((!ec->shaded) && (!ec->shading))
2998 evas_object_resize(ec->frame, ec->w, ec->h);
3000 prop |= E_CLIENT_PROPERTY_SIZE;
3002 if (ec->changes.pos)
3004 ec->changes.tz_position = 0;
3005 ec->changes.pos = 0;
3006 evas_object_move(ec->frame, ec->x, ec->y);
3007 prop |= E_CLIENT_PROPERTY_POS;
3010 if (ec->changes.reset_gravity)
3012 ec->changes.reset_gravity = 0;
3013 prop |= E_CLIENT_PROPERTY_GRAVITY;
3016 if (ec->changes.title)
3018 ec->changes.title = 0;
3019 prop |= E_CLIENT_PROPERTY_TITLE;
3022 if ((ec->changes.visible) && (ec->visible) && (ec->new_client) && (!ec->iconic))
3026 e_input_device_pointer_xy_get(NULL, &x, &y);
3027 if ((!ec->placed) && (!ec->re_manage) &&
3028 (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
3029 (!((ec->icccm.transient_for != 0) ||
3031 (!ecmove) && (!ecresize))
3033 /* Set this window into moving state */
3035 ec->cur_mouse_action = e_action_find("window_move");
3036 if (ec->cur_mouse_action)
3038 if ((!ec->cur_mouse_action->func.end_mouse) &&
3039 (!ec->cur_mouse_action->func.end))
3040 ec->cur_mouse_action = NULL;
3041 if (ec->cur_mouse_action)
3044 tx = x - (ec->w >> 1);
3045 e_comp_object_frame_geometry_get(ec->frame, NULL, NULL, &t, NULL);
3047 e_client_pos_set(ec, tx, ty);
3049 ec->changes.pos = 1;
3054 evas_object_show(ec->frame);
3055 if (evas_object_visible_get(ec->frame))
3057 if (ec->cur_mouse_action)
3059 ec->moveinfo.down.x = ec->x;
3060 ec->moveinfo.down.y = ec->y;
3061 ec->moveinfo.down.w = ec->w;
3062 ec->moveinfo.down.h = ec->h;
3063 ec->mouse.current.mx = x;
3064 ec->mouse.current.my = y;
3065 ec->moveinfo.down.button = 0;
3066 ec->moveinfo.down.mx = x;
3067 ec->moveinfo.down.my = y;
3069 e_object_ref(E_OBJECT(ec->cur_mouse_action));
3070 ec->cur_mouse_action->func.go(E_OBJECT(ec), NULL);
3071 if (e_config->border_raise_on_mouse_action)
3073 if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
3075 ELOGF("FOCUS", "focus set | client eval", ec);
3076 e_client_frame_focus_set(ec, EINA_TRUE);
3079 ec->changes.visible = 0;
3080 _e_client_event_show(ec);
3083 else if ((ec->changes.visible) && (ec->new_client))
3085 ec->changes.visible = 0;
3087 _e_client_event_hide(ec);
3090 if (ec->changes.icon)
3092 ec->changes.icon = 0;
3096 e_comp->new_clients--;
3098 ec->changed = ec->changes.pos || ec->changes.size ||
3099 ec->changes.stack || ec->changes.prop || ec->changes.border ||
3100 ec->changes.reset_gravity || ec->changes.shading || ec->changes.shaded ||
3101 ec->changes.shape || ec->changes.shape_input || ec->changes.icon ||
3102 ec->changes.internal_state ||
3103 ec->changes.need_maximize || ec->changes.need_unmaximize;
3104 ec->changes.stack = 0;
3106 if ((!ec->input_only) && (!ec->iconic) &&
3107 ((!ec->zone) || e_client_util_desk_visible(ec, e_desk_current_get(ec->zone))) &&
3108 ((ec->take_focus) || (ec->want_focus)))
3111 if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (ec->want_focus))
3114 #if 0 // focus should be set to the top window
3115 e_client_focus_set_with_pointer(ec);
3118 else if (ec->dialog)
3120 if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
3121 ((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
3122 (ec->parent == e_client_focused_get())))
3124 e_client_focus_set_with_pointer(ec);
3129 /* focus window by default when it is the only one on desk */
3130 E_Client *ec2 = NULL;
3132 EINA_LIST_FOREACH(focus_stack, l, ec2)
3134 if (ec == ec2) continue;
3135 if ((!ec2->iconic) && (ec2->visible) &&
3136 ((ec->desk == ec2->desk) || ec2->sticky))
3142 e_client_focus_set_with_pointer(ec);
3147 ec->take_focus = ec->want_focus = 0;
3149 if (ec->changes.need_maximize)
3151 E_Maximize max = ec->maximized;
3152 ec->maximized = E_MAXIMIZE_NONE;
3153 e_client_maximize(ec, max);
3154 ec->changes.need_maximize = 0;
3156 else if (ec->changes.need_unmaximize)
3158 e_client_unmaximize(ec, ec->maximized);
3159 ec->changes.need_unmaximize = 0;
3162 if (ec->need_fullscreen)
3164 e_client_fullscreen(ec, e_config->fullscreen_policy);
3165 ec->need_fullscreen = 0;
3168 if (ec->changes.accepts_focus)
3170 if ((!ec->icccm.accepts_focus) && (!ec->icccm.take_focus))
3173 ec->changes.accepts_focus = 0;
3177 if (send_event && prop)
3179 _e_client_event_property(ec, prop);
3182 _e_client_aux_hint_eval(ec);
3184 e_client_transform_core_update(ec);
3185 _e_client_hook_call(E_CLIENT_HOOK_EVAL_END, ec);
3191 _e_client_frame_update(E_Client *ec)
3193 const char *bordername;
3195 ec->border.changed = 0;
3196 if (!e_comp_object_frame_allowed(ec->frame)) return;
3197 if (ec->fullscreen || ec->borderless)
3198 bordername = "borderless";
3199 else if (ec->bordername)
3200 bordername = ec->bordername;
3201 else if (ec->mwm.borderless)
3202 bordername = "borderless";
3203 else if (((ec->icccm.transient_for != 0) || (ec->dialog)) &&
3204 (ec->icccm.min_w == ec->icccm.max_w) &&
3205 (ec->icccm.min_h == ec->icccm.max_h))
3206 bordername = "noresize_dialog";
3207 else if ((ec->icccm.min_w == ec->icccm.max_w) &&
3208 (ec->icccm.min_h == ec->icccm.max_h))
3209 bordername = "noresize";
3210 else if (ec->shaped)
3211 bordername = "shaped";
3212 else if (ec->urgent)
3213 bordername = "urgent";
3214 else if (ec->netwm.state.modal)
3215 bordername = "modal";
3216 else if ((ec->netwm.state.skip_taskbar) ||
3217 (ec->netwm.state.skip_pager))
3218 bordername = "skipped";
3220 else if ((ec->internal) && (ec->icccm.class) &&
3221 (!strncmp(ec->icccm.class, "e_fwin", 6)))
3222 bordername = "internal_fileman";
3225 bordername = e_config->theme_default_border_style;
3226 if (!bordername) bordername = "default";
3228 e_client_border_set(ec, bordername);
3232 _e_client_type_match(E_Client *ec, E_Config_Client_Type *m)
3234 if (!ec || !m) return EINA_FALSE;
3235 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
3237 if ((int)ec->netwm.type != m->window_type)
3240 #if defined(__cplusplus) || defined(c_plusplus)
3243 if (!ec->icccm.cpp_class)
3246 if (!e_util_glob_match(ec->icccm.cpp_class, m->clas))
3252 if (!ec->icccm.class)
3255 if (!e_util_glob_match(ec->icccm.class, m->clas))
3262 if (ec->icccm.name && e_util_glob_match(ec->icccm.name, m->name))
3265 if (ec->icccm.title && e_util_glob_match(ec->icccm.title, m->name))
3268 if (ec->netwm.name && e_util_glob_match(ec->netwm.name, m->name))
3276 _e_client_type_get(E_Client *ec)
3278 E_Config_Client_Type *m;
3282 if (!e_config->client_types) return 0;
3284 EINA_LIST_FOREACH(e_config->client_types, l, m)
3286 if (!_e_client_type_match(ec, m)) continue;
3289 type = m->client_type;
3294 ec->client_type = type;
3296 return ec->client_type;
3300 _e_client_transform_sub_apply(E_Client *ec, E_Client *epc, double zoom)
3302 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
3306 int ox = 0, oy = 0, ow, oh;
3310 EINA_SAFETY_ON_FALSE_RETURN(e_comp_wl_subsurface_check(ec));
3312 e_comp_wl_subsurface_position_get(ec, &ox, &oy);
3313 ow = cdata->width_from_viewport;
3314 oh = cdata->height_from_viewport;
3316 map = e_client_map_get(epc);
3317 e_map_point_coord_get(map, 0, &px, &py, 0);
3320 mx = ox * zoom + px;
3321 my = oy * zoom + py;
3325 map = e_map_new_with_direct_render(ec->transform_core.direct_render);
3326 e_map_util_points_populate_from_geometry(map, mx, my, mw, mh, 0);
3327 e_map_util_object_move_sync_set(map, EINA_TRUE);
3328 e_client_map_set(ec, map);
3329 e_client_map_enable_set(ec, EINA_TRUE);
3331 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
3332 _e_client_transform_sub_apply(subc, ec, zoom);
3333 EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
3334 _e_client_transform_sub_apply(subc, ec, zoom);
3340 _e_client_transient_for_group_make(E_Client *ec, Eina_List **list)
3347 if (e_config->transient.raise)
3349 EINA_LIST_FOREACH(ec->transients, l, child)
3351 if (!child) continue;
3354 if (e_client_transient_policy_get(child) == E_TRANSIENT_ABOVE)
3356 *list = eina_list_prepend(*list, child);
3357 _e_client_transient_for_group_make(child, list);
3365 e_client_transient_child_top_get(E_Client *ec, Eina_Bool consider_focus)
3367 E_Client *top_ec = NULL;
3368 Eina_List *transient_list = NULL;
3370 _e_client_transient_for_group_make(ec, &transient_list);
3374 Eina_List *l = NULL;
3375 E_Client *temp_ec = NULL;
3376 E_Client *temp_ec2 = NULL;
3378 E_CLIENT_REVERSE_FOREACH(temp_ec)
3387 EINA_LIST_FOREACH(transient_list, l, temp_ec2)
3389 if (temp_ec == temp_ec2)
3393 if ((temp_ec2->icccm.accepts_focus) ||
3394 (temp_ec2->icccm.take_focus))
3407 eina_list_free(transient_list);
3412 #ifdef EC_IS_NOT_VISIBLE
3413 # undef EC_IS_NOT_VISIBLE
3415 #define EC_IS_NOT_VISIBLE if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)
3418 _e_client_visibility_touched_check(E_Client *ec)
3422 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
3424 tx = wl_fixed_to_int(e_comp->wl_comp_data->ptr.x);
3425 ty = wl_fixed_to_int(e_comp->wl_comp_data->ptr.y);
3427 return _e_client_position_inside_input_rect(ec, tx, ty);
3431 _e_client_visibility_zone_calculate(E_Zone *zone)
3436 Eina_Rectangle r, *_r;
3438 Eina_Bool canvas_vis = EINA_TRUE;
3439 Eina_Bool ec_vis, ec_opaque, calc_region;
3440 Eina_Bool skip_rot_pending_show = EINA_FALSE;
3441 int skip_by_pending_show = 0;
3442 Eina_Bool is_above_show_pending = EINA_FALSE;
3443 Eina_Bool is_launching_effect = EINA_FALSE;
3444 Eina_Bool is_vis_on_skip = EINA_FALSE;
3445 Eina_Bool is_display_off = EINA_FALSE;
3447 int x = 0, y = 0, w = 0, h = 0;
3449 E_Comp_Wl_Client_Data *cdata;
3450 Eina_List *changed_list = NULL;
3451 Eina_List *l = NULL;
3452 Eina_Bool effect_running = EINA_FALSE;
3453 Eina_Bool ec_frame_visible = EINA_FALSE;
3454 int calc_skip_type = 0;
3456 Eina_Bool touched_win_changed = EINA_FALSE;
3457 E_Client *touched_ec;
3459 Eina_Bool iconified_by_client = EINA_FALSE;
3461 if (!e_config->calc_vis_without_effect)
3463 if (e_comp->animating) return;
3468 TRACE_DS_BEGIN(CLIENT:VISIBILITY CALCULATE);
3470 t = eina_tiler_new(zone->w + zone->x + edge, zone->h + zone->y + edge);
3471 eina_tiler_tile_size_set(t, 1, 1);
3473 if (zone->display_state != E_ZONE_DISPLAY_STATE_OFF)
3475 EINA_RECTANGLE_SET(&r, zone->x, zone->y, zone->w, zone->h);
3476 eina_tiler_rect_add(t, &r);
3480 is_display_off = EINA_TRUE;
3481 canvas_vis = EINA_FALSE;
3482 _e_client_hook_call(E_CLIENT_HOOK_CAL_VISIBILITY_DISPLAY_OFF, NULL);
3485 E_CLIENT_REVERSE_FOREACH(ec)
3488 if (e_object_is_del(E_OBJECT(ec))) continue;
3489 if (e_client_util_ignored_get(ec)) continue;
3490 if (ec->zone != zone) continue;
3491 if (!ec->frame) continue;
3492 if (ec->visibility.skip) continue;
3493 if (ec->is_cursor) continue;
3494 cdata = e_client_cdata_get(ec);
3495 if (e_comp_wl_subsurface_check(ec)) continue;
3496 if ((!ec->first_mapped) &&
3497 (e_comp_object_content_type_get(ec->frame) == E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)) continue;
3499 /* TODO: need to check whether window intersects with entire screen, not zone. */
3500 /* if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h)) continue; */
3504 if ((ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED) &&
3505 (ec->visibility.last_sent_type != E_VISIBILITY_FULLY_OBSCURED))
3507 ec->visibility.changed = 1;
3511 if (!e_config->calc_vis_without_effect)
3513 if ((e_comp_object_is_animating(ec->frame)) ||
3514 (evas_object_data_get(ec->frame, "effect_running")))
3516 effect_running = EINA_TRUE;
3518 is_launching_effect = EINA_TRUE;
3523 e_client_geometry_get(ec, &x, &y, &w, &h);
3527 ec_vis = ec_opaque = skip_rot_pending_show = is_vis_on_skip = EINA_FALSE;
3528 skip_by_pending_show = 0;
3529 calc_region = EINA_TRUE;
3530 ec_frame_visible = evas_object_visible_get(ec->frame);
3531 iconified_by_client = e_client_is_iconified_by_client(ec);
3535 EC_IS_NOT_VISIBLE continue;
3536 calc_region = EINA_FALSE;
3537 calc_skip_type |= 0x01;
3539 else if (!ec_frame_visible)
3541 if (ec->e.state.rot.pending_show)
3543 calc_region = EINA_FALSE;
3544 calc_skip_type |= 0x02;
3545 skip_rot_pending_show = EINA_TRUE;
3546 skip_by_pending_show = 1;
3548 else if (ec->show_pending.count > 0)
3550 calc_region = EINA_FALSE;
3551 calc_skip_type |= 0x40;
3552 skip_by_pending_show = 2;
3556 if (cdata && !cdata->mapped)
3558 EC_IS_NOT_VISIBLE continue;
3559 calc_region = EINA_FALSE;
3560 calc_skip_type |= 0x04;
3565 EC_IS_NOT_VISIBLE continue;
3566 calc_region = EINA_FALSE;
3567 calc_skip_type |= 0x08;
3571 if (iconified_by_client)
3573 EC_IS_NOT_VISIBLE continue;
3575 E_Iconified_Type iconified_type;
3576 iconified_type = e_client_iconified_type_get(ec);
3577 if (iconified_type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT)
3578 calc_skip_type |= 0x10;
3579 else if (iconified_type == E_ICONIFIED_TYPE_DESK_ICONIFY_BY_CLIENT)
3580 calc_skip_type |= 0x40;
3583 ELOGF("POL_VIS", "CRI. Check iconified_type... cur type:%d", ec, iconified_type);
3584 calc_skip_type |= 0x80;
3586 calc_region = EINA_FALSE;
3592 EC_IS_NOT_VISIBLE continue;
3593 calc_region = EINA_FALSE;
3594 calc_skip_type |= 0x20;
3599 if (ec->visibility.ignore_geometry)
3601 calc_region = EINA_FALSE;
3602 if (!is_display_off && ec_frame_visible)
3609 (!ec->visibility.force_obscured) &&
3610 (!iconified_by_client))
3612 it = eina_tiler_iterator_new(t);
3613 EINA_ITERATOR_FOREACH(it, _r)
3615 if (E_INTERSECTS(x, y, w, h,
3616 _r->x, _r->y, _r->w, _r->h))
3622 eina_iterator_free(it);
3628 /* unobscured case */
3631 if ((!is_above_show_pending) &&
3632 ((!effect_running) ||
3633 ((effect_running) && (!is_launching_effect))))
3635 /* previous state is obscured: -1 or 1 */
3636 ec->visibility.obscured = E_VISIBILITY_UNOBSCURED;
3637 ec->visibility.changed = 1;
3638 ELOGF("POL_VIS", "CLIENT VIS ON. argb:%d, opaque:%2d, frame_v:%d, ignore_geometry:%d, cdata:%p, geo(%d,%d,%dx%d), asp:%d, er:%d, le:%d", ec, ec->argb, ec->visibility.opaque, ec_frame_visible, ec->visibility.ignore_geometry, cdata, x, y, w, h, is_above_show_pending, effect_running, is_launching_effect);
3642 if (!is_above_show_pending)
3643 is_vis_on_skip = EINA_TRUE;
3644 ELOGF("POL_VIS", "CLIENT VIS ON-SKIP. argb:%d, opaque:%2d, frame_v:%d, ignore_geometry:%d, cdata:%p, geo(%d,%d,%dx%d), asp:%d, er:%d, le:%d", ec, ec->argb, ec->visibility.opaque, ec_frame_visible, ec->visibility.ignore_geometry, cdata, x, y, w, h, is_above_show_pending, effect_running, is_launching_effect);
3648 /* subtract window region from canvas region */
3649 if (canvas_vis && !skip_by_pending_show && !is_vis_on_skip)
3651 /* check alpha window is opaque or not. */
3652 if ((ec->visibility.opaque > 0) && (ec->argb))
3653 ec_opaque = EINA_TRUE;
3655 /* if e_client is not alpha or opaque then delete intersect rect */
3656 if (((!ec->argb) || (ec_opaque)) &&
3659 EINA_RECTANGLE_SET(&r,
3664 eina_tiler_rect_del(t, &r);
3666 if (eina_tiler_empty(t))
3667 canvas_vis = EINA_FALSE;
3673 /* It prevents unwanted iconification of the top visible window
3674 * while showing an window with rotation mode.
3675 * However, with rotation mode, iconification is done if client
3676 * is iconified by itself.
3678 if ((!skip_by_pending_show) ||
3679 (ec->visibility.force_obscured) ||
3681 (iconified_by_client))
3684 if (ec->visibility.obscured != E_VISIBILITY_FULLY_OBSCURED)
3686 /* previous state is unobscured: -1 or 0 */
3687 ec->visibility.obscured = E_VISIBILITY_FULLY_OBSCURED;
3688 ec->visibility.changed = 1;
3689 ELOGF("POL_VIS", "CLIENT VIS OFF. argb:%d, opaque:%2d, frame_v:%d, canvas_v:%d, calc_r:%d(%d), ignore_geometry:%d, show_p:%d, geo(%d,%d,%dx%d)",
3690 ec, ec->argb, ec->visibility.opaque,
3691 ec_frame_visible, canvas_vis, calc_region, calc_skip_type, ec->visibility.ignore_geometry, skip_by_pending_show, x, y, w, h);
3696 if (!is_vis_on_skip &&
3697 (!skip_rot_pending_show || ec->visibility.changed))
3698 changed_list = eina_list_append(changed_list, ec);
3700 if (skip_rot_pending_show)
3702 if (ec->e.state.rot.pending_show && !ec->argb)
3703 is_above_show_pending = EINA_TRUE;
3704 ELOGF("POL_VIS", "Rotation pending show. srps:%d, rps:%d, argb:%d, asp:%d", ec, skip_rot_pending_show, ec->e.state.rot.pending_show, ec->argb, is_above_show_pending);
3710 touched_ec = e_comp_wl->ptr.ec ? e_comp_wl->ptr.ec : e_comp_wl->touch.faked_ec;
3711 EINA_LIST_FOREACH(changed_list, l, ec)
3713 if (ec->visibility.changed)
3714 _e_client_event_simple(ec, E_EVENT_CLIENT_VISIBILITY_CHANGE);
3716 _e_client_hook_call(E_CLIENT_HOOK_EVAL_VISIBILITY, ec);
3718 if (ec == touched_ec)
3719 touched_win_changed = EINA_TRUE;
3721 if (ec->visibility.obscured == E_VISIBILITY_UNOBSCURED)
3723 if (e_comp_wl->touch.pressed && !touched_win_changed && !e_policy_client_is_keyboard_sub(ec))
3725 if (_e_client_visibility_touched_check(ec))
3727 touched_win_changed = EINA_TRUE;
3728 e_comp_wl_touch_cancel();
3733 ec->visibility.changed = 0;
3734 _e_visibility_changed = 1;
3737 changed_list = eina_list_free(changed_list);
3741 _e_client_hook_call(E_CLIENT_HOOK_EVAL_VISIBILITY_END, NULL);
3747 _e_client_merge_focus_stack_with_defer_focus(void)
3749 Eina_List *l = NULL;
3750 E_Client *ec = NULL, *defer_ec = NULL;
3751 Eina_Bool find_rel = EINA_FALSE;
3752 Eina_Bool inserted = EINA_FALSE;
3754 if (focus_track_frozen > 0) return;
3755 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
3759 focus_stack = eina_list_merge(focus_stack, defer_focus_stack);
3763 E_CLIENT_FOREACH(defer_ec)
3765 if (!eina_list_data_find(defer_focus_stack, defer_ec)) continue;
3767 find_rel = EINA_FALSE;
3768 inserted = EINA_FALSE;
3769 focus_stack = eina_list_remove(focus_stack, defer_ec);
3771 EINA_LIST_FOREACH(focus_stack, l, ec)
3773 if (ec == NULL) continue;
3778 find_rel = EINA_TRUE;
3782 if (ec->layer > defer_ec->layer) continue;
3784 focus_stack = eina_list_prepend_relative_list(focus_stack, defer_ec, l);
3785 inserted = EINA_TRUE;
3790 focus_stack = eina_list_append(focus_stack, defer_ec);
3794 defer_focus_stack = eina_list_free(defer_focus_stack);
3799 _e_client_focus_calculate(E_Zone *zone)
3801 E_Client *defered_focus_ec = NULL, *reverted_focus_ec = NULL;
3802 E_Client *ec = NULL, *old_focused = NULL, *cec = NULL;
3803 Eina_List *child_list = NULL;
3804 Eina_List *l = NULL;
3805 Eina_Bool child_deferred;
3807 EINA_SAFETY_ON_NULL_RETURN(zone);
3808 if (zone->display_state == E_ZONE_DISPLAY_STATE_OFF) return;
3810 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK)
3812 ec = _e_client_focus_topmost_focusable_get();
3816 if (!ec) ELOGF("FOCUS", "focus unset | No focusable ec", focused);
3817 e_client_frame_focus_set(focused, EINA_FALSE);
3821 ELOGF("FOCUS", "focus set | topmost focus calculate", ec);
3822 e_client_frame_focus_set(ec, EINA_TRUE);
3829 (focused != eina_list_data_get(focus_stack)) ||
3830 (!_e_client_focus_can_take(focused)))
3832 reverted_focus_ec = _e_client_revert_focus_get(focused);
3833 if (!reverted_focus_ec && focused)
3835 e_client_focus_defer_unset(focused);
3836 old_focused = focused;
3840 E_CLIENT_REVERSE_FOREACH(ec)
3842 if (!eina_list_data_find(defer_focus_stack, ec)) continue;
3844 if (e_object_is_del(E_OBJECT(ec))) continue;
3845 if (e_client_util_ignored_get(ec)) continue;
3846 if (ec->zone != zone) continue;
3847 if (!e_desk_current_get(ec->zone)) continue;
3848 if (ec->desk != e_desk_current_get(ec->zone)) continue;
3850 if (!(ec->icccm.accepts_focus || ec->icccm.take_focus)) continue;
3851 if (ec->lock_focus_in || ec->lock_focus_out) continue;
3852 if (!evas_object_visible_get(ec->frame)) continue;
3853 if (ec->iconic) continue;
3854 if (ec->bg_state) continue;
3856 if (!(cec = _e_client_check_obscured_by_children_group(ec)) ||
3857 _e_client_check_really_iconified(cec))
3859 if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) continue;
3860 if (_e_client_check_fully_contain_by_above(ec, EINA_FALSE)) continue;
3863 if (focused && (focused->layer > ec->layer)) continue;
3864 else if (!focused && reverted_focus_ec && (reverted_focus_ec->layer > ec->layer)) continue;
3866 // check transient_for child defered
3867 child_deferred = EINA_FALSE;
3868 child_list = eina_list_clone(ec->transients);
3869 EINA_LIST_FOREACH(child_list, l, cec)
3871 if (e_client_transient_policy_get(cec) == E_TRANSIENT_BELOW) continue;
3872 if (!(cec->icccm.accepts_focus || cec->icccm.take_focus)) continue;
3873 if (eina_list_data_find(defer_focus_stack, cec))
3875 child_deferred = EINA_TRUE;
3879 eina_list_free(child_list);
3880 if (child_deferred) continue;
3882 defered_focus_ec = ec;
3886 if (defered_focus_ec)
3888 if (defered_focus_ec != focused)
3890 ELOGF("FOCUS", "focus set | focus calculate (defer_focus)", defered_focus_ec);
3892 e_client_focus_defer_unset(focused);
3893 e_client_frame_focus_set(defered_focus_ec, EINA_TRUE);
3896 e_client_focus_defer_unset(defered_focus_ec);
3898 _e_client_merge_focus_stack_with_defer_focus();
3900 else if(reverted_focus_ec)
3902 if (reverted_focus_ec != focused)
3904 ELOGF("FOCUS", "focus set | focus calculate (revert_focus)", reverted_focus_ec);
3906 e_client_focus_defer_unset(focused);
3907 e_client_frame_focus_set(reverted_focus_ec, EINA_TRUE);
3910 else if (old_focused)
3912 ELOGF("FOCUS", "focus unset | focus calculate", old_focused);
3913 e_client_frame_focus_set(old_focused, EINA_FALSE);
3920 _e_client_transform_core_check_change(E_Client *ec)
3924 Eina_Bool check = EINA_FALSE;
3925 if (!ec) return EINA_FALSE;
3928 evas_object_geometry_get(ec->frame, 0, 0, &w, &h);
3930 // check client position or size change
3931 if (ec->x != ec->transform_core.backup.client_x ||
3932 ec->y != ec->transform_core.backup.client_y ||
3933 ec->w != ec->transform_core.backup.client_w ||
3934 ec->h != ec->transform_core.backup.client_h ||
3935 w != ec->transform_core.backup.frame_w ||
3936 h != ec->transform_core.backup.frame_h ||
3937 ec->argb != ec->transform_core.backup.argb)
3940 ec->transform_core.backup.client_x = ec->x;
3941 ec->transform_core.backup.client_y = ec->y;
3942 ec->transform_core.backup.client_w = ec->w;
3943 ec->transform_core.backup.client_h = ec->h;
3944 ec->transform_core.backup.frame_w = w;
3945 ec->transform_core.backup.frame_h = h;
3946 ec->transform_core.backup.argb = ec->argb;
3949 // check new transform or del transform
3950 if (ec->transform_core.changed)
3953 ec->transform_core.changed = EINA_FALSE;
3956 // check each transform change
3957 if (ec->transform_core.transform_list)
3961 E_Util_Transform *transform;
3963 EINA_LIST_FOREACH_SAFE(ec->transform_core.transform_list, l, l_next, transform)
3965 // del transform check
3966 if (e_util_transform_ref_count_get(transform) <= 1)
3968 ec->transform_core.transform_list = eina_list_remove(ec->transform_core.transform_list, transform);
3969 e_util_transform_unref(transform);
3974 // transform change test
3975 if (e_util_transform_change_get(transform))
3978 e_util_transform_change_unset(transform);
3983 if (e_comp_wl_subsurface_check(ec))
3985 // check parent matrix change
3986 E_Client *parent = e_comp_wl_subsurface_parent_get(ec);
3987 if (parent && parent->transform_core.result.enable)
3989 ec->transform_core.parent.enable = EINA_TRUE;
3991 if (!e_util_transform_matrix_equal_check(&ec->transform_core.parent.matrix,
3992 &parent->transform_core.result.matrix))
3995 ec->transform_core.parent.matrix = parent->transform_core.result.matrix;
3997 if (memcmp(&ec->transform_core.parent.zoom, &parent->transform_core.result.transform.zoom, sizeof(E_Util_Transform_Zoom)) != 0)
4000 ec->transform_core.parent.zoom = parent->transform_core.result.transform.zoom;
4003 else if (ec->transform_core.parent.enable)
4005 ec->transform_core.parent.enable = EINA_FALSE;
4006 e_util_transform_matrix_load_identity(&ec->transform_core.parent.matrix);
4007 ec->transform_core.parent.zoom.zoom_x = 1.0;
4008 ec->transform_core.parent.zoom.zoom_y = 1.0;
4009 ec->transform_core.parent.zoom.cx = 0;
4010 ec->transform_core.parent.zoom.cy = 0;
4019 _e_client_transform_core_boundary_update(E_Client *ec, E_Util_Transform_Rect_Vertex *vertices)
4021 int minx = 99999, miny = 99999;
4022 int maxx = -99999, maxy = -99999;
4027 if (!ec->frame) return;
4028 if (!ec->transform_core.result.enable) return;
4029 if (!vertices) return;
4031 for (i = 0; i < 4; ++i)
4036 e_util_transform_vertices_pos_round_get(vertices, i, &x, &y, 0, 0);
4038 if (x < minx) minx = x;
4039 if (y < miny) miny = y;
4040 if (x > maxx) maxx = x;
4041 if (y > maxy) maxy = y;
4044 ec->transform_core.result.boundary.x = minx;
4045 ec->transform_core.result.boundary.y = miny;
4046 ec->transform_core.result.boundary.w = maxx - minx;
4047 ec->transform_core.result.boundary.h = maxy - miny;
4049 ELOGF("COMP", "[Transform][boundary][%d %d %d %d]",
4051 ec->transform_core.result.boundary.x,
4052 ec->transform_core.result.boundary.y,
4053 ec->transform_core.result.boundary.w,
4054 ec->transform_core.result.boundary.h);
4058 _e_client_transform_core_map_new(Evas_Object *obj,
4059 E_Util_Transform_Rect_Vertex *vertices,
4060 E_Util_Transform *transform,
4061 Eina_Bool direct_render)
4068 map = e_map_new_with_direct_render(direct_render);
4069 EINA_SAFETY_ON_NULL_RETURN_VAL(map, NULL);
4071 e_map_util_points_populate_from_object_full(map, obj, 0);
4072 e_map_util_points_color_set(map, 255, 255, 255, 255);
4074 for (i = 0 ; i < 4 ; ++i)
4079 e_util_transform_vertices_pos_round_get(vertices, i, &x, &y, 0, 0);
4080 e_map_point_coord_set(map, i, x, y, 1.0);
4082 if (transform && e_util_transform_texcoord_flag_get(transform))
4087 e_util_transform_texcoord_get(transform, i, &u, &v);
4088 e_map_point_image_uv_set(map, i, u, v);
4096 _e_client_transform_core_vertices_apply_with_zoom(E_Client *ec,
4098 E_Util_Transform_Rect_Vertex *vertices,
4099 E_Util_Transform *transform,
4100 E_Util_Transform_Zoom zoom)
4108 map = _e_client_transform_core_map_new(obj, vertices, transform,
4109 ec->transform_core.direct_render);
4110 EINA_SAFETY_ON_NULL_RETURN(map);
4112 e_map_util_zoom(map, zoom.zoom_x, zoom.zoom_y, zoom.cx, zoom.cy);
4114 e_comp_object_map_set(obj, map);
4115 e_comp_object_map_enable_set(obj, EINA_TRUE);
4120 evas_object_map_enable_set(obj, EINA_FALSE);
4124 _e_client_transform_core_vertices_apply(E_Client *ec,
4126 E_Util_Transform_Rect_Vertex *vertices,
4127 E_Util_Transform *transform)
4135 map = _e_client_transform_core_map_new(obj, vertices, transform,
4136 ec->transform_core.direct_render);
4137 EINA_SAFETY_ON_NULL_RETURN(map);
4139 e_comp_object_map_set(obj, map);
4140 e_comp_object_map_enable_set(obj, EINA_TRUE);
4145 evas_object_map_enable_set(obj, EINA_FALSE);
4149 _e_client_transform_core_sub_update(E_Client *ec, E_Util_Transform_Rect_Vertex *vertices)
4153 E_Comp_Wl_Client_Data *cdata;
4157 cdata = e_client_cdata_get(ec);
4160 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
4161 e_client_transform_core_update(subc);
4163 EINA_LIST_FOREACH(cdata->sub.below_list, l, subc)
4164 e_client_transform_core_update(subc);
4168 _e_client_cb_hook_shell_surface_ready(void *data EINA_UNUSED, E_Client *ec)
4170 if (EINA_UNLIKELY(!ec))
4173 _e_client_aux_hint_eval(ec);
4177 e_client_visibility_calculate(void)
4179 _e_calc_visibility = EINA_TRUE;
4183 e_client_visibility_skip_set(E_Client *ec, Eina_Bool skip)
4187 ELOGF("POL_VIS", "visibility skip set to %d", ec, skip);
4188 ec->visibility.skip = skip;
4192 e_client_post_raise_lower_set(E_Client *ec, Eina_Bool raise_set, Eina_Bool lower_set)
4196 ec->post_raise = raise_set;
4197 ec->post_lower = lower_set;
4201 e_client_first_mapped_get(E_Client *ec)
4203 if (!ec) return EINA_FALSE;
4205 return ec->first_mapped;
4208 EINTERN Eina_Bool e_client_mapped_get(E_Client *ec)
4210 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
4211 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
4213 return cdata->mapped;
4217 e_client_mapped_set(E_Client *ec, Eina_Bool set)
4219 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
4220 EINA_SAFETY_ON_NULL_RETURN(cdata);
4222 cdata->mapped = set;
4226 ////////////////////////////////////////////////
4228 e_client_idler_before(void)
4232 Eina_Bool exist_clients_hash = EINA_FALSE;
4234 Eina_Bool check_focus = EINA_FALSE;
4236 for (pix_id = 0; pix_id < E_PIXMAP_TYPE_MAX; pix_id++)
4238 if (eina_hash_population(clients_hash[pix_id]))
4240 exist_clients_hash = EINA_TRUE;
4244 if (!exist_clients_hash) return;
4246 TRACE_DS_BEGIN(CLIENT:IDLE BEFORE);
4248 EINA_LIST_FOREACH(e_comp->clients, l, ec)
4250 Eina_Stringshare *title;
4253 // pass 1 - eval0. fetch properties on new or on change and
4254 // call hooks to decide what to do - maybe move/resize
4255 if (ec->ignored || (!ec->changed)) continue;
4257 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_FETCH, ec)) continue;
4258 /* FETCH is hooked by the compositor to get client hints */
4259 title = e_client_util_name_get(ec);
4260 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_FETCH, ec)) continue;
4261 if (title != e_client_util_name_get(ec))
4262 _e_client_event_property(ec, E_CLIENT_PROPERTY_TITLE);
4266 client_type = ec->client_type;
4267 if (client_type != _e_client_type_get(ec))
4268 _e_client_event_property(ec, E_CLIENT_PROPERTY_CLIENT_TYPE);
4271 /* PRE_POST_FETCH calls e_remember apply for new client */
4272 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_POST_FETCH, ec)) continue;
4273 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_FETCH, ec)) continue;
4274 if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_FRAME_ASSIGN, ec)) continue;
4276 if ((ec->border.changed) && (!ec->shaded) && (!e_client_is_stacking(ec)) &&
4277 ((!ec->override) || ec->internal) &&
4278 (!(((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
4279 _e_client_frame_update(ec);
4280 ec->border.changed = 0;
4281 _e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_FRAME_ASSIGN, ec);
4284 E_CLIENT_FOREACH(ec)
4286 if (ec->ignored) continue;
4287 // pass 2 - show windows needing show
4288 if ((ec->changes.visible) && (ec->visible) &&
4289 (!ec->new_client) && (!ec->changes.pos) &&
4290 (!ec->changes.size))
4292 evas_object_show(ec->frame);
4293 ec->changes.visible = !evas_object_visible_get(ec->frame);
4296 if ((!ec->new_client) && (!e_client_util_ignored_get(ec)) &&
4297 (!E_INSIDE(ec->x, ec->y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
4298 (!E_INSIDE(ec->x, ec->y, 0 - ec->w + 5, 0 - ec->h + 5, e_comp->w - 5, e_comp->h - 5))
4301 if (e_config->screen_limits != E_CLIENT_OFFSCREEN_LIMIT_ALLOW_FULL)
4302 _e_client_move_lost_window_to_center(ec);
4306 if (_e_client_layout_cb)
4307 _e_client_layout_cb();
4309 // pass 3 - hide windows needing hide and eval (main eval)
4310 E_CLIENT_FOREACH(ec)
4312 if (e_object_is_del(E_OBJECT(ec))) continue;
4315 // ignored client but needing eval (aux hint) such as remote surfaces
4318 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
4319 if (cdata && cdata->first_commit)
4320 _e_client_aux_hint_eval(ec);
4325 if ((ec->changes.visible) && (!ec->visible))
4327 evas_object_hide(ec->frame);
4328 ec->changes.visible = 0;
4334 e_client_visibility_calculate();
4335 if (ec->changes.accepts_focus)
4336 check_focus = EINA_TRUE;
4337 ec->changes.accepts_focus = 0;
4340 if ((ec->changes.visible) && (ec->visible) && (!ec->changed))
4342 evas_object_show(ec->frame);
4343 ec->changes.visible = !evas_object_visible_get(ec->frame);
4344 ec->changed = ec->changes.visible;
4345 e_client_visibility_calculate();
4349 if (e_comp_canvas_norender_get() <= 0)
4353 EINA_LIST_FOREACH(e_comp->zones, zl, zone)
4355 if (_e_calc_visibility)
4356 _e_client_visibility_zone_calculate(zone);
4358 (focused == NULL) ||
4359 (_e_calc_visibility && (defer_focus_stack != NULL)) ||
4360 (_e_visibility_changed))
4362 _e_client_focus_calculate(zone);
4365 _e_calc_visibility = EINA_FALSE;
4366 _e_visibility_changed = 0;
4378 for (pix_id = 0; pix_id < E_PIXMAP_TYPE_MAX; pix_id++)
4379 clients_hash[pix_id] = eina_hash_pointer_new(NULL);
4381 E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_WINDOW_PROFILE_CHANGE, _e_client_cb_desk_window_profile_change, NULL);
4383 E_COMP_WL_HOOK_APPEND(hooks, E_COMP_WL_HOOK_SHELL_SURFACE_READY, _e_client_cb_hook_shell_surface_ready, NULL);
4385 E_EVENT_CLIENT_ADD = ecore_event_type_new();
4386 E_EVENT_CLIENT_REMOVE = ecore_event_type_new();
4387 E_EVENT_CLIENT_DESK_SET = ecore_event_type_new();
4388 E_EVENT_CLIENT_ZONE_SET = ecore_event_type_new();
4389 E_EVENT_CLIENT_RESIZE = ecore_event_type_new();
4390 E_EVENT_CLIENT_MOVE = ecore_event_type_new();
4391 E_EVENT_CLIENT_SHOW = ecore_event_type_new();
4392 E_EVENT_CLIENT_HIDE = ecore_event_type_new();
4393 E_EVENT_CLIENT_ICONIFY = ecore_event_type_new();
4394 E_EVENT_CLIENT_UNICONIFY = ecore_event_type_new();
4395 E_EVENT_CLIENT_STACK = ecore_event_type_new();
4396 E_EVENT_CLIENT_FOCUS_IN = ecore_event_type_new();
4397 E_EVENT_CLIENT_FOCUS_OUT = ecore_event_type_new();
4398 E_EVENT_CLIENT_PROPERTY = ecore_event_type_new();
4399 E_EVENT_CLIENT_FULLSCREEN = ecore_event_type_new();
4400 E_EVENT_CLIENT_UNFULLSCREEN = ecore_event_type_new();
4401 #ifdef _F_ZONE_WINDOW_ROTATION_
4402 E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN = ecore_event_type_new();
4403 E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
4404 E_EVENT_CLIENT_ROTATION_CHANGE_END = ecore_event_type_new();
4405 E_EVENT_CLIENT_ROTATION_GEOMETRY_SET = ecore_event_type_new();
4407 E_EVENT_CLIENT_VISIBILITY_CHANGE = ecore_event_type_new();
4408 E_EVENT_CLIENT_BUFFER_CHANGE = ecore_event_type_new();
4409 E_EVENT_CLIENT_FOCUS_SKIP_SET = ecore_event_type_new();;
4410 E_EVENT_CLIENT_FOCUS_SKIP_UNSET = ecore_event_type_new();;
4412 return (!!clients_hash[1]);
4416 e_client_shutdown(void)
4419 for (pix_id = 0; pix_id < E_PIXMAP_TYPE_MAX; pix_id++)
4420 E_FREE_FUNC(clients_hash[pix_id], eina_hash_free);
4422 E_FREE_LIST(hooks, e_comp_wl_hook_del);
4423 E_FREE_LIST(handlers, ecore_event_handler_del);
4425 E_FREE_FUNC(warp_timer, ecore_timer_del);
4430 e_client_unignore(E_Client *ec)
4433 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4434 if (!ec->ignored) return;
4437 _e_client_event_add(ec);
4441 e_client_new(E_Pixmap *cp, int first_map, int internal)
4446 type = e_pixmap_type_get(cp);
4447 if (type >= E_PIXMAP_TYPE_MAX) return NULL;
4448 if (eina_hash_find(clients_hash[type], &cp)) return NULL;
4450 ec = E_OBJECT_ALLOC(E_Client, E_CLIENT_TYPE, _e_client_free);
4451 if (!ec) return NULL;
4452 e_object_del_func_set(E_OBJECT(ec), E_OBJECT_CLEANUP_FUNC(_e_client_del));
4454 uuid_generate(ec->uuid);
4456 ec->focus_policy_override = E_FOCUS_LAST;
4457 e_client_size_set(ec, 1, 1);
4458 ec->internal = internal;
4461 e_pixmap_client_set(cp, ec);
4462 ec->resize_mode = E_POINTER_RESIZE_NONE;
4463 ec->layer = E_LAYER_CLIENT_NORMAL;
4464 ec->first_mapped = EINA_FALSE;
4465 ec->post_raise = EINA_TRUE;
4466 ec->post_lower = EINA_FALSE;
4467 ec->animatable = EINA_TRUE;
4469 /* FIXME: if first_map is 1 then we should ignore the first hide event
4470 * or ensure the window is already hidden and events flushed before we
4471 * create a border for it */
4474 ec->changes.pos = 1;
4476 // needed to be 1 for internal windw and on restart.
4477 // ec->ignore_first_unmap = 2;
4479 ec->offer_resistance = 1;
4481 e_comp->new_clients++;
4483 ec->exp_iconify.by_client = 0;
4484 ec->exp_iconify.not_raise = 0;
4485 ec->exp_iconify.skip_iconify = 0;
4486 ec->exp_iconify.skip_by_remote = 0;
4487 if (e_config->deiconify_approve)
4488 ec->exp_iconify.deiconify_update= 1;
4490 ec->exp_iconify.deiconify_update= 0;
4491 if (e_config->use_buffer_flush)
4492 ec->exp_iconify.buffer_flush = 1;
4494 ec->exp_iconify.buffer_flush = 0;
4496 e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
4498 if (!_e_client_hook_call(E_CLIENT_HOOK_NEW_CLIENT, ec))
4500 /* delete the above allocated object */
4501 //e_object_del(E_OBJECT(ec));
4505 _e_client_aux_hint_eval(ec);
4508 _e_client_zone_update(ec);
4510 e_client_desk_set(ec, e_desk_current_get(e_zone_current_get()));
4512 ec->icccm.title = NULL;
4513 ec->icccm.name = NULL;
4514 #if defined(__cplusplus) || defined(c_plusplus)
4515 ec->icccm.cpp_class = NULL;
4517 ec->icccm.class = NULL;
4519 ec->icccm.icon_name = NULL;
4520 ec->icccm.machine = NULL;
4521 ec->icccm.min_w = 1;
4522 ec->icccm.min_h = 1;
4523 ec->icccm.max_w = 32767;
4524 ec->icccm.max_h = 32767;
4525 ec->icccm.base_w = 0;
4526 ec->icccm.base_h = 0;
4527 ec->icccm.step_w = -1;
4528 ec->icccm.step_h = -1;
4529 ec->icccm.min_aspect = 0.0;
4530 ec->icccm.max_aspect = 0.0;
4533 ec->netwm.name = NULL;
4534 ec->netwm.icon_name = NULL;
4535 ec->netwm.desktop = 0;
4536 ec->netwm.state.modal = 0;
4537 ec->netwm.state.sticky = 0;
4538 ec->netwm.state.shaded = 0;
4539 ec->netwm.state.hidden = 0;
4540 ec->netwm.state.maximized_v = 0;
4541 ec->netwm.state.maximized_h = 0;
4542 ec->netwm.state.skip_taskbar = 0;
4543 ec->netwm.state.skip_pager = 0;
4544 ec->netwm.state.fullscreen = 0;
4545 ec->netwm.state.stacking = E_STACKING_NONE;
4546 ec->netwm.action.move = 0;
4547 ec->netwm.action.resize = 0;
4548 ec->netwm.action.minimize = 0;
4549 ec->netwm.action.shade = 0;
4550 ec->netwm.action.stick = 0;
4551 ec->netwm.action.maximized_h = 0;
4552 ec->netwm.action.maximized_v = 0;
4553 ec->netwm.action.fullscreen = 0;
4554 ec->netwm.action.change_desktop = 0;
4555 ec->netwm.action.close = 0;
4556 ec->netwm.opacity = 255;
4558 ec->visibility.obscured = E_VISIBILITY_UNKNOWN;
4559 ec->visibility.opaque = -1;
4560 ec->visibility.changed = 0;
4561 ec->visibility.skip = 0;
4562 ec->visibility.last_sent_type = E_VISIBILITY_UNKNOWN;
4564 ec->transform.zoom = 1.0;
4565 ec->transform.angle = 0.0;
4566 ec->transform_core.direct_render = EINA_TRUE;
4568 ec->pointer_enter_sent = EINA_FALSE;
4572 e_comp->clients = eina_list_append(e_comp->clients, ec);
4573 eina_hash_add(clients_hash[type], &ec->pixmap, ec);
4575 ELOGF("COMP", "CLIENT ADD. cp:%p, argb:%d, internal:%d, ignored:%d", ec, cp, ec->argb, internal, ec->ignored);
4577 _e_client_event_add(ec);
4578 e_comp_object_client_add(ec);
4581 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_client_cb_evas_show, ec);
4582 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_client_cb_evas_hide, ec);
4583 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_client_cb_evas_move, ec);
4584 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE, _e_client_cb_evas_resize, ec);
4585 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_client_cb_evas_restack, ec);
4586 evas_object_smart_callback_add(ec->frame, "shade_done", _e_client_cb_evas_shade_done, ec);
4588 e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
4590 e_client_layer_set(ec, E_LAYER_CLIENT_NORMAL);
4593 #ifdef _F_E_CLIENT_NEW_CLIENT_POST_HOOK_
4594 _e_client_hook_call(E_CLIENT_HOOK_NEW_CLIENT_POST, ec);
4597 ec->manage_resize.resize_obj = NULL;
4598 ec->manage_resize.x = ec->manage_resize.y = ec->manage_resize.w = ec->manage_resize.h = 0;
4599 ec->manage_resize.enable_aspect_ratio = EINA_FALSE;
4600 ec->manage_resize.aw = ec->manage_resize.ah = 0;
4601 ec->manage_resize.header_h = 0;
4602 ec->manage_resize.footer_h = 0;
4604 ec->visibility.ignore_geometry = e_config->calc_vis_ignore_geometry;
4609 E_API Eina_Bool e_client_is_internal(E_Client *ec)
4611 E_OBJECT_CHECK_RETURN(ec, EINA_TRUE);
4612 return ec->internal;
4616 e_client_desk_window_profile_available_check(E_Client *ec, const char *profile)
4620 E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
4621 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
4622 EINA_SAFETY_ON_NULL_RETURN_VAL(profile, EINA_FALSE);
4623 EINA_SAFETY_ON_FALSE_RETURN_VAL(ec->e.state.profile.use, EINA_FALSE);
4624 if (ec->e.state.profile.num == 0) return EINA_TRUE;
4626 for (i = 0; i < ec->e.state.profile.num; i++)
4628 if (!e_util_strcmp(ec->e.state.profile.available_list[i],
4637 e_client_desk_window_profile_wait_desk_set(E_Client *ec, E_Desk *desk)
4640 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4641 E_OBJECT_CHECK(desk);
4642 E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
4644 if (ec->e.state.profile.wait_desk == desk) return;
4646 if (ec->e.state.profile.wait_desk_delfn)
4648 if (ec->e.state.profile.wait_desk)
4649 e_object_delfn_del(E_OBJECT(ec->e.state.profile.wait_desk),
4650 ec->e.state.profile.wait_desk_delfn);
4651 ec->e.state.profile.wait_desk_delfn = NULL;
4654 if (ec->e.state.profile.wait_desk)
4655 e_object_unref(E_OBJECT(ec->e.state.profile.wait_desk));
4656 ec->e.state.profile.wait_desk = NULL;
4660 ec->e.state.profile.wait_desk_delfn =
4661 e_object_delfn_add(E_OBJECT(desk),
4662 _e_client_desk_window_profile_wait_desk_delfn,
4665 ec->e.state.profile.wait_desk = desk;
4666 if (ec->e.state.profile.wait_desk)
4667 e_object_ref(E_OBJECT(ec->e.state.profile.wait_desk));
4671 e_client_desk_set(E_Client *ec, E_Desk *desk)
4673 E_Event_Client_Desk_Set *ev;
4677 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4678 E_OBJECT_CHECK(desk);
4679 E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
4680 if (ec->desk == desk) return;
4681 if ((e_config->use_desktop_window_profile) &&
4682 (ec->e.state.profile.use))
4684 if (e_util_strcmp(ec->e.state.profile.name, desk->window_profile))
4686 if (e_client_desk_window_profile_available_check(ec, desk->window_profile))
4688 eina_stringshare_replace(&ec->e.state.profile.set, desk->window_profile);
4689 eina_stringshare_replace(&ec->e.state.profile.wait, NULL);
4690 ec->e.state.profile.wait_for_done = 0;
4691 e_client_desk_window_profile_wait_desk_set(ec, desk);
4699 ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
4700 desk->fullscreen_clients = eina_list_append(desk->fullscreen_clients, ec);
4702 old_desk = ec->desk;
4704 e_desk_client_del(old_desk, ec);
4706 e_desk_client_add(desk, ec);
4709 e_comp_object_effect_unclip(ec->frame);
4710 e_comp_object_effect_set(ec->frame, NULL);
4712 if (desk->visible || ec->sticky)
4714 if ((!ec->hidden) && (!ec->iconic))
4715 evas_object_show(ec->frame);
4720 evas_object_hide(ec->frame);
4722 e_client_comp_hidden_set(ec, (!desk->visible) && (!ec->sticky));
4723 e_client_zone_set(ec, desk->zone);
4727 ev = E_NEW(E_Event_Client_Desk_Set, 1);
4732 e_object_ref(E_OBJECT(ec));
4733 ev->desk = old_desk;
4734 e_object_ref(E_OBJECT(old_desk));
4735 ecore_event_add(E_EVENT_CLIENT_DESK_SET, ev, (Ecore_End_Cb)_e_client_event_desk_set_free, NULL);
4738 if (old_desk->zone == ec->zone)
4740 e_client_res_change_geometry_save(ec);
4741 e_client_res_change_geometry_restore(ec);
4742 ec->pre_res_change.valid = 0;
4746 if (e_config->transient.desktop)
4751 EINA_LIST_FOREACH(ec->transients, l, child)
4752 e_client_desk_set(child, ec->desk);
4755 _e_client_hook_call(E_CLIENT_HOOK_DESK_SET, ec);
4756 evas_object_smart_callback_call(ec->frame, "desk_change", ec);
4758 if (ec->desk->desk_area.enable)
4760 if (!ec->desk_area.desk_area)
4763 eda = e_desk_desk_area_base_get(ec->desk);
4764 e_client_desk_area_set(ec, eda);
4767 e_client_desk_area_enable_set(ec, EINA_TRUE);
4772 e_client_desk_iconify_skip_set(E_Client *ec, Eina_Bool skip)
4775 ec->user_skip_winlist = skip;
4779 e_client_desk_iconify_skip_get(E_Client *ec)
4781 if (!ec) return EINA_FALSE;
4782 return ec->user_skip_winlist;
4786 e_client_comp_grabbed_get(void)
4788 return comp_grabbed;
4792 e_client_action_get(void)
4794 return action_client;
4798 e_client_warping_get(void)
4804 //////////////////////////////////////////////////////////
4807 e_client_mouse_in(E_Client *ec, int x, int y)
4809 if (comp_grabbed) return;
4810 if (warp_client && (ec != warp_client)) return;
4811 if (e_object_is_del(E_OBJECT(ec))) return;
4812 if (ec->desk && ec->desk->animate_count) return;
4813 ec->mouse.current.mx = x;
4814 ec->mouse.current.my = y;
4816 if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
4817 e_focus_event_mouse_in(ec);
4821 e_client_mouse_out(E_Client *ec, int x, int y)
4823 if (comp_grabbed) return;
4824 if (ec->fullscreen) return;
4825 if (e_object_is_del(E_OBJECT(ec))) return;
4826 if (ec->desk && ec->desk->animate_count) return;
4828 ec->mouse.current.mx = x;
4829 ec->mouse.current.my = y;
4831 if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
4832 e_focus_event_mouse_out(ec);
4836 e_client_mouse_wheel(E_Client *ec, Evas_Point *output, E_Binding_Event_Wheel *ev)
4838 EINA_SAFETY_ON_NULL_RETURN(ec);
4839 if (action_client) return;
4840 ec->mouse.current.mx = output->x;
4841 ec->mouse.current.my = output->y;
4845 e_client_mouse_down(E_Client *ec, int button, Evas_Point *output, E_Binding_Event_Mouse_Button *ev)
4847 EINA_SAFETY_ON_NULL_RETURN(ec);
4848 if (action_client || ec->iconic || e_client_util_ignored_get(ec)) return;
4849 if ((button >= 1) && (button <= 3))
4851 ec->mouse.last_down[button - 1].mx = output->x;
4852 ec->mouse.last_down[button - 1].my = output->y;
4853 ec->mouse.last_down[button - 1].x = ec->x;
4854 ec->mouse.last_down[button - 1].y = ec->y;
4855 ec->mouse.last_down[button - 1].w = ec->w;
4856 ec->mouse.last_down[button - 1].h = ec->h;
4860 ec->moveinfo.down.x = ec->x;
4861 ec->moveinfo.down.y = ec->y;
4862 ec->moveinfo.down.w = ec->w;
4863 ec->moveinfo.down.h = ec->h;
4865 ec->mouse.current.mx = output->x;
4866 ec->mouse.current.my = output->y;
4867 if ((button >= 1) && (button <= 3))
4869 ec->mouse.last_down[button - 1].mx = output->x;
4870 ec->mouse.last_down[button - 1].my = output->y;
4871 ec->mouse.last_down[button - 1].x = ec->x;
4872 ec->mouse.last_down[button - 1].y = ec->y;
4873 ec->mouse.last_down[button - 1].w = ec->w;
4874 ec->mouse.last_down[button - 1].h = ec->h;
4878 ec->moveinfo.down.x = ec->x;
4879 ec->moveinfo.down.y = ec->y;
4880 ec->moveinfo.down.w = ec->w;
4881 ec->moveinfo.down.h = ec->h;
4883 ec->mouse.current.mx = output->x;
4884 ec->mouse.current.my = output->y;
4888 e_client_mouse_up(E_Client *ec, int button, Evas_Point *output, E_Binding_Event_Mouse_Button* ev)
4890 EINA_SAFETY_ON_NULL_RETURN(ec);
4891 if (ec->iconic || e_client_util_ignored_get(ec)) return;
4892 if ((button >= 1) && (button <= 3))
4894 ec->mouse.last_up[button - 1].mx = output->x;
4895 ec->mouse.last_up[button - 1].my = output->y;
4896 ec->mouse.last_up[button - 1].x = ec->x;
4897 ec->mouse.last_up[button - 1].y = ec->y;
4899 ec->mouse.current.mx = output->x;
4900 ec->mouse.current.my = output->y;
4901 /* also we don't pass the same params that went in - then again that */
4902 /* should be ok as we are just ending the action if it has an end */
4903 if (ec->cur_mouse_action)
4905 if (ec->cur_mouse_action->func.end_mouse)
4906 ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", ev);
4907 else if (ec->cur_mouse_action->func.end)
4908 ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
4909 e_object_unref(E_OBJECT(ec->cur_mouse_action));
4910 ec->cur_mouse_action = NULL;
4914 e_focus_event_mouse_up(ec);
4916 if ((button >= 1) && (button <= 3))
4918 ec->mouse.last_up[button - 1].mx = output->x;
4919 ec->mouse.last_up[button - 1].my = output->y;
4920 ec->mouse.last_up[button - 1].x = ec->x;
4921 ec->mouse.last_up[button - 1].y = ec->y;
4928 e_client_stay_within_canvas_margin(E_Client *ec)
4935 _e_client_stay_within_canvas_margin(ec, ec->x, ec->y, &new_x, &new_y);
4937 if ((ec->x != new_x) || (ec->y != new_y))
4938 evas_object_move(ec->frame, new_x, new_y);
4943 e_client_mouse_move(E_Client *ec, Evas_Point *output)
4945 EINA_SAFETY_ON_NULL_RETURN(ec);
4946 if (ec->iconic || e_client_util_ignored_get(ec)) return;
4947 ec->mouse.current.mx = output->x;
4948 ec->mouse.current.my = output->y;
4949 if (e_client_util_moving_get(ec))
4951 _e_client_move_handle(ec);
4953 if (ec->zone) e_zone_flip_coords_handle(ec->zone, output->x, output->y);
4955 else if (e_client_util_resizing_get(ec))
4957 _e_client_resize_handle(ec);
4959 else if (ec->drag.start)
4961 if ((ec->drag.x == -1) && (ec->drag.y == -1))
4963 ec->drag.x = output->x;
4964 ec->drag.y = output->y;
4970 dx = ec->drag.x - output->x;
4971 dy = ec->drag.y - output->y;
4972 if (((dx * dx) + (dy * dy)) > (16 * 16))
4975 if (ec->netwm.icons || ec->internal_icon)
4977 Evas_Object *o = NULL;
4978 int x = 0, y = 0, w = 0, h = 0;
4979 const char *drag_types[] = { "enlightenment/border" };
4982 e_object_ref(E_OBJECT(ec));
4984 client_drag = e_drag_new(output->x, output->y,
4985 drag_types, 1, ec, -1,
4987 _e_client_cb_drag_finished);
4988 client_drag->button_mask = evas_pointer_button_down_mask_get(e_comp->evas);
4989 e_drag_resize(client_drag, w, h);
4991 /* FIXME: fallback icon for drag */
4992 o = evas_object_rectangle_add(client_drag->evas);
4993 evas_object_color_set(o, 255, 255, 255, 255);
4995 e_drag_object_set(client_drag, o);
4996 e_drag_start(client_drag,
4997 output->x + (ec->drag.x - x),
4998 output->y + (ec->drag.y - y));
5005 ///////////////////////////////////////////////////////
5008 e_client_res_change_geometry_save(E_Client *ec)
5011 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5013 if (ec->pre_res_change.valid) return;
5014 ec->pre_res_change.valid = 1;
5015 ec->pre_res_change.x = ec->x;
5016 ec->pre_res_change.y = ec->y;
5017 ec->pre_res_change.w = ec->w;
5018 ec->pre_res_change.h = ec->h;
5019 ec->pre_res_change.saved.x = ec->saved.x;
5020 ec->pre_res_change.saved.y = ec->saved.y;
5021 ec->pre_res_change.saved.w = ec->saved.w;
5022 ec->pre_res_change.saved.h = ec->saved.h;
5026 e_client_res_change_geometry_restore(E_Client *ec)
5030 unsigned char valid : 1;
5039 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5040 if (!ec->pre_res_change.valid) return;
5041 if (ec->new_client) return;
5042 if (!ec->zone) return;
5044 memcpy(&pre_res_change, &ec->pre_res_change, sizeof(pre_res_change));
5048 e_client_unfullscreen(ec);
5049 e_client_fullscreen(ec, e_config->fullscreen_policy);
5051 else if (ec->maximized != E_MAXIMIZE_NONE)
5055 max = ec->maximized;
5056 e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
5057 e_client_maximize(ec, max);
5061 int x, y, w, h, zx, zy, zw, zh;
5063 ec->saved.x = ec->pre_res_change.saved.x;
5064 ec->saved.y = ec->pre_res_change.saved.y;
5065 ec->saved.w = ec->pre_res_change.saved.w;
5066 ec->saved.h = ec->pre_res_change.saved.h;
5068 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
5070 if (ec->saved.w > zw)
5072 if ((ec->saved.x + ec->saved.w) > (zx + zw))
5073 ec->saved.x = zx + zw - ec->saved.w;
5075 if (ec->saved.h > zh)
5077 if ((ec->saved.y + ec->saved.h) > (zy + zh))
5078 ec->saved.y = zy + zh - ec->saved.h;
5080 x = ec->pre_res_change.x;
5081 y = ec->pre_res_change.y;
5082 w = ec->pre_res_change.w;
5083 h = ec->pre_res_change.h;
5088 if ((x + w) > (zx + zw))
5090 if ((y + h) > (zy + zh))
5092 evas_object_geometry_set(ec->frame, x, y, w, h);
5094 memcpy(&ec->pre_res_change, &pre_res_change, sizeof(pre_res_change));
5098 e_client_zone_set(E_Client *ec, E_Zone *zone)
5100 E_Event_Client_Zone_Set *ev;
5103 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5104 E_OBJECT_CHECK(zone);
5105 E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
5106 if (ec->zone == zone) return;
5108 ev = E_NEW(E_Event_Client_Zone_Set, 1);
5111 /* if the window does not lie in the new zone, move it so that it does */
5112 if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
5118 /* first guess -- get offset from old zone, and apply to new zone */
5119 x = zone->x + (ec->x - ec->zone->x);
5120 y = zone->y + (ec->y - ec->zone->y);
5123 x = ec->x, y = ec->y;
5125 /* keep window from hanging off bottom and left */
5126 if (x + ec->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + ec->w);
5127 if (y + ec->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + ec->h);
5129 /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
5130 if (x < zone->x) x = zone->x;
5131 if (y < zone->y) y = zone->y;
5133 if (!E_INTERSECTS(x, y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
5135 /* still not in zone at all, so just move it to closest edge */
5136 if (x < zone->x) x = zone->x;
5137 if (x >= zone->x + zone->w) x = zone->x + zone->w - ec->w;
5138 if (y < zone->y) y = zone->y;
5139 if (y >= zone->y + zone->h) y = zone->y + zone->h - ec->h;
5141 evas_object_move(ec->frame, x, y);
5146 if ((!ec->desk) || (ec->desk->zone != ec->zone))
5147 e_client_desk_set(ec, e_desk_current_get(ec->zone));
5151 e_object_ref(E_OBJECT(ec));
5153 e_object_ref(E_OBJECT(zone));
5155 ecore_event_add(E_EVENT_CLIENT_ZONE_SET, ev, (Ecore_End_Cb)_e_client_event_zone_set_free, NULL);
5157 e_client_res_change_geometry_save(ec);
5158 e_client_res_change_geometry_restore(ec);
5159 ec->pre_res_change.valid = 0;
5163 e_client_pos_set(E_Client *ec, int x, int y)
5171 e_client_pos_get(E_Client *ec, int *x, int *y)
5187 e_client_size_set(E_Client *ec, int w, int h)
5195 e_client_size_get(E_Client *ec, int *w, int *h)
5211 e_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
5219 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5221 if (e_client_transform_core_enable_get(ec))
5223 gx = ec->transform_core.result.boundary.x;
5224 gy = ec->transform_core.result.boundary.y;
5225 gw = ec->transform_core.result.boundary.w;
5226 gh = ec->transform_core.result.boundary.h;
5232 evas_object_geometry_get(ec->frame, &gx, &gy, &gw, &gh);
5233 if (gw == 0 && gh == 0)
5235 /* In this case, there is no image buffer in e_comp_object, thus it
5236 * should return geometry value of ec itself. It usually happens if
5237 * new ec is not mapped yet.
5261 e_client_above_get(const E_Client *ec)
5266 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
5267 if (EINA_INLIST_GET(ec)->next) //check current layer
5269 EINA_INLIST_FOREACH(EINA_INLIST_GET(ec)->next, ec2)
5273 ELOGF("FATAL", "CHECK the ec inlist next", ec);
5276 if (!e_object_is_del(E_OBJECT(ec2)))
5280 if (ec->layer == E_LAYER_CLIENT_CURSOR) return NULL;
5281 if (e_comp_canvas_client_layer_map(ec->layer) == 9999) return NULL;
5283 /* go up the layers until we find one */
5284 for (x = e_comp_canvas_layer_map(ec->layer) + 1; x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
5286 if (!e_comp->layers[x].clients) continue;
5287 EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
5291 ELOGF("FATAL", "EC exist above layer. ec layer_map:%d, cur layer_map:%d",
5292 ec, e_comp_canvas_layer_map(ec->layer), x);
5295 if (!e_object_is_del(E_OBJECT(ec2)))
5303 e_client_below_get(const E_Client *ec)
5308 E_Layer ec_layer, ec_layer_cw;
5311 E_OBJECT_CHECK_RETURN(ec, NULL);
5312 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, NULL);
5314 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
5315 if (EINA_INLIST_GET(ec)->prev) //check current layer
5317 for (l = EINA_INLIST_GET(ec)->prev; l; l = l->prev)
5319 ec2 = EINA_INLIST_CONTAINER_GET(l, E_Client);
5322 ELOGF("FATAL", "CHECK the ec inlist prev", ec);
5325 if (!e_object_is_del(E_OBJECT(ec2)))
5330 // check layer validation
5331 ec_layer = ec->layer;
5332 if (ec->layer_block || ec->layer_pending)
5334 cw_layer = e_comp_object_layer_get(ec->frame);
5337 ec_layer_cw = e_comp_canvas_layer_map_to(cw_layer);
5338 if (ec_layer != ec_layer_cw)
5340 ELOGF("COMP", "LAYER is not same. USE obj layer! (ec->layer:%d, obj:%d). block:%d, pending:%d)", ec, ec_layer, ec_layer_cw, ec->layer_block, ec->layer_pending);
5341 ec_layer = ec_layer_cw;
5346 if (ec_layer == E_LAYER_CLIENT_DESKTOP) return NULL;
5347 if (e_comp_canvas_client_layer_map(ec_layer) == 9999) return NULL;
5349 /* go down the layers until we find one */
5350 x = e_comp_canvas_layer_map(ec_layer);
5353 for (; x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
5355 if (!e_comp->layers[x].clients) continue;
5356 EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
5360 ELOGF("FATAL", "EC exist below layer. ec layer_map:%d, cur layer_map:%d",
5361 ec, e_comp_canvas_layer_map(ec_layer), x);
5364 if (!e_object_is_del(E_OBJECT(ec2)))
5372 e_client_bottom_get(void)
5375 for (x = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
5379 if (!e_comp->layers[x].clients) continue;
5380 EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
5381 if (!e_object_is_del(E_OBJECT(ec2)))
5388 e_client_top_get(void)
5391 for (x = e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
5395 if (!e_comp->layers[x].clients) continue;
5396 EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
5397 if (!e_object_is_del(E_OBJECT(ec2)))
5404 e_clients_count(void)
5406 return eina_list_count(e_comp->clients);
5411 * Set a callback which will be called just prior to updating the
5412 * move coordinates for a border
5415 e_client_move_intercept_cb_set(E_Client *ec, E_Client_Move_Intercept_Cb cb)
5417 ec->move_intercept_cb = cb;
5420 ///////////////////////////////////////
5422 E_API E_Client_Hook *
5423 e_client_hook_add(E_Client_Hook_Point hookpoint, E_Client_Hook_Cb func, const void *data)
5427 EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_CLIENT_HOOK_LAST, NULL);
5428 ch = E_NEW(E_Client_Hook, 1);
5429 if (!ch) return NULL;
5430 ch->hookpoint = hookpoint;
5432 ch->data = (void*)data;
5433 _e_client_hooks[hookpoint] = eina_inlist_append(_e_client_hooks[hookpoint], EINA_INLIST_GET(ch));
5438 e_client_hook_del(E_Client_Hook *ch)
5441 if (_e_client_hooks_walking == 0)
5443 _e_client_hooks[ch->hookpoint] = eina_inlist_remove(_e_client_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
5447 _e_client_hooks_delete++;
5450 ///////////////////////////////////////
5452 E_API E_Client_Intercept_Hook *
5453 e_client_intercept_hook_add(E_Client_Intercept_Hook_Point hookpoint, E_Client_Intercept_Hook_Cb func, const void *data)
5455 E_Client_Intercept_Hook *ch;
5457 EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_CLIENT_INTERCEPT_HOOK_LAST, NULL);
5458 ch = E_NEW(E_Client_Intercept_Hook, 1);
5459 if (!ch) return NULL;
5460 ch->hookpoint = hookpoint;
5462 ch->data = (void*)data;
5463 _e_client_intercept_hooks[hookpoint] = eina_inlist_append(_e_client_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
5468 e_client_intercept_hook_del(E_Client_Intercept_Hook *ch)
5473 if (_e_client_intercept_hooks_walking == 0)
5475 _e_client_intercept_hooks[ch->hookpoint] =
5476 eina_inlist_remove(_e_client_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
5480 _e_client_intercept_hooks_delete++;
5484 e_client_focus_stack_lower(E_Client *ec)
5486 Eina_List *l = NULL;
5487 E_Client *ec2 = NULL;
5489 EINA_SAFETY_ON_NULL_RETURN(ec);
5490 if (focus_track_frozen > 0) return;
5492 focus_stack = eina_list_remove(focus_stack, ec);
5494 EINA_LIST_REVERSE_FOREACH(focus_stack, l, ec2)
5496 if (ec2 == NULL) continue;
5497 if (ec2->layer < ec->layer) continue;
5499 focus_stack = eina_list_append_relative_list(focus_stack, ec, l);
5503 focus_stack = eina_list_prepend(focus_stack, ec);
5508 e_client_focus_latest_set(E_Client *ec)
5510 EINA_SAFETY_ON_NULL_RETURN(ec);
5511 if (focus_track_frozen > 0) return;
5513 focus_stack = eina_list_remove(focus_stack, ec);
5514 focus_stack = eina_list_prepend(focus_stack, ec);
5518 e_client_focus_stack_append_current_focused(E_Client *ec)
5520 Eina_List *l = NULL;
5521 E_Client *temp_ec = NULL;
5523 if (!ec) CRI("ACK");
5524 if (focus_track_frozen > 0) return;
5526 focus_stack = eina_list_remove(focus_stack, ec);
5528 EINA_LIST_FOREACH(focus_stack, l, temp_ec)
5530 if (temp_ec != focused) continue;
5532 focus_stack = eina_list_append_relative_list(focus_stack, ec, l);
5536 focus_stack = eina_list_prepend(focus_stack, ec);
5541 e_client_focus_defer_set(E_Client *ec)
5543 EINA_SAFETY_ON_NULL_RETURN(ec);
5544 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5546 ELOGF("FOCUS", "focus defer set", ec);
5548 defer_focus_stack = eina_list_remove(defer_focus_stack, ec);
5549 defer_focus_stack = eina_list_prepend(defer_focus_stack, ec);
5553 e_client_focus_defer_unset(E_Client *ec)
5555 EINA_SAFETY_ON_NULL_RETURN(ec);
5556 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5558 ELOGF("FOCUS", "focus defer unset", ec);
5560 defer_focus_stack = eina_list_remove(defer_focus_stack, ec);
5564 e_client_focus_defer_clear(void)
5566 if (!defer_focus_stack) return;
5568 ELOGF("FOCUS", "focus defer clear", NULL);
5570 defer_focus_stack = eina_list_free(defer_focus_stack);
5574 e_client_focus_track_enabled(void)
5576 return !focus_track_frozen;
5580 e_client_focus_track_freeze(void)
5582 focus_track_frozen++;
5586 e_client_focus_track_thaw(void)
5588 if (focus_track_frozen)
5589 focus_track_frozen--;
5593 e_client_refocus(void)
5598 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5600 EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
5601 if (ec->desk && ec->desk->visible && (!ec->iconic))
5603 if (e_comp->input_key_grabs || e_comp->input_mouse_grabs) break;
5604 ELOGF("FOCUS", "focus set | refocus", ec);
5605 e_client_frame_focus_set(ec, EINA_TRUE);
5612 * Sets the focus to the given client if necessary
5613 * There are 3 cases of different focus_policy-configurations:
5615 * - E_FOCUS_CLICK: just set the focus, the most simple one
5617 * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
5618 * warp the pointer to the window. If this fails (because
5619 * the pointer is already in the window), just set the focus.
5621 * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
5622 * last window which was focused, if the mouse is on the
5623 * desktop. So, we need to look if there is another window
5624 * under the pointer and warp to pointer to the right
5625 * one if so (also, we set the focus afterwards). In case
5626 * there is no window under pointer, the pointer is on the
5627 * desktop and so we just set the focus.
5630 * This function is to be called when setting the focus was not
5631 * explicitly triggered by the user (by moving the mouse or
5632 * clicking for example), but implicitly (by closing a window,
5633 * the last focused window should get focus).
5637 e_client_focus_set_with_pointer(E_Client *ec)
5640 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5641 /* note: this is here as it seems there are enough apps that do not even
5642 * expect us to emulate a look of focus but not actually set x input
5643 * focus as we do - so simply abort any focuse set on such windows */
5644 /* be strict about accepting focus hint */
5645 if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5647 if ((!ec->icccm.accepts_focus) &&
5648 (!ec->icccm.take_focus)) return;
5649 if (ec->lock_focus_out) return;
5650 if (ec == focused) return;
5652 TRACE_DS_BEGIN(CLIENT:FOCUS SET WITH POINTER);
5653 ELOGF("FOCUS", "focus set | focus with pointer", ec);
5654 e_client_frame_focus_set(ec, EINA_TRUE);
5656 if (e_config->focus_policy == E_FOCUS_CLICK)
5671 e_client_focused_set(E_Client *ec)
5673 E_Client *ec2, *ec_unfocus = focused;
5676 if (ec == focused) return;
5678 TRACE_DS_BEGIN(CLIENT:FOCUSED SET);
5680 ELOGF("FOCUS", "CLIENT FOCUS_SET", ec);
5682 if ((ec) && (ec->zone))
5685 e_client_urgent_set(ec, 0);
5686 int x, total = ec->zone->desk_x_count * ec->zone->desk_y_count;
5688 for (x = 0; x < total; x++)
5690 E_Desk *desk = ec->zone->desks[x];
5691 /* if there's any fullscreen non-parents on this desk, unfullscreen them */
5692 EINA_LIST_FOREACH_SAFE(desk->fullscreen_clients, l, ll, ec2)
5694 if (ec2 == ec) continue;
5695 if (e_object_is_del(E_OBJECT(ec2))) continue;
5696 /* but only if it's the same desk or one of the clients is sticky */
5697 if ((desk == ec->desk) || (ec->sticky || ec2->sticky))
5699 if (!eina_list_data_find(ec->transients, ec2))
5700 e_client_unfullscreen(ec2);
5706 while ((ec_unfocus) && (ec_unfocus->zone))
5708 ec_unfocus->want_focus = ec_unfocus->focused = 0;
5709 if (!e_object_is_del(E_OBJECT(ec_unfocus)))
5710 e_focus_event_focus_out(ec_unfocus);
5711 if (ec_unfocus->mouse.in && ec && (!e_client_util_is_popup(ec)) &&
5712 (e_config->focus_policy != E_FOCUS_CLICK))
5713 e_client_mouse_out(ec_unfocus, ec_unfocus->x - 1, ec_unfocus->y - 1);
5715 /* if there unfocus client is fullscreen and visible */
5716 if ((ec_unfocus->fullscreen) && (!ec_unfocus->iconic) && (!ec_unfocus->hidden) &&
5717 (ec_unfocus->zone == e_zone_current_get()) &&
5718 ((ec_unfocus->desk == e_desk_current_get(ec_unfocus->zone)) || (ec_unfocus->sticky)))
5720 Eina_Bool have_vis_child = EINA_FALSE;
5722 /* if any of its children are visible */
5723 EINA_LIST_FOREACH(ec_unfocus->transients, l, ec2)
5725 if ((ec2->zone == ec_unfocus->zone) &&
5726 ((ec2->desk == ec_unfocus->desk) ||
5727 (ec2->sticky) || (ec_unfocus->sticky)))
5729 have_vis_child = EINA_TRUE;
5733 /* if no children are visible, unfullscreen */
5734 if ((!e_object_is_del(E_OBJECT(ec_unfocus))) && (!have_vis_child))
5735 e_client_unfullscreen(ec_unfocus);
5738 if (!e_object_is_del(E_OBJECT(ec_unfocus)))
5739 _e_client_hook_call(E_CLIENT_HOOK_FOCUS_UNSET, ec_unfocus);
5740 /* only send event here if we're not being deleted */
5741 if ((!e_object_is_del(E_OBJECT(ec_unfocus))) &&
5742 (e_object_ref_get(E_OBJECT(ec_unfocus)) > 0))
5744 _e_client_event_simple(ec_unfocus, E_EVENT_CLIENT_FOCUS_OUT);
5745 e_client_urgent_set(ec_unfocus, ec_unfocus->icccm.urgent);
5748 e_client_focus_defer_unset(ec_unfocus);
5757 _e_client_hook_call(E_CLIENT_HOOK_FOCUS_SET, ec);
5758 e_focus_event_focus_in(ec);
5760 if (!focus_track_frozen)
5761 e_client_focus_latest_set(ec);
5763 _e_client_event_simple(ec, E_EVENT_CLIENT_FOCUS_IN);
5764 if (ec->sticky && ec->desk && (!ec->desk->visible))
5765 e_client_desk_set(ec, e_desk_current_get(ec->zone));
5771 e_client_activate(E_Client *ec, Eina_Bool just_do_it)
5774 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5776 TRACE_DS_BEGIN(CLIENT:ACTIVATE);
5778 if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
5780 ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
5781 ((ec->parent->focused) &&
5782 (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
5785 ELOGF("COMP", "Set launching flag..", ec);
5786 ec->launching = EINA_TRUE;
5788 ec->exp_iconify.not_raise = 0;
5792 if (!ec->lock_user_iconify)
5793 e_client_uniconify(ec);
5795 ELOGF("COMP", "Un-Set ICONIFY BY CLIENT", ec);
5796 ec->exp_iconify.by_client = 0;
5797 e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
5799 if ((!ec->iconic) && (!ec->sticky))
5801 e_desk_show(ec->desk);
5803 if (!ec->lock_user_stacking)
5805 if (ec->shaded || ec->shading)
5806 e_client_unshade(ec, ec->shade_dir);
5807 if (!ec->lock_focus_out)
5809 E_Client *focus_ec = NULL;
5810 E_Client *obscured_above = NULL;
5813 focus_ec = e_client_transient_child_top_get(ec, EINA_TRUE);
5819 e_client_focus_latest_set(ec);
5820 e_client_focus_latest_set(focus_ec);
5821 e_client_focus_defer_unset(ec);
5824 obscured_above = _e_client_check_fully_contain_by_above(focus_ec, EINA_FALSE);
5825 if (!obscured_above)
5827 if (!e_policy_visibility_client_is_uniconic(ec))
5829 e_client_focus_defer_set(focus_ec);
5830 e_client_focus_latest_set(focus_ec);
5834 if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
5836 ELOGF("FOCUS", "focus set | client activate", focus_ec);
5837 e_client_frame_focus_set(focus_ec, EINA_TRUE);
5843 e_client_focus_defer_set(focus_ec);
5844 e_client_focus_latest_set(focus_ec);
5848 if (!e_client_desk_iconify_skip_get(ec))
5850 e_desk_visible_client_iconified_list_remove_all(ec->desk);
5854 _e_client_hook_call(E_CLIENT_HOOK_ACTIVATE_DONE, ec);
5860 e_client_focused_get(void)
5866 e_client_focus_stack_get(void)
5872 e_client_focus_stack_set(Eina_List *l)
5878 e_client_focus_stack_clear(void)
5880 if (!focus_stack) return;
5882 focus_stack = eina_list_free(focus_stack);
5886 e_client_lost_windows_get(E_Zone *zone)
5888 Eina_List *list = NULL;
5891 int loss_overlap = 5;
5893 E_OBJECT_CHECK_RETURN(zone, NULL);
5894 E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
5895 EINA_LIST_FOREACH(e_comp->clients, l, ec)
5897 if (ec->zone != zone) continue;
5898 if (e_client_util_ignored_get(ec)) continue;
5900 if (!E_INTERSECTS(ec->zone->x + loss_overlap,
5901 ec->zone->y + loss_overlap,
5902 ec->zone->w - (2 * loss_overlap),
5903 ec->zone->h - (2 * loss_overlap),
5904 ec->x, ec->y, ec->w, ec->h))
5906 list = eina_list_append(list, ec);
5912 ///////////////////////////////////////
5915 e_client_shade(E_Client *ec, E_Direction dir)
5918 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5919 if ((ec->shaded) || (ec->shading) || (ec->fullscreen) ||
5920 ((ec->maximized) && (!e_config->allow_manip))) return;
5921 if (!e_util_strcmp("borderless", ec->bordername)) return;
5922 if (!e_comp_object_frame_allowed(ec->frame)) return;
5926 ec->shade_dir = dir;
5928 evas_object_smart_callback_call(ec->frame, "shaded", (uintptr_t*)dir);
5932 e_client_unshade(E_Client *ec, E_Direction dir)
5935 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5936 if ((!ec->shaded) || (ec->shading))
5942 evas_object_smart_callback_call(ec->frame, "unshaded", (uintptr_t*)dir);
5945 ///////////////////////////////////////
5948 e_client_maximized_geometry_set(E_Client *ec, int x, int y, int w, int h)
5952 ec->maximized_info.x = x;
5953 ec->maximized_info.y = y;
5954 ec->maximized_info.w = w;
5955 ec->maximized_info.h = h;
5957 e_client_frame_geometry_set(ec, x, y, w, h);
5961 e_client_maximized_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
5965 if (x) *x = ec->maximized_info.x;
5966 if (y) *y = ec->maximized_info.y;
5967 if (w) *w = ec->maximized_info.w;
5968 if (h) *h = ec->maximized_info.h;
5972 e_client_maximize_update(E_Client *ec)
5977 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5981 max = ec->maximized;
5983 e_client_maximize(ec, max);
5988 e_client_maximize(E_Client *ec, E_Maximize max)
5993 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5995 if (!ec->zone) return;
5996 if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
5998 if ((ec->shaded) || (ec->shading)) return;
6000 if ((ec->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION))
6002 if ((ec->maximized & E_MAXIMIZE_TYPE) == (max & E_MAXIMIZE_TYPE))
6008 ec->changes.need_maximize = 1;
6009 ec->maximized &= ~E_MAXIMIZE_TYPE;
6010 ec->maximized |= max;
6015 if (ec->desk_area.enable && ec->desk_area.desk_area)
6017 desk_x = ec->desk_area.desk_area->x;
6018 desk_y = ec->desk_area.desk_area->y;
6022 desk_x = ec->desk->geom.x;
6023 desk_y = ec->desk->geom.y;
6026 evas_object_smart_callback_call(ec->frame, "maximize_pre", NULL);
6029 e_client_unfullscreen(ec);
6030 ec->pre_res_change.valid = 0;
6031 if (!(ec->maximized & E_MAXIMIZE_HORIZONTAL))
6033 /* Horizontal hasn't been set */
6034 ec->saved.x = ec->client.x - desk_x;
6035 ec->saved.w = ec->client.w;
6037 if (!(ec->maximized & E_MAXIMIZE_VERTICAL))
6039 /* Vertical hasn't been set */
6040 ec->saved.y = ec->client.y - desk_y;
6041 ec->saved.h = ec->client.h;
6044 ec->saved.zone = ec->zone->num;
6046 _e_client_maximize(ec, max);
6048 ec->maximized = max;
6049 ec->changes.need_unmaximize = 0;
6051 evas_object_smart_callback_call(ec->frame, "maximize_done", NULL);
6055 e_client_unmaximize(E_Client *ec, E_Maximize max)
6058 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6059 if (!ec->zone) return;
6060 if (!(max & E_MAXIMIZE_DIRECTION))
6062 CRI("BUG: Unmaximize call without direction!");
6067 ec->changes.need_unmaximize = 1;
6072 if ((ec->shaded) || (ec->shading)) return;
6074 /* Remove directions not used */
6075 max &= (ec->maximized & E_MAXIMIZE_DIRECTION);
6076 /* Can only remove existing maximization directions */
6079 evas_object_smart_callback_call(ec->frame, "unmaximize_pre", NULL);
6081 if (ec->maximized & E_MAXIMIZE_TYPE)
6083 ec->pre_res_change.valid = 0;
6084 ec->changes.need_maximize = 0;
6086 if ((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
6088 E_Maximize tmp_max = ec->maximized;
6090 //un-set maximized state for updating frame.
6091 ec->maximized = E_MAXIMIZE_NONE;
6092 _e_client_frame_update(ec);
6093 // re-set maximized state for unmaximize smart callback.
6094 ec->maximized = tmp_max;
6095 evas_object_smart_callback_call(ec->frame, "unfullscreen", NULL);
6096 // un-set maximized state.
6097 ec->maximized = E_MAXIMIZE_NONE;
6098 e_client_util_move_resize_without_frame(ec,
6099 ec->saved.x + ec->zone->x,
6100 ec->saved.y + ec->zone->y,
6101 ec->saved.w, ec->saved.h);
6102 ec->saved.x = ec->saved.y = ec->saved.w = ec->saved.h = 0;
6107 Eina_Bool horiz = EINA_FALSE, vert = EINA_FALSE;
6114 if (max & E_MAXIMIZE_VERTICAL)
6116 /* Remove vertical */
6119 y = ec->saved.y + ec->zone->y;
6120 if ((max & E_MAXIMIZE_VERTICAL) == E_MAXIMIZE_VERTICAL)
6122 ec->maximized &= ~E_MAXIMIZE_VERTICAL;
6123 ec->maximized &= ~E_MAXIMIZE_LEFT;
6124 ec->maximized &= ~E_MAXIMIZE_RIGHT;
6126 if ((max & E_MAXIMIZE_LEFT) == E_MAXIMIZE_LEFT)
6127 ec->maximized &= ~E_MAXIMIZE_LEFT;
6128 if ((max & E_MAXIMIZE_RIGHT) == E_MAXIMIZE_RIGHT)
6129 ec->maximized &= ~E_MAXIMIZE_RIGHT;
6131 if (max & E_MAXIMIZE_HORIZONTAL)
6133 /* Remove horizontal */
6135 x = ec->saved.x + ec->zone->x;
6137 ec->maximized &= ~E_MAXIMIZE_HORIZONTAL;
6140 if (!(ec->maximized & E_MAXIMIZE_DIRECTION))
6142 ec->maximized = E_MAXIMIZE_NONE;
6143 _e_client_frame_update(ec);
6144 evas_object_smart_callback_call(ec->frame, "unmaximize", NULL);
6145 e_client_resize_limit(ec, &w, &h);
6146 e_client_pos_set(ec, x, y);
6147 e_policy_visibility_client_defer_move(ec);
6151 evas_object_smart_callback_call(ec->frame, "unmaximize", NULL);
6152 e_client_resize_limit(ec, &w, &h);
6153 e_client_pos_set(ec, x, y);
6154 e_policy_visibility_client_defer_move(ec);
6157 ec->saved.h = ec->saved.y = 0;
6159 ec->saved.w = ec->saved.x = 0;
6162 evas_object_smart_callback_call(ec->frame, "unmaximize_done", NULL);
6163 ec->changes.need_unmaximize = 0;
6167 e_client_fullscreen(E_Client *ec, E_Fullscreen policy)
6172 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6173 if (!ec->zone) return;
6175 if ((ec->shaded) || (ec->shading) || (ec->fullscreen)) return;
6177 _e_client_hook_call(E_CLIENT_HOOK_FULLSCREEN_PRE, ec);
6179 if (ec->skip_fullscreen) return;
6180 if (!ec->desk->visible) return;
6183 ec->need_fullscreen = 1;
6186 if (e_comp->nocomp_ec && (ec->desk == e_comp->nocomp_ec->desk))
6187 e_comp->nocomp_ec = ec;
6188 ec->desk->fullscreen_clients = eina_list_append(ec->desk->fullscreen_clients, ec);
6189 ec->pre_res_change.valid = 0;
6200 ec->saved.x = ec->client.x - ec->zone->x;
6201 ec->saved.y = ec->client.y - ec->zone->y;
6202 ec->saved.w = ec->client.w;
6203 ec->saved.h = ec->client.h;
6205 ec->saved.maximized = ec->maximized;
6206 ec->saved.zone = ec->zone->num;
6210 e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
6217 ec->saved.layer = ec->layer;
6218 e_client_layer_set(ec, E_LAYER_CLIENT_FULLSCREEN);
6221 if ((eina_list_count(e_comp->zones) > 1) ||
6222 (policy == E_FULLSCREEN_RESIZE))
6224 e_client_frame_geometry_set(ec, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h);
6226 else if (policy == E_FULLSCREEN_ZOOM)
6228 /* compositor backends! */
6229 evas_object_smart_callback_call(ec->frame, "fullscreen_zoom", NULL);
6232 if (!e_client_util_ignored_get(ec))
6233 _e_client_frame_update(ec);
6234 ec->fullscreen_policy = policy;
6235 evas_object_smart_callback_call(ec->frame, "fullscreen", NULL);
6237 _e_client_event_simple(ec, E_EVENT_CLIENT_FULLSCREEN);
6241 e_client_unfullscreen(E_Client *ec)
6244 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6245 if (!ec->zone) return;
6246 if ((ec->shaded) || (ec->shading)) return;
6247 if (!ec->fullscreen) return;
6248 ec->pre_res_change.valid = 0;
6250 ec->need_fullscreen = 0;
6251 ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
6253 if (ec->fullscreen_policy == E_FULLSCREEN_ZOOM)
6254 evas_object_smart_callback_call(ec->frame, "unfullscreen_zoom", NULL);
6256 if (!e_client_util_ignored_get(ec))
6257 _e_client_frame_update(ec);
6258 ec->fullscreen_policy = 0;
6259 evas_object_smart_callback_call(ec->frame, "unfullscreen", NULL);
6260 e_client_util_move_resize_without_frame(ec, ec->zone->x + ec->saved.x,
6261 ec->zone->y + ec->saved.y,
6262 ec->saved.w, ec->saved.h);
6264 if (ec->saved.maximized)
6265 e_client_maximize(ec, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
6266 ec->saved.maximized);
6268 e_client_layer_set(ec, ec->saved.layer);
6270 _e_client_event_simple(ec, E_EVENT_CLIENT_UNFULLSCREEN);
6272 if (!ec->desk->fullscreen_clients)
6273 e_comp_render_queue();
6276 ///////////////////////////////////////
6280 e_client_iconify(E_Client *ec)
6283 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6285 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
6286 Eina_Bool iconified_by_client = e_client_is_iconified_by_client(ec);
6288 ELOGF("TZVIS", "ICONIFY |iconic:%d |argb:%d |not_raise:%d |by_client:%d, type:%d",
6289 ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
6290 ec->exp_iconify.by_client, ec->exp_iconify.type);
6292 if (!ec->zone) return;
6293 if (ec->shading || ec->iconic) return;
6294 if (ec->exp_iconify.skip_iconify && !iconified_by_client) return;
6295 if (ec->exp_iconify.skip_by_remote) return;
6296 if (!cdata || !cdata->mapped)
6298 if (!iconified_by_client)
6300 ELOGF("TZVIS", "Not mapped.. So, don't iconify", ec);
6305 ELOGF("TZVIS", "Not mapped.. But, iconify by user request", ec);
6309 TRACE_DS_BEGIN(CLIENT:ICONIFY);
6311 e_comp_wl_remote_surface_image_save(ec);
6314 ec->want_focus = ec->take_focus = 0;
6315 ec->changes.visible = 0;
6317 ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
6318 e_client_comp_hidden_set(ec, 1);
6319 evas_object_hide(ec->frame);
6320 e_client_urgent_set(ec, ec->icccm.urgent);
6322 _e_client_event_simple(ec, E_EVENT_CLIENT_ICONIFY);
6324 if (e_config->transient.iconify)
6327 Eina_List *list = eina_list_clone(ec->transients);
6329 EINA_LIST_FREE(list, child)
6330 e_client_iconify(child);
6333 _e_client_hook_call(E_CLIENT_HOOK_ICONIFY, ec);
6339 e_client_uniconify(E_Client *ec)
6342 Eina_Bool not_raise;
6345 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6347 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
6349 ELOGF("TZVIS", "UNICONIFY|iconic:%d |argb:%d |not_raise:%d |by_client:%d, type:%d |mapped:%d",
6350 ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
6351 ec->exp_iconify.by_client, ec->exp_iconify.type,
6352 cdata ? cdata->mapped : 0);
6354 if (!ec->zone) return;
6355 if (ec->shading || (!ec->iconic)) return;
6357 TRACE_DS_BEGIN(CLIENT:UNICONIFY);
6359 e_comp_wl_remote_surface_image_save_cancel(ec);
6361 desk = e_desk_current_get(ec->desk->zone);
6362 e_client_desk_set(ec, desk);
6363 not_raise = ec->exp_iconify.not_raise;
6365 if (e_config->transient.iconify)
6368 Eina_List *list = eina_list_clone(ec->transients);
6370 EINA_LIST_FREE(list, child)
6372 if (e_client_transient_policy_get(child) == E_TRANSIENT_BELOW)
6374 child->exp_iconify.not_raise = not_raise;
6375 e_client_uniconify(child);
6385 ELOGF("TZVIS", "UNICONIFY|internal object force show", ec);
6386 evas_object_show(ec->frame);
6391 if (e_pixmap_usable_get(ec->pixmap))
6393 if (cdata && cdata->mapped)
6395 ELOGF("TZVIS", "UNICONIFY|object show. frame_visible:%d", ec, evas_object_visible_get(ec->frame));
6396 evas_object_show(ec->frame);
6400 ELOGF("TZVIS", "UNICONIFY|object no show. currently unmapped", ec);
6405 if (!ec->exp_iconify.buffer_flush &&
6406 !ec->exp_iconify.deiconify_update)
6408 if (cdata && cdata->mapped)
6410 ELOGF("TZVIS", "UNICONIFY|object show. no use buffer flush. frame_visible:%d", ec, evas_object_visible_get(ec->frame));
6411 evas_object_show(ec->frame);
6416 e_client_comp_hidden_set(ec, 0);
6417 ec->deskshow = ec->iconic = 0;
6419 #if 0 // focus should be set to the top window not uniconify window
6420 if (ec->pixmap && e_pixmap_usable_get(ec->pixmap))
6421 e_client_frame_focus_set(ec, EINA_TRUE);
6424 _e_client_event_simple(ec, E_EVENT_CLIENT_UNICONIFY);
6426 if (e_config->transient.iconify)
6429 Eina_List *list = eina_list_clone(ec->transients);
6431 EINA_LIST_FREE(list, child)
6433 if (e_client_transient_policy_get(child) == E_TRANSIENT_ABOVE)
6435 child->exp_iconify.not_raise = not_raise;
6436 e_client_uniconify(child);
6441 _e_client_hook_call(E_CLIENT_HOOK_UNICONIFY, ec);
6443 ec->exp_iconify.not_raise = 0;
6444 ec->exp_iconify.by_client = 0;
6445 e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
6451 e_client_iconified_type_set(E_Client *ec, E_Iconified_Type type)
6454 ec->exp_iconify.type = type;
6457 E_API E_Iconified_Type
6458 e_client_iconified_type_get(E_Client *ec)
6460 if (!ec) return E_ICONIFIED_TYPE_NONE;
6461 return ec->exp_iconify.type;
6464 E_API Eina_Bool e_client_is_iconified_by_client(E_Client *ec)
6466 if (!ec) return EINA_FALSE;
6468 if (ec->exp_iconify.type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT)
6471 if (ec->exp_iconify.type == E_ICONIFIED_TYPE_DESK_ICONIFY_BY_CLIENT)
6474 if (ec->exp_iconify.by_client)
6476 ELOGF("POL", "CHECK. mismatch value. by_client:%d, type:%d", ec, ec->exp_iconify.by_client, ec->exp_iconify.type);
6483 ///////////////////////////////////////
6486 e_client_urgent_set(E_Client *ec, Eina_Bool urgent)
6489 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6491 if (!ec->zone) return;
6494 if (urgent == ec->urgent) return;
6495 _e_client_event_property(ec, E_CLIENT_PROPERTY_URGENCY);
6496 if (urgent && (!ec->focused) && (!ec->want_focus))
6498 e_comp_object_signal_emit(ec->frame, "e,state,urgent", "e");
6499 ec->urgent = urgent;
6503 e_comp_object_signal_emit(ec->frame, "e,state,not_urgent", "e");
6508 ///////////////////////////////////////
6511 e_client_stick(E_Client *ec)
6516 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6517 if (!ec->zone) return;
6518 if (ec->sticky) return;
6523 e_client_desk_set(ec, desk);
6524 evas_object_smart_callback_call(ec->frame, "stick", NULL);
6526 if (e_config->transient.desktop)
6529 Eina_List *list = eina_list_clone(ec->transients);
6531 EINA_LIST_FREE(list, child)
6534 evas_object_show(ec->frame);
6538 _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
6542 e_client_unstick(E_Client *ec)
6547 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6548 if (!ec->zone) return;
6549 /* Set the desk before we unstick the client */
6550 if (!ec->sticky) return;
6551 desk = e_desk_current_get(ec->zone);
6553 ec->hidden = ec->sticky = 0;
6554 e_client_desk_set(ec, desk);
6555 evas_object_smart_callback_call(ec->frame, "unstick", NULL);
6557 if (e_config->transient.desktop)
6560 Eina_List *list = eina_list_clone(ec->transients);
6562 EINA_LIST_FREE(list, child)
6568 _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
6570 e_client_desk_set(ec, e_desk_current_get(ec->zone));
6574 e_client_pinned_set(E_Client *ec, Eina_Bool set)
6578 EINA_SAFETY_ON_NULL_RETURN(ec);
6580 layer = E_LAYER_CLIENT_ABOVE;
6582 layer = E_LAYER_CLIENT_NORMAL;
6584 e_client_layer_set(ec, layer);
6589 ///////////////////////////////////////
6592 e_client_border_set(E_Client *ec, const char *name)
6594 Eina_Stringshare *pborder;
6596 E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
6597 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
6598 if (!e_comp_object_frame_allowed(ec->frame)) return EINA_FALSE;
6599 if (ec->border.changed)
6600 CRI("CALLING WHEN border.changed SET!");
6602 if (!e_util_strcmp(ec->border.name, name)) return EINA_TRUE;
6603 if (ec->mwm.borderless && name && strcmp(name, "borderless"))
6605 CRI("border change attempted for MWM borderless client!");
6607 pborder = ec->border.name;
6608 ec->border.name = eina_stringshare_add(name);
6609 if (e_comp_object_frame_theme_set(ec->frame, name))
6611 eina_stringshare_del(pborder);
6614 eina_stringshare_del(ec->border.name);
6615 ec->border.name = pborder;
6619 ///////////////////////////////////////
6622 e_client_comp_hidden_set(E_Client *ec, Eina_Bool hidden)
6625 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6626 if (!ec->zone) return;
6629 if (ec->comp_hidden == hidden) return;
6630 ec->comp_hidden = hidden;
6631 evas_object_smart_callback_call(ec->frame, "comp_hidden", NULL);
6634 ///////////////////////////////////////
6637 e_client_act_move_keyboard(E_Client *ec)
6639 EINA_SAFETY_ON_NULL_RETURN(ec);
6640 if (!ec->zone) return;
6642 if (!_e_client_move_begin(ec))
6645 _e_client_action_init(ec);
6646 _e_client_action_move_timeout_add();
6647 if (!_e_client_hook_call(E_CLIENT_HOOK_MOVE_UPDATE, ec)) return;
6648 evas_object_freeze_events_set(ec->frame, 1);
6650 if (!action_handler_mouse)
6651 action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_client_move_mouse_down, NULL);
6655 e_client_act_resize_keyboard(E_Client *ec)
6657 EINA_SAFETY_ON_NULL_RETURN(ec);
6658 if (!ec->zone) return;
6660 ec->resize_mode = E_POINTER_RESIZE_TL;
6661 ec->keyboard_resizing = 1;
6662 if (!e_client_resize_begin(ec))
6664 ec->keyboard_resizing = 0;
6668 _e_client_action_init(ec);
6669 _e_client_action_resize_timeout_add();
6670 evas_object_freeze_events_set(ec->frame, 1);
6672 if (!action_handler_mouse)
6673 action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_client_resize_mouse_down, NULL);
6677 e_client_act_move_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev)
6680 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6681 if (!ec->zone) return;
6682 if (e_client_util_resizing_get(ec) || (ec->moving)) return;
6687 snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
6688 _e_client_moveinfo_gather(ec, source);
6690 if (!_e_client_move_begin(ec))
6693 _e_client_action_init(ec);
6694 e_zone_edge_disable();
6698 e_client_act_move_end(E_Client *ec, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
6701 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6702 if (!ec->zone) return;
6703 if (!ec->moving) return;
6704 e_zone_edge_enable();
6705 _e_client_move_end(ec);
6706 e_zone_flip_coords_handle(ec->zone, -1, -1);
6707 _e_client_action_finish();
6711 e_client_act_resize_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev, E_Pointer_Mode resize_mode)
6714 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6715 if (!ec->zone) return;
6716 if (ec->lock_user_size || ec->shaded || ec->shading) return;
6717 if (e_client_util_resizing_get(ec) || (ec->moving)) return;
6721 snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
6722 _e_client_moveinfo_gather(ec, source);
6724 if (resize_mode != E_POINTER_RESIZE_NONE)
6726 ec->resize_mode = resize_mode;
6730 /* Use canvas.x, canvas.y of event.
6731 * Transformed coordinates has to be considered for accurate resize_mode
6732 * rather than absolute coordinates. */
6733 if ((ev->canvas.x > (ec->x + ec->w / 5)) &&
6734 (ev->canvas.x < (ec->x + ec->w * 4 / 5)))
6736 if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_T;
6737 else ec->resize_mode = E_POINTER_RESIZE_B;
6739 else if (ev->canvas.x < (ec->x + ec->w / 2))
6741 if ((ev->canvas.y > (ec->y + ec->h / 5)) && (ev->canvas.y < (ec->y + ec->h * 4 / 5))) ec->resize_mode = E_POINTER_RESIZE_L;
6742 else if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_TL;
6743 else ec->resize_mode = E_POINTER_RESIZE_BL;
6747 if ((ev->canvas.y > (ec->y + ec->h / 5)) && (ev->canvas.y < (ec->y + ec->h * 4 / 5))) ec->resize_mode = E_POINTER_RESIZE_R;
6748 else if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_TR;
6749 else ec->resize_mode = E_POINTER_RESIZE_BR;
6753 if (!e_client_resize_begin(ec))
6755 _e_client_action_init(ec);
6759 e_client_act_resize_end(E_Client *ec, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
6762 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6763 if (!ec->zone) return;
6764 if (e_client_util_resizing_get(ec))
6766 _e_client_resize_end(ec);
6767 ec->changes.reset_gravity = 1;
6768 if (!e_object_is_del(E_OBJECT(ec)))
6771 _e_client_action_finish();
6775 e_client_act_menu_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev, int key)
6778 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6779 if (!ec->zone) return;
6783 e_client_act_close_begin(E_Client *ec)
6786 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6787 if (!ec->zone) return;
6788 if (ec->lock_close) return;
6789 if (ec->icccm.delete_request)
6791 ec->delete_requested = 1;
6792 evas_object_smart_callback_call(ec->frame, "delete_request", NULL);
6794 else if (e_config->kill_if_close_not_possible)
6796 e_client_act_kill_begin(ec);
6801 e_client_act_kill_begin(E_Client *ec)
6804 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6805 if (!ec->zone) return;
6806 if (ec->internal) return;
6807 if (ec->lock_close) return;
6808 if ((ec->netwm.pid > 1) && (e_config->kill_process))
6810 kill(ec->netwm.pid, SIGINT);
6811 ec->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
6812 _e_client_cb_kill_timer, ec);
6815 evas_object_smart_callback_call(ec->frame, "kill_request", NULL);
6818 ////////////////////////////////////////////
6821 e_client_ping(E_Client *ec)
6824 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6826 if (!e_config->ping_clients) return;
6828 EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ec)));
6831 evas_object_smart_callback_call(ec->frame, "ping", NULL);
6832 ec->ping = ecore_loop_time_get();
6833 if (ec->ping_poller) ecore_poller_del(ec->ping_poller);
6834 ec->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
6835 e_config->ping_clients_interval,
6836 _e_client_cb_ping_poller, ec);
6839 ////////////////////////////////////////////
6841 e_client_cursor_map_apply(E_Client *ec, int rotation, int x, int y)
6843 // TODO: remove(deprecate) this e_client_cursor_map_apply.
6847 e_client_move_cancel(void)
6849 if (!ecmove) return;
6850 if (ecmove->cur_mouse_action)
6855 e_object_ref(E_OBJECT(ec));
6856 if (ec->cur_mouse_action->func.end_mouse)
6857 ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
6858 else if (ec->cur_mouse_action->func.end)
6859 ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
6860 e_object_unref(E_OBJECT(ec->cur_mouse_action));
6861 ec->cur_mouse_action = NULL;
6862 e_object_unref(E_OBJECT(ec));
6865 _e_client_move_end(ecmove);
6869 e_client_resize_cancel(void)
6871 if (!ecresize) return;
6872 if (ecresize->cur_mouse_action)
6877 e_object_ref(E_OBJECT(ec));
6878 if (ec->cur_mouse_action->func.end_mouse)
6879 ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
6880 else if (ec->cur_mouse_action->func.end)
6881 ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
6882 e_object_unref(E_OBJECT(ec->cur_mouse_action));
6883 ec->cur_mouse_action = NULL;
6884 e_object_unref(E_OBJECT(ec));
6887 _e_client_resize_end(ecresize);
6891 e_client_resize_begin(E_Client *ec)
6893 if ((ec->shaded) || (ec->shading) ||
6894 (ec->fullscreen) || (ec->lock_user_size))
6896 if (!_e_client_action_input_win_new()) goto error;
6898 if (ec->manage_resize.enable_aspect_ratio)
6900 ELOGF("RESIZE", "Set resize aspect ratio.. ratio(%dx%d)", ec, ec->w, ec->h);
6901 ec->manage_resize.aw = ec->w;
6902 ec->manage_resize.ah = ec->h - ec->manage_resize.header_h - ec->manage_resize.footer_h;
6904 _e_client_hook_call(E_CLIENT_HOOK_RESIZE_BEGIN, ec);
6905 if (ec->transformed)
6906 _e_client_transform_resize_begin(ec);
6907 if (!e_client_util_resizing_get(ec))
6909 if (ecresize == ec) ecresize = NULL;
6910 _e_client_action_input_win_del();
6913 if (!ec->lock_user_stacking)
6915 if (e_config->border_raise_on_mouse_action)
6920 e_comp_client_override_add(ec);
6924 ec->resize_mode = E_POINTER_RESIZE_NONE;
6929 ////////////////////////////////////////////
6932 e_client_frame_recalc(E_Client *ec)
6934 EINA_SAFETY_ON_NULL_RETURN(ec);
6935 if (!ec->frame) return;
6936 evas_object_smart_callback_call(ec->frame, "frame_recalc", NULL);
6939 ////////////////////////////////////////////
6942 e_client_signal_move_begin(E_Client *ec, const char *sig, const char *src EINA_UNUSED)
6945 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6946 if (!ec->zone) return;
6948 if (e_client_util_resizing_get(ec) || (ec->moving)) return;
6949 _e_client_moveinfo_gather(ec, sig);
6950 if (!_e_client_move_begin(ec)) return;
6951 e_zone_edge_disable();
6955 e_client_signal_move_end(E_Client *ec, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
6958 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6959 if (!ec->zone) return;
6960 if (!ec->moving) return;
6961 _e_client_move_end(ec);
6962 e_zone_edge_enable();
6963 e_zone_flip_coords_handle(ec->zone, -1, -1);
6967 e_client_signal_resize_begin(E_Client *ec, const char *dir, const char *sig, const char *src EINA_UNUSED)
6969 int resize_mode = E_POINTER_RESIZE_BR;
6972 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6974 if (e_client_util_resizing_get(ec) || (ec->moving)) return;
6975 if (!strcmp(dir, "tl"))
6977 resize_mode = E_POINTER_RESIZE_TL;
6979 else if (!strcmp(dir, "t"))
6981 resize_mode = E_POINTER_RESIZE_T;
6983 else if (!strcmp(dir, "tr"))
6985 resize_mode = E_POINTER_RESIZE_TR;
6987 else if (!strcmp(dir, "r"))
6989 resize_mode = E_POINTER_RESIZE_R;
6991 else if (!strcmp(dir, "br"))
6993 resize_mode = E_POINTER_RESIZE_BR;
6995 else if (!strcmp(dir, "b"))
6997 resize_mode = E_POINTER_RESIZE_B;
6999 else if (!strcmp(dir, "bl"))
7001 resize_mode = E_POINTER_RESIZE_BL;
7003 else if (!strcmp(dir, "l"))
7005 resize_mode = E_POINTER_RESIZE_L;
7007 ec->resize_mode = resize_mode;
7008 _e_client_moveinfo_gather(ec, sig);
7009 if (!e_client_resize_begin(ec))
7014 e_client_signal_resize_end(E_Client *ec, const char *dir EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
7017 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7018 if (!e_client_util_resizing_get(ec)) return;
7019 _e_client_resize_handle(ec);
7020 _e_client_resize_end(ec);
7021 ec->changes.reset_gravity = 1;
7025 ////////////////////////////////////////////
7028 e_client_resize_limit(E_Client *ec, int *w, int *h)
7034 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7036 inc_h = (*h - ec->h > 0);
7038 e_comp_object_frame_wh_unadjust(ec->frame, *w, *h, w, h);
7041 if ((ec->icccm.base_w >= 0) &&
7042 (ec->icccm.base_h >= 0))
7046 tw = *w - ec->icccm.base_w;
7047 th = *h - ec->icccm.base_h;
7050 a = (double)(tw) / (double)(th);
7051 if ((ec->icccm.min_aspect != 0.0) &&
7052 (a < ec->icccm.min_aspect))
7055 tw = th * ec->icccm.min_aspect;
7057 th = tw / ec->icccm.max_aspect;
7058 *w = tw + ec->icccm.base_w;
7059 *h = th + ec->icccm.base_h;
7061 else if ((ec->icccm.max_aspect != 0.0) &&
7062 (a > ec->icccm.max_aspect))
7064 tw = th * ec->icccm.max_aspect;
7065 *w = tw + ec->icccm.base_w;
7070 a = (double)*w / (double)*h;
7071 if ((ec->icccm.min_aspect != 0.0) &&
7072 (a < ec->icccm.min_aspect))
7075 *w = *h * ec->icccm.min_aspect;
7077 *h = *w / ec->icccm.min_aspect;
7079 else if ((ec->icccm.max_aspect != 0.0) &&
7080 (a > ec->icccm.max_aspect))
7081 *w = *h * ec->icccm.max_aspect;
7083 if (ec->icccm.step_w > 0)
7085 if (ec->icccm.base_w >= 0)
7086 *w = ec->icccm.base_w +
7087 (((*w - ec->icccm.base_w) / ec->icccm.step_w) *
7090 *w = ec->icccm.min_w +
7091 (((*w - ec->icccm.min_w) / ec->icccm.step_w) *
7094 if (ec->icccm.step_h > 0)
7096 if (ec->icccm.base_h >= 0)
7097 *h = ec->icccm.base_h +
7098 (((*h - ec->icccm.base_h) / ec->icccm.step_h) *
7101 *h = ec->icccm.min_h +
7102 (((*h - ec->icccm.min_h) / ec->icccm.step_h) *
7109 if ((ec->icccm.max_w > 0) && (*w > ec->icccm.max_w)) *w = ec->icccm.max_w;
7110 else if (*w < ec->icccm.min_w)
7111 *w = ec->icccm.min_w;
7112 if ((ec->icccm.max_h > 0) && (*h > ec->icccm.max_h)) *h = ec->icccm.max_h;
7113 else if (*h < ec->icccm.min_h)
7114 *h = ec->icccm.min_h;
7117 e_comp_object_frame_wh_adjust(ec->frame, *w, *h, w, h);
7120 ////////////////////////////////////////////
7125 e_client_under_pointer_get(E_Desk *desk, E_Client *exclude)
7129 /* We need to ensure that we can get the comp window for the
7130 * zone of either the given desk or the desk of the excluded
7131 * window, so return if neither is given */
7133 e_input_device_pointer_xy_get(NULL, &x, &y);
7135 e_input_device_pointer_xy_get(NULL, &x, &y);
7141 desk = exclude->desk;
7145 desk = e_desk_current_get(exclude->zone);
7147 desk = e_desk_current_get(e_zone_current_get());
7151 return desk ? _e_client_under_pointer_helper(desk, exclude, x, y) : NULL;
7154 E_API E_Client *e_client_under_position_get(E_Desk *desk, int x, int y, E_Client *exclude)
7156 if (!desk) return NULL;
7158 return _e_client_under_pointer_helper(desk, exclude, x, y);
7162 e_client_input_rect_under_pointer_get(E_Desk *desk, E_Client *exclude)
7166 /* We need to ensure that we can get the comp window for the
7167 * zone of either the given desk or the desk of the excluded
7168 * window, so return if neither is given */
7170 e_input_device_pointer_xy_get(NULL, &x, &y);
7172 e_input_device_pointer_xy_get(NULL, &x, &y);
7178 desk = exclude->desk;
7182 desk = e_desk_current_get(exclude->zone);
7184 desk = e_desk_current_get(e_zone_current_get());
7188 return desk ? _e_client_input_rect_under_pointer_helper(desk, exclude, x, y) : NULL;
7191 ////////////////////////////////////////////
7194 e_client_pointer_warp_to_center_now(E_Client *ec)
7196 if (warp_client == ec)
7198 e_input_device_pointer_warp(NULL, warp_to_x, warp_to_y);
7200 _e_client_pointer_warp_to_center_timer(NULL);
7204 if (e_client_pointer_warp_to_center(ec))
7205 e_client_pointer_warp_to_center_now(ec);
7211 e_client_pointer_warp_to_center(E_Client *ec)
7214 E_Client *cec = NULL;
7216 if (!ec->zone) return 0;
7217 /* Only warp the pointer if it is not already in the area of
7218 * the given border */
7219 e_input_device_pointer_xy_get(NULL, &x, &y);
7220 if ((x >= ec->x) && (x <= (ec->x + ec->w)) &&
7221 (y >= ec->y) && (y <= (ec->y + ec->h)))
7223 cec = _e_client_under_pointer_helper(ec->desk, ec, x, y);
7224 if (cec == ec) return 0;
7227 warp_to_x = ec->x + (ec->w / 2);
7228 if (warp_to_x < (ec->zone->x + 1))
7229 warp_to_x = ec->zone->x + ((ec->x + ec->w - ec->zone->x) / 2);
7230 else if (warp_to_x > (ec->zone->x + ec->zone->w))
7231 warp_to_x = (ec->zone->x + ec->zone->w + ec->x) / 2;
7233 warp_to_y = ec->y + (ec->h / 2);
7234 if (warp_to_y < (ec->zone->y + 1))
7235 warp_to_y = ec->zone->y + ((ec->y + ec->h - ec->zone->y) / 2);
7236 else if (warp_to_y > (ec->zone->y + ec->zone->h))
7237 warp_to_y = (ec->zone->y + ec->zone->h + ec->y) / 2;
7239 /* TODO: handle case where another border is over the exact center,
7240 * find a place where the requested border is not overlapped?
7242 if (!cec) cec = _e_client_under_pointer_helper(ec->desk, ec, x, y);
7250 e_input_device_pointer_xy_get(NULL, &warp_x[0], &warp_y[0]);
7251 if (warp_timer) ecore_timer_del(warp_timer);
7252 warp_timer = ecore_timer_add(0.01, _e_client_pointer_warp_to_center_timer, ec);
7256 ////////////////////////////////////////////
7259 e_client_redirected_set(E_Client *ec, Eina_Bool set)
7261 EINA_SAFETY_ON_NULL_RETURN(ec);
7262 if (ec->input_only) return;
7264 if (ec->redirected == set) return;
7267 e_client_frame_recalc(ec);
7268 if (!_e_client_hook_call(E_CLIENT_HOOK_REDIRECT, ec)) return;
7272 if (!_e_client_hook_call(E_CLIENT_HOOK_UNREDIRECT, ec)) return;
7274 e_comp_object_redirected_set(ec->frame, set);
7275 ec->redirected = !!set;
7278 ////////////////////////////////////////////
7281 e_client_is_stacking(const E_Client *ec)
7283 return e_comp->layers[e_comp_canvas_layer_map(ec->layer)].obj == ec->frame;
7286 ////////////////////////////////////////////
7289 e_client_layout_cb_set(E_Client_Layout_Cb cb)
7291 if (_e_client_layout_cb && cb)
7292 CRI("ATTEMPTING TO OVERWRITE EXISTING CLIENT LAYOUT HOOK!!!");
7293 _e_client_layout_cb = cb;
7296 ////////////////////////////////////////////
7299 e_client_transform_update(E_Client *ec)
7301 if (e_client_util_resizing_get(ec))
7302 _e_client_transform_resize(ec);
7305 ////////////////////////////////////////////
7308 e_client_transform_apply(E_Client *ec, double angle, double zoom, int cx, int cy)
7311 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
7315 if (e_comp_wl_subsurface_check(ec))
7318 /* check if it's different with current state */
7319 if ((ec->transform.angle == angle) &&
7320 (ec->transform.zoom == zoom) &&
7321 (ec->transform.center.x == cx) &&
7322 (ec->transform.center.y == cy))
7325 /* use previous value if any required value is invalid */
7327 angle = ec->transform.angle;
7329 zoom = ec->transform.zoom;
7330 if (!E_INSIDE(cx, cy,
7331 ec->client.x, ec->client.y,
7332 ec->client.w, ec->client.h))
7334 cx = ec->transform.center.x;
7335 cy = ec->transform.center.y;
7338 if ((angle == 0) && (zoom == 1.0))
7340 e_client_transform_clear(ec);
7344 map = e_map_new_with_direct_render(ec->transform_core.direct_render);
7345 e_map_util_points_populate_from_object_full(map, ec->frame, 0);
7347 e_map_util_rotate(map, angle, cx, cy);
7348 _e_client_transform_geometry_save(ec, map);
7350 e_map_util_zoom(map, zoom, zoom, cx, cy);
7352 e_map_util_object_move_sync_set(map, EINA_TRUE);
7353 e_client_map_set(ec, map);
7354 e_client_map_enable_set(ec, EINA_TRUE);
7356 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
7357 _e_client_transform_sub_apply(subc, ec, zoom);
7358 EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
7359 _e_client_transform_sub_apply(subc, ec, zoom);
7363 ec->transform.zoom = zoom;
7364 ec->transform.angle = angle;
7365 ec->transform.center.x = cx;
7366 ec->transform.center.y = cy;
7367 ec->transformed = EINA_TRUE;
7370 ////////////////////////////////////////////
7373 e_client_transform_clear(E_Client *ec)
7375 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
7379 e_client_map_enable_set(ec, EINA_FALSE);
7380 e_client_map_set(ec, NULL);
7382 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
7383 _e_client_transform_sub_apply(subc, ec, 1.0);
7384 EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
7385 _e_client_transform_sub_apply(subc, ec, 1.0);
7387 ec->transform.zoom = 1.0;
7388 ec->transform.angle = 0.0;
7389 ec->transformed = EINA_FALSE;
7393 e_client_transform_core_enable_get(E_Client *ec)
7395 if (!ec) return EINA_FALSE;
7396 return ec->transform_core.result.enable;
7400 e_client_transform_core_add(E_Client *ec, E_Util_Transform *transform)
7403 if (!transform) return;
7405 // duplication check
7406 if (ec->transform_core.transform_list &&
7407 eina_list_data_find(ec->transform_core.transform_list, transform) == transform)
7412 ec->transform_core.transform_list = eina_list_append(ec->transform_core.transform_list, transform);
7413 ec->transform_core.changed = EINA_TRUE;
7414 e_util_transform_ref(transform);
7415 // e_client_transform_core_update(ec);
7419 e_client_transform_core_remove(E_Client *ec, E_Util_Transform *transform)
7422 if (!transform) return;
7424 if (ec->transform_core.transform_list &&
7425 eina_list_data_find(ec->transform_core.transform_list, transform) == transform)
7427 ec->transform_core.transform_list = eina_list_remove(ec->transform_core.transform_list, transform);
7428 e_util_transform_unref(transform);
7429 ec->transform_core.changed = EINA_TRUE;
7432 e_client_transform_core_update(ec);
7436 e_client_transform_core_update(E_Client *ec)
7439 if (ec->new_client) return;
7440 if (!_e_client_transform_core_check_change(ec)) return;
7442 if (ec->transform_core.transform_list || ec->transform_core.parent.enable)
7444 E_Util_Transform_Rect source_rect;
7445 E_Util_Transform_Matrix matrix, boundary_matrix;
7446 E_Util_Transform_Zoom zoom;
7448 Eina_Bool background;
7449 E_Util_Transform *temp_trans;
7452 ec->transform_core.result.enable = EINA_TRUE;
7453 e_util_transform_rect_client_rect_get(&source_rect, ec);
7454 e_util_transform_init(&ec->transform_core.result.transform);
7456 // 2. merge transform
7457 EINA_LIST_FOREACH(ec->transform_core.transform_list, l, temp_trans)
7459 e_util_transform_merge(&ec->transform_core.result.transform, temp_trans);
7461 zoom = ec->transform_core.result.transform.zoom;
7463 // 2.5 check viewport
7464 if (e_util_transform_viewport_flag_get(&ec->transform_core.result.transform))
7466 int vx = 0, vy = 0, vw = 0, vh = 0;
7467 e_util_transform_viewport_get(&ec->transform_core.result.transform, &vx, &vy, &vw, &vh);
7468 e_util_transform_rect_init(&source_rect, vx, vy, vw, vh);
7471 // 3. apply background transform
7472 matrix = e_util_transform_convert_to_matrix(&ec->transform_core.result.transform, &source_rect);
7474 if (e_util_transform_bg_transform_flag_get(&ec->transform_core.result.transform))
7476 boundary_matrix = e_util_transform_bg_convert_to_matrix(&ec->transform_core.result.transform, &source_rect);
7477 background = EINA_TRUE;
7481 background = EINA_FALSE;
7482 boundary_matrix = matrix;
7485 if (background != ec->transform_core.background)
7489 e_comp_object_transform_bg_set(ec->frame, EINA_TRUE);
7493 e_comp_object_transform_bg_set(ec->frame, EINA_FALSE);
7496 ec->transform_core.background = background;
7499 // 3.1 if 24bit window then set transp rect
7504 e_util_transform_rotation_round_get(&ec->transform_core.result.transform, 0, 0, &angle);
7507 if (angle == 0) // when transform angle is 0, 90, 180, 270, 360. then set transp rect
7508 e_comp_object_transform_transp_set(ec->frame, EINA_TRUE);
7510 e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
7513 e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
7515 // 3.5 parent matrix multiply
7516 if (ec->transform_core.parent.enable)
7518 matrix = e_util_transform_matrix_multiply(&ec->transform_core.parent.matrix,
7520 boundary_matrix = e_util_transform_matrix_multiply(&ec->transform_core.parent.matrix,
7523 ec->transform_core.result.transform.use_zoom = EINA_TRUE;
7524 zoom.zoom_x *= ec->transform_core.parent.zoom.zoom_x;
7525 zoom.zoom_y *= ec->transform_core.parent.zoom.zoom_y;
7526 zoom.cx += ec->transform_core.parent.zoom.cx;
7527 zoom.cy += ec->transform_core.parent.zoom.cy;
7530 // 4. apply matrix to vertices
7531 ec->transform_core.result.matrix = matrix;
7532 ec->transform_core.result.inv_matrix = e_util_transform_matrix_inverse_get(&matrix);
7533 ec->transform_core.result.vertices = e_util_transform_rect_to_vertices(&source_rect);
7534 ec->transform_core.result.boundary.vertices = e_util_transform_rect_to_vertices(&source_rect);
7535 ec->transform_core.result.vertices = e_util_transform_matrix_multiply_rect_vertex(&matrix,
7536 &ec->transform_core.result.vertices);
7537 ec->transform_core.result.boundary.vertices = e_util_transform_matrix_multiply_rect_vertex(&boundary_matrix,
7538 &ec->transform_core.result.boundary.vertices);
7539 ec->transform_core.result.transform.zoom = zoom;
7541 // 5. apply vertices
7542 if (ec->transform_core.result.transform.use_zoom)
7544 // TODO: apply zoom values to vertices
7545 e_comp_object_transform_transp_vertices_set_with_zoom(ec->frame, &ec->transform_core.result.vertices,
7546 ec->transform_core.result.transform.zoom);
7547 e_comp_object_transform_bg_vertices_set_with_zoom(ec->frame, &ec->transform_core.result.boundary.vertices,
7548 ec->transform_core.result.transform.zoom);
7549 _e_client_transform_core_boundary_update(ec, &ec->transform_core.result.boundary.vertices);
7550 _e_client_transform_core_vertices_apply_with_zoom(ec, ec->frame, &ec->transform_core.result.vertices, &ec->transform_core.result.transform,
7551 ec->transform_core.result.transform.zoom);
7555 e_comp_object_transform_transp_vertices_set(ec->frame, &ec->transform_core.result.vertices);
7556 e_comp_object_transform_bg_vertices_set(ec->frame, &ec->transform_core.result.boundary.vertices);
7557 _e_client_transform_core_boundary_update(ec, &ec->transform_core.result.boundary.vertices);
7558 _e_client_transform_core_vertices_apply(ec, ec->frame, &ec->transform_core.result.vertices, &ec->transform_core.result.transform);
7561 // 6. subsurface update
7562 _e_client_transform_core_sub_update(ec, &ec->transform_core.result.vertices);
7564 if (!e_object_is_del(E_OBJECT(ec)))
7565 _e_client_hook_call(E_CLIENT_HOOK_TRANSFORM_CHANGE, ec);
7569 if (ec->transform_core.result.enable)
7571 ec->transform_core.result.enable = EINA_FALSE;
7572 _e_client_transform_core_vertices_apply(ec, ec->frame, NULL, NULL);
7573 e_comp_object_transform_bg_set(ec->frame, EINA_FALSE);
7574 ec->transform_core.background = EINA_FALSE;
7575 e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
7576 _e_client_transform_core_sub_update(ec, NULL);
7578 if (!e_object_is_del(E_OBJECT(ec)))
7579 _e_client_hook_call(E_CLIENT_HOOK_TRANSFORM_CHANGE, ec);
7583 e_client_visibility_calculate();
7587 e_client_transform_core_transform_count_get(E_Client *ec)
7590 if (!ec->transform_core.transform_list) return 0;
7591 return eina_list_count(ec->transform_core.transform_list);
7594 E_API E_Util_Transform*
7595 e_client_transform_core_transform_get(E_Client *ec, int index)
7597 if (!ec) return NULL;
7598 if (!ec->transform_core.transform_list) return NULL;
7599 if (index < 0 || index >= e_client_transform_core_transform_count_get(ec))
7602 return (E_Util_Transform*)eina_list_nth(ec->transform_core.transform_list, index);
7606 e_client_transform_core_input_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
7608 E_Util_Transform_Vertex vertex, result_vertex;
7611 if (!e_client_transform_core_enable_get(ec)) return;
7613 e_util_transform_vertex_init(&vertex, x, y, 0.0, 1.0);
7615 result_vertex = e_util_transform_matrix_multiply_vertex(&ec->transform_core.result.inv_matrix, &vertex);
7616 e_util_transform_vertex_pos_round_get(&result_vertex, out_x, out_y, NULL, NULL);
7620 e_client_transform_core_input_inv_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
7622 E_Util_Transform_Vertex vertex, result_vertex;
7625 if (!e_client_transform_core_enable_get(ec)) return;
7627 e_util_transform_vertex_init(&vertex, x, y, 0.0, 1.0);
7629 result_vertex = e_util_transform_matrix_multiply_vertex(&ec->transform_core.result.matrix, &vertex);
7630 e_util_transform_vertex_pos_round_get(&result_vertex, out_x, out_y, NULL, NULL);
7634 e_client_transform_core_input_inv_rect_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
7638 if (!e_client_transform_core_enable_get(ec)) return;
7639 e_client_geometry_get(ec, NULL, NULL, &gw, &gh);
7641 e_util_transform_matrix_inv_rect_coords_get(&ec->transform_core.result.transform,
7642 &ec->transform_core.result.vertices,
7644 x, y, out_x, out_y);
7648 e_client_transform_core_direct_render_set(E_Client *ec, Eina_Bool set)
7650 EINA_SAFETY_ON_NULL_RETURN(ec);
7652 if (ec->transform_core.direct_render == set) return;
7654 ec->transform_core.direct_render = set;
7655 ec->transform_core.changed = EINA_TRUE;
7657 e_client_transform_core_update(ec);
7661 e_client_pixmap_change(E_Client *ec, E_Pixmap *newcp)
7663 E_Pixmap_Type oldtype, newtype;
7666 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
7667 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, NULL);
7668 EINA_SAFETY_ON_NULL_RETURN_VAL(newcp, NULL);
7672 oldtype = e_pixmap_type_get(oldcp);
7673 if (oldtype >= E_PIXMAP_TYPE_MAX) return NULL;
7675 newtype = e_pixmap_type_get(newcp);
7676 if (newtype >= E_PIXMAP_TYPE_MAX) return NULL;
7678 if (eina_hash_find(clients_hash[oldtype], &oldcp))
7679 eina_hash_del_by_key(clients_hash[oldtype], &oldcp);
7680 e_pixmap_client_set(oldcp, NULL);
7683 e_pixmap_client_set(newcp, ec);
7685 eina_hash_add(clients_hash[newtype], &newcp, ec);
7691 e_client_window_role_set(E_Client *ec, const char *role)
7693 EINA_SAFETY_ON_NULL_RETURN(ec);
7695 if (eina_stringshare_replace(&ec->icccm.window_role, role))
7696 _e_client_hook_call(E_CLIENT_HOOK_WINDOW_ROLE_CHANGE, ec);
7700 e_client_key_send(E_Client *ec, int keycode, Eina_Bool pressed, Ecore_Device *dev, unsigned int time)
7704 res = e_comp_wl_key_send(ec, keycode, pressed, dev, time);
7710 e_client_key_cancel(E_Client *ec, int keycode, Ecore_Device *dev, unsigned int time)
7714 res = e_comp_wl_key_cancel(ec, keycode, dev, time);
7720 e_client_touch_send(E_Client *ec, int idx, int x, int y, Eina_Bool pressed, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, unsigned int time)
7724 res = e_comp_wl_touch_send(ec, idx, x, y, pressed, dev, radius_x, radius_y, pressure, angle, time);
7730 e_client_touch_update_send(E_Client *ec, int idx, int x, int y, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, unsigned int time)
7734 res = e_comp_wl_touch_update_send(ec, idx, x, y, dev, radius_x, radius_y, pressure, angle, time);
7740 e_client_touch_cancel_send(E_Client *ec)
7744 res = e_comp_wl_touch_cancel_send(ec);
7750 e_client_mouse_button_send(E_Client *ec, int buttons, Eina_Bool pressed, Ecore_Device *dev, unsigned int time)
7754 res = e_comp_wl_mouse_button_send(ec, buttons, pressed, dev, time);
7760 e_client_mouse_move_send(E_Client *ec, int x, int y, Ecore_Device *dev, unsigned int time)
7764 res = e_comp_wl_mouse_move_send(ec, x, y, dev, time);
7770 e_client_mouse_wheel_send(E_Client *ec, int direction, int z, Ecore_Device *dev, unsigned int time)
7774 res = e_comp_wl_mouse_wheel_send(ec, direction, z, dev, time);
7780 e_client_mouse_in_send(E_Client *ec, int x, int y, Ecore_Device *dev, unsigned int time)
7784 res = e_comp_wl_mouse_in_send(ec, x, y, dev, time);
7790 e_client_mouse_out_send(E_Client *ec, Ecore_Device *dev, unsigned int time)
7794 res = e_comp_wl_mouse_out_send(ec, dev, time);
7800 e_client_video_client_has(E_Client *ec)
7802 return e_comp_wl_video_subsurface_has(ec);
7806 e_client_normal_client_has(E_Client *ec)
7808 return e_comp_wl_normal_subsurface_has(ec);
7812 e_client_cursor_hide(E_Client *ec)
7814 return e_comp_wl_cursor_hide(ec);
7818 e_client_visibility_force_obscured_set(E_Client *ec, Eina_Bool set)
7822 ELOGF("TZVIS", "VIS_FORCE_OBSCURED :%d", ec, set);
7824 ec->visibility.force_obscured = set;
7825 e_client_visibility_calculate();
7828 E_API E_Capture_Save_State
7829 e_client_image_save(E_Client *ec, const char *dir, const char *name, E_Capture_Client_Save_End_Cb func_end, void *data, Eina_Bool skip_child)
7831 return e_comp_wl_capture_client_image_save(ec, dir, name, func_end, data, skip_child);
7835 _e_client_base_output_resolution_hook_subsurf_create(void *data, E_Client *subc)
7837 E_Client *ec, *parent;
7843 ec->base_output_resolution.use = 0;
7844 ec->base_output_resolution.w = 0;
7845 ec->base_output_resolution.h = 0;
7846 if (ec->base_output_resolution.transform)
7848 e_client_transform_core_remove(ec, ec->base_output_resolution.transform);
7849 E_FREE_FUNC(ec->base_output_resolution.transform, e_util_transform_del);
7850 ELOGF("POL_APPINFO", "Cancel TRANSFORM for subsurface", ec);
7853 /* Update transform for toplevel surface.
7854 * The transform of subsurface will be updated by its parent accordingly. */
7855 parent = e_comp_wl_topmost_parent_get(ec);
7858 parent->transform_core.changed = EINA_TRUE;
7859 e_client_transform_core_update(parent);
7862 /* TODO: Do we need to apply it again if subsurface is destroyed? */
7866 _e_client_base_output_resolution_set(E_Client *ec, int width, int height)
7869 ec->base_output_resolution.use = 1;
7870 ec->base_output_resolution.w = width;
7871 ec->base_output_resolution.h = height;
7872 ec->base_output_resolution.transform = e_util_transform_new();
7873 e_util_transform_role_set(ec->base_output_resolution.transform, "base_output_resolution");
7874 e_client_transform_core_add(ec, ec->base_output_resolution.transform);
7876 if (!ec->base_output_resolution.hook_subsurf_create)
7878 ec->base_output_resolution.hook_subsurf_create =
7879 e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_CREATE,
7880 _e_client_base_output_resolution_hook_subsurf_create,
7886 e_client_base_output_resolution_transform_adjust(E_Client *ec)
7888 EINA_SAFETY_ON_NULL_RETURN(ec);
7889 if (!ec->base_output_resolution.use) return;
7890 if (!ec->base_output_resolution.transform) return;
7892 ELOGF("POL_APPINFO", "Apply TRANSFORM... desk:(%dx%d), ec:(%dx%d)",
7893 ec, ec->desk->geom.w, ec->desk->geom.h, ec->w, ec->h);
7894 e_util_transform_scale(ec->base_output_resolution.transform,
7895 (double)ec->desk->geom.w /(double)ec->base_output_resolution.w,
7896 (double)ec->desk->geom.h /(double)ec->base_output_resolution.h,
7898 e_client_transform_core_update(ec);
7902 e_client_base_output_resolution_update(E_Client *ec)
7904 E_Appinfo *eai = NULL;
7905 int configured_width, configured_height;
7908 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
7910 if (!e_config->configured_output_resolution.use) return EINA_TRUE;
7911 if (ec->base_output_resolution.use) return EINA_TRUE;
7913 /* Check whether it's subsurface or not
7914 * The resolution of subsurface will follow the resolution of its toplevel surface.
7915 * Transform for subsurface will be applied when toplevel surface does by
7916 * implementation of e_client_transform_core.
7918 if (e_comp_wl_subsurface_check(ec))
7921 configured_width = e_config->configured_output_resolution.w;
7922 configured_height = e_config->configured_output_resolution.h;
7926 ELOGF("POL_APPINFO", "NO PID... USE configured_output_resolution(%d,%d) pid:%d", ec,
7927 configured_width, configured_height, ec->netwm.pid);
7928 goto use_configured;
7931 eai = e_appinfo_find_with_pid(ec->netwm.pid);
7934 ELOGF("POL_APPINFO", "NO APPINFO... USE configured_output_resolution(%d,%d) pid:%d", ec,
7935 configured_width, configured_height, ec->netwm.pid);
7936 goto use_configured;
7939 if (!e_appinfo_base_output_resolution_get(eai, &width, &height))
7941 ELOGF("POL_APPINFO", "NO BASE SCREEN RESOLUTION... USE configured_output_resolution(%d,%d) pid:%d", ec,
7942 configured_width, configured_height, ec->netwm.pid);
7943 goto use_configured;
7946 if ((width == 0) && (height == 0))
7948 ELOGF("POL_APPINFO", "SKIP SET BASE SCREEN RESOLUTION... base_output_resolution size:(%d,%d) pid:%d", ec, width, height, ec->netwm.pid);
7952 if ((ec->desk->geom.w == width) && (ec->desk->geom.h == height))
7954 ELOGF("POL_APPINFO", "SKIP SET BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), pid:%d", ec, width, height, ec->netwm.pid);
7958 /* set the base_output_resolution of the e_client */
7959 _e_client_base_output_resolution_set(ec, width, height);
7961 ELOGF("POL_APPINFO", "USE base_output_resolution(%d,%d) pid:%d", ec, width, height, ec->netwm.pid);
7967 if ((ec->desk->geom.w == configured_width) && (ec->desk->geom.h == configured_height))
7969 ELOGF("POL_APPINFO", "SKIP use configured_output_resolution (same with desk size:(%d,%d), pid:%d)", ec, configured_width, configured_height, ec->netwm.pid);
7973 /* set the base_output_resolution of the e_client as a default */
7974 _e_client_base_output_resolution_set(ec, configured_width, configured_height);
7981 e_client_base_output_resolution_useful_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
7985 E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
7986 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->zone, EINA_FALSE);
7988 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
7995 if (ec->base_output_resolution.use)
7997 if (w) *w = ec->base_output_resolution.w;
7998 if (h) *h = ec->base_output_resolution.h;
8004 /* change the base_output_resolution of the bind_ec by checking the base_output_resolution of provider_ec's appinfo */
8006 e_client_base_output_resolution_rsm_update(E_Client *bind_ec, E_Client *provider_ec)
8008 E_Appinfo *epai = NULL;
8009 int configured_width, configured_height;
8012 EINA_SAFETY_ON_NULL_RETURN_VAL(bind_ec, EINA_FALSE);
8013 EINA_SAFETY_ON_NULL_RETURN_VAL(provider_ec, EINA_FALSE);
8015 if (!e_config->configured_output_resolution.use) return EINA_TRUE;
8017 configured_width = e_config->configured_output_resolution.w;
8018 configured_height = e_config->configured_output_resolution.h;
8020 if (bind_ec->base_output_resolution.use)
8022 ELOGF("POL_APPINFO", "DELETE EXISTED BINDER BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), bind_pid:%d", bind_ec,
8023 bind_ec->base_output_resolution.w, bind_ec->base_output_resolution.h, bind_ec->netwm.pid);
8025 bind_ec->base_output_resolution.use = 0;
8026 bind_ec->base_output_resolution.w = 0;
8027 bind_ec->base_output_resolution.h = 0;
8028 e_client_transform_core_remove(bind_ec, bind_ec->base_output_resolution.transform);
8029 E_FREE_FUNC(bind_ec->base_output_resolution.transform, e_util_transform_del);
8032 if (!provider_ec->netwm.pid)
8034 ELOGF("POL_APPINFO", "NO PROVIDER PID... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
8035 configured_width, configured_height, provider_ec->netwm.pid);
8036 goto use_configured;
8039 epai = e_appinfo_find_with_pid(provider_ec->netwm.pid);
8042 ELOGF("POL_APPINFO", "NO PROVIDER APPINFO... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
8043 configured_width, configured_height, provider_ec->netwm.pid);
8044 goto use_configured;
8047 if (!e_appinfo_base_output_resolution_get(epai, &width, &height))
8049 ELOGF("POL_APPINFO", "NO PROVIDER APPINFO BASE SCREEN RESOLUTION... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
8050 configured_width, configured_height, provider_ec->netwm.pid);
8051 goto use_configured;
8054 if ((width == 0) && (height == 0))
8056 ELOGF("POL_APPINFO", "NO PROVIDER WIDTH and HEIGHT... SKIP base_output_resolution due to size:(%d,%d) provider_pid:%d", provider_ec,
8057 width, height, provider_ec->netwm.pid);
8061 if ((bind_ec->desk->geom.w == width) && (bind_ec->desk->geom.h == height))
8063 ELOGF("POL_APPINFO", "SKIP SET BINDER BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), bind_pid:%d", bind_ec,
8064 width, height, bind_ec->netwm.pid);
8068 /* set the base_output_resolution of the e_client */
8069 _e_client_base_output_resolution_set(bind_ec, width, height);
8070 e_client_base_output_resolution_transform_adjust(bind_ec);
8072 ELOGF("POL_APPINFO", "USE BINDER base_output_resolution(%d,%d) bind_pid:%d", bind_ec, width, height, bind_ec->netwm.pid);
8078 if ((bind_ec->desk->geom.w == configured_width) && (bind_ec->desk->geom.h == configured_height))
8080 ELOGF("POL_APPINFO", "SKIP BINDER use configured_output_resolution (same with desk size:(%d,%d), bind_pid:%d)", bind_ec,
8081 configured_width, configured_height, bind_ec->netwm.pid);
8085 /* set the base_output_resolution of the e_client as a default */
8086 _e_client_base_output_resolution_set(bind_ec, configured_width, configured_height);
8092 /* tizen_move_resize */
8094 e_client_pending_geometry_has(E_Client *ec)
8096 if (!eina_list_count(ec->surface_sync.pending_geometry))
8099 return ec->surface_sync.wait_commit;
8103 e_client_pending_geometry_flush(E_Client *ec)
8105 E_Client_Pending_Geometry *geo;
8107 if (!eina_list_count(ec->surface_sync.pending_geometry))
8109 EINA_LIST_FREE(ec->surface_sync.pending_geometry, geo)
8113 ec->surface_sync.wait_commit = EINA_FALSE;
8114 ELOGF("POSSIZE", "pending geometry has flushed", ec);
8119 e_client_pending_geometry_last_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
8122 E_Client_Pending_Geometry *geo;
8128 EINA_LIST_REVERSE_FOREACH(ec->surface_sync.pending_geometry, l, geo)
8144 e_client_frame_focus_set(E_Client *ec, Eina_Bool focus)
8147 evas_object_focus_set(ec->frame, focus);
8151 e_client_frame_geometry_set(E_Client *ec, int x, int y, int w, int h)
8155 if (ec->internal || ec->input_only)
8157 evas_object_geometry_set(ec->frame, x, y, w, h);
8161 if ((ec->w != w) || (ec->h != h))
8163 ELOGF("POSSIZE", "Set move_after_resize. old(%d,%d,%dx%d), new(%d,%d,%dx%d)", ec, ec->x, ec->y, ec->w, ec->h, x, y, w, h);
8164 ec->move_after_resize = EINA_TRUE;
8166 e_client_pos_set(ec, x, y);
8167 evas_object_resize(ec->frame, w, h);
8170 evas_object_geometry_set(ec->frame, x, y, w, h);
8175 e_client_util_move_resize_without_frame(E_Client *ec, int x, int y, int w, int h)
8179 if (ec->internal || ec->input_only)
8181 e_client_util_move_without_frame(ec, x, y);
8182 e_client_util_resize_without_frame(ec, w, h);
8186 if ((ec->w != w) || (ec->h != h))
8188 ELOGF("POSSIZE", "Set move_after_resize. old(%d,%d,%dx%d), new(%d,%d,%dx%d)", ec, ec->x, ec->y, ec->w, ec->h, x, y, w, h);
8189 ec->move_after_resize = EINA_TRUE;
8191 e_comp_object_frame_xy_adjust(ec->frame, x, y, &x, &y);
8192 e_client_pos_set(ec, x, y);
8193 e_client_util_resize_without_frame(ec, w, h);
8197 e_client_util_move_without_frame(ec, x, y);
8198 e_client_util_resize_without_frame(ec, w, h);
8204 e_client_layer_set(E_Client *ec,
8207 E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8208 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
8209 if (!ec->frame) return EINA_FALSE;
8211 if (e_comp_canvas_client_layer_map(layer) == 9999)
8212 return EINA_FALSE; //invalid layer is not allowed
8214 if (ec->desk_area.enable)
8216 if (e_client_layer_set_by_desk_area(ec, layer))
8218 // restack according to desk group rule
8219 e_desk_area_ec_rearrange(ec->desk_area.desk_area, ec);
8223 ec->desk_area.layer_backup = layer;
8225 evas_object_layer_set(ec->frame, layer);
8226 if (ec->layer != layer)
8228 /* check exceptional case */
8229 if ((ec->fullscreen) &&
8230 (ec->saved.layer != layer))
8232 ELOGF("LAYER", "(%d) fail to backup at saved.layer for fullscreen", ec, layer);
8235 // if e_comp_object fail to change ec->layer due to ec->layer_pending or block
8236 // leave log and apply ec->layer according to set
8237 // as a result it restores back to given layer when pending or block is free
8238 ELOGF("LAYER", "change layer from %d to %d if in case layer pending(%d) or block(%d)",
8239 ec, ec->layer, layer, ec->layer_pending, ec->layer_block);
8240 if (ec->layer_pending || ec->layer_block)
8251 e_client_layer_get(E_Client *ec)
8255 E_OBJECT_CHECK_RETURN(ec, E_LAYER_BOTTOM);
8256 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, E_LAYER_BOTTOM);
8257 if (!ec->frame) return E_LAYER_BOTTOM;
8259 layer = evas_object_layer_get(ec->frame);
8260 if (ec->layer != layer)
8262 /* client could be on temperory layer while pending or block,
8263 * in that case, client restores back to ec->layer after pending/block finish */
8264 if (ec->layer_block || ec->layer_pending)
8267 /* otherwise, client is on unexpected layer */
8268 ELOGF("LAYER", "layer dismatch ec->layer %d | evas obj layer %d ",
8269 ec, ec->layer, layer);
8271 if (e_comp_canvas_client_layer_map(layer) == 9999)
8272 return E_LAYER_BOTTOM; //not on E_LAYER_CLIENT
8279 _e_client_desk_area_original_layer_save(E_Client *ec, E_Layer layer)
8282 E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
8283 ec->desk_area.layer_backup = layer;
8287 e_client_layer_set_by_desk_area(E_Client *ec, E_Layer layer)
8293 if (!ec) return EINA_FALSE;
8294 if (!ec->frame) return EINA_FALSE;
8295 if (!ec->desk_area.enable) return EINA_FALSE;
8296 if (!ec->desk_area.desk_area) return EINA_FALSE;
8298 eda = ec->desk_area.desk_area;
8300 // save original layer
8301 _e_client_desk_area_original_layer_save(ec, layer);
8303 // get desk_area layer
8304 edg_layer = (E_Layer)e_desk_area_layer_get(eda);
8305 org_layer = e_client_desk_area_original_layer_get(ec);
8307 ELOGF("EDG", "layer_set by desk_area... layer:%d, org_layer:%d, new_layer:%d", ec, layer, org_layer, edg_layer);
8308 if (org_layer == edg_layer)
8314 evas_object_layer_set(ec->frame, edg_layer);
8315 if (edg_layer == ec->layer)
8323 e_client_desk_area_original_layer_restore(E_Client *ec)
8327 // Do we need to check ec->desk_area.enable?
8328 // if ec->desk_area.enable is true, then e_client_layer_set calls
8329 // e_desk_area_ec_layer_set(). that's too bad. :(
8330 // so, we MUST make a policy for ordering of the desk group layer restore
8331 // and the desk group enable.
8332 if (ec->desk_area.enable) return;
8333 e_client_layer_set(ec, ec->desk_area.layer_backup);
8337 e_client_desk_area_original_layer_get(E_Client *ec)
8339 if (!ec) return E_LAYER_DESKTOP;
8341 if (ec->desk_area.enable)
8342 return ec->desk_area.layer_backup;
8348 e_client_desk_area_client_layer_set(E_Client *ec, E_Desk_Area_Client_Layer edgc_layer)
8350 E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8351 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
8352 if ((edgc_layer < E_DESK_AREA_CLIENT_LAYER_DESKTOP) ||
8353 (edgc_layer >= E_DESK_AREA_CLIENT_LAYER_MAX))
8356 ec->desk_area.edgc_layer = edgc_layer;
8360 EINTERN E_Desk_Area_Client_Layer
8361 e_client_desk_area_client_layer_get(E_Client *ec)
8363 E_OBJECT_CHECK_RETURN(ec, E_DESK_AREA_CLIENT_LAYER_DESKTOP);
8365 return ec->desk_area.edgc_layer;
8369 e_client_desk_area_enable_set(E_Client *ec, Eina_Bool enable)
8371 E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8372 E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
8374 ec->desk_area.enable = enable;
8376 ELOGF("EDG", "Desk group enable set to %d", ec, enable);
8379 if (!ec->desk_area.transform)
8381 ec->desk_area.transform = e_util_transform_new();
8382 e_util_transform_role_set(ec->desk_area.transform, "desk_area");
8387 if (ec->desk_area.transform)
8389 e_util_transform_del(ec->desk_area.transform);
8390 ec->desk_area.transform = NULL;
8394 e_desk_area_ec_update(ec->desk_area.desk_area, ec);
8399 e_client_desk_area_set(E_Client *ec, E_Desk_Area *eda)
8401 E_Desk_Area *old_edg;
8403 if (!ec) return EINA_FALSE;
8405 #if 0 // if this is removed.. then below if (eda != old_edg) is removed also...
8406 if (ec->desk_area.desk_area == eda)
8410 ELOGF("EDG", "Desk Group Set (new:%p, old:%p)", ec, eda, ec->desk_area.desk_area);
8411 old_edg = ec->desk_area.desk_area;
8413 e_desk_area_ec_remove(old_edg, ec);
8415 ec->desk_area.desk_area = eda;
8416 e_desk_area_ec_add(eda, ec);
8418 #if 0 // if this is removed.. then above if (ec->desk_area.desk_area == eda) is removed also...
8422 e_desk_area_ec_update(eda, ec);
8423 e_desk_area_ec_rearrange(ec->desk_area.desk_area, ec);
8430 _raise_between_sibling_under_parent(E_Client *ec)
8432 ELOGF("POL", "RAISE child window between sibling. So, stack below under the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
8433 e_client_stack_below(ec, ec->parent);
8437 _raise_between_sibling_on_parent(E_Client *ec)
8439 E_Client *top_child = NULL;
8440 top_child = e_client_transient_child_top_get(ec->parent, EINA_FALSE);
8443 ELOGF("POL", "RAISE child window... Stack above on the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
8444 e_client_stack_above(ec, ec->parent);
8448 if (top_child != ec)
8450 ELOGF("POL", "RAISE child window between sibling... Stack above on the top child (win:%zx, ec:%p)", ec, e_client_util_win_get(top_child), top_child);
8451 e_client_stack_above(ec, top_child);
8454 ELOGF("POL", "RAISE child window between sibling... already on the top. STAY", ec);
8459 _raise_belong_to_parent(E_Client *ec)
8461 if (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW)
8462 _raise_between_sibling_under_parent(ec);
8464 _raise_between_sibling_on_parent(ec);
8468 e_client_raise(E_Client *ec)
8472 if (ec->desk_area.enable)
8475 eda = ec->desk_area.desk_area;
8478 e_desk_area_ec_raise(eda, ec);
8483 if (ec->parent && e_client_is_belong_to_parent(ec))
8484 _raise_belong_to_parent(ec);
8486 evas_object_raise(ec->frame);
8490 _e_client_transient_for_below_group_make(E_Client *ec, Eina_List **list)
8492 // list : Head is the bottommost child
8498 EINA_LIST_REVERSE_FOREACH(ec->transients, l, child)
8500 if (!child) continue;
8501 if (e_client_transient_policy_get(child) != E_TRANSIENT_BELOW) continue;
8502 if (!e_client_is_belong_to_parent(child)) continue;
8504 *list = eina_list_prepend(*list, child);
8505 _e_client_transient_for_group_make(child, list);
8510 e_client_transient_child_bottom_get(E_Client *ec)
8512 E_Client *bottom_ec = NULL;
8513 Eina_List *transient_below_list = NULL;
8514 Eina_List *l = NULL;
8516 _e_client_transient_for_below_group_make(ec, &transient_below_list);
8518 if (transient_below_list)
8520 E_Client *temp_ec = NULL;
8521 E_Client *temp_ec2 = NULL;
8523 E_CLIENT_FOREACH(temp_ec)
8525 if (bottom_ec) break;
8533 EINA_LIST_FOREACH(transient_below_list, l, temp_ec2)
8535 if (temp_ec == temp_ec2)
8537 bottom_ec = temp_ec2;
8542 eina_list_free(transient_below_list);
8548 _lower_between_sibling_under_parent(E_Client *ec)
8550 E_Client *bottom_child = NULL;
8551 bottom_child = e_client_transient_child_bottom_get(ec->parent);
8554 ELOGF("POL", "LOWER child window between sibling... Stack below under the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
8555 e_client_stack_below(ec, ec->parent);
8559 if (bottom_child != ec)
8561 ELOGF("POL", "LOWER child window between sibling... Stack below under the bottom child (win:%zx, ec:%p)", ec, e_client_util_win_get(bottom_child), bottom_child);
8562 e_client_stack_below(ec, bottom_child);
8565 ELOGF("POL", "LOWER child window between sibling... already under the bottom. STAY", ec);
8570 _lower_between_sibling_on_parent(E_Client *ec)
8572 ELOGF("POL", "LOWER child window between sibling... So, stack above on the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
8573 e_client_stack_above(ec, ec->parent);
8577 _lower_belong_to_parent(E_Client *ec)
8579 if (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW)
8580 _lower_between_sibling_under_parent(ec);
8582 _lower_between_sibling_on_parent(ec);
8586 e_client_lower(E_Client *ec)
8590 if (ec->desk_area.enable)
8593 eda = ec->desk_area.desk_area;
8596 e_desk_area_ec_lower(eda, ec);
8601 if (ec->parent && e_client_is_belong_to_parent(ec))
8602 _lower_belong_to_parent(ec);
8604 evas_object_lower(ec->frame);
8608 e_client_stack_above(E_Client *ec, E_Client *above)
8611 if (!ec->frame) return;
8613 if (!above->frame) return;
8615 if (ec->desk_area.enable)
8618 eda = ec->desk_area.desk_area;
8621 e_desk_area_ec_stack_above(eda, ec, above);
8626 evas_object_stack_above(ec->frame, above->frame);
8630 e_client_stack_below(E_Client *ec, E_Client *below)
8633 if (!ec->frame) return;
8635 if (!below->frame) return;
8637 if (ec->desk_area.enable)
8640 eda = ec->desk_area.desk_area;
8643 e_desk_area_ec_stack_below(eda, ec, below);
8648 evas_object_stack_below(ec->frame, below->frame);
8652 e_client_show_pending_set(E_Client *ec)
8656 ec->show_pending.count++;
8657 ELOGF("E_CLIENT", "SET show_pending. (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
8658 return ec->show_pending.count;
8662 e_client_show_pending_unset(E_Client *ec)
8665 if (ec->show_pending.count <= 0) return 0;
8667 ec->show_pending.count--;
8668 ELOGF("E_CLIENT", "UNSET show_pending. (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
8669 if (ec->show_pending.count == 0 && ec->show_pending.running)
8671 ec->show_pending.running = EINA_FALSE;
8674 ELOGF("E_CLIENT", "evas_object_show by unset show_pending", ec);
8675 evas_object_show(ec->frame);
8676 //e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
8681 return ec->show_pending.count;
8685 _e_client_surface_tree_foreach_helper(E_Client *ec, E_Client_Surface_Tree_Foreach func, void *data)
8689 Eina_Bool res = EINA_TRUE;
8690 E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
8692 if ((e_object_is_del(E_OBJECT(ec))) || (!cdata))
8695 EINA_LIST_FOREACH_SAFE(cdata->sub.below_list, l, ll, subc)
8697 res = _e_client_surface_tree_foreach_helper(subc, func, data);
8704 res = func(data, ec);
8707 EINA_LIST_FOREACH_SAFE(cdata->sub.list, l, ll, subc)
8709 res = _e_client_surface_tree_foreach_helper(subc,
8722 e_client_surface_tree_foreach(E_Client *ec, E_Client_Surface_Tree_Foreach func, void *data)
8724 EINA_SAFETY_ON_NULL_RETURN(ec);
8725 EINA_SAFETY_ON_NULL_RETURN(func);
8727 _e_client_surface_tree_foreach_helper(ec, func, data);
8730 EINTERN E_Comp_Wl_Client_Data *
8731 e_client_cdata_new(E_Client *ec)
8733 E_Comp_Wl_Client_Data *cdata;
8735 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
8737 if (!(cdata = E_NEW(E_Comp_Wl_Client_Data, 1)))
8739 ERR("Could not allocate new E_Comp_Wl_Client_Data structure");
8742 ec->comp_data = cdata;
8748 e_client_cdata_free(E_Client *ec)
8750 EINA_SAFETY_ON_NULL_RETURN(ec);
8751 if (!ec->comp_data) return;
8753 E_FREE(ec->comp_data);
8756 EINTERN E_Comp_Wl_Client_Data *
8757 e_client_cdata_get(E_Client *ec)
8759 if (!ec) return NULL;
8761 return ec->comp_data;
8765 e_client_map_set(E_Client *ec, E_Map *em)
8767 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8769 return e_map_set_to_comp_object(em, ec->frame);
8773 e_client_map_get(const E_Client *ec)
8775 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
8777 return e_map_get_from_comp_object(ec->frame);
8781 e_client_map_enable_set(E_Client *ec, Eina_Bool enable)
8783 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8784 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
8786 evas_object_map_enable_set(ec->frame, enable);
8792 e_client_belong_to_parent_set(E_Client *ec, Eina_Bool set)
8795 ec->belong_to_parent = set;
8799 e_client_is_belong_to_parent(E_Client *ec)
8801 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8802 return ec->belong_to_parent;
8806 e_client_transient_policy_set(E_Client *ec, E_Transient policy)
8809 ec->transient_policy = policy;
8813 e_client_transient_policy_get(E_Client *ec)
8815 if (!ec) return E_TRANSIENT_ABOVE;
8816 return ec->transient_policy;
8820 e_client_resize_object_create_cb_set(E_Client_Resize_Object_Create_Cb cb)
8822 if (_e_client_resize_object_create_cb && cb)
8823 CRI("ATTEMPTING TO OVERWRITE EXISTING CLIENT RESIZE OBJECT CREATE HOOK!!!");
8824 _e_client_resize_object_create_cb = cb;
8828 e_client_resize_unit_size_set(E_Client *ec, unsigned int unit_size)
8832 // FYI, we consider 0 and 1 to be the same value as a default unit size.
8833 ec->manage_resize.unit_size = unit_size;
8837 e_client_desk_zoom_enable_set(E_Client *ec, Eina_Bool enable)
8840 ec->desk_zoom.enable = enable;
8844 e_client_desk_zoom_enable_get(E_Client *ec)
8846 if (!ec) return EINA_FALSE;
8847 return ec->desk_zoom.enable;
8851 e_client_layout_apply(E_Client *ec, Eina_Bool apply)
8854 ec->apply_layout = apply;
8858 e_client_is_layout_apply(E_Client *ec)
8860 if (!ec) return EINA_FALSE;
8861 return ec->apply_layout;
8865 e_client_from_surface_resource(struct wl_resource *surface_resource)
8867 return wl_resource_get_user_data(surface_resource);
8871 e_client_fps_update(E_Client *ec)
8876 EINA_SAFETY_ON_NULL_RETURN(ec);
8878 if (!ec->fps.enabled) return;
8880 tim = ecore_time_get();
8882 dt = tim - ec->fps.frametimes[0];
8884 ec->fps.frametimes[0] = tim;
8888 if (ec->fps.lapse == 0.0)
8890 ec->fps.lapse = tim;
8891 ec->fps.flapse = ec->fps.cframes;
8893 else if ((tim - ec->fps.lapse) >= 0.5)
8895 ec->fps.fps = (ec->fps.cframes - ec->fps.flapse) /
8896 (tim - ec->fps.lapse);
8897 ec->fps.lapse = tim;
8898 ec->fps.flapse = ec->fps.cframes;
8904 e_client_fps_get(E_Client *ec, double *fps)
8906 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8908 if (ec->fps.old_fps == ec->fps.fps)
8911 if (ec->fps.fps > 0.0)
8914 ec->fps.old_fps = ec->fps.fps;
8922 e_client_fps_enable(E_Client *ec, Eina_Bool enable)
8924 EINA_SAFETY_ON_NULL_RETURN(ec);
8926 ec->fps.enabled = enable;