#include "e.h"
+#include "e_zone_intern.h"
+#include "e_client_intern.h"
#ifdef REFACTOR_FOCUS_POLICY
typedef struct _E_Focus_Policy_Topmost_Impl E_Focus_Policy_Topmost;
+typedef struct _E_Focus_Policy_Topmost_Client E_Focus_Policy_Topmost_Client;
struct _E_Focus_Policy_Topmost_Impl
{
GMutex focused_ec_mutex;
- Eina_List *ec_hooks;
- Eina_List *zone_hooks;
+ struct wl_listener zone_client_add;
+ struct wl_listener zone_client_remove;
+ struct wl_listener zone_focus_clear;
};
+struct _E_Focus_Policy_Topmost_Client
+{
+ E_Client *ec;
+ E_Focus_Policy_Topmost *topmost_policy;
+
+ struct wl_listener client_destroy;
+ struct wl_listener client_mouse_in;
+ struct wl_listener client_mouse_out;
+ struct wl_listener client_mouse_down;
+ struct wl_listener client_focus_set;
+ struct wl_listener client_focus_unset;
+ struct wl_listener client_lower;
+ struct wl_listener client_move;
+ struct wl_listener client_eval_end;
+};
+
+// Trace the focus topmost
+//#define FOCUS_TOPMOST_TRACE
+#ifdef FOCUS_TOPMOST_TRACE
+#define E_FOCUS_TOPMOST_TRACE(topmost_policy, ec) \
+ do \
+ { \
+ ELOGF( \
+ "FOCUS_TOPMOST", "[FOCUS][Trace][%s]:(%p, %d) focused_ec:%p", ec, \
+ __FUNCTION__, topmost_policy, topmost_policy->zone->id, topmost_policy->focused_ec)\
+ ); \
+ } \
+ while (0)
+#else
+#define E_FOCUS_TOPMOST_TRACE(topmost_policy, ec)
+#endif
+
static Eina_Bool
_e_focus_policy_topmost_focus_can_take_by_vis_obscured(E_Client *ec)
{
}
static void
-_focus_policy_topmost_hook_cb_client_del(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_destroy(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_destroy);
- // find the next focus and set it when ec is focused.
- if (ec->focused)
- {
- _focus_policy_topmost_next_focus_set(topmost_policy);
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
- // check the critical case
- if (topmost_policy->focused_ec == ec)
- {
- ELOGF("FOCUS_TOPMOST", "CRITICAL. focused is deleted ec.", ec);
- ELOGF("FOCUS_TOPMOST", "CLIENT FOCUS_SET", NULL);
- g_mutex_lock(&topmost_policy->focused_ec_mutex);
- topmost_policy->focused_ec = NULL;
- g_mutex_unlock(&topmost_policy->focused_ec_mutex);
- }
- }
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
+
+ wl_list_remove(&topmost_client->client_eval_end.link);
+ wl_list_remove(&topmost_client->client_move.link);
+ wl_list_remove(&topmost_client->client_lower.link);
+ wl_list_remove(&topmost_client->client_focus_unset.link);
+ wl_list_remove(&topmost_client->client_focus_set.link);
+ wl_list_remove(&topmost_client->client_mouse_down.link);
+ wl_list_remove(&topmost_client->client_mouse_out.link);
+ wl_list_remove(&topmost_client->client_mouse_in.link);
+ wl_list_remove(&topmost_client->client_destroy.link);
+
+ E_FREE(topmost_client);
}
static void
-_focus_policy_topmost_hook_cb_client_mouse_in(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_mouse_in(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_mouse_in);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
{
}
static void
-_focus_policy_topmost_hook_cb_client_mouse_out(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_mouse_out(struct wl_listener *listener, void *data)
{
// nothing to do
}
static void
-_focus_policy_topmost_hook_cb_client_mouse_down(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_mouse_down(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
- E_Client *focused_ec;
+ E_Client *focused_ec, *ec;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_mouse_down);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
if (e_object_is_del(E_OBJECT(ec))) return;
}
static void
-_focus_policy_topmost_hook_cb_client_focus_set(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_focus_set(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *focused_ec, *ec, *ec2;
E_Zone *zone;
- E_Client *focused_ec, *ec2;
Eina_List *l, *ll;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_focus_set);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
focused_ec = topmost_policy->focused_ec;
if (ec == focused_ec) return;
}
static void
-_focus_policy_topmost_hook_cb_client_focus_unset(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_focus_unset(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec, *ec2;
E_Zone *zone;
E_Desk *desk, *desk2;
- E_Client *ec2;
Eina_List *l;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_focus_unset);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+ ec = topmost_client->ec;
EINA_SAFETY_ON_NULL_RETURN(ec);
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
+
zone = topmost_policy->zone;
ec->want_focus = ec->focused = 0;
}
static void
-_focus_policy_topmost_hook_cb_client_lower(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_lower(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_lower);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
// no need to change the focused ec when ec is not focused.
if (!ec->focused) return;
}
static void
-_focus_policy_topmost_hook_cb_client_move(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_move(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec;
E_Zone *zone;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_move);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
zone = e_comp_zone_find_by_ec(ec);
if (!zone) return;
}
static void
-_focus_policy_topmost_hook_cb_client_eval_end(void *data, E_Client *ec)
+_focus_policy_topmost_cb_client_eval_end(struct wl_listener *listener, void *data)
{
+ E_Focus_Policy_Topmost_Client *topmost_client;
E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_client = wl_container_of(listener, topmost_client, client_eval_end);
+
+ topmost_policy = topmost_client->topmost_policy;
+ EINA_SAFETY_ON_NULL_RETURN(topmost_policy);
+
+ ec = topmost_client->ec;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
if (e_object_is_del(E_OBJECT(ec))) return;
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
+
ec->take_focus = ec->want_focus = 0;
}
static void
-_focus_policy_topmost_hook_cb_zone_focus_clear(void *data, E_Zone *zone)
+_focus_policy_topmost_cb_zone_client_add(struct wl_listener *listener, void *data)
{
E_Focus_Policy_Topmost *topmost_policy;
+ E_Focus_Policy_Topmost_Client *topmost_client;
+ E_Client *ec;
- topmost_policy = (E_Focus_Policy_Topmost *)data;
- if (!topmost_policy) return;
+ topmost_policy = wl_container_of(listener, topmost_policy, zone_client_add);
+
+ ec = (E_Client *)data;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
+
+ topmost_client = E_NEW(E_Focus_Policy_Topmost_Client, 1);
+ EINA_SAFETY_ON_NULL_RETURN(topmost_client);
+
+ topmost_client->ec = ec;
+ topmost_client->topmost_policy = topmost_policy;
+
+ // e_client listeners
+ topmost_client->client_destroy.notify = _focus_policy_topmost_cb_client_destroy;
+ e_client_destroy_listener_add(ec, &topmost_client->client_destroy);
+ topmost_client->client_mouse_in.notify = _focus_policy_topmost_cb_client_mouse_in;
+ e_client_mouse_in_listener_add(ec, &topmost_client->client_mouse_in);
+ topmost_client->client_mouse_out.notify = _focus_policy_topmost_cb_client_mouse_out;
+ e_client_mouse_out_listener_add(ec, &topmost_client->client_mouse_out);
+ topmost_client->client_mouse_down.notify = _focus_policy_topmost_cb_client_mouse_down;
+ e_client_mouse_down_listener_add(ec, &topmost_client->client_mouse_down);
+ topmost_client->client_focus_set.notify = _focus_policy_topmost_cb_client_focus_set;
+ e_client_focus_set_listener_add(ec, &topmost_client->client_focus_set);
+ topmost_client->client_focus_unset.notify = _focus_policy_topmost_cb_client_focus_unset;
+ e_client_focus_unset_listener_add(ec, &topmost_client->client_focus_unset);
+ topmost_client->client_lower.notify = _focus_policy_topmost_cb_client_lower;
+ e_client_lower_listener_add(ec, &topmost_client->client_lower);
+ topmost_client->client_move.notify = _focus_policy_topmost_cb_client_move;
+ e_client_move_listener_add(ec, &topmost_client->client_move);
+ topmost_client->client_eval_end.notify = _focus_policy_topmost_cb_client_eval_end;
+ e_client_eval_end_listener_add(ec, &topmost_client->client_eval_end);
+
+ ELOGF("FOCUS_TOPMOST", "zone_client_add | ", ec);
+}
+
+static void
+_focus_policy_topmost_cb_zone_client_remove(struct wl_listener *listener, void *data)
+{
+ E_Focus_Policy_Topmost *topmost_policy;
+ E_Client *ec;
+
+ topmost_policy = wl_container_of(listener, topmost_policy, zone_client_remove);
+
+ ec = (E_Client *)data;
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ E_FOCUS_TOPMOST_TRACE(topmost_policy, ec);
+
+ ELOGF("FOCUS_TOPMOST", "zone_client_remove | ", ec);
+
+ // find the next focus and set it when ec is focused.
+ if (ec->focused)
+ {
+ _focus_policy_topmost_next_focus_set(topmost_policy);
+
+ // check the critical case
+ if (topmost_policy->focused_ec == ec)
+ {
+ ELOGF("FOCUS_TOPMOST", "CRITICAL. focused is deleted ec.", ec);
+ ELOGF("FOCUS_TOPMOST", "CLIENT FOCUS_SET", NULL);
+ g_mutex_lock(&topmost_policy->focused_ec_mutex);
+ topmost_policy->focused_ec = NULL;
+ g_mutex_unlock(&topmost_policy->focused_ec_mutex);
+ }
+ }
+}
+
+static void
+_focus_policy_topmost_cb_zone_focus_clear(struct wl_listener *listener, void *data)
+{
+ E_Focus_Policy_Topmost *topmost_policy;
+ E_Zone *zone;
+
+ topmost_policy = wl_container_of(listener, topmost_policy, zone_focus_clear);
+ zone = (E_Zone *)data;
if (topmost_policy->zone != zone) return;
// make focused_ec be NULL
if (!topmost_policy) return;
- E_FREE_LIST(topmost_policy->zone_hooks, e_zone_hook_del);
- E_FREE_LIST(topmost_policy->ec_hooks, e_client_hook_del);
+ wl_list_remove(&topmost_policy->zone_focus_clear.link);
+ wl_list_remove(&topmost_policy->zone_client_remove.link);
+ wl_list_remove(&topmost_policy->zone_client_add.link);
g_mutex_clear(&topmost_policy->focused_ec_mutex);
{
E_Focus_Policy_Iface *policy_iface;
E_Focus_Policy_Topmost *topmost_policy;
- E_Zone_Hook *zone_hook;
EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
policy_iface->focused_ec_get = _focus_policy_topmost_focused_ec_get;
policy_iface->update = _focus_policy_topmost_update;
- // e_client hooks
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_DEL, _focus_policy_topmost_hook_cb_client_del, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_MOUSE_IN, _focus_policy_topmost_hook_cb_client_mouse_in, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_MOUSE_OUT, _focus_policy_topmost_hook_cb_client_mouse_out, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_MOUSE_DOWN, _focus_policy_topmost_hook_cb_client_mouse_down, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_FOCUS_SET, _focus_policy_topmost_hook_cb_client_focus_set, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_FOCUS_UNSET, _focus_policy_topmost_hook_cb_client_focus_unset, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_LOWER, _focus_policy_topmost_hook_cb_client_lower, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_MOVE, _focus_policy_topmost_hook_cb_client_move, topmost_policy);
- E_LIST_HOOK_APPEND(topmost_policy->ec_hooks, E_CLIENT_HOOK_EVAL_END, _focus_policy_topmost_hook_cb_client_eval_end, topmost_policy);
-
- // e_zone hooks
- zone_hook = e_zone_hook_add(E_ZONE_HOOK_FOCUS_CLEAR, _focus_policy_topmost_hook_cb_zone_focus_clear, topmost_policy);
- if (zone_hook) topmost_policy->zone_hooks = eina_list_append(topmost_policy->zone_hooks, zone_hook);
+ // zone listeners
+ topmost_policy->zone_client_add.notify = _focus_policy_topmost_cb_zone_client_add;
+ e_zone_client_add_listener_add(zone, &topmost_policy->zone_client_add);
+ topmost_policy->zone_client_remove.notify = _focus_policy_topmost_cb_zone_client_remove;
+ e_zone_client_remove_listener_add(zone, &topmost_policy->zone_client_remove);
+ topmost_policy->zone_focus_clear.notify = _focus_policy_topmost_cb_zone_focus_clear;
+ e_zone_focus_clear_listener_add(zone, &topmost_policy->zone_focus_clear);
return policy_iface;