e_policy_visibility: fix pre-visibility bug 59/165459/2
authorDoyoun Kang <doyoun.kang@samsung.com>
Fri, 29 Dec 2017 02:31:17 +0000 (11:31 +0900)
committerDoyoun Kang <doyoun.kang@samsung.com>
Tue, 2 Jan 2018 05:31:29 +0000 (05:31 +0000)
we add code checking above window of the window when it is under uniconifying.
so, if it is obscured by above window, then we don't send the pre-visibility event.

Change-Id: Id29876f0a87b14a7b784e0c685a18ed9d607c892

src/bin/e_policy_visibility.c

index 5ae4c784fa8bca7716a76bea573ed2bcfb3dfe17..19610dc2c01767207c1c7ba7ab65fb2057f63a7a 100644 (file)
@@ -1033,10 +1033,6 @@ _e_vis_client_is_uniconify_render_necessary(E_Vis_Client *vc)
           goto need_deiconify_render;
 
         VS_INF(ec, "Not necessary deiconify rendering");
-
-        ELOGF("POL", "SEND pre-unobscured visibility event", ec->pixmap, ec);
-        e_vis_client_send_pre_visibility_event(ec);
-
         return EINA_FALSE;
      }
 
@@ -1050,6 +1046,161 @@ need_deiconify_render:
    return EINA_TRUE;
 }
 
+static Eina_Bool
+_e_vis_client_check_obscured_by_children(E_Client *ec)
+{
+   Eina_Bool obscured = EINA_FALSE;
+   E_Client *child = NULL;
+   const Eina_List *l = NULL;
+
+   EINA_LIST_FOREACH(ec->transients, l, child)
+     {
+        if (child->transient_policy == E_TRANSIENT_BELOW)
+          continue;
+
+        if (!child->argb)
+          {
+             ELOGF("POL_VIS", "Fully Obscured by child (win:%x, child:%p)",
+                   ec->pixmap, ec, e_client_util_win_get(child), child);
+             obscured = EINA_TRUE;
+             break;
+          }
+        else
+          {
+             if (child->visibility.opaque > 0)
+               {
+                  ELOGF("POL_VIS", "Fully Obscured by alpha opaque child (win:%x, child:%p)",
+                        ec->pixmap, ec, e_client_util_win_get(child), child);
+                  obscured = EINA_TRUE;
+                  break;
+               }
+          }
+     }
+
+   return obscured;
+}
+
+static Eina_Bool
+_e_vis_client_check_obscured_by_same_layer(E_Client *ec)
+{
+   Eina_Bool obscured = EINA_FALSE;
+   E_Client *above = NULL;
+
+   for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
+     {
+        if (above->layer > ec->layer) break;
+        if (e_client_util_ignored_get(above)) continue;
+        if (e_object_is_del(E_OBJECT(above))) continue;
+        if (above->iconic && above->exp_iconify.by_client) continue;
+        if (above->comp_data && !above->comp_data->mapped) continue;
+        if (!E_CONTAINS(above->x, above->y, above->w, above->h, ec->x, ec->y, ec->w, ec->h)) continue;
+
+        if (!above->argb)
+          {
+             ELOGF("POL_VIS", "Fully Obscured by above (win:%x, ec:%p, layer:%d)",
+                   ec->pixmap, ec, e_client_util_win_get(above), above, above->layer);
+             obscured = EINA_TRUE;
+             break;
+          }
+        else
+          {
+             if (above->visibility.opaque <= 0)
+               continue;
+             else
+               {
+                  ELOGF("POL_VIS", "Fully Obscured by alpha opaque above (win:%x, ec:%p, layer:%d)",
+                        ec->pixmap, ec, e_client_util_win_get(above), above, above->layer);
+                  obscured = EINA_TRUE;
+                  break;
+               }
+          }
+     }
+
+   return obscured;
+}
+
+static Eina_Bool
+_e_vis_client_check_obscured_by_above_layers(E_Client *ec)
+{
+   Eina_Bool obscured = EINA_FALSE;
+   E_Client *above = NULL;
+
+   for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
+     {
+        if (above->layer <= ec->layer) continue;
+        if (e_client_util_ignored_get(above)) continue;
+        if (e_object_is_del(E_OBJECT(above))) continue;
+        if (above->iconic && above->exp_iconify.by_client) continue;
+        if (above->comp_data && !above->comp_data->mapped) continue;
+        if (!E_CONTAINS(above->x, above->y, above->w, above->h, ec->x, ec->y, ec->w, ec->h)) continue;
+
+        if (!above->argb)
+          {
+             ELOGF("POL_VIS", "Fully Obscured by above (win:%x, ec:%p, layer:%d)",
+                   ec->pixmap, ec, e_client_util_win_get(above), above, above->layer);
+             obscured = EINA_TRUE;
+             break;
+          }
+        else
+          {
+             if (above->visibility.opaque <= 0)
+               continue;
+             else
+               {
+                  ELOGF("POL_VIS", "Fully Obscured by alpha opaque above (win:%x, ec:%p, layer:%d)",
+                        ec->pixmap, ec, e_client_util_win_get(above), above, above->layer);
+                  obscured = EINA_TRUE;
+                  break;
+               }
+          }
+     }
+
+   return obscured;
+}
+
+static Eina_Bool
+_e_vis_client_check_send_pre_visibility(E_Vis_Client *vc, Eina_Bool raise)
+{
+   Eina_Bool send_vis_event = EINA_TRUE;
+   E_Client *ec;
+
+   ec = vc->ec;
+
+   if (_e_vis_client_is_uniconic(vc))
+     return EINA_FALSE;
+
+   // check all windows on above layers, if obscured by above then return FALSE
+   if (_e_vis_client_check_obscured_by_above_layers(ec))
+     {
+        ELOGF("POL_VIS", "DO NOT Need to SEND pre-visibility.. obscured by above (above layer)", ec->pixmap, ec);
+        return EINA_FALSE;
+     }
+
+   if (!raise)
+     {
+        // check above windows in same layer
+        if (_e_vis_client_check_obscured_by_same_layer(ec))
+          {
+             ELOGF("POL_VIS", "DO NOT Need to SEND pre-visibility.. obscured by above (same layer)", ec->pixmap, ec);
+             send_vis_event = EINA_FALSE;
+          }
+     }
+   else
+     {
+        if (ec->transients)
+          {
+             // check children windows
+             if (_e_vis_client_check_obscured_by_children(ec))
+               {
+                  ELOGF("POL_VIS", "DO NOT Need to SEND pre-visibility.. obscured by child", ec->pixmap, ec);
+                  send_vis_event = EINA_FALSE;
+               }
+          }
+     }
+
+   return send_vis_event;
+}
+
 static Eina_Bool
 _e_vis_client_add_uniconify_render_pending(E_Vis_Client *vc, E_Vis_Job_Type type, Eina_Bool raise)
 {
@@ -1076,6 +1227,13 @@ _e_vis_client_add_uniconify_render_pending(E_Vis_Client *vc, E_Vis_Job_Type type
    if (_e_vis_client_is_uniconify_render_running(vc))
      goto end;
 
+   send_vis_event = _e_vis_client_check_send_pre_visibility(vc, raise);
+   if (send_vis_event)
+     {
+        ELOGF("POL_VIS", "SEND pre-unobscured visibility event", ec->pixmap, ec);
+        e_vis_client_send_pre_visibility_event(ec);
+     }
+
    if (!_e_vis_client_is_uniconify_render_necessary(vc))
      return EINA_FALSE;
 
@@ -1083,60 +1241,6 @@ _e_vis_client_add_uniconify_render_pending(E_Vis_Client *vc, E_Vis_Job_Type type
 
    VS_DBG(ec, "BEGIN Uniconify render: raise %d", raise);
 
-   if (ec->transients)
-     {
-        if (raise)
-          {
-             E_Client *child;
-             const Eina_List *l;
-
-             EINA_LIST_FOREACH(ec->transients, l, child)
-               {
-                  if (child->transient_policy == E_TRANSIENT_BELOW)
-                    continue;
-                  if (!child->argb)
-                    {
-                       send_vis_event = EINA_FALSE;
-                       break;
-                    }
-                  else
-                    {
-                       if (child->visibility.opaque > 0)
-                         {
-                            send_vis_event = EINA_FALSE;
-                            break;
-                         }
-                    }
-               }
-          }
-        else
-          {
-             E_Client *above = NULL;
-             for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
-               {
-                  if (e_client_util_ignored_get(above)) continue;
-                  if (!E_CONTAINS(above->x, above->y, above->w, above->h, ec->x, ec->y, ec->w, ec->h)) continue;
-                  if ((above->parent == ec))
-                    {
-                       if (!above->argb)
-                         send_vis_event = EINA_FALSE;
-                       else
-                         {
-                            if (above->visibility.opaque > 0)
-                              send_vis_event = EINA_FALSE;
-                         }
-                    }
-                  break;
-               }
-          }
-     }
-
-   if (send_vis_event)
-     {
-        ELOGF("POL", "SEND pre-unobscured visibility event", ec->pixmap, ec);
-        e_vis_client_send_pre_visibility_event(ec);
-     }
-
    _e_vis_client_prepare_foreground_signal_emit(vc);
    vc->state = E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY;
    VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
@@ -1407,7 +1511,7 @@ _e_vis_ec_below_uniconify(E_Client *ec)
                        continue;
                     }
 
-                  ELOGF("POL", "SEND pre-unobscured visibility event", below_ec->pixmap, below_ec);
+                  ELOGF("POL_VIS", "SEND pre-unobscured visibility event", below_ec->pixmap, below_ec);
                   e_vis_client_send_pre_visibility_event(below_ec);
                }