1 #include "e_focus_policy_iface.h"
2 #include "e_zone_intern.h"
3 #include "e_client_intern.h"
4 #include "e_comp_object_intern.h"
5 #include "e_comp_intern.h"
6 #include "e_policy_visibility_intern.h"
7 #include "e_desk_intern.h"
8 #include "e_config_intern.h"
10 typedef struct _E_Focus_Policy_History_Impl E_Focus_Policy_History;
11 typedef struct _E_Focus_Policy_History_Client E_Focus_Policy_History_Client;
13 struct _E_Focus_Policy_History_Impl
18 Eina_List *focus_stack;
19 Eina_List *defer_focus_stack;
21 struct wl_listener zone_client_add;
22 struct wl_listener zone_client_remove;
23 struct wl_listener zone_focus_clear;
24 struct wl_listener zone_focus_reset;
27 struct _E_Focus_Policy_History_Client
30 E_Focus_Policy_History *history_policy;
32 struct wl_listener client_destroy;
33 struct wl_listener client_mouse_in;
34 struct wl_listener client_mouse_out;
35 struct wl_listener client_mouse_down;
36 struct wl_listener client_focus_set;
37 struct wl_listener client_focus_unset;
38 struct wl_listener client_lower;
39 struct wl_listener client_move;
40 struct wl_listener client_focus_defer_set;
41 struct wl_listener client_focus_latest_set;
42 struct wl_listener client_activate_done;
43 struct wl_listener client_eval_end;
44 struct wl_listener stack_transient_for_done;
46 #ifdef REFACTOR_DESK_AREA
47 struct wl_listener comp_object_lower_done;
49 struct wl_listener comp_object_lower;
51 struct wl_listener comp_object_show;
52 struct wl_listener comp_object_hide;
55 // Trace the focus history
56 //#define FOCUS_HISTORY_TRACE
57 #ifdef FOCUS_HISTORY_TRACE
58 #define E_FOCUS_HISTORY_TRACE(history_policy, ec) \
62 "FOCUS_HISTORY", "[FOCUS][Trace][%s]:(%p, %d) focused_ec:%p focus_stack#:%d defer_stack#:%d", ec, \
63 __FUNCTION__, history_policy, history_policy->zone->id, history_policy->focused_ec, \
64 eina_list_count(history_policy->focus_stack), eina_list_count(history_policy->defer_focus_stack)\
69 #define E_FOCUS_HISTORY_TRACE(history_policy, ec)
73 _focus_policy_history_focus_stack_latest_set(E_Focus_Policy_History *history_policy, E_Client *ec)
75 history_policy->focus_stack = eina_list_remove(history_policy->focus_stack, ec);
76 history_policy->focus_stack = eina_list_prepend(history_policy->focus_stack, ec);
78 E_FOCUS_HISTORY_TRACE(history_policy, ec);
82 _focus_policy_history_focus_stack_lower(E_Focus_Policy_History *history_policy, E_Client *ec)
87 history_policy->focus_stack = eina_list_remove(history_policy->focus_stack, ec);
89 EINA_LIST_REVERSE_FOREACH(history_policy->focus_stack, l, ec2)
91 if (ec2 == NULL) continue;
92 if (ec2->layer < ec->layer) continue;
94 history_policy->focus_stack = eina_list_append_relative_list(history_policy->focus_stack, ec, l);
99 history_policy->focus_stack = eina_list_prepend(history_policy->focus_stack, ec);
103 _e_focus_policy_history_focus_focus_defer_set(E_Focus_Policy_History *history_policy, E_Client *ec)
105 ELOGF("FOCUS_HISTORY", "focus defer set", ec);
107 history_policy->defer_focus_stack = eina_list_remove(history_policy->defer_focus_stack, ec);
108 history_policy->defer_focus_stack = eina_list_prepend(history_policy->defer_focus_stack, ec);
110 E_FOCUS_HISTORY_TRACE(history_policy, ec);
114 _e_focus_policy_history_focus_defer_unset(E_Focus_Policy_History *history_policy, E_Client *ec)
116 ELOGF("FOCUS_HISTORY", "focus defer unset", ec);
118 history_policy->defer_focus_stack = eina_list_remove(history_policy->defer_focus_stack, ec);
120 E_FOCUS_HISTORY_TRACE(history_policy, ec);
124 _e_focus_policy_history_merge_focus_stack_with_defer_focus(E_Focus_Policy_History *history_policy)
127 E_Client *ec = NULL, *defer_ec = NULL;
128 Eina_Bool find_rel = EINA_FALSE;
129 Eina_Bool inserted = EINA_FALSE;
130 E_Client *focused_ec;
132 focused_ec = history_policy->focused_ec;
134 if (!history_policy->focus_stack)
136 history_policy->focus_stack = eina_list_merge(history_policy->focus_stack, history_policy->defer_focus_stack);
140 E_CLIENT_FOREACH(defer_ec)
142 if (!eina_list_data_find(history_policy->defer_focus_stack, defer_ec)) continue;
144 find_rel = EINA_FALSE;
145 inserted = EINA_FALSE;
146 history_policy->focus_stack = eina_list_remove(history_policy->focus_stack, defer_ec);
148 EINA_LIST_FOREACH(history_policy->focus_stack, l, ec)
150 if (ec == NULL) continue;
154 if (ec == focused_ec)
155 find_rel = EINA_TRUE;
159 if (ec->layer > defer_ec->layer) continue;
161 history_policy->focus_stack = eina_list_prepend_relative_list(history_policy->focus_stack, defer_ec, l);
162 inserted = EINA_TRUE;
167 history_policy->focus_stack = eina_list_append(history_policy->focus_stack, defer_ec);
171 history_policy->defer_focus_stack = eina_list_free(history_policy->defer_focus_stack);
175 _e_focus_policy_history_candidate_focus_get(E_Focus_Policy_History *history_policy, E_Client *reverted_focus_ec)
178 E_Client *focused_ec, *defered_focus_ec = NULL;
179 Eina_List *child_list = NULL;
181 Eina_Bool child_deferred;
185 zone = history_policy->zone;
186 focused_ec = history_policy->focused_ec;
188 desk = e_desk_current_get(zone);
190 E_CLIENT_REVERSE_FOREACH(ec)
192 if (!eina_list_data_find(history_policy->defer_focus_stack, ec)) continue;
194 if (e_object_is_del(E_OBJECT(ec))) continue;
195 if (e_client_util_ignored_get(ec)) continue;
196 if (!e_zone_has_ec(zone, ec)) continue;
198 if (!e_desk_has_ec(desk, ec)) continue;
200 if (!(ec->icccm.accepts_focus || ec->icccm.take_focus)) continue;
201 if (ec->lock_focus_in || ec->lock_focus_out) continue;
202 if (!evas_object_visible_get(ec->frame)) continue;
203 if (ec->iconic) continue;
204 if (ec->bg_state) continue;
206 if (!(cec = e_client_check_obscured_by_children_group(ec)) ||
207 e_client_check_really_iconified(cec))
209 if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) continue;
210 if (e_client_check_fully_contain_by_above(ec, EINA_FALSE)) continue;
213 if (focused_ec && (focused_ec->layer > ec->layer)) continue;
214 else if (!focused_ec && reverted_focus_ec && (reverted_focus_ec->layer > ec->layer)) continue;
216 // check transient_for child defered
217 child_deferred = EINA_FALSE;
218 child_list = eina_list_clone(ec->transients);
219 EINA_LIST_FOREACH(child_list, l, cec)
221 if (e_client_transient_policy_get(cec) == E_TRANSIENT_BELOW) continue;
222 if (!(cec->icccm.accepts_focus || cec->icccm.take_focus)) continue;
223 if (eina_list_data_find(history_policy->defer_focus_stack, cec))
225 child_deferred = EINA_TRUE;
229 eina_list_free(child_list);
230 if (child_deferred) continue;
232 defered_focus_ec = ec;
236 return defered_focus_ec;
240 _e_focus_policy_history_focus_can_take_by_vis_obscured(E_Focus_Policy_History *history_policy, E_Client *ec)
242 switch (ec->visibility.obscured)
244 case E_VISIBILITY_UNKNOWN:
245 if (e_client_check_really_iconified(ec))
248 if (!evas_object_visible_get(ec->frame) &&
249 !eina_list_data_find(history_policy->defer_focus_stack, ec))
253 case E_VISIBILITY_FULLY_OBSCURED:
254 if (e_client_check_really_iconified(ec))
258 case E_VISIBILITY_UNOBSCURED:
259 case E_VISIBILITY_PARTIALLY_OBSCURED:
260 case E_VISIBILITY_PRE_UNOBSCURED:
268 _e_focus_policy_history_focus_can_take(E_Focus_Policy_History *history_policy, E_Client *ec)
271 E_Client *child_ec, *above_ec;
272 int x = 0, y = 0, w = 0, h = 0;
274 if (!ec) return EINA_FALSE;
275 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
276 if (e_client_util_ignored_get(ec)) return EINA_FALSE;
278 if (!(ec->icccm.accepts_focus || ec->icccm.take_focus)) return EINA_FALSE;
279 if (ec->lock_focus_in || ec->lock_focus_out) return EINA_FALSE;
281 if (!ec->visible) return EINA_FALSE;
282 if (ec->bg_state) return EINA_FALSE;
283 if (ec->visibility.force_obscured) return EINA_FALSE;
284 if (!_e_focus_policy_history_focus_can_take_by_vis_obscured(history_policy, ec)) return EINA_FALSE;
286 zone = e_comp_zone_find_by_ec(ec);
289 e_client_geometry_get(ec, &x, &y, &w, &h);
290 if (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h, x, y, w, h))
294 above_ec = e_client_check_fully_contain_by_above(ec, EINA_FALSE);
297 child_ec = e_client_check_obscured_by_children_group(ec);
298 if (!child_ec) return EINA_FALSE;
299 if (above_ec != child_ec) return EINA_FALSE;
301 if (_e_focus_policy_history_focus_can_take(history_policy, child_ec))
303 else if (e_client_check_fully_contain_by_above(child_ec, EINA_FALSE))
311 _focus_policy_history_find_next_focusable_ec(E_Focus_Policy_History *history_policy, E_Client *ec)
314 E_Client *temp_ec = NULL;
316 // call the intercept hook of the revert focus
317 if (e_client_intercept_hook_focus_revert_call(ec))
320 EINA_LIST_FOREACH(history_policy->focus_stack, l, temp_ec)
322 if (_e_focus_policy_history_focus_can_take(history_policy, temp_ec))
330 _focus_policy_history_focusable_get(E_Focus_Policy_History *history_policy, E_Client *ec)
332 E_Client *pec = NULL, *focusable_ec = NULL;
336 if (stopping) return NULL;
339 return _focus_policy_history_find_next_focusable_ec(history_policy, NULL);
341 zone = history_policy->zone;
343 desk = e_desk_current_get(zone);
344 if (!desk) return NULL;
345 if (!e_comp_client_zone_is_displaying(ec)) return NULL;
347 if (e_config->focus_policy == E_FOCUS_MOUSE)
349 // set mouse over focus
350 pec = e_client_under_pointer_get(desk, ec);
353 /* no autoraise/revert here because it's probably annoying */
356 focusable_ec = _focus_policy_history_find_next_focusable_ec(history_policy, ec);
362 _focus_policy_history_next_focus_set(E_Focus_Policy_History *history_policy, E_Client *ec)
364 E_Client *focusable_ec;
366 focusable_ec = _focus_policy_history_focusable_get(history_policy, ec);
367 if (!focusable_ec) return;
369 if (focusable_ec != ec)
371 _e_focus_policy_history_focus_defer_unset(history_policy, ec);
372 ELOGF("FOCUS_HISTORY", "focus unset | revert_focus", ec);
373 e_client_frame_focus_set(ec, EINA_FALSE);
376 if (!focusable_ec->iconic || focusable_ec->exp_iconify.buffer_flush)
378 ELOGF("FOCUS_HISTORY", "focus set | revert_focus", focusable_ec);
379 e_client_frame_focus_set(focusable_ec, EINA_TRUE);
384 _focus_policy_history_cb_client_destroy(struct wl_listener *listener, void *data)
386 E_Focus_Policy_History_Client *history_client;
387 E_Focus_Policy_History *history_policy;
390 history_client = wl_container_of(listener, history_client, client_destroy);
392 history_policy = history_client->history_policy;
393 EINA_SAFETY_ON_NULL_RETURN(history_policy);
395 ec = history_client->ec;
396 EINA_SAFETY_ON_NULL_RETURN(ec);
398 E_FOCUS_HISTORY_TRACE(history_policy, ec);
400 wl_list_remove(&history_client->comp_object_hide.link);
401 wl_list_remove(&history_client->comp_object_show.link);
402 #ifdef REFACTOR_DESK_AREA
403 wl_list_remove(&history_client->comp_object_lower_done.link);
405 wl_list_remove(&history_client->comp_object_lower.link);
408 wl_list_remove(&history_client->stack_transient_for_done.link);
409 wl_list_remove(&history_client->client_eval_end.link);
410 wl_list_remove(&history_client->client_activate_done.link);
411 wl_list_remove(&history_client->client_focus_latest_set.link);
412 wl_list_remove(&history_client->client_focus_defer_set.link);
413 wl_list_remove(&history_client->client_lower.link);
414 wl_list_remove(&history_client->client_move.link);
415 wl_list_remove(&history_client->client_focus_unset.link);
416 wl_list_remove(&history_client->client_focus_set.link);
417 wl_list_remove(&history_client->client_mouse_down.link);
418 wl_list_remove(&history_client->client_mouse_out.link);
419 wl_list_remove(&history_client->client_mouse_in.link);
420 wl_list_remove(&history_client->client_destroy.link);
422 E_FREE(history_client);
426 _focus_policy_history_cb_client_mouse_in(struct wl_listener *listener, void *data)
428 E_Focus_Policy_History_Client *history_client;
429 E_Focus_Policy_History *history_policy;
432 history_client = wl_container_of(listener, history_client, client_mouse_in);
434 history_policy = history_client->history_policy;
435 EINA_SAFETY_ON_NULL_RETURN(history_policy);
437 ec = history_client->ec;
438 EINA_SAFETY_ON_NULL_RETURN(ec);
440 E_FOCUS_HISTORY_TRACE(history_policy, ec);
442 if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
444 if ((e_config->focus_policy == E_FOCUS_MOUSE) ||
445 (e_config->focus_policy == E_FOCUS_SLOPPY))
447 ELOGF("FOCUS_HISTORY", "focus set | mouse in", ec);
448 e_client_frame_focus_set(ec, EINA_TRUE);
451 if (e_config->use_auto_raise)
453 if (!ec->lock_user_stacking)
460 _focus_policy_history_cb_client_mouse_out(struct wl_listener *listener, void *data)
462 E_Focus_Policy_History_Client *history_client;
463 E_Focus_Policy_History *history_policy;
466 history_client = wl_container_of(listener, history_client, client_mouse_out);
468 history_policy = history_client->history_policy;
469 EINA_SAFETY_ON_NULL_RETURN(history_policy);
471 ec = history_client->ec;
472 EINA_SAFETY_ON_NULL_RETURN(ec);
474 E_FOCUS_HISTORY_TRACE(history_policy, ec);
476 if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
478 if (e_config->focus_policy == E_FOCUS_MOUSE)
480 if (!ec->lock_focus_in)
484 ELOGF("FOCUS_HISTORY", "focus unset | mouse out", ec);
485 e_client_frame_focus_set(ec, EINA_FALSE);
493 _focus_policy_history_cb_client_mouse_down(struct wl_listener *listener, void *data)
495 E_Focus_Policy_History_Client *history_client;
496 E_Focus_Policy_History *history_policy;
498 E_Client *focused_ec;
500 history_client = wl_container_of(listener, history_client, client_mouse_down);
502 history_policy = history_client->history_policy;
503 EINA_SAFETY_ON_NULL_RETURN(history_policy);
505 ec = history_client->ec;
506 EINA_SAFETY_ON_NULL_RETURN(ec);
508 E_FOCUS_HISTORY_TRACE(history_policy, ec);
510 focused_ec = history_policy->focused_ec;
511 if ((focused_ec) && (ec != focused_ec))
513 if (e_client_focus_policy_click(ec) ||
514 e_config->always_click_to_focus)
516 ELOGF("FOCUS_HISTORY", "focus set | mouse down", ec);
517 e_client_frame_focus_set(ec, EINA_TRUE);
523 if (e_config->always_click_to_raise)
525 if (!ec->lock_user_stacking)
528 _e_focus_policy_history_focus_focus_defer_set(history_policy, ec);
531 if (ec->parent && e_client_is_belong_to_parent(ec))
533 if (!ec->parent->lock_user_stacking)
534 e_client_raise(ec->parent);
540 static void set_focused_ec(E_Focus_Policy_History *history_policy, E_Client *ec)
542 atomic_store(&history_policy->focused_ec, ec);
546 _focus_policy_history_cb_client_focus_set(struct wl_listener *listener, void *data)
548 E_Focus_Policy_History_Client *history_client;
549 E_Focus_Policy_History *history_policy;
550 #ifdef REFACTOR_DESK_AREA
551 E_Client *focused_ec, *ec;
553 E_Client *focused_ec, *ec, *ec2;
558 history_client = wl_container_of(listener, history_client, client_focus_set);
560 history_policy = history_client->history_policy;
561 EINA_SAFETY_ON_NULL_RETURN(history_policy);
563 ec = history_client->ec;
564 EINA_SAFETY_ON_NULL_RETURN(ec);
566 E_FOCUS_HISTORY_TRACE(history_policy, ec);
568 focused_ec = history_policy->focused_ec;
569 if (ec == focused_ec) return;
571 #ifdef REFACTOR_DESK_AREA
573 zone = history_policy->zone;
578 #ifdef REFACTOR_DESK_AREA
580 // TODO: This is not for focus policy, but for fullscreen(Window State) policy.
581 // Move this code to the better place.
582 int x, total = zone->desk_x_count * zone->desk_y_count;
583 for (x = 0; x < total; x++)
585 E_Desk *desk = zone->desks[x];
586 /* if there's any fullscreen non-parents on this desk, unfullscreen them */
587 EINA_LIST_FOREACH_SAFE(desk->fullscreen_clients, l, ll, ec2)
589 if (ec2 == ec) continue;
590 if (e_object_is_del(E_OBJECT(ec2))) continue;
591 /* but only if it's the same desk or one of the clients is sticky */
592 if (e_desk_has_ec(desk, ec) || (ec->sticky || ec2->sticky))
594 if (!eina_list_data_find(ec->transients, ec2))
595 e_client_unfullscreen(ec2);
601 _focus_policy_history_focus_stack_latest_set(history_policy, ec);
603 // assign the focused_ec
604 set_focused_ec(history_policy, ec);
606 ELOGF("FOCUS_HISTORY", "focus_set | focused_ec SET", ec);
610 _focus_policy_history_cb_client_focus_unset(struct wl_listener *listener, void *data)
612 E_Focus_Policy_History_Client *history_client;
613 E_Focus_Policy_History *history_policy;
618 history_client = wl_container_of(listener, history_client, client_focus_unset);
620 history_policy = history_client->history_policy;
621 EINA_SAFETY_ON_NULL_RETURN(history_policy);
623 ec = history_client->ec;
624 EINA_SAFETY_ON_NULL_RETURN(ec);
626 E_FOCUS_HISTORY_TRACE(history_policy, ec);
628 zone = history_policy->zone;
630 ec->want_focus = ec->focused = 0;
631 if (ec->mouse.in && ec && (!e_client_util_is_popup(ec)) &&
632 (e_config->focus_policy != E_FOCUS_CLICK))
633 e_client_mouse_out(ec, ec->x - 1, ec->y - 1);
635 /* if there unfocus client is fullscreen and visible */
636 if ((ec->fullscreen) && (!ec->iconic) && (!ec->hidden) &&
637 (zone == e_zone_current_get()) &&
638 (e_desk_has_ec(e_desk_current_get(zone), ec) || (ec->sticky)))
640 Eina_Bool have_vis_child = EINA_FALSE;
641 E_Desk *desk, *desk2;
642 desk = e_zone_desk_find_by_ec(zone, ec);
643 /* if any of its children are visible */
644 EINA_LIST_FOREACH(ec->transients, l, ec2)
646 desk2 = e_zone_desk_find_by_ec(zone, ec2);
647 if (((desk2 == desk) ||
648 (ec2->sticky) || (ec->sticky)))
650 have_vis_child = EINA_TRUE;
654 /* if no children are visible, unfullscreen */
655 if ((!e_object_is_del(E_OBJECT(ec))) && (!have_vis_child))
656 e_client_unfullscreen(ec);
659 _e_focus_policy_history_focus_defer_unset(history_policy, ec);
661 // assign the focused_ec
662 set_focused_ec(history_policy, NULL);
664 ELOGF("FOCUS_HISTORY", "focus_set | focused_ec UNSET", ec);
668 _focus_policy_history_cb_client_lower(struct wl_listener *listener, void *data)
670 E_Focus_Policy_History_Client *history_client;
671 E_Focus_Policy_History *history_policy;
674 history_client = wl_container_of(listener, history_client, client_lower);
676 history_policy = history_client->history_policy;
677 EINA_SAFETY_ON_NULL_RETURN(history_policy);
679 ec = history_client->ec;
680 EINA_SAFETY_ON_NULL_RETURN(ec);
682 E_FOCUS_HISTORY_TRACE(history_policy, ec);
684 // no need to change the focused ec when ec is not focused.
685 if (!ec->focused) return;
687 // no need to change the focused ec when calc_vis_without_effect is not set.
688 if (e_config->calc_vis_without_effect) return;
690 // find the next focus and set it
691 _focus_policy_history_next_focus_set(history_policy, ec);
695 _focus_policy_history_cb_client_move(struct wl_listener *listener, void *data)
697 E_Focus_Policy_History_Client *history_client;
698 E_Focus_Policy_History *history_policy;
702 history_client = wl_container_of(listener, history_client, client_move);
704 history_policy = history_client->history_policy;
705 EINA_SAFETY_ON_NULL_RETURN(history_policy);
707 ec = history_client->ec;
708 EINA_SAFETY_ON_NULL_RETURN(ec);
710 E_FOCUS_HISTORY_TRACE(history_policy, ec);
712 zone = e_comp_zone_find_by_ec(ec);
715 // no need to change the focused ec when ec is not focused.
716 if (!ec->focused) return;
718 // no need to change the focused ec when ec is in the area of a zone.
719 if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h,
720 zone->x, zone->y, zone->w, zone->h))
722 // find the next focus and set it
723 _focus_policy_history_next_focus_set(history_policy, ec);
728 _focus_policy_history_cb_client_focus_defer_set(struct wl_listener *listener, void *data)
730 E_Focus_Policy_History_Client *history_client;
731 E_Focus_Policy_History *history_policy;
734 history_client = wl_container_of(listener, history_client, client_focus_defer_set);
736 history_policy = history_client->history_policy;
737 EINA_SAFETY_ON_NULL_RETURN(history_policy);
739 ec = history_client->ec;
740 EINA_SAFETY_ON_NULL_RETURN(ec);
742 E_FOCUS_HISTORY_TRACE(history_policy, ec);
744 ELOGF("FOCUS_HISTORY", "focus defer set callback. e_client_focus_defer_set is called.", ec);
746 _e_focus_policy_history_focus_focus_defer_set(history_policy, ec);
750 _focus_policy_history_cb_client_focus_latest_set(struct wl_listener *listener, void *data)
752 E_Focus_Policy_History_Client *history_client;
753 E_Focus_Policy_History *history_policy;
756 history_client = wl_container_of(listener, history_client, client_focus_latest_set);
758 history_policy = history_client->history_policy;
759 EINA_SAFETY_ON_NULL_RETURN(history_policy);
761 ec = history_client->ec;
762 EINA_SAFETY_ON_NULL_RETURN(ec);
764 E_FOCUS_HISTORY_TRACE(history_policy, ec);
766 //ELOGF("FOCUS_HISTORY", "focus latest set", ec);
768 _focus_policy_history_focus_stack_latest_set(history_policy, ec);
772 _focus_policy_history_cb_client_activate_done(struct wl_listener *listener, void *data)
774 E_Focus_Policy_History_Client *history_client;
775 E_Focus_Policy_History *history_policy;
777 E_Client *focus_ec = NULL;
778 E_Client *obscured_above = NULL;
780 history_client = wl_container_of(listener, history_client, client_activate_done);
782 history_policy = history_client->history_policy;
783 EINA_SAFETY_ON_NULL_RETURN(history_policy);
785 ec = history_client->ec;
786 EINA_SAFETY_ON_NULL_RETURN(ec);
788 E_FOCUS_HISTORY_TRACE(history_policy, ec);
790 if (ec->lock_focus_out) return;
793 focus_ec = e_client_transient_child_top_get(ec, EINA_TRUE);
799 _focus_policy_history_focus_stack_latest_set(history_policy, ec);
800 _focus_policy_history_focus_stack_latest_set(history_policy, focus_ec);
801 _e_focus_policy_history_focus_defer_unset(history_policy, ec);
804 obscured_above = e_client_check_fully_contain_by_above(focus_ec, EINA_FALSE);
807 if (!e_policy_visibility_client_is_uniconic(ec) ||
808 (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED))
810 _e_focus_policy_history_focus_focus_defer_set(history_policy, focus_ec);
811 _focus_policy_history_focus_stack_latest_set(history_policy, focus_ec);
815 ELOGF("FOCUS_HISTORY", "focus set | client activate", focus_ec);
816 e_client_frame_focus_set(focus_ec, EINA_TRUE);
821 _e_focus_policy_history_focus_focus_defer_set(history_policy, focus_ec);
822 _focus_policy_history_focus_stack_latest_set(history_policy, focus_ec);
827 _focus_policy_history_cb_client_eval_end(struct wl_listener *listener, void *data)
829 E_Focus_Policy_History_Client *history_client;
830 E_Focus_Policy_History *history_policy;
831 E_Client *focused_ec, *ec;
834 history_client = wl_container_of(listener, history_client, client_eval_end);
836 history_policy = history_client->history_policy;
837 EINA_SAFETY_ON_NULL_RETURN(history_policy);
839 ec = history_client->ec;
840 EINA_SAFETY_ON_NULL_RETURN(ec);
842 E_FOCUS_HISTORY_TRACE(history_policy, ec);
844 zone = history_policy->zone;
845 focused_ec = history_policy->focused_ec;
847 if ((!ec->input_only) && (!ec->iconic) &&
848 (e_desk_has_ec(e_desk_current_get(zone), ec)) &&
849 ((ec->take_focus) || (ec->want_focus)))
858 /* focus window by default when it is the only one on desk */
859 E_Client *ec2 = NULL;
862 desk = e_zone_desk_find_by_ec(zone, ec);
863 EINA_LIST_FOREACH(history_policy->focus_stack, l, ec2)
865 if (ec == ec2) continue;
866 if ((!ec2->iconic) && (ec2->visible) &&
867 ((e_desk_has_ec(desk, ec2)) || ec2->sticky))
873 if ((!ec->icccm.accepts_focus) &&
874 (!ec->icccm.take_focus))
876 if (ec->lock_focus_out) return;
877 if (ec == focused_ec) return;
879 ELOGF("FOCUS_HISTORY", "focus set | focus with pointer", ec);
880 e_client_frame_focus_set(ec, EINA_TRUE);
885 ec->take_focus = ec->want_focus = 0;
889 _focus_policy_history_cb_stack_transient_for_done(struct wl_listener *listener, void *data)
891 E_Focus_Policy_History_Client *history_client;
892 E_Focus_Policy_History *history_policy;
893 E_Client *new_focus, *ec;
895 history_client = wl_container_of(listener, history_client, stack_transient_for_done);
897 history_policy = history_client->history_policy;
898 EINA_SAFETY_ON_NULL_RETURN(history_policy);
900 ec = history_client->ec;
901 EINA_SAFETY_ON_NULL_RETURN(ec);
903 E_FOCUS_HISTORY_TRACE(history_policy, ec);
905 if (!ec->parent) return;
906 if (ec->parent != history_policy->focused_ec) return;
908 new_focus = e_client_transient_child_top_get(ec->parent, EINA_TRUE);
909 if (!new_focus) return;
911 ELOGF("FOCUS_HISTORY", "focus set | tranient_for fetch", new_focus);
913 e_client_frame_focus_set(new_focus, EINA_TRUE);
916 #ifdef REFACTOR_DESK_AREA
918 _focus_policy_history_cb_comp_object_lower_done(struct wl_listener *listener, void *data)
921 _focus_policy_history_cb_comp_object_lower(struct wl_listener *listener, void *data)
924 E_Focus_Policy_History_Client *history_client;
925 E_Focus_Policy_History *history_policy;
928 #ifdef REFACTOR_DESK_AREA
929 history_client = wl_container_of(listener, history_client, comp_object_lower_done);
931 history_client = wl_container_of(listener, history_client, comp_object_lower);
934 history_policy = history_client->history_policy;
935 EINA_SAFETY_ON_NULL_RETURN(history_policy);
937 ec = history_client->ec;
938 EINA_SAFETY_ON_NULL_RETURN(ec);
940 E_FOCUS_HISTORY_TRACE(history_policy, ec);
942 // return if post_lower of ec is set
943 if (ec->post_lower) return;
945 _focus_policy_history_focus_stack_lower(history_policy, ec);
949 _e_focus_policy_history_focus_stack_append_current_focused(E_Focus_Policy_History *history_policy, E_Client *ec)
952 E_Client *focused_ec, *temp_ec = NULL;
954 focused_ec = history_policy->focused_ec;
955 history_policy->focus_stack = eina_list_remove(history_policy->focus_stack, ec);
957 EINA_LIST_FOREACH(history_policy->focus_stack, l, temp_ec)
959 if (temp_ec != focused_ec) continue;
961 history_policy->focus_stack = eina_list_append_relative_list(history_policy->focus_stack, ec, l);
965 history_policy->focus_stack = eina_list_prepend(history_policy->focus_stack, ec);
969 _focus_policy_history_cb_comp_object_show(struct wl_listener *listener, void *data)
971 E_Focus_Policy_History_Client *history_client;
972 E_Focus_Policy_History *history_policy;
975 history_client = wl_container_of(listener, history_client, comp_object_show);
977 history_policy = history_client->history_policy;
978 EINA_SAFETY_ON_NULL_RETURN(history_policy);
980 ec = history_client->ec;
981 EINA_SAFETY_ON_NULL_RETURN(ec);
983 E_FOCUS_HISTORY_TRACE(history_policy, ec);
985 if (!e_client_is_iconified_by_client(ec)||
986 e_policy_visibility_client_is_uniconic(ec))
989 e_policy_visibility_client_is_uniconic(ec))
991 if (ec->exp_iconify.not_raise &&
992 e_client_check_above_focused(ec))
993 _e_focus_policy_history_focus_stack_append_current_focused(history_policy, ec);
995 _e_focus_policy_history_focus_focus_defer_set(history_policy, ec);
1001 _focus_policy_history_cb_comp_object_hide(struct wl_listener *listener, void *data)
1003 E_Focus_Policy_History_Client *history_client;
1004 E_Focus_Policy_History *history_policy;
1007 history_client = wl_container_of(listener, history_client, comp_object_hide);
1009 history_policy = history_client->history_policy;
1010 EINA_SAFETY_ON_NULL_RETURN(history_policy);
1012 ec = history_client->ec;
1013 EINA_SAFETY_ON_NULL_RETURN(ec);
1015 E_FOCUS_HISTORY_TRACE(history_policy, ec);
1019 /* ensure focus-out */
1020 ELOGF("FOCUS_HISTORY", "focus unset | comp_object_hide ", ec);
1021 e_client_frame_focus_set(ec, EINA_FALSE);
1022 _e_focus_policy_history_focus_defer_unset(history_policy, ec);
1027 _focus_policy_history_cb_zone_client_add(struct wl_listener *listener, void *data)
1029 E_Focus_Policy_History *history_policy;
1030 E_Focus_Policy_History_Client *history_client;
1034 history_policy = wl_container_of(listener, history_policy, zone_client_add);
1036 ec = (E_Client *)data;
1037 EINA_SAFETY_ON_NULL_RETURN(ec);
1039 E_FOCUS_HISTORY_TRACE(history_policy, ec);
1042 EINA_SAFETY_ON_NULL_RETURN(obj);
1044 history_client = E_NEW(E_Focus_Policy_History_Client, 1);
1045 EINA_SAFETY_ON_NULL_RETURN(history_client);
1047 history_client->ec = ec;
1048 history_client->history_policy = history_policy;
1050 // e_client listeners
1051 history_client->client_destroy.notify = _focus_policy_history_cb_client_destroy;
1052 e_client_destroy_listener_add(ec, &history_client->client_destroy);
1053 history_client->client_mouse_in.notify = _focus_policy_history_cb_client_mouse_in;
1054 e_client_mouse_in_listener_add(ec, &history_client->client_mouse_in);
1055 history_client->client_mouse_out.notify = _focus_policy_history_cb_client_mouse_out;
1056 e_client_mouse_out_listener_add(ec, &history_client->client_mouse_out);
1057 history_client->client_mouse_down.notify = _focus_policy_history_cb_client_mouse_down;
1058 e_client_mouse_down_listener_add(ec, &history_client->client_mouse_down);
1059 history_client->client_focus_set.notify = _focus_policy_history_cb_client_focus_set;
1060 e_client_focus_set_listener_add(ec, &history_client->client_focus_set);
1061 history_client->client_focus_unset.notify = _focus_policy_history_cb_client_focus_unset;
1062 e_client_focus_unset_listener_add(ec, &history_client->client_focus_unset);
1063 history_client->client_lower.notify = _focus_policy_history_cb_client_lower;
1064 e_client_lower_listener_add(ec, &history_client->client_lower);
1065 history_client->client_move.notify = _focus_policy_history_cb_client_move;
1066 e_client_move_listener_add(ec, &history_client->client_move);
1067 history_client->client_focus_defer_set.notify = _focus_policy_history_cb_client_focus_defer_set;
1068 e_client_focus_defer_set_listener_add(ec, &history_client->client_focus_defer_set);
1069 history_client->client_focus_latest_set.notify = _focus_policy_history_cb_client_focus_latest_set;
1070 e_client_focus_latest_set_listener_add(ec, &history_client->client_focus_latest_set);
1071 history_client->client_activate_done.notify = _focus_policy_history_cb_client_activate_done;
1072 e_client_activate_done_listener_add(ec, &history_client->client_activate_done);
1073 history_client->client_eval_end.notify = _focus_policy_history_cb_client_eval_end;
1074 e_client_eval_end_listener_add(ec, &history_client->client_eval_end);
1075 history_client->stack_transient_for_done.notify = _focus_policy_history_cb_stack_transient_for_done;
1076 e_client_stack_transient_for_done_listener_add(ec, &history_client->stack_transient_for_done);
1078 // e_comp_object listeners
1079 #ifdef REFACTOR_DESK_AREA
1080 history_client->comp_object_lower_done.notify = _focus_policy_history_cb_comp_object_lower_done;
1081 e_comp_object_lower_done_listener_add(obj, &history_client->comp_object_lower_done);
1083 history_client->comp_object_lower.notify = _focus_policy_history_cb_comp_object_lower;
1084 e_comp_object_lower_listener_add(obj, &history_client->comp_object_lower);
1086 history_client->comp_object_show.notify = _focus_policy_history_cb_comp_object_show;
1087 e_comp_object_show_listener_add(obj, &history_client->comp_object_show);
1088 history_client->comp_object_hide.notify = _focus_policy_history_cb_comp_object_hide;
1089 e_comp_object_hide_listener_add(obj, &history_client->comp_object_hide);
1091 ELOGF("FOCUS_HISTORY", "zone_client_add | ", ec);
1095 _focus_policy_history_cb_zone_client_remove(struct wl_listener *listener, void *data)
1097 E_Focus_Policy_History *history_policy;
1100 history_policy = wl_container_of(listener, history_policy, zone_client_remove);
1102 ec = (E_Client *)data;
1103 EINA_SAFETY_ON_NULL_RETURN(ec);
1105 E_FOCUS_HISTORY_TRACE(history_policy, ec);
1107 ELOGF("FOCUS_HISTORY", "zone_client_remove | ", ec);
1109 // remove ec from focus stack and defer_focus_stack
1110 history_policy->focus_stack = eina_list_remove(history_policy->focus_stack, ec);
1111 _e_focus_policy_history_focus_defer_unset(history_policy, ec);
1113 // find the next focus and set it when ec is focused.
1116 _focus_policy_history_next_focus_set(history_policy, ec);
1118 // check the critical case
1119 if (history_policy->focused_ec == ec)
1121 ELOGF("FOCUS_HISTORY", "CRITICAL. focused is deleted ec.", ec);
1122 ELOGF("FOCUS_HISTORY", "CLIENT FOCUS_SET", NULL);
1123 set_focused_ec(history_policy, NULL);
1129 _focus_policy_history_cb_zone_focus_clear(struct wl_listener *listener, void *data)
1131 E_Focus_Policy_History *history_policy;
1134 history_policy = wl_container_of(listener, history_policy, zone_focus_clear);
1136 E_FOCUS_HISTORY_TRACE(history_policy, NULL);
1138 zone = history_policy->zone;
1139 EINA_SAFETY_ON_NULL_RETURN(zone);
1141 // make focused_ec be NULL
1142 set_focused_ec(history_policy, NULL);
1144 ELOGF("FOCUS_HISTORY", "focus_clear | focused_ec UNSET", NULL);
1148 _focus_policy_history_cb_zone_focus_reset(struct wl_listener *listener, void *data)
1150 E_Focus_Policy_History *history_policy;
1156 history_policy = wl_container_of(listener, history_policy, zone_focus_reset);
1158 E_FOCUS_HISTORY_TRACE(history_policy, NULL);
1160 zone = history_policy->zone;
1161 EINA_SAFETY_ON_NULL_RETURN(zone);
1163 if (e_config->focus_policy == E_FOCUS_MOUSE) return;
1165 EINA_LIST_FOREACH(history_policy->focus_stack, l, ec)
1167 desk = e_zone_desk_find_by_ec(zone, ec);
1168 if (!desk) continue;
1169 if (desk->visible && (!ec->iconic))
1171 if (e_comp->input_key_grabs || e_comp->input_mouse_grabs)
1176 ELOGF("FOCUS_HISTORY", "focus set | refocus", ec);
1177 e_client_frame_focus_set(ec, EINA_TRUE);
1184 _focus_policy_history_del(E_Focus_Policy_Impl *impl)
1186 E_Focus_Policy_History *history_policy = (E_Focus_Policy_History *)impl;
1188 if (!history_policy) return;
1190 E_FOCUS_HISTORY_TRACE(history_policy, NULL);
1192 ELOGF("FOCUS_HISTORY", "delete history focus policy.", NULL);
1194 if (history_policy->defer_focus_stack)
1195 history_policy->defer_focus_stack = eina_list_free(history_policy->defer_focus_stack);
1197 wl_list_remove(&history_policy->zone_focus_reset.link);
1198 wl_list_remove(&history_policy->zone_focus_clear.link);
1199 wl_list_remove(&history_policy->zone_client_remove.link);
1200 wl_list_remove(&history_policy->zone_client_add.link);
1202 E_FREE(history_policy);
1206 _focus_policy_history_focused_ec_get(E_Focus_Policy_Impl *impl)
1208 E_Focus_Policy_History *history_policy;
1209 E_Client *focused_ec = NULL;
1211 history_policy = (E_Focus_Policy_History *)impl;
1212 EINA_SAFETY_ON_NULL_RETURN_VAL(history_policy, NULL);
1214 //E_FOCUS_HISTORY_TRACE(history_policy, NULL);
1215 focused_ec = atomic_load(&history_policy->focused_ec);
1221 _focus_policy_history_update(E_Focus_Policy_Impl *impl)
1223 E_Focus_Policy_History *history_policy;
1225 E_Client *defered_focus_ec, *reverted_focus_ec = NULL;
1226 E_Client *focused_ec, *old_focused_ec = NULL;
1228 history_policy = (E_Focus_Policy_History *)impl;
1229 EINA_SAFETY_ON_NULL_RETURN_VAL(history_policy, EINA_FALSE);
1231 zone = history_policy->zone;
1232 EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
1234 //E_FOCUS_HISTORY_TRACE(history_policy, NULL);
1236 // no need to update the focused ec when zone is not displaying
1237 if (!e_zone_is_displaying(zone)) return EINA_FALSE;
1239 // current focused ec
1240 focused_ec = history_policy->focused_ec;
1242 if ((!focused_ec) ||
1243 (focused_ec != eina_list_data_get(history_policy->focus_stack)) ||
1244 (!_e_focus_policy_history_focus_can_take(history_policy, focused_ec)))
1246 reverted_focus_ec = _focus_policy_history_focusable_get(history_policy, focused_ec);
1247 if (!reverted_focus_ec && focused_ec)
1249 _e_focus_policy_history_focus_defer_unset(history_policy, focused_ec);
1250 old_focused_ec = focused_ec;
1254 defered_focus_ec = _e_focus_policy_history_candidate_focus_get(history_policy, reverted_focus_ec);
1256 if (defered_focus_ec)
1258 if (defered_focus_ec != focused_ec)
1260 ELOGF("FOCUS_HISTORY", "focus set | focus calculate (defer_focus) Zone(%d)", defered_focus_ec, zone->id);
1262 _e_focus_policy_history_focus_defer_unset(history_policy, focused_ec);
1263 e_client_frame_focus_set(defered_focus_ec, EINA_TRUE);
1266 _e_focus_policy_history_focus_defer_unset(history_policy, defered_focus_ec);
1268 _e_focus_policy_history_merge_focus_stack_with_defer_focus(history_policy);
1270 else if(reverted_focus_ec)
1272 if (reverted_focus_ec != focused_ec)
1274 ELOGF("FOCUS_HISTORY", "focus set | focus calculate (revert_focus) Zone(%d)", reverted_focus_ec, zone->id);
1276 _e_focus_policy_history_focus_defer_unset(history_policy, focused_ec);
1277 e_client_frame_focus_set(reverted_focus_ec, EINA_TRUE);
1280 else if (old_focused_ec)
1282 ELOGF("FOCUS_HISTORY", "focus unset | focus calculate Zone(%d)", old_focused_ec, zone->id);
1283 e_client_frame_focus_set(old_focused_ec, EINA_FALSE);
1289 EINTERN E_Focus_Policy_Iface *
1290 e_focus_policy_iface_history_new(E_Zone* zone)
1292 E_Focus_Policy_Iface *policy_iface;
1293 E_Focus_Policy_History *history_policy;
1295 EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
1297 policy_iface = E_NEW(E_Focus_Policy_Iface, 1);
1298 EINA_SAFETY_ON_NULL_RETURN_VAL(policy_iface, NULL);
1300 history_policy = E_NEW(E_Focus_Policy_History, 1);
1301 EINA_SAFETY_ON_NULL_GOTO(history_policy, fail);
1303 history_policy->zone = zone;
1305 E_FOCUS_HISTORY_TRACE(history_policy, NULL);
1307 policy_iface->impl = (E_Focus_Policy_Impl *)history_policy;
1308 policy_iface->del = _focus_policy_history_del;
1309 policy_iface->focused_ec_get = _focus_policy_history_focused_ec_get;
1310 policy_iface->update = _focus_policy_history_update;
1313 history_policy->zone_client_add.notify = _focus_policy_history_cb_zone_client_add;
1314 e_zone_client_add_listener_add(zone, &history_policy->zone_client_add);
1315 history_policy->zone_client_remove.notify = _focus_policy_history_cb_zone_client_remove;
1316 e_zone_client_remove_listener_add(zone, &history_policy->zone_client_remove);
1317 history_policy->zone_focus_clear.notify = _focus_policy_history_cb_zone_focus_clear;
1318 e_zone_focus_clear_listener_add(zone, &history_policy->zone_focus_clear);
1319 history_policy->zone_focus_reset.notify = _focus_policy_history_cb_zone_focus_reset;
1320 e_zone_focus_reset_listener_add(zone, &history_policy->zone_focus_reset);
1322 return policy_iface;
1325 _focus_policy_history_del(history_policy);
1327 E_FREE(policy_iface);