#include "e_mod_main.h"
#include "e_mod_rotation_wl.h"
#include "e_mod_rotation_private.h"
-
-#ifdef HAVE_WAYLAND_ONLY
-
#include <wayland-server.h>
#include "tizen_policy_ext-server-protocol.h"
+#ifdef HAVE_AUTO_ROTATION
+#include "e_mod_sensord.h"
+#endif
+
#define TIZEN_ROTATION_ANGLE_TO_INT(angle) ((angle == TIZEN_ROTATION_ANGLE_0) ? 0 : \
(angle == TIZEN_ROTATION_ANGLE_90) ? 90 : \
(angle == TIZEN_ROTATION_ANGLE_180) ? 180 : \
NULL,
}
};
-static Eina_Hash *hash_policy_ext_rotation = NULL;
-static Eina_List *rot_handlers = NULL;
-static Eina_List *rot_hooks = NULL;
-static Eina_List *rot_intercept_hooks = NULL;
+static Eina_Hash *rot_hash = NULL;
+static Eina_List *rot_cbs = NULL;
+static Eina_List *rot_ec_hooks = NULL;
+static Eina_List *rot_obj_hooks = NULL;
static Ecore_Idle_Enterer *rot_idle_enterer = NULL;
static E_Client *fg_ec = NULL;
static Eina_Bool _rot_intercept_hook_hide(void *d EINA_UNUSED, E_Client *ec);
static Eina_Bool _rot_cb_idle_enterer(void *data EINA_UNUSED);
+static Eina_Bool
+_camera_check(E_Client *ec)
+{
+ const char *name = e_client_util_name_get(ec);
+ if (!name) return EINA_FALSE;
+ if (!strncmp(name, "camera-app", 10)) return EINA_TRUE;
+ if (!strncmp(name, "com.samsung.camera-app-lite", 27)) return EINA_TRUE;
+ return EINA_FALSE;
+}
+
+static void
+_unlock_rot_for_fg_app(E_Zone *zone)
+{
+ ELOGF("ROTATION", "UNLOCK for app-hint", NULL, NULL);
+
+ e_zone_rotation_unblock_type_set(zone,
+ E_ZONE_ROT_UNBLOCK_TYPE_APP_HINT,
+ "camera",
+ EINA_TRUE);
+
+ e_zone_rotation_set(zone, e_mod_sensord_cur_angle_get());
+}
+
+static void
+_try_lock_rot_for_fg_app(E_Zone *zone)
+{
+ ELOGF("ROTATION", "LOCK for app-hint", NULL, NULL);
+
+ if (zone->rot.block.sys_auto_rot)
+ e_zone_rotation_set(zone, 0);
+
+ e_zone_rotation_unblock_type_set(zone,
+ E_ZONE_ROT_UNBLOCK_TYPE_APP_HINT,
+ "camera",
+ EINA_FALSE);
+}
+
static void
_rot_client_cb_vis_prepare_foreground(void *data, Evas_Object *obj, void *event_info)
{
{
EDBG(ec, "Set the fg_ec to %x", e_client_util_win_get(ec));
fg_ec = ec;
+
+ if (_camera_check(ec))
+ _unlock_rot_for_fg_app(ec->zone);
+ else
+ _try_lock_rot_for_fg_app(ec->zone);
}
_e_client_rotation_zone_set(ec->zone, ec, NULL);
{
Policy_Ext_Rotation *rot;
- EINA_SAFETY_ON_NULL_RETURN_VAL(hash_policy_ext_rotation, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(rot_hash, NULL);
- rot = eina_hash_find(hash_policy_ext_rotation, &ec);
+ rot = eina_hash_find(rot_hash, &ec);
if (!rot)
{
rot = E_NEW(Policy_Ext_Rotation, 1);
rot->ec = ec;
rot->angle_change_done = EINA_TRUE;
- eina_hash_add(hash_policy_ext_rotation, &ec, rot);
+ eina_hash_add(rot_hash, &ec, rot);
evas_object_smart_callback_add(ec->frame,
"e,visibility,prepare,foreground",
_rot_client_cb_vis_prepare_foreground,
int ver;
EINA_SAFETY_ON_NULL_RETURN(ec);
- EINA_SAFETY_ON_NULL_RETURN(hash_policy_ext_rotation);
+ EINA_SAFETY_ON_NULL_RETURN(rot_hash);
- rot = eina_hash_find(hash_policy_ext_rotation, &ec);
+ rot = eina_hash_find(rot_hash, &ec);
if (!rot) return;
switch (angle)
{
/* if this client don't have parent, rotate */
if (!ec->parent)
- e_client_rotation_set(ec, zone->rot.curr);
+ {
+ /* rotate window only if auto-rotation is enabled.
+ * it can show wrong rotated window if we don't check auto-rot value.
+ *
+ * assuming that auto-rotation is disabled and window A is 0 degree.
+ * in this case, when we attempt to run the camera-app which can be
+ * always rotated, window A is changed to 270 degrees before showing
+ * camera-app window. to prevent this we should check whether auto
+ * rotation is enabled.
+ */
+ if ((!zone->rot.block.sys_auto_rot) &&
+ (e_mod_pol_conf_rot_enable_get(zone->rot.curr)))
+ e_client_rotation_set(ec, zone->rot.curr);
+ }
continue;
}
/*
}
}
+ /* TODO: Fix me. To prevent rotation of 180 degrees for normal app */
+ if ((!_camera_check(ec)) &&
+ (!e_mod_pol_conf_rot_enable_get(zone->rot.curr)))
+ continue;
+
EDBG(ec, "Append Rotation List '%s'(%p)", ec->icccm.name, ec);
target_list = eina_list_append(target_list, ec);
if (ec == fg_ec)
evas_object_show(ec->frame); // e_client_show(ec);
e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
}
- er = eina_hash_find(hash_policy_ext_rotation, &ec);
+ er = eina_hash_find(rot_hash, &ec);
if ((er) && (er->show_grab))
E_FREE_FUNC(er->show_grab, e_policy_visibility_client_grab_release);
ec->e.state.rot.ang.next = -1;
E_OBJECT_CHECK(zone);
E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
- if (!e_config->wm_win_rotation) return;
-
- ELOGF("ROTATION", "ZONE_ROT |zone:%d|rot curr:%d, rot:%d",
- NULL, NULL, zone->num, zone->rot.curr, rot);
-
- if ((zone->rot.wait_for_done) ||
- (zone->rot.block_count > 0))
+ if (zone->rot.wait_for_done)
{
INF("Pending Zone Rotation: wait_for_done %d block_count %d",
- zone->rot.wait_for_done, zone->rot.block_count);
+ zone->rot.wait_for_done, zone->rot.block.mod_count);
zone->rot.next = rot;
zone->rot.pending = EINA_TRUE;
return;
}
+ if (!e_config->wm_win_rotation) return;
+
+ ELOGF("ROTATION", "ZONE_ROT |zone:%d|rot curr:%d, rot:%d",
+ NULL, NULL, zone->num, zone->rot.curr, rot);
+
if (zone->rot.curr == rot) return;
zone->rot.prev = zone->rot.curr;
TRACE_DS_BEGIN(ZONE ROTATION SET);
+ zone->rot.unknown_state = EINA_TRUE;
+
if (rotation == -1)
{
- zone->rot.unknown_state = EINA_TRUE;
ELOGF("ROTATION", "ZONE_ROT |UNKOWN SET|zone:%d|rot curr:%d, rot:%d",
NULL, NULL, zone->num, zone->rot.curr, rotation);
return;
}
- else
- zone->rot.unknown_state = EINA_FALSE;
+
+ if (e_zone_rotation_block_get(zone, rotation))
+ {
+ if ((zone->rot.wait_for_done) ||
+ (zone->rot.block.mod_count > 0))
+ {
+ INF("Pending Zone Rotation: wait_for_done %d block_count %d",
+ zone->rot.wait_for_done, zone->rot.block.mod_count);
+ zone->rot.next = rotation;
+ zone->rot.pending = EINA_TRUE;
+ return;
+ }
+
+ ELOGF("ROTATION", "ZONE_ROT |UNKOWN SET|zone:%d|rot curr:%d, rot:%d",
+ NULL, NULL, zone->num, zone->rot.curr, rotation);
+ return;
+ }
+
+ zone->rot.unknown_state = EINA_FALSE;
_e_zone_rotation_set_internal(zone, rotation);
TRACE_DS_END();
_e_zone_rotation_set_internal(zone, rotation);
}
+/* This function has the policy of window rotation LOCK which is
+ * determined according to the UX or the system order of priority.
+ */
EINTERN Eina_Bool
-e_zone_rotation_block_set(E_Zone *zone, const char *name_hint, Eina_Bool set)
+e_zone_rotation_block_get(E_Zone *zone, int rot)
{
- E_Event_Zone_Rotation_Change_Begin *ev;
+ /* 1. specific app which set special hint such as camera */
+ if (zone->rot.unblock.app_hint)
+ {
+ ELOGF("ROTATION", "BLOCK Get. unblocked by app_hint", NULL, NULL);
+ return EINA_FALSE;
+ }
+
+ /* 2. not supported angle in wm-policy configuration */
+ if (!e_mod_pol_conf_rot_enable_get(rot))
+ {
+ ELOGF("ROTATION", "BLOCK Get. CONF disabled", NULL, NULL);
+ return EINA_TRUE;
+ }
+
+ /* 3. auto-rotation through vconf */
+ if (zone->rot.block.sys_auto_rot)
+ {
+ ELOGF("ROTATION", "BLOCK Get. AUTO_ROT disabled", NULL, NULL);
+ return EINA_TRUE;
+ }
+
+ /* 4. temporary block count for the E sub-modules */
+ if (zone->rot.block.mod_count > 0)
+ {
+ ELOGF("ROTATION", "BLOCK Get. E internal block. %d", NULL, NULL,
+ zone->rot.block.mod_count);
+ return EINA_TRUE;
+ }
+ return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_zone_rotation_block_type_set(E_Zone *zone, E_Zone_Rot_Block_Type type, const char *name_hint, Eina_Bool block)
+{
E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
- if (set) zone->rot.block_count++;
- else zone->rot.block_count--;
+ switch (type)
+ {
+ case E_ZONE_ROT_BLOCK_TYPE_SYSTEM_AUTO_ROTATION:
+ zone->rot.block.sys_auto_rot = block;
+ ELOGF("ROTATION", "BLOCK_SET. sys_auto_rot:%s", NULL, NULL,
+ block ? "true" : "false");
+ break;
+ case E_ZONE_ROT_BLOCK_TYPE_E_MODULE:
+ if (block) zone->rot.block.mod_count++;
+ else zone->rot.block.mod_count--;
+ if (zone->rot.block.mod_count <= 0) zone->rot.block.mod_count = 0;
+ ELOGF("ROTATION", "BLOCK_SET. e modules:%s count:%d", NULL, NULL,
+ block ? "true" : "false", zone->rot.block.mod_count);
+ break;
+ default:
+ break;
+ }
- ELOGF("ROTATION", "ROT_BLOCK|%s|zone:%d|count:%d|from:%s", NULL, NULL,
- set ? "PAUSE" : "RESUME", zone->num, zone->rot.block_count, name_hint);
+ return EINA_TRUE;
+}
- if (zone->rot.block_count <= 0)
+EINTERN Eina_Bool
+e_zone_rotation_unblock_type_set(E_Zone *zone, E_Zone_Rot_Unblock_Type type, const char *name_hint, Eina_Bool unblock)
+{
+ E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
+ E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
+
+ switch (type)
{
- zone->rot.block_count = 0;
+ case E_ZONE_ROT_UNBLOCK_TYPE_APP_HINT:
+ zone->rot.unblock.app_hint = unblock;
+ ELOGF("ROTATION", "UnBLOCK_SET app hint:%s", NULL, NULL,
+ unblock ? "true" : "false");
+ break;
+ default:
+ break;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_zone_rotation_block_set(E_Zone *zone, const char *name_hint, Eina_Bool block)
+{
+ E_Event_Zone_Rotation_Change_Begin *ev;
+
+ E_OBJECT_CHECK_RETURN(zone, EINA_FALSE);
+ E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE);
+
+ e_zone_rotation_block_type_set(zone,
+ E_ZONE_ROT_BLOCK_TYPE_E_MODULE,
+ name_hint,
+ block);
+ if (block) return EINA_TRUE;
- if (zone->rot.pending)
+ ELOGF("ROTATION", "ROT_BLOCK|RESUME|zone:%d|count:%d|from:%s|rot.pending:%d|next:%d",
+ NULL, NULL,
+ zone->num,
+ zone->rot.block.mod_count,
+ name_hint,
+ zone->rot.pending,
+ zone->rot.next);
+
+ if (zone->rot.pending)
+ {
+ zone->rot.pending = EINA_FALSE;
+ if (zone->rot.curr != zone->rot.next)
{
- zone->rot.pending = EINA_FALSE;
- if (zone->rot.curr != zone->rot.next)
+ if (e_zone_rotation_block_get(zone, zone->rot.next))
{
- zone->rot.prev = zone->rot.curr;
- zone->rot.curr = zone->rot.next;
- zone->rot.wait_for_done = EINA_TRUE;
- zone->rot.pending = EINA_FALSE;
+ zone->rot.pending = EINA_TRUE;
+ ELOGF("ROTATION", "ROT_BLOCK|PAUSE|zone:%d|count:%d|from:%s", NULL, NULL,
+ zone->num, zone->rot.block.mod_count, name_hint);
+ return EINA_TRUE;
+ }
- ev = E_NEW(E_Event_Zone_Rotation_Change_Begin, 1);
- if (ev)
- {
- ev->zone = zone;
- e_object_ref(E_OBJECT(ev->zone));
- ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN,
- ev, _e_zone_event_rotation_change_begin_free, NULL);
+ zone->rot.prev = zone->rot.curr;
+ zone->rot.curr = zone->rot.next;
+ zone->rot.wait_for_done = EINA_TRUE;
+ zone->rot.pending = EINA_FALSE;
- ELOGF("ROTATION", "ROT_SET(P|zone:%d|rot:%d",
- NULL, NULL, zone->num, zone->rot.curr);
- }
+ ev = E_NEW(E_Event_Zone_Rotation_Change_Begin, 1);
+ if (ev)
+ {
+ ev->zone = zone;
+ e_object_ref(E_OBJECT(ev->zone));
+ ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN,
+ ev, _e_zone_event_rotation_change_begin_free, NULL);
+
+ ELOGF("ROTATION", "ROT_SET(P|zone:%d|rot:%d",
+ NULL, NULL, zone->num, zone->rot.curr);
}
}
}
}
zone->rot.wait_for_done = EINA_FALSE;
- if ((zone->rot.block_count == 0) && (zone->rot.pending))
+ if ((zone->rot.block.mod_count == 0) && (zone->rot.pending))
{
zone->rot.pending = EINA_FALSE;
if (zone->rot.curr != zone->rot.next)
if (EINA_UNLIKELY(!ev->ec))
goto end;
- rot = eina_hash_find(hash_policy_ext_rotation, &ev->ec);
+ rot = eina_hash_find(rot_hash, &ev->ec);
if (!rot)
goto end;
ec->e.state.rot.ang.curr = 0;
ec->e.state.rot.ang.prev = 0;
- EINA_SAFETY_ON_NULL_RETURN(hash_policy_ext_rotation);
+ EINA_SAFETY_ON_NULL_RETURN(rot_hash);
- rot = eina_hash_find(hash_policy_ext_rotation, &ec);
+ rot = eina_hash_find(rot_hash, &ec);
if (!rot) return;
if (rot->preferred_angle)
if (ec->e.state.rot.available_rots)
E_FREE(ec->e.state.rot.available_rots);
- ext_rot = eina_hash_find(hash_policy_ext_rotation, &ec);
+ ext_rot = eina_hash_find(rot_hash, &ec);
if (ext_rot)
{
EINA_LIST_FREE(ext_rot->rotation_list, res)
wl_resource_set_user_data(res, NULL);
- eina_hash_del_by_key(hash_policy_ext_rotation, &ec);
+ eina_hash_del_by_key(rot_hash, &ec);
}
if (fg_ec == ec)
{
EDBG(ec, "Set the fg_ec to NULL");
fg_ec = NULL;
+
+ if (_camera_check(ec))
+ _try_lock_rot_for_fg_app(ec->zone);
}
}
if (ec->moving) e_client_act_move_end(ec, NULL);
- if ((!zone->rot.block_count) &&
+ if ((!zone->rot.block.mod_count) &&
((!evas_object_visible_get(ec->frame)) ||
(!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))))
{
if (!ec) return;
- rot = eina_hash_find(hash_policy_ext_rotation, &ec);
+ rot = eina_hash_find(rot_hash, &ec);
if (!rot) return;
if(ec->e.fetch.rot.support)
{
Policy_Ext_Rotation *rot;
- rot = eina_hash_find(hash_policy_ext_rotation, &ec);
+ rot = eina_hash_find(rot_hash, &ec);
if (!rot)
return EINA_TRUE;
{
EDBG(ec, "Set the fg_ec to %x", e_client_util_win_get(ec));
fg_ec = ec;
+
+ if (_camera_check(ec))
+ _unlock_rot_for_fg_app(ec->zone);
+ else
+ _try_lock_rot_for_fg_app(ec->zone);
}
_e_client_rotation_zone_set(ec->zone, ec, NULL);
{
EDBG(ec, "Set the fg_ec to NULL");
fg_ec = NULL;
+
+ if (_camera_check(ec))
+ _try_lock_rot_for_fg_app(ec->zone);
}
// for rotating ec in the force_update_list
EINA_LIST_FOREACH(rot.list, l, ec)
{
if (!ec->zone) continue;
- if (ec->zone->rot.block_count)
+ if (ec->zone->rot.block.mod_count)
{
rot_block = EINA_TRUE;
}
return ECORE_CALLBACK_RENEW;
}
-#endif //#ifdef HAVE_WAYLAND_ONLY
-
Eina_Bool
e_mod_rot_wl_init(void)
{
-#ifdef HAVE_WAYLAND_ONLY
EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
return EINA_FALSE;
}
- hash_policy_ext_rotation = eina_hash_pointer_new(_policy_ext_rotation_free);
-
- E_LIST_HANDLER_APPEND(rot_handlers, E_EVENT_ZONE_ROTATION_CHANGE_BEGIN,
- _rot_cb_zone_rotation_change_begin, NULL);
- E_LIST_HANDLER_APPEND(rot_handlers, E_EVENT_CLIENT_BUFFER_CHANGE,
- _rot_cb_buffer_change, NULL);
-
- E_CLIENT_HOOK_APPEND(rot_hooks, E_CLIENT_HOOK_NEW_CLIENT,
- _rot_hook_new_client, NULL);
- E_CLIENT_HOOK_APPEND(rot_hooks, E_CLIENT_HOOK_DEL,
- _rot_hook_client_del, NULL);
- E_CLIENT_HOOK_APPEND(rot_hooks, E_CLIENT_HOOK_EVAL_END,
- _rot_hook_eval_end, NULL);
- E_CLIENT_HOOK_APPEND(rot_hooks, E_CLIENT_HOOK_EVAL_FETCH,
- _rot_hook_eval_fetch, NULL);
+ rot_hash = eina_hash_pointer_new(_policy_ext_rotation_free);
- E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(rot_intercept_hooks,
- E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER,
- _rot_intercept_hook_show_helper, NULL);
- E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(rot_intercept_hooks,
- E_COMP_OBJECT_INTERCEPT_HOOK_HIDE,
- _rot_intercept_hook_hide, NULL);
+ E_LIST_HANDLER_APPEND(rot_cbs, E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _rot_cb_zone_rotation_change_begin, NULL);
+ E_LIST_HANDLER_APPEND(rot_cbs, E_EVENT_CLIENT_BUFFER_CHANGE, _rot_cb_buffer_change, NULL);
+ E_CLIENT_HOOK_APPEND(rot_ec_hooks, E_CLIENT_HOOK_NEW_CLIENT, _rot_hook_new_client, NULL);
+ E_CLIENT_HOOK_APPEND(rot_ec_hooks, E_CLIENT_HOOK_DEL, _rot_hook_client_del, NULL);
+ E_CLIENT_HOOK_APPEND(rot_ec_hooks, E_CLIENT_HOOK_EVAL_END, _rot_hook_eval_end, NULL);
+ E_CLIENT_HOOK_APPEND(rot_ec_hooks, E_CLIENT_HOOK_EVAL_FETCH, _rot_hook_eval_fetch, NULL);
+ E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(rot_obj_hooks, E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, _rot_intercept_hook_show_helper, NULL);
+ E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(rot_obj_hooks, E_COMP_OBJECT_INTERCEPT_HOOK_HIDE, _rot_intercept_hook_hide, NULL);
rot_idle_enterer = ecore_idle_enterer_add(_rot_cb_idle_enterer, NULL);
-#endif
+
return EINA_TRUE;
}
void
e_mod_rot_wl_shutdown(void)
{
-#ifdef HAVE_WAYLAND_ONLY
- E_FREE_FUNC(hash_policy_ext_rotation, eina_hash_free);
+ E_FREE_FUNC(rot_hash, eina_hash_free);
E_FREE_FUNC(rot.force_update_list, eina_list_free);
- E_FREE_LIST(rot_hooks, e_client_hook_del);
- E_FREE_LIST(rot_handlers, ecore_event_handler_del);
- E_FREE_LIST(rot_intercept_hooks, e_comp_object_intercept_hook_del);
+ E_FREE_LIST(rot_ec_hooks, e_client_hook_del);
+ E_FREE_LIST(rot_cbs, ecore_event_handler_del);
+ E_FREE_LIST(rot_obj_hooks, e_comp_object_intercept_hook_del);
if (rot_idle_enterer)
{
ecore_idle_enterer_del(rot_idle_enterer);
rot_idle_enterer = NULL;
}
-#endif
}
EINTERN void