discomfitor pushed a commit to branch enlightenment-0.20.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=bb6a0455874f6491ae1244facf6ccae35d479f07

commit bb6a0455874f6491ae1244facf6ccae35d479f07
Author: Toan Pham <reset.poin...@gmail.com>
Date:   Tue Dec 22 14:15:17 2015 +0900

    enhance winlist next window selection
    
    Summary:
    The original next window selection of winlist is weak.  It searches the 
next window with the following conditions:
    
    1.  Next non-overlaped window in the direction of user's selection 
(up,down,right,left).
    2.  The next window has to be the closest window from the currently 
selected window (calculated from shortest distance from each window's border, 
in the direction of selection)
    3.  the second distant requirement is this:
          delta2_next = abs(ec_orig->x - ec_orig->w / 2 - ec->x + ec->w/2);
        * Which I believe is a mistake, should be:
          delta2_next = abs(ec_orig->x + ec_orig->w / 2 - ec->x + ec->w/2);
    
    These two conditions are weak, and they sometimes can result in unexpected 
selection to the user.
    
    The enclosed patch enhances the next window selection: 1) A next window 
selection can be the window that's overlapping with the in-focused window.  2)  
calculates the next window from the center of the currently focused window to 
the next window, and it also takes into account directionality (a window that's 
farther in the direction of selection has a better chance of being selected 
then a window that's closer in the direction of selection, but offset-ed in the 
lateral direction.)
    
    Test Plan:
    1.  Create 4 key binds for "next window to left, right, up, down".
    2.  Open up 4 different windows and position them in odd/random positions.
    3.  Try to navigate to each window (with the winlist shortcut keys) before 
this patch.
    4.  Try with this patch, and evaluate if the window selection is more 
**PREDICTABLE**.
    
    Reviewers: zmike
    
    Subscribers: cedric
    
    Differential Revision: https://phab.enlightenment.org/D2661
    
    I fixed the weridness and it behaves much more reliably now with
    "tall" or "wide" windows. also fixed some formatting etc. etc. - this
    now works better and now if u alt+tab AND then use arrow keys while
    holding alt... it'll navigate around geometrically rather nicely.
    
    so big fixes and good for pointing out the simpleness of the original
    code. :)
    
      - raster
    
    @feat
---
 src/modules/winlist/e_mod_main.c |  19 +--
 src/modules/winlist/e_winlist.c  | 356 +++++++++++----------------------------
 2 files changed, 102 insertions(+), 273 deletions(-)

diff --git a/src/modules/winlist/e_mod_main.c b/src/modules/winlist/e_mod_main.c
index 890eb7b..36018af 100644
--- a/src/modules/winlist/e_mod_main.c
+++ b/src/modules/winlist/e_mod_main.c
@@ -156,21 +156,10 @@ _e_mod_action_winlist_cb_helper(E_Object *obj 
EINA_UNUSED, const char *params, i
    else if (direction == -1)
      e_winlist_prev();
    if (direction) return;
-   switch (udlr)
-     {
-      case 0:
-        e_winlist_up(zone);
-        break;
-      case 1:
-        e_winlist_down(zone);
-        break;
-      case 2:
-        e_winlist_left(zone);
-        break;
-      case 3:
-        e_winlist_right(zone);
-        break;
-     }
+   
+   if (udlr == -1) return;
+   
+   e_winlist_direction_select(zone, udlr);
 }
 
 static void
diff --git a/src/modules/winlist/e_winlist.c b/src/modules/winlist/e_winlist.c
index 28e2276..2bc13cd 100644
--- a/src/modules/winlist/e_winlist.c
+++ b/src/modules/winlist/e_winlist.c
@@ -406,262 +406,53 @@ _e_winlist_select(E_Client *ec)
      evas_object_focus_set(ec->frame, 1);
 }
 
-void
-e_winlist_left(E_Zone *zone)
+static int
+point_line_dist(int x, int y, int lx1, int ly1, int lx2, int ly2)
 {
-   E_Client *ec;
-   Eina_List *l;
-   E_Desk *desk;
-   E_Client *ec_orig;
-   int delta = INT_MAX;
-   int delta2 = INT_MAX;
-   int center;
-
-   _ec_next = NULL;
-
-   E_OBJECT_CHECK(zone);
-   E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
+   double xx, yy, dx, dy, dist;
+   double a = x - lx1;
+   double b = y - ly1;
+   double c = lx2 - lx1;
+   double d = ly2 - ly1;
 
-   ec_orig = e_client_focused_get();
-   if (!ec_orig) return;
+   double dot = (a * c) + (b * d);
+   double len_sq = (c * c) + (d * d);
+   double param = -1;
 
-   center = ec_orig->x + ec_orig->w / 2;
+   // if line is 0 length
+   if (len_sq != 0) param = dot / len_sq;
 
-   desk = e_desk_current_get(zone);
-   EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
+   if (param < 0)
      {
-        int center_next;
-        int delta_next;
-        int delta2_next;
-
-        if (ec == ec_orig) continue;
-        if ((!ec->icccm.accepts_focus) &&
-            (!ec->icccm.take_focus)) continue;
-        if (ec->netwm.state.skip_taskbar) continue;
-        if (ec->user_skip_winlist) continue;
-        if (ec->iconic)
-          {
-             if (!e_config->winlist_list_show_iconified) continue;
-             if ((ec->zone != zone) &&
-                 (!e_config->winlist_list_show_other_screen_iconified))
-               continue;
-             if ((ec->desk != desk) &&
-                 (!e_config->winlist_list_show_other_desk_iconified)) continue;
-          }
-        else
-          {
-             if (ec->sticky)
-               {
-                  if ((ec->zone != zone) &&
-                      (!e_config->winlist_list_show_other_screen_windows))
-                    continue;
-               }
-             else
-               {
-                  if (ec->desk != desk)
-                    {
-                       if ((ec->zone) && (ec->zone != zone))
-                         {
-                            if 
(!e_config->winlist_list_show_other_screen_windows)
-                              continue;
-                         }
-                       else if 
(!e_config->winlist_list_show_other_desk_windows)
-                         continue;
-                    }
-               }
-          }
-        /* ec is suitable */
-        center_next = ec->x + ec->w / 2;
-        if (center_next >= center) continue;
-        delta_next = ec_orig->x - (ec->x + ec->w);
-        if (delta_next < 0) delta_next = center - center_next;
-        delta2_next = abs(ec_orig->y - ec_orig->h / 2 - ec->y + ec->h/2);
-        if (delta_next >= 0 && delta_next <= delta &&
-            delta2_next >= 0 && delta2_next <= delta2)
-          {
-             _ec_next = ec;
-             delta = delta_next;
-             delta2 = delta2_next;
-          }
+        xx = lx1;
+        yy = ly1;
      }
-
-   if (_ec_next) _e_winlist_select(_ec_next);
-}
-
-void
-e_winlist_down(E_Zone *zone)
-{
-   E_Client *ec;
-   Eina_List *l;
-   E_Desk *desk;
-   E_Client *ec_orig;
-   int delta = INT_MAX;
-   int delta2 = INT_MAX;
-   int center;
-
-   _ec_next = NULL;
-
-   E_OBJECT_CHECK(zone);
-   E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
-
-   ec_orig = e_client_focused_get();
-   if (!ec_orig) return;
-
-   center = ec_orig->y + ec_orig->h / 2;
-
-   desk = e_desk_current_get(zone);
-   EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
+   else if (param > 1)
      {
-        int center_next;
-        int delta_next;
-        int delta2_next;
-
-        if (ec == ec_orig) continue;
-        if ((!ec->icccm.accepts_focus) &&
-            (!ec->icccm.take_focus)) continue;
-        if (ec->netwm.state.skip_taskbar) continue;
-        if (ec->user_skip_winlist) continue;
-        if (ec->iconic)
-          {
-             if (!e_config->winlist_list_show_iconified) continue;
-             if ((ec->zone != zone) &&
-                 (!e_config->winlist_list_show_other_screen_iconified))
-               continue;
-             if ((ec->desk != desk) &&
-                 (!e_config->winlist_list_show_other_desk_iconified)) continue;
-          }
-        else
-          {
-             if (ec->sticky)
-               {
-                  if ((ec->zone != zone) &&
-                      (!e_config->winlist_list_show_other_screen_windows))
-                    continue;
-               }
-             else
-               {
-                  if (ec->desk != desk)
-                    {
-                       if ((ec->zone) && (ec->zone != zone))
-                         {
-                            if 
(!e_config->winlist_list_show_other_screen_windows)
-                              continue;
-                         }
-                       else if 
(!e_config->winlist_list_show_other_desk_windows)
-                         continue;
-                    }
-               }
-          }
-        /* ec is suitable */
-        center_next = ec->y + ec->h / 2;
-        if (center_next <= center) continue;
-        delta_next = ec->y - (ec_orig->y + ec_orig->h);
-        if (delta_next < 0) delta_next = center - center_next;
-        delta2_next = abs(ec_orig->x - ec_orig->w / 2 - ec->x + ec->w/2);
-        if (delta_next >= 0 && delta_next <= delta &&
-            delta2_next >= 0 && delta2_next <= delta2)
-          {
-             _ec_next = ec;
-             delta = delta_next;
-             delta2 = delta2_next;
-          }
+        xx = lx2;
+        yy = ly2;
      }
-
-   if (_ec_next) _e_winlist_select(_ec_next);
-}
-
-void
-e_winlist_up(E_Zone *zone)
-{
-   E_Client *ec;
-   Eina_List *l;
-   E_Desk *desk;
-   E_Client *ec_orig;
-   int delta = INT_MAX;
-   int delta2 = INT_MAX;
-   int center;
-
-   _ec_next = NULL;
-
-   E_OBJECT_CHECK(zone);
-   E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
-
-   ec_orig = e_client_focused_get();
-   if (!ec_orig) return;
-
-   center = ec_orig->y + ec_orig->h / 2;
-
-   desk = e_desk_current_get(zone);
-   EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
+   else
      {
-        int center_next;
-        int delta_next;
-        int delta2_next;
-
-        if (ec == ec_orig) continue;
-        if ((!ec->icccm.accepts_focus) &&
-            (!ec->icccm.take_focus)) continue;
-        if (ec->netwm.state.skip_taskbar) continue;
-        if (ec->user_skip_winlist) continue;
-        if (ec->iconic)
-          {
-             if (!e_config->winlist_list_show_iconified) continue;
-             if ((ec->zone != zone) &&
-                 (!e_config->winlist_list_show_other_screen_iconified))
-               continue;
-             if ((ec->desk != desk) &&
-                 (!e_config->winlist_list_show_other_desk_iconified)) continue;
-          }
-        else
-          {
-             if (ec->sticky)
-               {
-                  if ((ec->zone != zone) &&
-                      (!e_config->winlist_list_show_other_screen_windows))
-                    continue;
-               }
-             else
-               {
-                  if (ec->desk != desk)
-                    {
-                       if ((ec->zone) && (ec->zone != zone))
-                         {
-                            if 
(!e_config->winlist_list_show_other_screen_windows)
-                              continue;
-                         }
-                       else if 
(!e_config->winlist_list_show_other_desk_windows)
-                         continue;
-                    }
-               }
-          }
-        /* ec is suitable */
-        center_next = ec->y + ec->h / 2;
-        if (center_next >= center) continue;
-        delta_next = ec_orig->y - (ec->y + ec->h);
-        if (delta_next < 0) delta_next = center - center_next;
-        delta2_next = abs(ec_orig->x - ec_orig->w / 2 - ec->x + ec->w/2);
-        if (delta_next >= 0 && delta_next <= delta &&
-            delta2_next >= 0 && delta2_next <= delta2)
-          {
-             _ec_next = ec;
-             delta = delta_next;
-             delta2 = delta2_next;
-          }
-     }
-
-   if (_ec_next) _e_winlist_select(_ec_next);
+        xx = lx1 + (param * c);
+        yy = ly1 + (param * d);
+   }
+
+   dx = x - xx;
+   dy = y - yy;
+   dist = sqrt((dx * dx) + (dy * dy));
+   return (int)dist;
 }
 
 void
-e_winlist_right(E_Zone *zone)
+e_winlist_direction_select(E_Zone *zone, int dir)
 {
    E_Client *ec;
    Eina_List *l;
    E_Desk *desk;
    E_Client *ec_orig;
-   int delta = INT_MAX;
-   int delta2 = INT_MAX;
-   int center;
+   int distance = INT_MAX;
+   int cx, cy;
 
    _ec_next = NULL;
 
@@ -671,14 +462,13 @@ e_winlist_right(E_Zone *zone)
    ec_orig = e_client_focused_get();
    if (!ec_orig) return;
 
-   center = ec_orig->x + ec_orig->w / 2;
+   cx = ec_orig->x + (ec_orig->w / 2);
+   cy = ec_orig->y + (ec_orig->h / 2);
 
    desk = e_desk_current_get(zone);
    EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
      {
-        int center_next;
-        int delta_next;
-        int delta2_next;
+        int a = 0, d = 0;
 
         if (ec == ec_orig) continue;
         if ((!ec->icccm.accepts_focus) &&
@@ -716,24 +506,74 @@ e_winlist_right(E_Zone *zone)
                     }
                }
           }
-        /* ec is suitable */
-        center_next = ec->x + ec->w / 2;
-        if (center_next <= center) continue;
-        delta_next = ec->x - (ec_orig->x + ec_orig->w);
-        if (delta_next < 0) delta = center_next - center;
-        delta2_next = abs(ec_orig->y - ec_orig->h / 2 - ec->y + ec->h/2);
-        if (delta_next >= 0 && delta_next <= delta &&
-            delta2_next >= 0 && delta2_next <= delta2)
+
+        switch (dir)
           {
-             _ec_next = ec;
-             delta = delta_next;
-             delta2 = delta2_next;
+           case 0: /* up */
+             d = point_line_dist(cx, cy,
+                                 ec->x,         ec->y + ec->h,
+                                 ec->x + ec->w, ec->y + ec->h);
+             if (d >= distance) continue;
+             d = point_line_dist(cx, cy,
+                                 ec->x,         ec->y + (ec->h / 2),
+                                 ec->x + ec->w, ec->y + (ec->h / 2));
+             if (d >= distance) continue;
+             if (cy <= (ec->y + (ec->h / 2))) continue;
+             a = abs(cx - (ec->x + (ec->w / 2)));
+             d += (a * a) / d;
+             if (d >= distance) continue;
+             break;
+           case 1: /* down */
+             d = point_line_dist(cx, cy,
+                                 ec->x,         ec->y,
+                                 ec->x + ec->w, ec->y);
+             if (d >= distance) continue;
+             d = point_line_dist(cx, cy,
+                                 ec->x,         ec->y + (ec->h / 2),
+                                 ec->x + ec->w, ec->y + (ec->h / 2));
+             if (d >= distance) continue;
+             if (cy >= (ec->y + (ec->h / 2))) continue;
+             a = abs(cx - (ec->x + (ec->w / 2)));
+             d += (a * a) / d;
+             if (d >= distance) continue;
+             break;
+           case 2: /* left */
+             d = point_line_dist(cx, cy,
+                                 ec->x + ec->w, ec->y,
+                                 ec->x + ec->w, ec->y + ec->h);
+             if (d >= distance) continue;
+             d = point_line_dist(cx, cy,
+                                 ec->x + (ec->w / 2), ec->y,
+                                 ec->x + (ec->w / 2), ec->y + ec->h);
+             if (d >= distance) continue;
+             if (cx <= (ec->x + (ec->w / 2))) continue;
+             a = abs(cy - (ec->y + (ec->h / 2)));
+             d += (a * a) / d;
+             if (d >= distance) continue;
+             break;
+           case 3: /* right */
+             d = point_line_dist(cx, cy,
+                                 ec->x, ec->y,
+                                 ec->x, ec->y + ec->h);
+             if (d >= distance) continue;
+             d = point_line_dist(cx, cy,
+                                 ec->x + (ec->w / 2), ec->y,
+                                 ec->x + (ec->w / 2), ec->y + ec->h);
+             if (d >= distance) continue;
+             if (cx >= (ec->x + (ec->w / 2))) continue;
+             a = abs(cy - (ec->y + (ec->h / 2)));
+             d += (a * a) / d;
+             if (d >= distance) continue;
+             break;
           }
+        _ec_next = ec;
+        distance = d;
      }
 
    if (_ec_next) _e_winlist_select(_ec_next);
 }
 
+
 void
 e_winlist_modifiers_set(int mod, E_Winlist_Activate_Type type)
 {
@@ -1108,13 +948,13 @@ _e_winlist_cb_key_down(void *data EINA_UNUSED, int type 
EINA_UNUSED, void *event
 
    if (ev->window != _input_window) return ECORE_CALLBACK_PASS_ON;
    if (!strcmp(ev->key, "Up"))
-     e_winlist_prev();
+     e_winlist_direction_select(_winlist_zone, 0);
    else if (!strcmp(ev->key, "Down"))
-     e_winlist_next();
+     e_winlist_direction_select(_winlist_zone, 1);
    else if (!strcmp(ev->key, "Left"))
-     e_winlist_prev();
+     e_winlist_direction_select(_winlist_zone, 2);
    else if (!strcmp(ev->key, "Right"))
-     e_winlist_next();
+     e_winlist_direction_select(_winlist_zone, 3);
    else if (!strcmp(ev->key, "Return"))
      e_winlist_hide();
    else if (!strcmp(ev->key, "space"))

-- 


Reply via email to