Merge from TIZEN 2.3
[platform/core/uifw/e17.git] / src / bin / e_border.c
index 2532fb9..23ac2d2 100644 (file)
 //#define INOUTDEBUG_MOUSE 1
 //#define INOUTDEBUG_FOCUS 1
 
+# ifdef _F_USE_DLOG_
+#  include "dlog.h"
+#  undef LOG_TAG
+#  define LOG_TAG "E17"
+# endif
+
 /* These are compatible with netwm */
 #define RESIZE_TL   0
 #define RESIZE_T    1
@@ -289,6 +295,16 @@ static void _e_border_focus_top_stack_set (E_Border* bd);
 #if _F_BORDER_CLIP_TO_ZONE_
 static void      _e_border_shape_input_clip_to_zone(E_Border *bd);
 #endif /* _F_BORDER_CLIP_TO_ZONE_ */
+
+#ifdef _F_DEICONIFY_APPROVE_
+static void _e_border_msg_handler(void       *data,
+                                  const char *name,
+                                  const char *info,
+                                  int         val,
+                                  E_Object   *obj,
+                                  void       *msgdata);
+#endif
+
 /* local subsystem globals */
 static Eina_List *handlers = NULL;
 static Eina_List *borders = NULL;
@@ -320,6 +336,10 @@ static int warp_y = 0;
 static Ecore_X_Window warp_to_win;
 static Ecore_Timer *warp_timer = NULL;
 
+#ifdef _F_DEICONIFY_APPROVE_
+static E_Msg_Handler *_msg_handler = NULL;
+#endif
+
 #ifdef _F_ZONE_WINDOW_ROTATION_
 typedef struct _E_Border_Rotation      E_Border_Rotation;
 typedef struct _E_Border_Rotation_Info E_Border_Rotation_Info;
@@ -488,6 +508,10 @@ e_border_init(void)
    handlers = eina_list_append(handlers, ecore_event_handler_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _e_border_cb_zone_rotation_change_begin, NULL));
 #endif
 
+#ifdef _F_DEICONIFY_APPROVE_
+   _msg_handler = e_msg_handler_add(_e_border_msg_handler, NULL);
+#endif
+
    if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL);
 
    E_EVENT_BORDER_ADD = ecore_event_type_new();
@@ -858,6 +882,10 @@ e_border_new(E_Container   *con,
    bd->client.w = att->w;
    bd->client.h = att->h;
 
+#ifdef _F_FIX_POSITION_PROBLEM_
+   bd->x = att->x;
+   bd->y = att->y;
+#endif
    bd->w = bd->client.w;
    bd->h = bd->client.h;
 
@@ -1389,11 +1417,11 @@ e_border_show(E_Border *bd)
 #ifdef _F_ZONE_WINDOW_ROTATION_
    // 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.
-#if 0
    if ((bd->new_client) &&
        (bd->client.e.state.rot.changes != -1))
      {
-        // if this window is in withdrawn state, show this window right now.
+        ELB(ELBT_BD, "PENDING SHOW UNTIL GETTING ROT_DONE", bd->client.win);
+        // if this window is in withdrawn state, set the normal state
         // that's because the window in withdrawn state can't render its canvas.
         // eventually, this window will not send the message of rotation done,
         // even if e17 request to rotation this window.
@@ -1403,7 +1431,6 @@ e_border_show(E_Border *bd)
         bd->client.e.state.rot.pending_show = 1;
         return;
      }
-#endif
    if ((e_config->wm_win_rotation) &&
        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
        (bd == rot.vkbd) &&
@@ -3765,6 +3792,7 @@ static void
 _e_border_deiconify_approve_send_pending_end(void *data)
 {
    E_Border *bd = (E_Border *)data;
+   E_Border *bd_ancestor;
 
    if (e_config->deiconify_approve)
      {
@@ -3780,8 +3808,14 @@ _e_border_deiconify_approve_send_pending_end(void *data)
                                            ECORE_X_ATOM_E_DEICONIFY_APPROVE,
                                            ECORE_X_EVENT_MASK_WINDOW_CONFIGURE,
                                            bd->client.win, 0, 0, 0, 0);
+             bd_ancestor = bd->client.e.state.deiconify_approve.ancestor;
+             if (bd_ancestor)
+               {
+                  bd_ancestor->client.e.state.deiconify_approve.req_list = eina_list_append(bd_ancestor->client.e.state.deiconify_approve.req_list, bd);
+               }
 
-             bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
+             if (!bd->client.e.state.deiconify_approve.wait_timer)
+               bd->client.e.state.deiconify_approve.wait_timer = ecore_timer_add(e_config->deiconify_timeout, _e_border_uniconify_timeout, bd);
           }
      }
 }
@@ -3818,7 +3852,7 @@ _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor, Eina_Bool
                   _e_border_deiconify_approve_send(child, bd_ancestor, p);
                   if (child->client.e.state.deiconify_approve.support)
                     {
-                       if (p)
+                       if (!p)
                          {
                             ELBF(ELBT_BD, 0, child->client.win,
                                  "SEND DEICONIFY_APPROVE. ancestor:%x pending(%d,%d)",
@@ -3838,6 +3872,7 @@ _e_border_deiconify_approve_send(E_Border *bd, E_Border *bd_ancestor, Eina_Bool
                             ELBF(ELBT_BD, 0, child->client.win,
                                  "SEND DEICONIFY_APPROVE. (PENDING) ancestor:%x",
                                  bd_ancestor->client.win);
+                            child->client.e.state.deiconify_approve.ancestor = bd_ancestor;
                             child->client.e.state.deiconify_approve.pending_job = ecore_job_add(_e_border_deiconify_approve_send_pending_end, child);
                          }
                     }
@@ -3912,6 +3947,13 @@ e_border_uniconify(E_Border *bd)
                   ELB(ELBT_BD, "DEICONIFY_APPROVE WAIT_TIMER is already running", bd->client.win);
                   return;
                }
+
+             if (bd->client.e.state.deiconify_approve.pending_job)
+               {
+                  ELB(ELBT_BD, "DEICONIFY_APPROVE PENDING_JOB is already running", bd->client.win);
+                  return;
+               }
+
              if (bd->client.e.state.deiconify_approve.render_done == 0)
                {
                   ELB(ELBT_BD, "DEICONIFY_APPROVE to all transient", bd->client.win);
@@ -4388,14 +4430,16 @@ e_border_idler_before(void)
                        if ((zone) && (rot.wait_prepare_done))
                          {
                             if (rot.list)
+                              _e_border_rotation_change_request(zone);
+                            else if (rot.async_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;
-
+                                 _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
+                                 rot.async_list = NULL;
                               }
+                            if (rot.prepare_timer)
+                              ecore_timer_del(rot.prepare_timer);
+                            rot.prepare_timer = NULL;
+                            rot.wait_prepare_done = EINA_FALSE;
                          }
                     }
                }
@@ -5896,6 +5940,12 @@ _e_border_del(E_Border *bd)
         bd->client.e.state.deiconify_approve.wait_timer = NULL;
      }
 
+   if (bd->client.e.state.deiconify_approve.pending_job)
+     {
+        ecore_job_del(bd->client.e.state.deiconify_approve.pending_job);
+        bd->client.e.state.deiconify_approve.pending_job = NULL;
+     }
+
    if (bd->client.e.state.deiconify_approve.req_list)
      {
         EINA_LIST_FREE(bd->client.e.state.deiconify_approve.req_list, child)
@@ -5966,6 +6016,7 @@ _e_border_cb_window_show_request(void *data  __UNUSED__,
    bd = e_border_find_by_client_window(e->win);
    if (!bd) return ECORE_CALLBACK_PASS_ON;
 
+#ifdef _F_ZONE_WINDOW_ROTATION_
    if ((e_config->wm_win_rotation) &&
        (rot.vkbd_ctrl_win) && (rot.vkbd) &&
        (bd == rot.vkbd) &&
@@ -5974,6 +6025,7 @@ _e_border_cb_window_show_request(void *data  __UNUSED__,
         con = bd->zone->container;
         bd = e_border_new(con, e->win, 0, 0);
      }
+#endif
 
    if (bd->iconic)
      {
@@ -6022,11 +6074,93 @@ _e_border_cb_window_destroy(void *data  __UNUSED__,
           }
      }
 #endif
+
+#ifdef _F_DEICONIFY_APPROVE_
+   if (e_config->deiconify_approve)
+     {
+        if (bd->client.e.state.pending_event.pending)
+          {
+             bd->client.e.state.pending_event.destroy.pending = 1;
+             bd->client.e.state.pending_event.destroy.win = e->win;
+             bd->client.e.state.pending_event.destroy.event_win = e->event_win;
+             ELB(ELBT_BD, "PENDING destroy event", bd->client.win);
+             return ECORE_CALLBACK_CANCEL;
+          }
+     }
+
+   ELB(ELBT_BD, "Real Destroy", bd->client.win);
+#endif
+
    e_border_hide(bd, 0);
    e_object_del(E_OBJECT(bd));
    return ECORE_CALLBACK_PASS_ON;
 }
 
+#ifdef _F_DEICONIFY_APPROVE_
+static E_Border *
+_e_border_find_below_win(E_Border* bd)
+{
+   Eina_List *l;
+   int i, pos;
+   Eina_Bool passed;
+   E_Border *temp_bd;
+   E_Border *below_bd;
+
+   passed = EINA_FALSE;
+   below_bd = NULL;
+
+   E_Border_List *bl;
+   bl = e_container_border_list_last(bd->zone->container);
+   while ((temp_bd = e_container_border_list_prev(bl)))
+     {
+        /* skip if it's the same border */
+        if (temp_bd == bd)
+          {
+             passed = EINA_TRUE;
+             continue;
+          }
+
+        if (e_object_is_del(E_OBJECT(temp_bd))) continue;
+
+        /* skip if it's not on this zone */
+        if (temp_bd->zone != bd->zone) continue;
+
+        if (E_CONTAINS(temp_bd->x, temp_bd->y, temp_bd->w, temp_bd->h, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
+          {
+             if (!temp_bd->client.argb && temp_bd->visible)
+               {
+                  below_bd = NULL;
+                  break;
+               }
+          }
+
+        if (!passed) continue;
+
+        if ((!temp_bd->client.argb) &&
+            (temp_bd->x == temp_bd->zone->x) &&
+            (temp_bd->y == temp_bd->zone->y) &&
+            (temp_bd->w == temp_bd->zone->w) &&
+            (temp_bd->h == temp_bd->zone->h))
+          {
+             if (temp_bd->visible)
+               {
+                  below_bd = NULL;
+                  break;
+               }
+
+             if (ecore_x_window_visible_get(temp_bd->client.win))
+               {
+                  below_bd = temp_bd;
+                  break;
+               }
+          }
+     }
+   e_container_border_list_free(bl);
+
+   return below_bd;
+}
+#endif
+
 static Eina_Bool
 _e_border_cb_window_hide(void *data  __UNUSED__,
                          int ev_type __UNUSED__,
@@ -6062,6 +6196,52 @@ _e_border_cb_window_hide(void *data  __UNUSED__,
         return ECORE_CALLBACK_PASS_ON;
      }
 
+#ifdef _F_DEICONIFY_APPROVE_
+   if (e_config->deiconify_approve)
+     {
+        if (bd->client.e.state.pending_event.done)
+           goto do_hide;
+
+        if (bd->client.e.state.pending_event.pending)
+          {
+             return ECORE_CALLBACK_CANCEL;
+          }
+
+        if (!E_CONTAINS(bd->x, bd->y, bd->w, bd->h, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
+           goto do_hide;
+
+        E_Border *below_bd;
+        // 1. find below non-alpha full size win
+        below_bd = _e_border_find_below_win(bd);
+
+        if (below_bd)
+          {
+             // 2. check those rotation
+             bd->client.e.state.pending_event.pending = 1;
+             bd->client.e.state.pending_event.hold_bd = below_bd;
+
+             bd->client.e.state.pending_event.hide.pending = 1;
+             bd->client.e.state.pending_event.hide.win = e->win;
+             bd->client.e.state.pending_event.hide.event_win = e->event_win;
+             bd->client.e.state.pending_event.hide.send_event = e->send_event;
+
+             below_bd->client.e.state.deiconify_approve.pending_bd = bd;
+             ELBF(ELBT_ROT, 0, bd->client.win, "below_win:%x, below_win's wait_bd:%x", below_bd->client.win, below_bd->client.e.state.deiconify_approve.pending_bd->client.win);
+
+             // 3. if not same then uniconify
+             e_border_uniconify(below_bd);
+
+             ELB(ELBT_BD, "PENDING hide event", bd->client.win);
+             return ECORE_CALLBACK_CANCEL;
+          }
+     }
+
+do_hide:
+   bd->client.e.state.pending_event.done = 0;
+   bd->client.e.state.pending_event.pending = 0;
+   ELB(ELBT_BD, "Real hide", bd->client.win);
+#endif
+
 //   printf("  bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
    if (bd->ignore_first_unmap > 0)
      {
@@ -7064,6 +7244,13 @@ _e_border_cb_client_message(void *data  __UNUSED__,
                          {
                             ecore_timer_del(ancestor_bd->client.e.state.deiconify_approve.wait_timer);
                             ancestor_bd->client.e.state.deiconify_approve.wait_timer = NULL;
+
+                            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;
+                              }
+
                             e_border_uniconify(ancestor_bd);
                          }
                        else
@@ -7072,6 +7259,15 @@ _e_border_cb_client_message(void *data  __UNUSED__,
                             ancestor_bd->client.e.state.deiconify_approve.render_done = 0;
                          }
                     }
+
+                  if (bd != 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;
+                         }
+                    }
                }
           }
         return ECORE_CALLBACK_PASS_ON;
@@ -7121,14 +7317,16 @@ _e_border_cb_client_message(void *data  __UNUSED__,
              if ((int)e->data.l[1] == bd->client.e.state.rot.curr)
                {
                   _e_border_rotation_list_remove(bd);
-#if 0
                   if (bd->client.e.state.rot.pending_show)
                     {
                        ELB(ELBT_BD, "SHOW_BD (PEND)", bd->client.win);
                        e_border_show(bd);
+#ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
+                       if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
+                         _e_border_check_stack(bd);
+#endif
                        bd->client.e.state.rot.pending_show = 0;
                     }
-#endif
                }
           }
      }
@@ -8031,12 +8229,16 @@ _e_border_cb_rotation_sync_job(void *data)
    Eina_List *l;
    E_Border_Rotation_Info *info = NULL;
 
-   ELB(ELBT_ROT, "DO ROTATION SYNC_JOB", zone->id);
-
+   ELBF(ELBT_ROT, 0, zone->id, "DO ROTATION SYNC_JOB rot.list:%p(%d) wait_prepare_done:%d zone_block_count:%d",
+        rot.list, eina_list_count(rot.list), rot.wait_prepare_done, zone->rot.block_count);
    if (rot.list)
      {
         EINA_LIST_FOREACH(rot.list, l, info)
            _e_border_hook_call(E_BORDER_HOOK_ROTATION_LIST_ADD, info->bd);
+
+        ELBF(ELBT_ROT, 0, zone->id, "SYNC_JOB list(%d) wait_prepare_done:%d zone_block_count:%d",
+             eina_list_count(rot.list), rot.wait_prepare_done, zone->rot.block_count);
+
         if (!rot.wait_prepare_done)
           {
              _e_border_rotation_change_request(zone);
@@ -8061,8 +8263,11 @@ _e_border_cb_rotation_async_job(void *data)
 
    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;
+   if (!rot.wait_prepare_done)
+     {
+        _e_border_rotation_list_flush(rot.async_list, EINA_TRUE);
+        rot.async_list = NULL;
+     }
 
 end:
    // clear async job
@@ -8102,7 +8307,8 @@ _e_border_rotation_change_request(E_Zone *zone)
    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;
+   /* pending rotation problem occurred while launching app by the tray */
+   //if (zone->rot.block_count) return;
 
    if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer);
    rot.prepare_timer = NULL;
@@ -8144,6 +8350,12 @@ _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
              "SEND ROT_CHANGE_PREPARE a%d res%d %dx%d",
              info->ang, info->win_resize, info->w, info->h);
 
+#ifdef _F_USE_DLOG_
+             SECURE_SLOGD("[ROTATION] SEND PREP_ROT, win:0x%08x a%d resize%d %dx%d",
+                          info->bd->client.win, info->ang, info->win_resize,
+                          info->w, info->h);
+#endif
+
         ecore_x_e_window_rotation_change_prepare_send
            (info->bd->client.win, info->ang,
             info->win_resize, info->w, info->h);
@@ -8151,6 +8363,10 @@ _e_border_rotation_list_flush(Eina_List *list, Eina_Bool flush)
         if (!info->bd->client.e.state.rot.pending_change_request)
           {
              ELBF(ELBT_ROT, 1, 0, "SEND ROT_CHANGE_REQUEST");
+#ifdef _F_USE_DLOG_
+             SECURE_SLOGD("[ROTATION] SEND REQ_ROT, win:0x%08x, rot:%d",
+                          info->bd->client.win, info->ang);
+#endif
              ecore_x_e_window_rotation_change_request_send(info->bd->client.win,
                                                            info->ang);
              info->bd->client.e.state.rot.wait_for_done = 1;
@@ -8262,6 +8478,10 @@ _e_border_rotation_change_done(void)
                {
                   ELB(ELBT_ROT, "SHOW PEND(TIMEOUT)", info->bd->client.win);
                   e_border_show(info->bd);
+#ifdef _F_FOCUS_WINDOW_IF_TOP_STACK_
+                  if (e_config->focus_setting == E_FOCUS_NEW_WINDOW_IF_TOP_STACK)
+                    _e_border_check_stack(info->bd);
+#endif
                   info->bd->client.e.state.rot.pending_show = 0;
                }
              info->bd->client.e.state.rot.wait_for_done = 0;
@@ -8370,6 +8590,7 @@ _e_border_rotation_angle_get(E_Border *bd)
    // the window with "ECORE_X_WINDOW_TYPE_NORMAL" type
    // should follow the state of rotation of zone.
    if ((bd->parent) &&
+       (bd->parent->visible) &&
        (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_NORMAL))
      will_ang = bd->parent->client.e.state.rot.curr;
    else will_ang = zone->rot.curr;
@@ -8415,6 +8636,7 @@ _e_border_rotation_angle_get(E_Border *bd)
          * rotation of the transient_for window.
          */
         if ((bd->parent) &&
+            (bd->parent->visible) &&
             (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UTILITY))
           {
              will_ang = bd->parent->client.e.state.rot.curr;
@@ -8524,6 +8746,7 @@ _e_border_rotation_set_internal(E_Border *bd, int rotation, Eina_Bool *pending)
 
    /* step 2. add to async/sync list */
    if ((!zone->rot.block_count) &&
+       (!bd->client.e.state.deiconify_approve.pending_bd) &&
        ((!bd->visible) ||
         (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))))
      {
@@ -8674,7 +8897,6 @@ _e_border_is_vkbd(E_Border *bd)
    if ((rot.vkbd_ctrl_win) &&
        (rot.vkbd == bd) &&
        (!e_object_is_del(E_OBJECT(rot.vkbd))) &&
-       (rot.vkbd->visible) &&
        (rot.vkbd->zone == bd->zone) &&
        (E_INTERSECTS(bd->zone->x, bd->zone->y,
                      bd->zone->w, bd->zone->h,
@@ -8859,10 +9081,14 @@ _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w
                                       &_x, &_y, &_w, &_h, &move);
    if (hint)
      {
-        _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);
+        if (((move) && ((bd->x !=_x) || (bd->y !=_y))) ||
+            (bd->w != _w) || (bd->h != _h))
+          {
+             resize = EINA_TRUE;
+             _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 resize:%d",
+                  bd->client.icccm.name, _x, _y, _w, _h, resize);
+          }
      }
    else
      {
@@ -8878,7 +9104,7 @@ _e_border_rotation_pre_resize(E_Border *bd, int rotation, int *x, int *y, int *w
         if (rot_dif < 0) rot_dif = -rot_dif;
         if (rot_dif != 180)
           {
-             if (w != h)
+             if (_w != _h)
                {
                   _w = bd->h;
                   _h = bd->w;
@@ -8933,11 +9159,6 @@ _e_border_cb_window_configure(void *data    __UNUSED__,
              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,
@@ -8948,6 +9169,10 @@ _e_border_cb_window_configure(void *data    __UNUSED__,
                   "SEND ROT_CHANGE_REQUEST a%d %dx%d",
                   bd->client.e.state.rot.curr,
                   bd->w, bd->h);
+#ifdef _F_USE_DLOG_
+             SECURE_SLOGD("[ROTATION] SEND REQ_ROT(CONFIGURE_NOTI), win:0x%08x, rot:%d",
+                          bd->client.win, bd->client.e.state.rot.curr);
+#endif
              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;
@@ -9948,6 +10173,20 @@ _e_border_eval0(E_Border *bd)
         bd->client.illume.win_state.state =
            ecore_x_e_illume_window_state_get(bd->client.win);
         bd->client.illume.win_state.fetch.state = 0;
+#ifdef _F_ZONE_WINDOW_ROTATION_
+        /* E should rotate the window if the property "win_state" of window is
+         * changed to "ECORE_X_ILLUME_WINDOW_STATE_NORMAL".
+         * FIXME: To move below code into illume seems to better.
+         */
+        if (e_config->wm_win_rotation)
+          {
+             if (bd->client.illume.win_state.state == ECORE_X_ILLUME_WINDOW_STATE_NORMAL)
+               {
+                  bd->client.e.state.rot.type = E_BORDER_ROTATION_TYPE_NORMAL;
+                  need_rotation_set = EINA_TRUE;
+               }
+          }
+#endif
      }
    if (bd->changes.shape)
      {
@@ -10313,7 +10552,8 @@ _e_border_eval0(E_Border *bd)
 #ifdef _F_ZONE_WINDOW_ROTATION_
    if (e_config->wm_win_rotation)
      {
-        if (need_rotation_set)
+        if ((need_rotation_set) &&
+            (bd->client.e.state.rot.type == E_BORDER_ROTATION_TYPE_NORMAL))
           {
              Eina_Bool hint = EINA_FALSE;
              int ang = 0;
@@ -10322,20 +10562,19 @@ _e_border_eval0(E_Border *bd)
              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)
+             if (bd->client.e.state.rot.changes == -1)
                {
-                  ang = bd->client.e.state.rot.changes;
-                  bd->changed = 1;
-               }
-             else ang = bd->client.e.state.rot.curr;
+                  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);
+                  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);
+                    }
                }
+             else bd->changed = 1;
           }
      }
 #endif
@@ -11513,11 +11752,13 @@ _e_border_eval(E_Border *bd)
    bd->changes.stack = 0;
    bd->changes.prop = 0;
 
+#ifdef _F_ZONE_WINDOW_ROTATION_
    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;
      }
+#endif
 
    if ((bd->take_focus) || (bd->want_focus))
      {
@@ -12789,4 +13030,135 @@ e_border_activate(E_Border *bd, Eina_Bool just_do_it)
           }
      }
 }
+
+#ifdef _F_DEICONIFY_APPROVE_
+static void
+_e_border_window_pending_destroy_event_free(void *data __UNUSED__,
+                                            void *ev)
+{
+   Ecore_X_Event_Window_Destroy *e;
+
+   e = ev;
+   E_FREE(e);
+}
+
+static void
+_e_border_window_pending_hide_event_free(void *data __UNUSED__,
+                                         void *ev)
+{
+   Ecore_X_Event_Window_Hide *e;
+
+   e = ev;
+   E_FREE(e);
+}
+
+static void
+_e_border_window_pending_hide_event_send(E_Border *bd)
+{
+   Ecore_X_Event_Window_Hide *e;
+
+   if (!bd) return;
+
+   e = E_NEW(Ecore_X_Event_Window_Hide, 1);
+   if (e)
+     {
+        e->win = bd->client.e.state.pending_event.hide.win;
+        e->event_win = bd->client.e.state.pending_event.hide.event_win;
+        e->time = ecore_x_current_time_get();
+        e->send_event = bd->client.e.state.pending_event.hide.send_event;
+
+        ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e,
+                        _e_border_window_pending_hide_event_free, NULL);
+
+        ELB(ELBT_BD, "Send pended HIDE event", e->win);
+     }
+}
+
+static void
+_e_border_window_pending_destroy_event_send(E_Border *bd)
+{
+   Ecore_X_Event_Window_Destroy *e;
+
+   if (!bd) return;
+
+   e = E_NEW(Ecore_X_Event_Window_Destroy, 1);
+   if (e)
+     {
+        e->win = bd->client.e.state.pending_event.destroy.win;
+        e->event_win = bd->client.e.state.pending_event.destroy.event_win;
+        e->time = ecore_x_current_time_get();
+
+        ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e,
+                        _e_border_window_pending_destroy_event_free, NULL);
+
+        ELB(ELBT_BD, "Send pended DESTROY event", e->win);
+     }
+}
+
+static void
+_e_border_msg_handler(void       *data,
+                      const char *name,
+                      const char *info,
+                      int         val,
+                      E_Object   *obj,
+                      void       *msgdata)
+{
+   E_Manager *man = (E_Manager *)obj;
+   E_Manager_Comp_Source *src = (E_Manager_Comp_Source *)msgdata;
+
+   // handle only comp.manager msg
+   if (strncmp(name, "comp.manager", sizeof("comp.manager"))) return;
+
+   if (!strncmp(info, "visibility.src", sizeof("visibility.src")))
+     {
+        Ecore_X_Window win;
+        E_Border *bd;
+        Eina_Bool visible;
+
+        win = e_manager_comp_src_window_get(man, src);
+        bd = e_border_find_by_window(win);
+
+        if (!bd) return;
+        if (!bd->client.e.state.deiconify_approve.pending_bd) return;
+
+        visible = e_manager_comp_src_visible_get(man, src);
+        if (visible)
+          {
+             E_Border *pending_bd = bd->client.e.state.deiconify_approve.pending_bd;
+             if (!pending_bd->client.e.state.pending_event.pending)
+               {
+                  bd->client.e.state.deiconify_approve.pending_bd = NULL;
+                  return;
+               }
+
+             pending_bd->client.e.state.pending_event.done = 1;
+             pending_bd->client.e.state.pending_event.hold_bd = NULL;
+
+             if (pending_bd->client.e.state.pending_event.hide.pending)
+               {
+                  _e_border_window_pending_hide_event_send(pending_bd);
+
+                  // clear hide event data
+                  pending_bd->client.e.state.pending_event.hide.pending = 0;
+                  pending_bd->client.e.state.pending_event.hide.win = 0;
+                  pending_bd->client.e.state.pending_event.hide.event_win = 0;
+                  pending_bd->client.e.state.pending_event.hide.send_event = 0;
+               }
+
+             if (pending_bd->client.e.state.pending_event.destroy.pending)
+               {
+                  _e_border_window_pending_destroy_event_send(pending_bd);
+
+                  // clear destroy event data
+                  pending_bd->client.e.state.pending_event.destroy.pending = 0;
+                  pending_bd->client.e.state.pending_event.destroy.win = 0;
+                  pending_bd->client.e.state.pending_event.destroy.event_win = 0;
+               }
+
+             bd->client.e.state.deiconify_approve.pending_bd = NULL;
+             ELBF(ELBT_ROT, 0, bd->client.win, "RESET pending_bd:%x", bd->client.e.state.deiconify_approve.pending_bd);
+          }
+     }
+}
+#endif
 /*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/