On Tue, 29 Aug 2017 04:32:21 -0700
Carsten Haitzler <ras...@rasterman.com> wrote:

> raster pushed a commit to branch master.
> 
> http://git.enlightenment.org/core/enlightenment.git/commit/?id=5ec93f15ffa57d10fa513edbb1661450e1ec2fff
> 
> commit 5ec93f15ffa57d10fa513edbb1661450e1ec2fff
> Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
> Date:   Tue Aug 29 20:31:30 2017 +0900
> 
>     e actions - add actions for moving focus around - feature request
>     
>     was simple. winlist already had it. added action to focus next/prev or
>     up/down/left/right. useful for tiling... :)
>     
>     @feature
> ---
>  src/bin/e_actions.c | 212 
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 212 insertions(+)
> 
> diff --git a/src/bin/e_actions.c b/src/bin/e_actions.c
> index 0252b5354..718455b9a 100644
> --- a/src/bin/e_actions.c
> +++ b/src/bin/e_actions.c
> @@ -2991,6 +2991,197 @@ ACT_FN_GO(screen_redo, EINA_UNUSED)
>  #endif
>  }
>  
> +/***************************************************************************/
> +static Eina_Bool
> +_skip_win(E_Client *ec, E_Zone *zone, E_Desk *desk)
> +{
> +   if ((!ec->icccm.accepts_focus) && (!ec->icccm.take_focus)) return 
> EINA_TRUE;
> +   if (ec->netwm.state.skip_taskbar) return EINA_TRUE;
> +   if (ec->user_skip_winlist) return EINA_TRUE;
> +   if (ec->iconic) return EINA_TRUE;
> +   if (ec->zone != zone) return EINA_TRUE;
> +   if (!((ec->sticky) || (ec->desk == desk))) return EINA_TRUE;
> +   return EINA_FALSE;
> +}
> +
> +static int
> +_point_line_dist(int x, int y, int lx1, int ly1, int lx2, int ly2)
> +{
> +   int xx, yy, dx, dy;
> +   int a = x - lx1;
> +   int b = y - ly1;
> +   int c = lx2 - lx1;
> +   int d = ly2 - ly1;
> +   int dot = (a * c) + (b * d);
> +   int len_sq = (c * c) + (d * d);
> +   double dist, param = -1.0;
> +
> +   // if line is 0 length
> +   if (len_sq) param = (double)dot / len_sq;
> +
> +   if (param < 0)
> +     {
> +        xx = lx1;
> +        yy = ly1;
> +     }
> +   else if (param > 1)
> +     {
> +        xx = lx2;
> +        yy = ly2;
> +     }
> +   else
> +     {
> +        xx = lx1 + lround(param * c);
> +        yy = ly1 + lround(param * d);
> +     }
> +
> +   dx = x - xx;
> +   dy = y - yy;
> +   dist = sqrt((dx * dx) + (dy * dy));
> +   return lround(dist);
> +}
> +
> +ACT_FN_GO(window_focus, EINA_UNUSED)
> +{
> +   E_Zone *zone = e_zone_current_get();
> +   E_Desk *desk = e_desk_current_get(zone);
> +   E_Client *ec, *ec_orig,
> +     *ec_prev = NULL, *ec_last = NULL, *ec_first = NULL, *ec_next = NULL;
> +   Eina_List *l;
> +   int distance = INT_MAX, cx, cy, dir = -1, found = 0;
> +
> +   if (!params) return;
> +   ec_orig = e_client_focused_get();
> +   if (!ec_orig)
> +     {
> +        // XXX: just pick any window to focus
> +        EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
> +          {
> +             if (_skip_win(ec, zone, desk)) continue;
> +             e_client_focus_set_with_pointer(ec);
> +             return;
> +          }
> +        return;
> +     }
> +
> +   if      (!strcmp(params, "next"))  dir = -1;
> +   else if (!strcmp(params, "prev"))  dir = -2;
> +   else if (!strcmp(params, "up"))    dir =  0;
> +   else if (!strcmp(params, "down"))  dir =  1;
> +   else if (!strcmp(params, "left"))  dir =  2;
> +   else if (!strcmp(params, "right")) dir =  3;
> +   else
> +     {
> +        e_util_dialog_show(_("Error: window_focus action"),
> +                           _("Invalid parameter: %s"), params);
> +        return;
> +     }
> +   if (dir < 0)
> +     {
> +        EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
> +          {
> +             if (_skip_win(ec, zone, desk)) continue;
> +
> +             if (ec == ec_orig)
> +               {
> +                  found = 1;
> +                  return;
> +               }
> +             else if (!found) ec_prev = ec;
> +             else if ((found) && (!ec_next)) ec_next = ec;

This conditional block is logically dead code and has turned into a coverity 
issue.

> +
> +             if (!ec_first) ec_first = ec;
> +             ec_last = ec;
> +          }
> +        if (dir == -1) /* next */
> +          {
> +             if (ec_next) e_client_focus_set_with_pointer(ec_next);
> +             else if (ec_first) e_client_focus_set_with_pointer(ec_first);
> +          }
> +        else if (dir == -2)
> +          {
> +             if (ec_prev) e_client_focus_set_with_pointer(ec_prev);
> +             else if (ec_last) e_client_focus_set_with_pointer(ec_last);
> +          }
> +        return;
> +     }
> +
> +   cx = ec_orig->x + (ec_orig->w / 2);
> +   cy = ec_orig->y + (ec_orig->h / 2);
> +
> +   EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
> +     {
> +        int a = 0, d = 0;
> +
> +        if (ec == ec_orig) continue;
> +        if (_skip_win(ec, zone, desk)) continue;
> +
> +        switch (dir)
> +          {
> +           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_client_focus_set_with_pointer(ec_next);
> +}
> +
>  /* local subsystem globals */
>  static Eina_Hash *actions = NULL;
>  static Eina_List *action_list = NULL;
> @@ -3440,6 +3631,27 @@ e_actions_init(void)
>     e_action_predef_name_set(N_("Window : Moving"), N_("To Previous Screen"),
>                              "window_zone_move_by", "-1", NULL, 0);
>  
> +   /* Move window focus somewhere */
> +   ACT_GO(window_focus);
> +   e_action_predef_name_set(N_("Window : Focus"),
> +                            N_("Focus next window"),
> +                            "window_focus", "next", NULL, 0);
> +   e_action_predef_name_set(N_("Window : Focus"),
> +                            N_("Focus previous window"),
> +                            "window_focus", "prev", NULL, 0);
> +   e_action_predef_name_set(N_("Window : Focus"),
> +                            N_("Focus window above"),
> +                            "window_focus", "up", NULL, 0);
> +   e_action_predef_name_set(N_("Window : Focus"),
> +                            N_("Focus window below"),
> +                            "window_focus", "down", NULL, 0);
> +   e_action_predef_name_set(N_("Window : Focus"),
> +                            N_("Focus window left"),
> +                            "window_focus", "left", NULL, 0);
> +   e_action_predef_name_set(N_("Window : Focus"),
> +                            N_("Focus window right"),
> +                            "window_focus", "right", NULL, 0);
> +
>     /* menu_show */
>     ACT_GO(menu_show);
>     e_action_predef_name_set(N_("Menu"), N_("Show Main Menu"),
> 

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to