X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fbin%2Fe_border.c;h=d23bcc5c6f2bd6688e17dac44a9398a829967ec7;hb=6142e9f8c2988f3537ef6f0e0eeb787147b1ee77;hp=2abc95e9b46384d79a9e8982490bb4ebdf907220;hpb=065c18f2ec5783cdf3d1c0e253edb3f8c3c42f93;p=platform%2Fcore%2Fuifw%2Fe17.git diff --git a/src/bin/e_border.c b/src/bin/e_border.c index 2abc95e..d23bcc5 100644 --- a/src/bin/e_border.c +++ b/src/bin/e_border.c @@ -149,11 +149,14 @@ static Eina_Bool _e_border_cb_desk_window_profile_change(void *data, void *ev); #endif #ifdef _F_ZONE_WINDOW_ROTATION_ -static Eina_Bool _e_border_cb_zone_rotation_change(void *data, - int ev_type, - void *ev); +static Eina_Bool _e_border_cb_zone_rotation_change_begin(void *data, + int ev_type, + void *ev); +static void _e_border_cb_rotation_sync_job(void *data); +static void _e_border_cb_rotation_async_job(void *data); static Eina_Bool _e_border_rotation_change_prepare_timeout(void *data); static void _e_border_rotation_change_request(E_Zone *zone); +static void _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush); static Eina_Bool _e_border_rotation_change_done_timeout(void *data); static void _e_border_rotation_change_done(void); static Eina_Bool _e_border_rotation_geom_get(E_Border *bd, @@ -164,14 +167,12 @@ static Eina_Bool _e_border_rotation_geom_get(E_Border *bd, int *w, int *h, Eina_Bool *move); -static Eina_Bool _e_border_rotation_list_add(E_Zone *zone, Eina_Bool without_vkbd); static void _e_border_rotation_list_remove(E_Border *bd); -static Eina_Bool _e_border_rotation_check(E_Border *bd); -static Eina_Bool _e_border_rotation_zone_check(E_Zone *zone); -static Eina_Bool _e_border_rotation_border_check(E_Border *bd, int ang); -static Eina_Bool _e_border_rotation_zone_vkbd_check(E_Zone *zone); -static Eina_Bool _e_border_rotation_vkbd_transient_for_check(E_Border *bd); -static Eina_Bool _e_border_rotation_transient_for_check(E_Border *bd, int ang); +static Eina_Bool _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h); +static int _e_border_rotation_angle_get(E_Border *bd); +static Eina_Bool _e_border_rotation_zone_set(E_Zone *zone); +static Eina_Bool _e_border_rotatable_check(E_Border *bd, int ang); +static Eina_Bool _e_border_is_vkbd(E_Border *bd); static Eina_Bool _e_border_cb_window_configure(void *data, int ev_type, void *ev); @@ -239,8 +240,13 @@ static void _e_border_event_border_fullscreen_free(void *data, static void _e_border_event_border_unfullscreen_free(void *data, void *ev); #ifdef _F_ZONE_WINDOW_ROTATION_ -static void _e_border_event_border_rotation_free(void *data, - void *ev); +static void _e_border_event_border_rotation_change_begin_free(void *data, + void *ev); +static void _e_border_event_border_rotation_change_cancel_free(void *data, + void *ev); +static void _e_border_event_border_rotation_change_end_free(void *data, + void *ev); +static void _e_border_event_border_rotation_change_begin_send(E_Border *bd); #endif static void _e_border_zone_update(E_Border *bd); @@ -320,10 +326,13 @@ typedef struct _E_Border_Rotation_Info E_Border_Rotation_Info; struct _E_Border_Rotation { Eina_List *list; + Eina_List *async_list; Eina_Bool wait_prepare_done; Ecore_Timer *prepare_timer; Ecore_Timer *done_timer; + Ecore_Job *sync_job; + Ecore_Job *async_job; Ecore_X_Window vkbd_ctrl_win; E_Border *vkbd; @@ -353,9 +362,12 @@ struct _E_Border_Rotation_Info static E_Border_Rotation rot = { NULL, + NULL, EINA_FALSE, NULL, NULL, + NULL, + NULL, 0, NULL, NULL, @@ -391,7 +403,10 @@ EAPI int E_EVENT_BORDER_PROPERTY = 0; EAPI int E_EVENT_BORDER_FULLSCREEN = 0; EAPI int E_EVENT_BORDER_UNFULLSCREEN = 0; #ifdef _F_ZONE_WINDOW_ROTATION_ -EAPI int E_EVENT_BORDER_ROTATION = 0; +EAPI int E_EVENT_BORDER_ROTATION = 0; /* deprecated */ +EAPI int E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = 0; +EAPI int E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = 0; +EAPI int E_EVENT_BORDER_ROTATION_CHANGE_END = 0; #endif #define GRAV_SET(bd, grav) \ @@ -469,7 +484,7 @@ e_border_init(void) handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_DESK_WINDOW_PROFILE_CHANGE, _e_border_cb_desk_window_profile_change, NULL)); #endif #ifdef _F_ZONE_WINDOW_ROTATION_ - handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_ZONE_ROTATION_CHANGE, _e_border_cb_zone_rotation_change, NULL)); + handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _e_border_cb_zone_rotation_change_begin, NULL)); #endif if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL); @@ -495,7 +510,10 @@ e_border_init(void) E_EVENT_BORDER_FULLSCREEN = ecore_event_type_new(); E_EVENT_BORDER_UNFULLSCREEN = ecore_event_type_new(); #ifdef _F_ZONE_WINDOW_ROTATION_ - E_EVENT_BORDER_ROTATION = ecore_event_type_new(); + E_EVENT_BORDER_ROTATION = ecore_event_type_new(); /* deprecated */ + E_EVENT_BORDER_ROTATION_CHANGE_BEGIN = ecore_event_type_new(); + E_EVENT_BORDER_ROTATION_CHANGE_CANCEL = ecore_event_type_new(); + E_EVENT_BORDER_ROTATION_CHANGE_END = ecore_event_type_new(); #endif // e_init_undone(); @@ -868,6 +886,11 @@ e_border_new(E_Container *con, bd->changed = 1; #ifdef _F_ZONE_WINDOW_ROTATION_ bd->client.e.state.rot.preferred_rot = -1; + bd->client.e.state.rot.type = E_BORDER_ROTATION_TYPE_NORMAL; + bd->client.e.state.rot.changes = -1; + bd->client.e.state.rot.pending_show = 0; + bd->client.e.state.rot.curr = 0; + bd->client.e.state.rot.prev = 0; #endif // bd->zone = e_zone_current_get(con); @@ -1315,7 +1338,13 @@ _e_border_vkbd_hide(E_Border *bd) rot.vkbd_hide_timer = NULL; if ((bd) && ((E_OBJECT(bd)->type) == (E_BORDER_TYPE))) { + ELB(ELBT_BD, "HIDE VKBD", bd->client.win); e_border_hide(bd, 0); + if (!e_object_is_del(E_OBJECT(bd))) + { + ELB(ELBT_BD, "DEL VKBD", bd->client.win); + e_object_del(E_OBJECT(bd)); + } rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_border_vkbd_hide_timeout, bd); } } @@ -1357,6 +1386,14 @@ e_border_show(E_Border *bd) E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE); if (bd->visible) return; #ifdef _F_ZONE_WINDOW_ROTATION_ + if ((bd->new_client) && + (bd->client.e.state.rot.changes != -1)) + { + // newly created window that has to be rotated will be show after rotation done. + // so, skip at this time. it will be called again after GETTING ROT_DONE. + bd->client.e.state.rot.pending_show = 1; + return; + } if ((e_config->wm_win_rotation) && (rot.vkbd_ctrl_win) && (rot.vkbd) && (bd == rot.vkbd) && @@ -1398,7 +1435,8 @@ e_border_show(E_Border *bd) (bd->client.e.state.rot.app_set))) { ELB(ELBT_ROT, "CHECK", bd->client.win); - _e_border_rotation_check(bd); + int rotation = _e_border_rotation_angle_get(bd); + if (rotation != -1) e_border_rotation_set(bd, rotation); } #endif } @@ -1498,7 +1536,8 @@ e_border_hide(E_Border *bd, if (!bd->need_reparent) { - if (bd->focused) + if ((bd->focused) || + (e_grabinput_last_focus_win_get() == bd->client.win)) { e_border_focus_set(bd, 0, 1); if (manage != 2) @@ -1562,6 +1601,10 @@ e_border_hide(E_Border *bd, send_event: if (!stopping) { +#ifdef _F_ZONE_WINDOW_ROTATION_ + _e_border_rotation_list_remove(bd); +#endif + E_Event_Border_Hide *ev; ev = E_NEW(E_Event_Border_Hide, 1); @@ -3676,17 +3719,110 @@ static Eina_Bool _e_border_uniconify_timeout(void *data) { E_Border *bd; + E_Border *child_bd; + bd = data; if (!e_object_is_del(E_OBJECT(bd))) { + ELB(ELBT_BD, "TIMEOUT UNICONIFY_APPROVE", bd->client.win); bd->client.e.state.deiconify_approve.render_done = 1; - e_border_uniconify(bd); + if (bd->client.e.state.deiconify_approve.req_list) + { + EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child_bd) + { + child_bd->client.e.state.deiconify_approve.render_done = 1; + child_bd->client.e.state.deiconify_approve.ancestor = NULL; + } + } + bd->client.e.state.deiconify_approve.req_list = NULL; bd->client.e.state.deiconify_approve.wait_timer = NULL; + e_border_uniconify(bd); } return ECORE_CALLBACK_CANCEL; } + +static void +_e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor) +{ + if (!bd || !bd_ancestor) return; + + if (e_config->deiconify_approve) + { + if (e_config->transient.iconify) + { + Eina_List *l; + E_Border *child; + Eina_List *list = _e_border_sub_borders_new(bd); + EINA_LIST_FOREACH(list, l, child) + { +#ifdef _F_ZONE_WINDOW_ROTATION_ + if ((e_config->wm_win_rotation) && + ((child->client.e.state.rot.support) || + (child->client.e.state.rot.app_set))) + { + ELB(ELBT_ROT, "CHECK_DEICONIFY CHILD", child->client.win); + int rotation = _e_border_rotation_angle_get(bd); + if (rotation != -1) e_border_rotation_set(bd, rotation); + } +#endif + _e_border_deiconify_approve_send(child, bd_ancestor); + if (child->client.e.state.deiconify_approve.support) + { + ELBF(ELBT_BD, 0, child->client.win, + "SEND DEICONIFY_APPROVE. ancestor:%x", bd_ancestor->client.win); + + ecore_x_client_message32_send(child->client.win, + ECORE_X_ATOM_E_DEICONIFY_APPROVE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + child->client.win, 0, 0, 0, 0); + child->client.e.state.deiconify_approve.ancestor = bd_ancestor; + bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, child); + } + } + eina_list_free(list); + } + } +} + +static void +_e_border_deiconify_approve_send_all_transient(E_Border *bd) +{ + E_Border *bd_ancestor; + bd_ancestor = bd; + + if (e_config->deiconify_approve) + { +#ifdef _F_ZONE_WINDOW_ROTATION_ + if ((e_config->wm_win_rotation) && + ((bd->client.e.state.rot.support) || + (bd->client.e.state.rot.app_set))) + { + ELB(ELBT_ROT, "CHECK_DEICONIFY", bd->client.win); + int rotation = _e_border_rotation_angle_get(bd); + if (rotation != -1) e_border_rotation_set(bd, rotation); + } +#endif + + if (e_config->transient.iconify) + { + _e_border_deiconify_approve_send(bd, bd_ancestor); + } + + if (bd->client.e.state.deiconify_approve.support) + { + ELBF(ELBT_BD, 0, bd->client.win, + "SEND DEICONIFY_APPROVE.. ancestor:%x", bd_ancestor->client.win); + + ecore_x_client_message32_send(bd->client.win, + ECORE_X_ATOM_E_DEICONIFY_APPROVE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + bd->client.win, 0, 0, 0, 0); + bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd); + } + } +} #endif EAPI void @@ -3704,18 +3840,18 @@ e_border_uniconify(E_Border *bd) { if (bd->client.e.state.deiconify_approve.support) { - if (bd->client.e.state.deiconify_approve.wait_timer) return; + if (bd->client.e.state.deiconify_approve.wait_timer) + { + ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win); + return; + } if (bd->client.e.state.deiconify_approve.render_done == 0) { - ecore_x_client_message32_send(bd->client.win, - ECORE_X_ATOM_E_DEICONIFY_APPROVE, - ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, - bd->client.win, 0, 0, 0, 0); - bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd); + ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win); + _e_border_deiconify_approve_send_all_transient(bd); return; } } - bd->client.e.state.deiconify_approve.render_done = 0; } #endif @@ -4184,14 +4320,14 @@ e_border_idler_before(void) if (m) zone = e_util_zone_current_get(m); if ((zone) && (rot.wait_prepare_done)) { - if (_e_border_rotation_list_add(zone, EINA_FALSE)) - _e_border_rotation_change_request(zone); - else + if (rot.list) { + _e_border_rotation_change_request(zone); if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer); rot.prepare_timer = NULL; rot.wait_prepare_done = EINA_FALSE; + } } } @@ -5639,14 +5775,6 @@ _e_border_del(E_Border *bd) ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL); } -#ifdef _F_DEICONIFY_APPROVE_ - if (bd->client.e.state.deiconify_approve.wait_timer) - { - ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer); - bd->client.e.state.deiconify_approve.wait_timer = NULL; - } -#endif - if (bd->parent) { bd->parent->transients = eina_list_remove(bd->parent->transients, bd); @@ -5665,6 +5793,61 @@ _e_border_del(E_Border *bd) child->parent = NULL; } +#ifdef _F_DEICONIFY_APPROVE_ + bd->client.e.state.deiconify_approve.render_done = 0; + + E_Border *ancestor_bd; + ancestor_bd = bd->client.e.state.deiconify_approve.ancestor; + if ((ancestor_bd) && + (!e_object_is_del(E_OBJECT(ancestor_bd)))) + { + ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd); + bd->client.e.state.deiconify_approve.ancestor = NULL; + + if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) && + (ancestor_bd->client.e.state.deiconify_approve.render_done)) + { + if (ancestor_bd->client.e.state.deiconify_approve.wait_timer) + { + ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer); + ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL; + e_border_uniconify(ancestor_bd); + } + } + } + + if (bd->client.e.state.deiconify_approve.wait_timer) + { + ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer); + bd->client.e.state.deiconify_approve.wait_timer = NULL; + } + + if (bd->client.e.state.deiconify_approve.req_list) + { + EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child) + { + child->client.e.state.deiconify_approve.render_done = 0; + child->client.e.state.deiconify_approve.ancestor = NULL; + } + } +#endif + +#ifdef _F_ZONE_WINDOW_ROTATION_ + if (rot.list) _e_border_rotation_list_remove(bd); + if (rot.async_list) + { + Eina_List *l; + E_Border_Rotation_Info *info = NULL; + + EINA_LIST_FOREACH(rot.async_list, l, info) + if (info->bd == bd) + { + rot.async_list = eina_list_remove(rot.async_list, info); + E_FREE(info); + } + } +#endif + if (bd->leader) { bd->leader->group = eina_list_remove(bd->leader->group, bd); @@ -5702,11 +5885,22 @@ _e_border_cb_window_show_request(void *data __UNUSED__, void *ev) { E_Border *bd; + E_Container *con; Ecore_X_Event_Window_Show_Request *e; e = ev; bd = e_border_find_by_client_window(e->win); if (!bd) return ECORE_CALLBACK_PASS_ON; + + if ((e_config->wm_win_rotation) && + (rot.vkbd_ctrl_win) && (rot.vkbd) && + (bd == rot.vkbd) && + (rot.vkbd_hide_prepare_timer)) + { + con = bd->zone->container; + bd = e_border_new(con, e->win, 0, 0); + } + if (bd->iconic) { if (!bd->lock_client_iconify) @@ -5733,6 +5927,27 @@ _e_border_cb_window_destroy(void *data __UNUSED__, e = ev; bd = e_border_find_by_client_window(e->win); if (!bd) return ECORE_CALLBACK_PASS_ON; + ELB(ELBT_BD, "X_WIN_DEL", bd->client.win); +#ifdef _F_ZONE_WINDOW_ROTATION_ + if (e_config->wm_win_rotation) + { + if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD) + { + ELB(ELBT_BD, "X_DEL_NOTIFY", bd->client.win); + if (!rot.vkbd_hide_prepare_timer) + { + ELB(ELBT_BD, "HIDE VKBD", bd->client.win); + e_border_hide(bd, 0); + if (!rot.vkbd_hide_prepare_timer) + { + ELB(ELBT_BD, "DEL VKBD", bd->client.win); + e_object_del(E_OBJECT(bd)); + } + } + return ECORE_CALLBACK_PASS_ON; + } + } +#endif e_border_hide(bd, 0); e_object_del(E_OBJECT(bd)); return ECORE_CALLBACK_PASS_ON; @@ -5763,7 +5978,16 @@ _e_border_cb_window_hide(void *data __UNUSED__, } if (!bd) bd = e_border_find_by_client_window(e->win); // printf(" bd = %p\n", bd); - if (!bd) return ECORE_CALLBACK_PASS_ON; + if (!bd) + { + if (ecore_x_window_visible_get(e->win)) + { + ELB(ELBT_BD, "FORCE UNMAP client window", e->win); + ecore_x_window_hide(e->win); + } + return ECORE_CALLBACK_PASS_ON; + } + // printf(" bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap); if (bd->ignore_first_unmap > 0) { @@ -5801,6 +6025,27 @@ _e_border_cb_window_hide(void *data __UNUSED__, bd->visible = 1; } #endif + +#ifdef _F_ZONE_WINDOW_ROTATION_ + if (e_config->wm_win_rotation) + { + if (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD) + { + ELB(ELBT_BD, "X_UNMAP_NOTIFY", bd->client.win); + if (!rot.vkbd_hide_prepare_timer) + { + ELB(ELBT_BD, "HIDE VKBD", bd->client.win); + e_border_hide(bd, 0); + if (!rot.vkbd_hide_prepare_timer) + { + ELB(ELBT_BD, "DEL VKBD", bd->client.win); + e_object_del(E_OBJECT(bd)); + } + } + return ECORE_CALLBACK_PASS_ON; + } + } +#endif e_border_hide(bd, 0); e_object_del(E_OBJECT(bd)); } @@ -6721,13 +6966,38 @@ _e_border_cb_client_message(void *data __UNUSED__, if (bd->client.e.state.deiconify_approve.support) { if (e->data.l[1] != 1) return ECORE_CALLBACK_PASS_ON; - if (bd->client.e.state.deiconify_approve.wait_timer) + bd->client.e.state.deiconify_approve.render_done = 1; + + E_Border *ancestor_bd; + ancestor_bd = bd->client.e.state.deiconify_approve.ancestor; + if (ancestor_bd) { - ecore_timer_del(bd->client.e.state.deiconify_approve.wait_timer); - bd->client.e.state.deiconify_approve.wait_timer = NULL; + ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd); + bd->client.e.state.deiconify_approve.ancestor = NULL; + } + else + { + ancestor_bd = bd; + } + + ELBF(ELBT_BD, 0, bd->client.win, + "RECEIVE DEICONIFY_APPROVE.. ancestor:%x", ancestor_bd->client.win); + + if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) && + (ancestor_bd->client.e.state.deiconify_approve.render_done)) + { + if (ancestor_bd->client.e.state.deiconify_approve.wait_timer) + { + ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer); + ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL; + e_border_uniconify(ancestor_bd); + } + else + { + ELB(ELBT_BD, "Unset DEICONIFY_APPROVE render_done", ancestor_bd->client.win); + ancestor_bd->client.e.state.deiconify_approve.render_done = 0; + } } - bd->client.e.state.deiconify_approve.render_done = 1; - e_border_uniconify(bd); } } return ECORE_CALLBACK_PASS_ON; @@ -6775,7 +7045,15 @@ _e_border_cb_client_message(void *data __UNUSED__, if (e_config->wm_win_rotation) { if ((int)e->data.l[1] == bd->client.e.state.rot.curr) - _e_border_rotation_list_remove(bd); + { + _e_border_rotation_list_remove(bd); + if (bd->client.e.state.rot.pending_show) + { + ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win); + e_border_show(bd); + bd->client.e.state.rot.pending_show = 0; + } + } } } #endif @@ -7653,61 +7931,71 @@ _e_border_cb_desk_window_profile_change(void *data __UNUSED__, #ifdef _F_ZONE_WINDOW_ROTATION_ static Eina_Bool -_e_border_cb_zone_rotation_change(void *data __UNUSED__, - int ev_type __UNUSED__, - void *ev) +_e_border_cb_zone_rotation_change_begin(void *data __UNUSED__, + int ev_type __UNUSED__, + void *ev) { - E_Event_Zone_Rotation_Change *e = ev; - Eina_Bool res = EINA_FALSE; + E_Event_Zone_Rotation_Change_Begin *e = ev; if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON; if ((!e) || (!e->zone)) return ECORE_CALLBACK_PASS_ON; - res = _e_border_rotation_zone_check(e->zone); - ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: result:%d (%d)", res, e->zone->rot.curr); - if (res) + if (!_e_border_rotation_zone_set(e->zone)) { - e_manager_comp_screen_lock(e_manager_current_get()); - res = _e_border_rotation_zone_vkbd_check(e->zone); - ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: vkbd result:%d (%d)", res, e->zone->rot.curr); - if (res) - { - res = _e_border_rotation_transient_for_check(rot.vkbd, - e->zone->rot.curr); - ELBF(ELBT_ROT, 0, e->zone->id, "ZONE ROT CHECK: vkbd transient_for result:%d (%d)", res, e->zone->rot.curr); - } + /* there is no border which supports window manager rotation */ + e_zone_rotation_update_cancel(e->zone); + } + return ECORE_CALLBACK_PASS_ON; +} - if (res) - { - if (rot.prepare_timer) - ecore_timer_del(rot.prepare_timer); - rot.prepare_timer = NULL; +static void +_e_border_cb_rotation_sync_job(void *data) +{ + E_Zone *zone = data; + Eina_List *l; + E_Border_Rotation_Info *info = NULL; - if (rot.done_timer) - ecore_timer_del(rot.done_timer); - rot.done_timer = NULL; + ELB(ELBT_ROT, "DO ROTATION SYNC_JOB", zone->id); - ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win); - ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win, - e->zone->rot.curr, - EINA_FALSE, 1, 1); - rot.prepare_timer = ecore_timer_add(4.0f, - _e_border_rotation_change_prepare_timeout, - NULL); - rot.wait_prepare_done = EINA_TRUE; - } - else + if (rot.list) + { + EINA_LIST_FOREACH(rot.list, l, info) + _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd); + if (!rot.wait_prepare_done) { - _e_border_rotation_list_add(e->zone, EINA_TRUE); - _e_border_rotation_change_request(e->zone); + _e_border_rotation_change_request(zone); } } - else + + // clear job + if (rot.sync_job) { - /* there is no border which supports window manager rotation */ - e_zone_rotation_update_cancel(e->zone); + ELB(ELBT_ROT, "DEL SYNC_JOB", zone->id); + ecore_job_del(rot.sync_job); + rot.sync_job = NULL; + } +} + +static void +_e_border_cb_rotation_async_job(void *data) +{ + E_Zone *zone = data; + + if (rot.list) goto end; + + ELB(ELBT_ROT, "FLUSH ASYNC LIST TO ROT_CHANGE_REQ", zone->id); + + _e_border_rotation_list_flush(rot.async_list, EINA_TRUE); + rot.async_list = NULL; + +end: + // clear async job + if (rot.async_job) + { + ELB(ELBT_ROT, "DEL ASYNC_JOB", zone->id); + ecore_job_del(rot.async_job); + rot.async_job = NULL; } - return ECORE_CALLBACK_PASS_ON; } static Eina_Bool @@ -7718,56 +8006,101 @@ _e_border_rotation_change_prepare_timeout(void *data) ELB(ELBT_ROT, "TIMEOUT ROT_CHANGE_PREPARE", 0); - if ((rot.wait_prepare_done) && - (zone) && - (_e_border_rotation_list_add(zone, EINA_FALSE))) - { - _e_border_rotation_change_request(zone); - } - else + if ((zone) && (rot.wait_prepare_done)) { - if (rot.prepare_timer) - ecore_timer_del(rot.prepare_timer); - rot.prepare_timer = NULL; - rot.wait_prepare_done = EINA_FALSE; + if (rot.list) + { + _e_border_rotation_change_request(zone); + if (rot.prepare_timer) + ecore_timer_del(rot.prepare_timer); + rot.prepare_timer = NULL; + rot.wait_prepare_done = EINA_FALSE; + } } return ECORE_CALLBACK_CANCEL; } static void -_e_border_rotation_change_request(E_Zone *zone __UNUSED__) +_e_border_rotation_change_request(E_Zone *zone) { - Eina_List *l = NULL; - E_Border_Rotation_Info *info = NULL; - if (!e_config->wm_win_rotation) return; + if (!rot.list) return; + if (eina_list_count(rot.list) <= 0) return; + if (zone->rot.block_count) return; + if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer); rot.prepare_timer = NULL; rot.wait_prepare_done = EINA_FALSE; - EINA_LIST_FOREACH(rot.list, l, info) + _e_border_rotation_list_flush(rot.list, EINA_FALSE); + + if (rot.done_timer) + ecore_timer_del(rot.done_timer); + ELB(ELBT_ROT, "ADD TIMEOUT ROT_DONE", zone->id); + rot.done_timer = ecore_timer_add(5.0f, + _e_border_rotation_change_done_timeout, + NULL); +} + +static void +_e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush) +{ + Eina_List *l; + E_Border_Rotation_Info *info =NULL; + int x, y, w, h; + + EINA_LIST_FOREACH (list, l, info) { + if (!info->bd) continue; + if ((info->bd->client.e.state.rot.wait_for_done) && + (info->bd->client.e.state.rot.wait_done_ang == info->ang)) continue; + + _e_border_event_border_rotation_change_begin_send(info->bd); + + /* resize border */ + info->win_resize = _e_border_rotation_pre_resize(info->bd, info->ang, &x, &y, &w, &h); + info->bd->client.e.state.rot.pending_change_request = info->win_resize; + + info->x = x; info->y = y; + info->w = w; info->h = h; + ELBF(ELBT_ROT, 1, info->bd->client.win, "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d", info->ang, info->win_resize, info->w, info->h); ecore_x_e_window_rotation_change_prepare_send - (info->bd->client.win, info->ang, - info->win_resize, info->w, info->h); + (info->bd->client.win, info->ang, + info->win_resize, info->w, info->h); if (!info->bd->client.e.state.rot.pending_change_request) { ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST"); ecore_x_e_window_rotation_change_request_send(info->bd->client.win, info->ang); + info->bd->client.e.state.rot.wait_for_done = 1; + info->bd->client.e.state.rot.wait_done_ang = info->ang; } } - if (rot.done_timer) - ecore_timer_del(rot.done_timer); - rot.done_timer = ecore_timer_add(4.0f, - _e_border_rotation_change_done_timeout, - NULL); + if (flush) + { + EINA_LIST_FREE(list, info) + E_FREE(info); + } +} + +EAPI void +e_border_rotation_list_clear(E_Zone *zone, Eina_Bool send_request) +{ + E_Border_Rotation_Info *info = NULL; + + if (send_request) _e_border_rotation_change_request(zone); + else + { + EINA_LIST_FREE(rot.list, info) + E_FREE(info); + rot.list = NULL; + } } static void @@ -7775,7 +8108,10 @@ _e_border_rotation_list_remove(E_Border *bd) { Eina_List *l = NULL; E_Border_Rotation_Info *info = NULL; - if (!e_config->wm_win_rotation) return; + E_Event_Border_Rotation_Change_End *ev = NULL; + Eina_Bool found = EINA_FALSE; + + if (!e_config->wm_win_rotation) return; EINA_LIST_FOREACH(rot.list, l, info) { @@ -7783,13 +8119,33 @@ _e_border_rotation_list_remove(E_Border *bd) { rot.list = eina_list_remove(rot.list, info); E_FREE(info); + found = EINA_TRUE; } } if (bd->client.e.state.rot.wait_for_done) { bd->client.e.state.rot.wait_for_done = 0; - if (eina_list_count(rot.list) == 0) + + /* if we make the border event in the _e_border_free function, + * then we may meet a crash problem, only work this at least e_border_hide. + */ + if (!e_object_is_del(E_OBJECT(bd))) + { + ev = E_NEW(E_Event_Border_Rotation_Change_End, 1); + if (ev) + { + ev->border = bd; + e_object_ref(E_OBJECT(bd)); + ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_END, + ev, + _e_border_event_border_rotation_change_end_free, + NULL); + } + } + + if ((found) && + (eina_list_count(rot.list) == 0)) { _e_border_rotation_change_done(); } @@ -7813,27 +8169,34 @@ _e_border_rotation_change_done(void) if (!e_config->wm_win_rotation) return; - if (rot.prepare_timer) - ecore_timer_del(rot.prepare_timer); + if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer); rot.prepare_timer = NULL; rot.wait_prepare_done = EINA_FALSE; - if (rot.done_timer) - ecore_timer_del(rot.done_timer); + if (rot.done_timer) ecore_timer_del(rot.done_timer); rot.done_timer = NULL; EINA_LIST_FREE(rot.list, info) { if (info->bd) { - info->bd->client.e.state.rot.wait_for_done = 0; ELB(ELBT_ROT, "TIMEOUT ROT_DONE", info->bd->client.win); + if (info->bd->client.e.state.rot.pending_show) + { + ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win); + e_border_show(info->bd); + info->bd->client.e.state.rot.pending_show = 0; + } + info->bd->client.e.state.rot.wait_for_done = 0; } E_FREE(info); } + _e_border_rotation_list_flush(rot.async_list, EINA_TRUE); + rot.list = NULL; + rot.async_list = NULL; m = e_manager_current_get(); e_manager_comp_screen_unlock(m); @@ -7862,8 +8225,10 @@ _e_border_rotation_get(E_Border *bd, int base_ang) { int ang = -1; + int current_ang = bd->client.e.state.rot.curr; unsigned int i; Eina_Bool found = EINA_FALSE; + Eina_Bool found_curr_ang = EINA_FALSE; if (!e_config->wm_win_rotation) return ang; if (!bd->client.e.state.rot.app_set) return ang; @@ -7884,6 +8249,8 @@ _e_border_rotation_get(E_Border *bd, found = EINA_TRUE; break; } + if (bd->client.e.state.rot.available_rots[i] == current_ang) + found_curr_ang = EINA_TRUE; } /* do nothing. this window wants to maintain current state. @@ -7893,7 +8260,7 @@ _e_border_rotation_get(E_Border *bd, */ if (!found) { - if (bd->client.e.state.rot.curr != -1) + if ((bd->client.e.state.rot.curr != -1) && (found_curr_ang)) ang = bd->client.e.state.rot.curr; else ang = bd->client.e.state.rot.available_rots[0]; @@ -7911,30 +8278,23 @@ _e_border_rotation_get(E_Border *bd, return ang; } -#define REGION_EQUAL_TO_ZONE(a, z) \ - ((((a)->x) == ((z)->x)) && \ - (((a)->y) == ((z)->y)) && \ - (((a)->w) == ((z)->w)) && \ - (((a)->h) == ((z)->h))) - -static Eina_Bool -_e_border_rotation_check(E_Border *bd) +static int +_e_border_rotation_angle_get(E_Border *bd) { E_Zone *zone = bd->zone; - int x, y, w, h, ang = 0; - int diff = 0, _ang = 0; - Eina_Bool resize = EINA_TRUE; - Eina_Bool hint = EINA_FALSE; - Eina_Bool move = EINA_TRUE; + int will_ang = 0; + int _ang = 0; + int ret = -1; - if (!e_config->wm_win_rotation) return EINA_FALSE; + if (!e_config->wm_win_rotation) return ret; + if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) return ret; ELB(ELBT_ROT, "CHECK ROT", bd->client.win); - ang = zone->rot.curr; + if (bd->parent) will_ang = bd->parent->client.e.state.rot.curr; + else will_ang = zone->rot.curr; - if (((rot.vkbd) && (rot.vkbd == bd)) || - ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd))) + if (bd->client.vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE) { ELBF(ELBT_ROT, 1, bd->client.win, "%s->parent:0x%08x (support:%d app_set:%d ang:%d)", @@ -7946,11 +8306,11 @@ _e_border_rotation_check(E_Border *bd) if (bd->parent) { - ang = bd->parent->client.e.state.rot.curr; + will_ang = bd->parent->client.e.state.rot.curr; if ((!bd->parent->client.e.state.rot.support) && (!bd->parent->client.e.state.rot.app_set)) { - ang = 0; + will_ang = 0; } } } @@ -7963,16 +8323,9 @@ _e_border_rotation_check(E_Border *bd) (bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP)) { ELB(ELBT_BD, "MAG", bd->client.win); - ang = 0; + will_ang = 0; if ((rot.vkbd) && (rot.vkbd->visible)) - ang = rot.vkbd->client.e.state.rot.curr; - hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move); - if (hint) - { - ELBF(ELBT_ROT, 1, bd->client.win, "MAG %d,%d %dx%d m:%d", x, y, w, h, move); - _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move); - } - return EINA_FALSE; + will_ang = rot.vkbd->client.e.state.rot.curr; } } @@ -7984,7 +8337,7 @@ _e_border_rotation_check(E_Border *bd) if ((bd->parent) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY)) { - ang = bd->parent->client.e.state.rot.curr; + will_ang = bd->parent->client.e.state.rot.curr; if ((!bd->parent->client.e.state.rot.support) && (!bd->parent->client.e.state.rot.app_set)) { @@ -7992,38 +8345,29 @@ _e_border_rotation_check(E_Border *bd) * then this window should't be rotated. * TODO: need to check whether window supports '0' degree or not. */ - ang = 0; + will_ang = 0; ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d Transient_For:0x%08x Not support rot", - ang, bd->parent->client.win); + will_ang, bd->parent->client.win); } else { - ang = _e_border_rotation_get(bd->parent, ang); + will_ang = _e_border_rotation_get(bd->parent, will_ang); ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d Transient_For:0x%08x", - ang, bd->parent->client.win); + will_ang, bd->parent->client.win); } } else { - ang = _e_border_rotation_get(bd, ang); + will_ang = _e_border_rotation_get(bd, will_ang); ELBF(ELBT_ROT, 0, bd->client.win, "GET ROT ang:%d bd->parent:0x%08x type:%d", - ang, bd->parent ? bd->parent->client.win : 0, + will_ang, bd->parent ? bd->parent->client.win : 0, bd->client.netwm.type); } } - hint = _e_border_rotation_geom_get(bd, zone, ang, &x, &y, &w, &h, &move); - if (hint) - _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move); - - /* need to check previous rotation angle, this may be because - * the window was unmapped with non-0 rotation degree. - * and now, the window wants to show on the 0 degree zone, - * thus the wm should request to rotate the window to 0 degree. - */ - if (!bd->visible) + if (bd->new_client) { _ang = _prev_angle_get(bd->client.win); if (_ang != -1) @@ -8031,166 +8375,175 @@ _e_border_rotation_check(E_Border *bd) ELBF(ELBT_ROT, 1, bd->client.win, "prev_ang:%d", _ang); } - if (bd->client.e.state.rot.curr != ang) - { - Eina_Bool is_screen_locked = EINA_FALSE; - - if ((rot.vkbd != bd) && (rot.vkbd_prediction != bd) && - /* check whether virtual keyboard is visible on the zone */ - (_e_border_rotation_zone_vkbd_check(bd->zone)) && - /* check whether virtual keyboard belongs to this border (transient_for) */ - (_e_border_rotation_vkbd_transient_for_check(bd)) && - /* check rotation of the virtual keyboard */ - (((rot.vkbd) && (rot.vkbd->client.e.state.rot.curr != ang)) || - ((rot.vkbd_prediction) && (rot.vkbd_prediction->client.e.state.rot.curr != ang))) && - (!rot.wait_prepare_done)) - { - ELB(ELBT_ROT, "DO VKBD ROT", bd->client.win); - e_manager_comp_screen_lock(e_manager_current_get()); - is_screen_locked = EINA_TRUE; + if (bd->client.e.state.rot.curr != will_ang) + ret = will_ang; - if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer); - rot.prepare_timer = NULL; + return ret; +} - if (rot.done_timer) ecore_timer_del(rot.done_timer); - rot.done_timer = NULL; - ELB(ELBT_ROT, "send rot_change_prepare", rot.vkbd_ctrl_win); - ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win, - bd->zone->rot.curr, - EINA_FALSE, 1, 1); - rot.prepare_timer = ecore_timer_add(4.0f, - _e_border_rotation_change_prepare_timeout, - NULL); - rot.wait_prepare_done = EINA_TRUE; - } +static Eina_Bool +_e_border_rotation_zone_set(E_Zone *zone) +{ + E_Border_List *l = NULL; + E_Border *bd = NULL; + Eina_Bool ret = EINA_FALSE; - bd->client.e.state.rot.prev = bd->client.e.state.rot.curr; - bd->client.e.state.rot.curr = ang; - bd->client.e.state.rot.wait_for_done = 1; + if (!e_config->wm_win_rotation) return EINA_FALSE; - diff = bd->client.e.state.rot.curr - bd->client.e.state.rot.prev; - if ((diff == 180) || (diff == -180)) - resize = EINA_FALSE; + l = e_container_border_list_last(zone->container); + if (!l) return ret; - /* Check if it has size hint, full size or not, and needs to resize. - * Under the below condition, replace width value with height. - */ - if ((!hint) && (!REGION_EQUAL_TO_ZONE(bd, bd->zone)) && (resize)) - { - x = bd->x; y = bd->y; - w = bd->w; h = bd->h; + /* step 1. make the list needs to be rotated. */ + while ((bd = e_container_border_list_prev(l))) + { + if (!bd) continue; - if (w == h) - resize = EINA_FALSE; - else - { - w = bd->h; - h = bd->w; + // if this window have parent, + // it will be rotated when parent do rotate itself. + // so skip here. + if (bd->parent) continue; - _e_border_move_resize_internal(bd, x, y, w, h, - EINA_TRUE, EINA_FALSE); - } - } + // this type is set by illume. + // if it's not normal type window, will be rotated by illume. + // so skip here. + if (bd->client.e.state.rot.type != E_BORDER_ROTATION_TYPE_NORMAL) continue; - /* hack ... */ - if (bd->client.e.state.rot.app_set) resize = EINA_FALSE; + if ((!bd->visible) || + (!E_INTERSECTS(bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h, + bd->x, bd->y, bd->w, bd->h))) continue; - E_Border_Rotation_Info *info = NULL; - info = E_NEW(E_Border_Rotation_Info, 1); - if (info) + if (_e_border_rotatable_check(bd, zone->rot.curr)) { - if (!is_screen_locked) - e_manager_comp_screen_lock(e_manager_current_get()); + ELBF(ELBT_ROT, 0, bd->client.win, "ROT_SET(main) curr:%d != TOBE:%d", + bd->client.e.state.rot.curr, zone->rot.curr); - info->bd = bd; - info->ang = ang; - info->x = x; info->y = y; - info->w = w; info->h = h; - info->win_resize = resize; - rot.list = eina_list_append(rot.list, info); + ret = e_border_rotation_set(bd, zone->rot.curr); + } + } + if (l) e_container_border_list_free(l); - if (info->win_resize) - bd->client.e.state.rot.pending_change_request = 1; + return ret; +} + +EAPI Eina_Bool +e_border_rotation_set(E_Border *bd, int rotation) +{ + E_Zone *zone = bd->zone; + E_Border_Rotation_Info *info = NULL; + Eina_List *list, *l; + E_Border *child; - ELBF(ELBT_ROT, 1, info->bd->client.win, - "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d", - info->ang, info->win_resize, info->w, info->h); + if (rotation < 0) return EINA_FALSE; - ecore_x_e_window_rotation_change_prepare_send - (info->bd->client.win, info->ang, - info->win_resize, info->w, info->h); + /* step 1. check if rotation */ + if (!_e_border_rotatable_check(bd, rotation)) return EINA_FALSE; - if (!info->bd->client.e.state.rot.pending_change_request) - { - ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST"); - ecore_x_e_window_rotation_change_request_send(info->bd->client.win, - info->ang); - } + /* step 2. add to async/sync list */ + if ((!zone->rot.block_count) && + ((!bd->visible) || + (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h)))) + { + // send rotation change request later. + // and no need to wait message of rotation done. + + // async list add + info = E_NEW(E_Border_Rotation_Info, 1); + if (!info) return EINA_FALSE; + ELB(ELBT_ROT, "ADD ASYNC LIST", 0); + info->bd = bd; + info->ang = rotation; + rot.async_list = eina_list_append(rot.async_list, info); - if (rot.done_timer) - ecore_timer_del(rot.done_timer); - rot.done_timer = ecore_timer_add(4.0f, - _e_border_rotation_change_done_timeout, - NULL); + // add job for sending event. + if (!rot.async_job) + { + ELB(ELBT_ROT, "ADD ASYNC_JOB", bd->client.win); + rot.async_job = ecore_job_add(_e_border_cb_rotation_async_job, zone); } } - return EINA_TRUE; -} + else + { + // sync list add + info = E_NEW(E_Border_Rotation_Info, 1); + if (!info) return EINA_FALSE; + ELB(ELBT_ROT, "ADD SYNC LIST", 0); + info->bd = bd; + info->ang = rotation; + rot.list = eina_list_append(rot.list, info); -static Eina_Bool -_e_border_rotation_zone_check(E_Zone *zone) -{ - Eina_Bool wait = EINA_FALSE; - E_Border_List *l = NULL; - E_Border *bd = NULL; + // add job for sending event. + if (!rot.sync_job) + { + ELB(ELBT_ROT, "ADD SYNC_JOB", bd->client.win); + rot.sync_job = ecore_job_add(_e_border_cb_rotation_sync_job, zone); + } - if (!e_config->wm_win_rotation) return EINA_FALSE; + // if there is windows over 2 that has to be rotated or is existed window needs resizing, + // lock the screen. + // but, DO NOT lock the screen when rotation block state. + if ((!zone->rot.block_count) && + ((eina_list_count(rot.list) == 2))) + e_manager_comp_screen_lock(e_manager_current_get()); + } - l = e_container_border_list_last(zone->container); - if (!l) return EINA_FALSE; - while ((bd = e_container_border_list_prev(l))) + /* step 3. search rotatable window in this window's child */ + list = _e_border_sub_borders_new(bd); + EINA_LIST_FOREACH(list, l, child) { - if ((!bd) || (e_object_is_del(E_OBJECT(bd))) || - (!bd->visible) || (bd->zone != zone) || - (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h, - bd->x, bd->y, bd->w, bd->h))) continue; - - if (((rot.vkbd) && (rot.vkbd == bd)) || - ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)) || - ((REGION_EQUAL_TO_ZONE(bd, zone)) && - (bd->client.e.state.rot.preferred_rot != -1))) continue; - - if (_e_border_rotation_border_check(bd, zone->rot.curr)) + if (_e_border_rotatable_check(child, rotation)) { - wait = EINA_TRUE; - break; + ELBF(ELBT_ROT, 0, child->client.win, "ROT_SET(child) curr:%d != TOBE:%d", + bd->client.e.state.rot.curr, rotation); + e_border_rotation_set(child, rotation); } } - if (l) e_container_border_list_free(l); - return wait; + /* step 4. if there is vkbd window, send message to prepare rotation */ + if (_e_border_is_vkbd(bd)) + { + ELB(ELBT_ROT, "PENDING ROT_REQ UNTIL GET PREP_DONE", rot.vkbd_ctrl_win); + if (rot.prepare_timer) + ecore_timer_del(rot.prepare_timer); + rot.prepare_timer = NULL; + + if (rot.done_timer) + ecore_timer_del(rot.done_timer); + rot.done_timer = NULL; + + ELB(ELBT_ROT, "SEND ROT_CHANGE_PREPARE", rot.vkbd_ctrl_win); + ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win, + zone->rot.curr, + EINA_FALSE, 1, 1); + rot.prepare_timer = ecore_timer_add(4.0f, + _e_border_rotation_change_prepare_timeout, + NULL); + + rot.wait_prepare_done = EINA_TRUE; + } + + bd->client.e.state.rot.prev = bd->client.e.state.rot.curr; + bd->client.e.state.rot.curr = rotation; + + return EINA_TRUE; } // check if border is rotatable in ang. static Eina_Bool -_e_border_rotation_border_check(E_Border *bd, int ang) +_e_border_rotatable_check(E_Border *bd, int ang) { - Eina_Bool wait = EINA_FALSE; + Eina_Bool ret = EINA_FALSE; - if (!bd) return wait; + if (!bd) return ret; + if (ang < 0) return ret; + if ((!bd->client.e.state.rot.support) && (!bd->client.e.state.rot.app_set)) return ret; + if (e_object_is_del(E_OBJECT(bd))) return ret; - if (((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) && - /* basically WM allows only fullscreen window to rotate */ - ((REGION_EQUAL_TO_ZONE(bd, bd->zone)) || - /* we don't like this kind of code. - * it means that the WM also allows non-fullscreen window to rotate if it sets geom hint. - * such as large editable window. - */ - ((bd->client.vkbd.win_type == E_VIRTUAL_KEYBOARD_WINDOW_TYPE_NONE) && (bd->client.e.state.rot.geom_hint)) || - /* and floating mode window is also rotatable */ - (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_FLOATING)) && - (bd->client.e.state.rot.preferred_rot == -1)) + // same with current angle of window, then false return. + if (ang == bd->client.e.state.rot.curr) return ret; + + /* basically WM allows only fullscreen window to rotate */ + if (bd->client.e.state.rot.preferred_rot == -1) { unsigned int i; @@ -8207,40 +8560,36 @@ _e_border_rotation_border_check(E_Border *bd, int ang) found = EINA_TRUE; } } - if ((found) && (ang != bd->client.e.state.rot.curr)) - { - wait = EINA_TRUE; - } - else - { - ELB(ELBT_ROT, "ROT CANCEL for preferred rot", bd->client.win); - wait = EINA_FALSE; - } + if (found) ret = EINA_TRUE; } } else { ELB(ELBT_ROT, "DO ROT", 0); - wait = EINA_TRUE; + ret = EINA_TRUE; } } + // if it has preferred rotation angle, + // it will be rotated at border's evaluation time. + // so skip it. + else if (bd->client.e.state.rot.preferred_rot == ang) ret = EINA_TRUE; - return wait; + return ret; } /* check whether virtual keyboard is visible on the zone */ static Eina_Bool -_e_border_rotation_zone_vkbd_check(E_Zone *zone) +_e_border_is_vkbd(E_Border *bd) { if (!e_config->wm_win_rotation) return EINA_FALSE; if ((rot.vkbd_ctrl_win) && - (rot.vkbd) && + (rot.vkbd == bd) && (!e_object_is_del(E_OBJECT(rot.vkbd))) && (rot.vkbd->visible) && - (rot.vkbd->zone == zone) && - (E_INTERSECTS(zone->x, zone->y, - zone->w, zone->h, + (rot.vkbd->zone == bd->zone) && + (E_INTERSECTS(bd->zone->x, bd->zone->y, + bd->zone->w, bd->zone->h, rot.vkbd->x, rot.vkbd->y, rot.vkbd->w, rot.vkbd->h))) { @@ -8249,182 +8598,72 @@ _e_border_rotation_zone_vkbd_check(E_Zone *zone) return EINA_FALSE; } -/* check whether border is parent of the virtual keyboard */ +#define SIZE_EQUAL_TO_ZONE(a, z) \ + ((((a)->w) == ((z)->w)) && \ + (((a)->h) == ((z)->h))) static Eina_Bool -_e_border_rotation_vkbd_transient_for_check(E_Border *bd) +_e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w, int *h) { - if (!e_config->wm_win_rotation) return EINA_FALSE; - - if (rot.vkbd_ctrl_win) - { - if ((rot.vkbd) && (!e_object_is_del(E_OBJECT(rot.vkbd))) && - (rot.vkbd != bd)) - { - if (rot.vkbd->parent == bd) - return EINA_TRUE; - } - - if ((rot.vkbd_prediction) && (!e_object_is_del(E_OBJECT(rot.vkbd_prediction))) && - (rot.vkbd_prediction != bd)) - { - if (rot.vkbd_prediction == bd) - return EINA_TRUE; - } - } + E_Zone *zone = bd->zone; + int rot_dif; + int _x, _y, _w, _h; + Eina_Bool move = EINA_FALSE; + Eina_Bool hint = EINA_FALSE; + Eina_Bool resize = EINA_FALSE; - return EINA_FALSE; -} + if (x) *x = bd->x; + if (y) *y = bd->y; + if (w) *w = bd->w; + if (h) *h = bd->h; -// check if bd's parent is rotatable. -static Eina_Bool -_e_border_rotation_transient_for_check(E_Border *bd, int ang) -{ - Eina_Bool ret = EINA_FALSE; + if (SIZE_EQUAL_TO_ZONE(bd, zone)) return resize; - if (!e_config->wm_win_rotation) return EINA_FALSE; - if (!bd) return EINA_FALSE; + ELB(ELBT_ROT, "SIZE DIFF WITH ZONE", 0); + ELBF(ELBT_ROT, 0, bd->client.win, "ORIGIN_SIZE name:%s (%d,%d) %dx%d", + bd->client.icccm.name, bd->x, bd->y, bd->w, bd->h); - if (!bd->parent) ret = EINA_TRUE; - else + hint = _e_border_rotation_geom_get(bd, bd->zone, rotation, + &_x, &_y, &_w, &_h, &move); + if (hint) { - if (_e_border_rotation_border_check(bd->parent, ang)) - ret = EINA_TRUE; + _e_border_move_resize_internal(bd, _x, _y, _w, _h, EINA_TRUE, move); + resize = EINA_TRUE; + ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d", + bd->client.icccm.name, _x, _y, _w, _h); } - - return ret; -} - -static Eina_Bool -_e_border_rotation_list_add(E_Zone *zone, Eina_Bool without_vkbd) -{ - Eina_Bool wait = EINA_FALSE; - E_Border_List *l = NULL; - Eina_List *nl = NULL; - E_Border *bd = NULL; - E_Border_Rotation_Info *info = NULL; - - if (!e_config->wm_win_rotation) return EINA_FALSE; - - l = e_container_border_list_last(zone->container); - if (!l) return EINA_FALSE; - while ((bd = e_container_border_list_prev(l))) + else { - if ((!bd) || (e_object_is_del(E_OBJECT(bd)))) continue; - - if ((without_vkbd) && - (((rot.vkbd) && (rot.vkbd == bd)) || - ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)))) continue; + _x = bd->x; _y = bd->y; + _w = bd->w; _h = bd->h; - if ((bd->visible) && - ((bd->client.e.state.rot.support) || (bd->client.e.state.rot.app_set)) && - (bd->zone == zone) && - (E_INTERSECTS(zone->x, zone->y, zone->w, zone->h, - bd->x, bd->y, bd->w, bd->h))) + rot_dif = bd->client.e.state.rot.prev - rotation; + if (rot_dif < 0) rot_dif = -rot_dif; + if (rot_dif != 180) { - // check if this window is available to be rotate. - if ((bd->client.e.state.rot.app_set) && - (bd->client.e.state.rot.preferred_rot != -1)) continue; - - /* check list of available rotations */ - int ang = zone->rot.curr; - if (bd->client.e.state.rot.app_set) + if (w != h) { - ang = _e_border_rotation_get(bd, ang); - ELBF(ELBT_ROT, 0, bd->client.win, "returned ang:%d", ang); - } + _w = bd->h; + _h = bd->w; + resize = EINA_TRUE; - /* skip same angle */ - if (bd->client.e.state.rot.curr == ang) - { - ELBF(ELBT_ROT, 0, bd->client.win, "SKIP ang:%d", ang); - continue; - } - else - { - ELBF(ELBT_ROT, 0, bd->client.win, "ADD ROT_LIST curr:%d != ang:%d", - bd->client.e.state.rot.curr, ang); - } + _e_border_move_resize_internal(bd, _x, _y, _w, _h, + EINA_TRUE, EINA_TRUE); + ELBF(ELBT_ROT, 0, bd->client.win, "MANUAL_RESIZE name:%s (%d,%d) %dx%d", + bd->client.icccm.name, _x, _y, _w, _h); - bd->client.e.state.rot.prev = bd->client.e.state.rot.curr; - bd->client.e.state.rot.curr = ang; - bd->client.e.state.rot.wait_for_done = 1; - - info = E_NEW(E_Border_Rotation_Info, 1); - if (info) - { - info->bd = bd; - info->ang = ang; - info->x = bd->x; info->y = bd->y; - info->w = bd->w; info->h = bd->h; - info->win_resize = EINA_FALSE; - nl = eina_list_append(nl, info); - } - - if (REGION_EQUAL_TO_ZONE(bd, zone)) - { - wait = EINA_TRUE; // for the maximized window - } - else - { - int diff = bd->client.e.state.rot.curr - bd->client.e.state.rot.prev; - int x, y, w, h; - Eina_Bool resize = EINA_TRUE; - if ((diff == 180) || (diff == -180)) - resize = EINA_FALSE; - - Eina_Bool move = EINA_TRUE; - Eina_Bool hint = EINA_FALSE; - hint = _e_border_rotation_geom_get(bd, zone, zone->rot.curr, &x, &y, &w, &h, &move); - if (hint) - _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move); - else - { - x = bd->x; y = bd->y; - w = bd->w; h = bd->h; - if (resize) - { - if (w == h) - resize = EINA_FALSE; - else - { - // swap width and height and resize border - w = bd->h; - h = bd->w; - - _e_border_move_resize_internal(bd, x, y, w, h, - EINA_TRUE, EINA_TRUE); - } - } - } - - if (info) - { - info->x = x; info->y = y; - info->w = w; info->h = h; - info->win_resize = resize; - } - - if (resize) - bd->client.e.state.rot.pending_change_request = 1; - - wait = EINA_TRUE; } } } - if (l) e_container_border_list_free(l); - - if (nl) + if (resize) { - // clear previous list - EINA_LIST_FREE(rot.list, info) - { - E_FREE(info); - } - rot.list = nl; + if (x) *x = _x; + if (y) *y = _y; + if (w) *w = _w; + if (h) *h = _h; } - return wait; + return resize; } static Eina_Bool @@ -8433,6 +8672,10 @@ _e_border_cb_window_configure(void *data __UNUSED__, void *ev) { Ecore_X_Event_Window_Configure *e = ev; + E_Border_Rotation_Info *info = NULL; + Eina_List *l; + Eina_Bool found = EINA_FALSE; + if (!e) return ECORE_CALLBACK_PASS_ON; if (!e_config->wm_win_rotation) return ECORE_CALLBACK_PASS_ON; @@ -8443,17 +8686,35 @@ _e_border_cb_window_configure(void *data __UNUSED__, { if ((e->w == bd->w) && (e->h == bd->h)) { + ELB(ELBT_BD, "GET CONFIGURE_NOTI (ROTATION)", bd->client.win); + bd->client.e.state.rot.pending_change_request = 0; + + if ((bd->client.e.state.rot.wait_for_done) && + (bd->client.e.state.rot.wait_done_ang == bd->client.e.state.rot.curr)) goto end; + + // if this window is rotation dependent window and zone is blocked to rotate, + // then skip here, request will be sent after cancel block. + if ((bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_DEPENDENT) && + (bd->zone->rot.block_count)) goto end; + + EINA_LIST_FOREACH(rot.list, l, info) + if (info->bd == bd) found = EINA_TRUE; + // send request message if it's async rotation window, + // even if wait prepare done. + if ((found) && (rot.wait_prepare_done)) goto end; + ELBF(ELBT_ROT, 0, bd->client.win, "SEND ROT_CHANGE_REQUEST a%d %dx%d", bd->client.e.state.rot.curr, bd->w, bd->h); - - bd->client.e.state.rot.pending_change_request = 0; - ecore_x_e_window_rotation_change_request_send(bd->client.win, bd->client.e.state.rot.curr); + bd->client.e.state.rot.wait_for_done = 1; + bd->client.e.state.rot.wait_done_ang = bd->client.e.state.rot.curr; } } + +end: return ECORE_CALLBACK_PASS_ON; } @@ -8827,7 +9088,7 @@ _e_border_eval0(E_Border *bd) { const char **profiles = NULL; const char *str; - int num, i; + int num = 0, i; if (bd->client.e.state.profile) eina_stringshare_del(bd->client.e.state.profile); @@ -8865,7 +9126,11 @@ _e_border_eval0(E_Border *bd) } if (profiles) - free(profiles); + { + for (i = 0; i < num; i++) + if (profiles[i]) free(profiles[i]); + free(profiles); + } bd->client.e.fetch.profile_list = 0; } @@ -9195,6 +9460,9 @@ _e_border_eval0(E_Border *bd) { /* TODO: What do to if the transient for isn't mapped yet? */ E_Border *bd_parent = NULL; +#ifdef _F_DEICONIFY_APPROVE_ + Eina_Bool change_parent = EINA_FALSE; +#endif bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win); if (bd->client.icccm.transient_for) @@ -9216,6 +9484,9 @@ _e_border_eval0(E_Border *bd) { bd_parent->transients = eina_list_append(bd_parent->transients, bd); bd->parent = bd_parent; +#ifdef _F_DEICONIFY_APPROVE_ + change_parent = EINA_TRUE; +#endif } if (bd->parent) { @@ -9235,6 +9506,33 @@ _e_border_eval0(E_Border *bd) (bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED))) bd->take_focus = 1; } + +#ifdef _F_DEICONIFY_APPROVE_ + if (change_parent) + { + bd->client.e.state.deiconify_approve.render_done = 0; + + E_Border *ancestor_bd; + ancestor_bd = bd->client.e.state.deiconify_approve.ancestor; + if ((ancestor_bd) && + (!e_object_is_del(E_OBJECT(ancestor_bd)))) + { + ancestor_bd->client.e.state.deiconify_approve.req_list = eina_list_remove(ancestor_bd->client.e.state.deiconify_approve.req_list, bd); + bd->client.e.state.deiconify_approve.ancestor = NULL; + + if ((ancestor_bd->client.e.state.deiconify_approve.req_list == NULL) && + (ancestor_bd->client.e.state.deiconify_approve.render_done)) + { + if (ancestor_bd->client.e.state.deiconify_approve.wait_timer) + { + ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer); + ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL; + e_border_uniconify(ancestor_bd); + } + } + } + } +#endif bd->client.icccm.fetch.transient_for = 0; rem_change = 1; } @@ -9765,20 +10063,44 @@ _e_border_eval0(E_Border *bd) } } #endif -#ifdef _F_ZONE_WINDOW_ROTATION_ - if ((e_config->wm_win_rotation) && - (need_rotation_set)) - { - ELB(ELBT_ROT, "NEED ROT", bd->client.win); - _e_border_rotation_check(bd); - } -#endif /* PRE_POST_FETCH calls e_remember apply for new client */ _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd); _e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd); _e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd); +#ifdef _F_ZONE_WINDOW_ROTATION_ + if (e_config->wm_win_rotation) + { + if (need_rotation_set) + { + ELB(ELBT_ROT, "NEED ROT", bd->client.win); + bd->client.e.state.rot.changes = _e_border_rotation_angle_get(bd); + if (bd->client.e.state.rot.changes != -1) bd->changed = 1; + } + + if (bd->new_client) + { + Eina_Bool hint = EINA_FALSE; + int ang = 0; + int x, y, w, h, move; + + if (bd->client.e.state.rot.changes != -1) + ang = bd->client.e.state.rot.changes; + else ang = bd->client.e.state.rot.curr; + + hint = _e_border_rotation_geom_get(bd, bd->zone, ang, &x, &y, &w, &h, &move); + if (hint) + { + _e_border_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move); + ELBF(ELBT_ROT, 0, bd->client.win, "RESIZE_BY_HINT name:%s (%d,%d) %dx%d", + bd->client.icccm.name, x, y, w, h); + } + } + + } +#endif + if (bd->need_reparent) { if (!bd->internal) @@ -10952,6 +11274,12 @@ _e_border_eval(E_Border *bd) bd->changes.stack = 0; bd->changes.prop = 0; + if (bd->client.e.state.rot.changes != -1) + { + e_border_rotation_set(bd, bd->client.e.state.rot.changes); + bd->client.e.state.rot.changes = -1; + } + if ((bd->take_focus) || (bd->want_focus)) { bd->take_focus = 0; @@ -11528,15 +11856,50 @@ _e_border_event_border_unfullscreen_free(void *data __UNUSED__, #ifdef _F_ZONE_WINDOW_ROTATION_ static void -_e_border_event_border_rotation_free(void *data __UNUSED__, - void *ev) +_e_border_event_border_rotation_change_begin_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Border_Rotation_Change_Begin *e; + e = ev; + e_object_unref(E_OBJECT(e->border)); + E_FREE(e); +} + +static void +_e_border_event_border_rotation_change_cancel_free(void *data __UNUSED__, + void *ev) { - E_Event_Border_Rotation *e; + E_Event_Border_Rotation_Change_Cancel *e; + e = ev; + e_object_unref(E_OBJECT(e->border)); + E_FREE(e); +} +static void +_e_border_event_border_rotation_change_end_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Border_Rotation_Change_End *e; e = ev; e_object_unref(E_OBJECT(e->border)); E_FREE(e); } + +static void +_e_border_event_border_rotation_change_begin_send(E_Border *bd) +{ + E_Event_Border_Rotation_Change_Begin *ev = NULL; + ev = E_NEW(E_Event_Border_Rotation_Change_End, 1); + if (ev) + { + ev->border = bd; + e_object_ref(E_OBJECT(bd)); + ecore_event_add(E_EVENT_BORDER_ROTATION_CHANGE_BEGIN, + ev, + _e_border_event_border_rotation_change_begin_free, + NULL); + } +} #endif static void