Enlightenment CVS committal

Author  : morlenxus
Project : e17
Module  : apps/e

Dir     : e17/apps/e/src/bin


Modified Files:
        e_border.c e_border.h 


Log Message:
This patch fixes a few sloppy focus problems (mouse was over a window which 
doesn't have the focus,...). See bug #210.
Great work sECuRE!

===================================================================
RCS file: /cvs/e/e17/apps/e/src/bin/e_border.c,v
retrieving revision 1.610
retrieving revision 1.611
diff -u -3 -r1.610 -r1.611
--- e_border.c  22 Nov 2007 20:38:35 -0000      1.610
+++ e_border.c  26 Nov 2007 21:33:23 -0000      1.611
@@ -115,11 +115,20 @@
 static int grabbed = 0;
 
 static Evas_List *focus_stack = NULL;
+static Evas_List *raise_stack = NULL;
 
 static Ecore_X_Screen_Size screen_size = { -1, -1 };
 
 static int focus_track_frozen = 0;
 
+static int warp_to = 0;
+static int warp_to_x = 0;
+static int warp_to_y = 0;
+static int warp_x = 0;
+static int warp_y = 0;
+static Ecore_X_Window warp_to_win;
+static Ecore_Timer *warp_timer = NULL;
+
 EAPI int E_EVENT_BORDER_ADD = 0;
 EAPI int E_EVENT_BORDER_REMOVE = 0;
 EAPI int E_EVENT_BORDER_ZONE_SET = 0;
@@ -731,7 +740,7 @@
             e_border_focus_set(bd, 0, 1);
             if (manage != 2)
               {
-                 if (e_config->focus_revert_on_hide_or_close)
+                 if (e_config->focus_policy == E_FOCUS_CLICK && 
e_config->focus_revert_on_hide_or_close)
                    e_desk_last_focused_focus(bd->desk);
               }
          }
@@ -1077,6 +1086,7 @@
 
        /* If we don't have any children, raise this border */
        above = e_container_border_raise(bd);
+       e_border_raise_latest_set(bd);
        if (above)
          {
             /* We ended up above a border */
@@ -1310,6 +1320,58 @@
 }
 
 EAPI void
+e_border_raise_latest_set(E_Border *bd)
+{
+   raise_stack = evas_list_remove(raise_stack, bd);
+   raise_stack = evas_list_prepend(raise_stack, bd);
+}
+
+/*
+ * Sets the focus to the given border if necessary
+ * There are 3 cases of different focus_policy-configurations:
+ *
+ * - E_FOCUS_CLICK: just set the focus, the most simple one
+ *
+ * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
+ *   warp the pointer to the window. If this fails (because
+ *   the pointer is already in the window), just set the focus.
+ *
+ * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
+ *   last window which was focused, if the mouse is on the
+ *   desktop. So, we need to look if there is another window
+ *   under the pointer and warp to pointer to the right
+ *   one if so (also, we set the focus afterwards). In case
+ *   there is no window under pointer, the pointer is on the
+ *   desktop and so we just set the focus.
+ *
+ *
+ * This function is to be called when setting the focus was not
+ * explicitly triggered by the user (by moving the mouse or
+ * clicking for example), but implicitly (by closing a window,
+ * the last focused window should get focus).
+ *
+ */
+EAPI void
+e_border_focus_set_with_pointer(E_Border *bd)
+{
+   if (e_config->focus_policy == E_FOCUS_SLOPPY)
+     {
+       if (e_border_under_pointer_get(NULL, bd))
+         {
+            if (!e_border_pointer_warp_to_center(bd))
+              e_border_focus_set(bd, 1, 1);
+         }
+       else
+         e_border_focus_set(bd, 1, 1);
+     }
+   else if (e_config->focus_policy == E_FOCUS_CLICK)
+     e_border_focus_set(bd, 1, 1);
+   else
+     if (!e_border_pointer_warp_to_center(bd))
+       e_border_focus_set(bd, 1, 1);
+}
+
+EAPI void
 e_border_focus_set(E_Border *bd, int focus, int set)
 {
    E_OBJECT_CHECK(bd);
@@ -2748,6 +2810,12 @@
 }
 
 EAPI Evas_List *
+e_border_raise_stack_get(void)
+{
+   return raise_stack;
+}
+
+EAPI Evas_List *
 e_border_lost_windows_get(E_Zone *zone)
 {
    Evas_List *list = NULL, *l;
@@ -3252,6 +3320,7 @@
    borders_hash = evas_hash_del(borders_hash, e_util_winid_str_get(bd->win), 
bd);
    borders = evas_list_remove(borders, bd);
    focus_stack = evas_list_remove(focus_stack, bd);
+   raise_stack = evas_list_remove(raise_stack, bd);
    
    e_container_border_remove(bd);
    free(bd);
@@ -3441,7 +3510,19 @@
      }
    else
      {
+       E_Border *pbd;
+
        e_border_hide(bd, 0);
+       pbd = e_border_under_pointer_get(bd->desk, bd);
+       if (pbd)
+         e_border_focus_set(pbd, 1, 1);
+       else if (e_config->focus_policy == E_FOCUS_SLOPPY)
+         {
+            /* If we could not determine a window under cursor but
+             * sloppy focus is enabled, we focus the most recently 
+             * focused window */
+            e_desk_last_focused_focus(bd->desk);
+         }
        e_object_del(E_OBJECT(bd));
      }
    return 1;
@@ -5292,8 +5373,10 @@
             e_border_layer_set(bd, bd->parent->layer);
             if ((e_config->modal_windows) && (bd->client.netwm.state.modal))
               bd->parent->modal = bd;
-            if (bd->parent->focused)
-              e_border_focus_set(bd, 1, 1);
+
+            if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
+                (bd->parent->focused && (e_config->focus_setting == 
E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
+              bd->take_focus = 1;
          }
        bd->client.icccm.fetch.transient_for = 0;
        rem_change = 1;
@@ -6710,7 +6793,7 @@
          {
             bd->want_focus = 0;
             if (!bd->lock_focus_out)
-              e_border_focus_set(bd, 1, 1);
+              e_border_focus_set_with_pointer(bd);
          }
        else
          {
@@ -6722,7 +6805,7 @@
                        e_border_focused_get())))
                    {
                       if (!bd->lock_focus_out)
-                        e_border_focus_set(bd, 1, 1);
+                        e_border_focus_set_with_pointer(bd);
                    }
               }
          }
@@ -7579,4 +7662,114 @@
 e_border_focus_track_thaw(void)
 {
    focus_track_frozen--;
+}
+
+EAPI E_Border *
+e_border_under_pointer_get(E_Desk *desk, E_Border *exclude)
+{
+   E_Border *bd = NULL;
+   Evas_List *l;
+   int x, y;
+
+   /* We need to ensure that we can get the container window for the
+    * zone of either the given desk or the desk of the excluded
+    * window, so return if neither is given */
+   if (desk)
+     ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
+   else if (exclude)
+     ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
+   else return;
+
+   for (l = e_border_raise_stack_get(); l; l = l->next)
+     {
+       E_Border *cbd;
+
+       cbd = l->data;
+       if (!cbd) continue;
+       /* If a border was specified which should be excluded from the list
+        * (because it will be closed shortly for example), skip */
+       if ((exclude) && (cbd == exclude)) continue;
+       if ((desk) && (cbd->desk != desk)) continue;
+       if ((x < cbd->x) || (x > (cbd->x + cbd->w)) ||
+           (y < cbd->y) || (y > (cbd->y + cbd->h))) continue;
+       /* If the layer is higher, the position of the window is higher
+        * (always on top vs always below) */
+       if (!bd || (cbd->layer > bd->layer))
+        {
+           bd = cbd;
+           break;
+        }
+     }
+   return bd;
+}
+
+static int
+_e_border_pointer_warp_to_center_timer(void *data)
+{
+   if (warp_to)
+     {
+       int dx, dy, x, y;
+       double spd;
+
+       ecore_x_pointer_xy_get(warp_to_win, &x, &y);
+       if ((x - warp_x) > 5 || (x - warp_x) < -5 ||
+           (y - warp_y) > 5 || (y - warp_y) < -5)
+         {
+            /* User moved the mouse, so stop warping */
+            warp_to = 0;
+            goto cleanup;
+         }
+
+       /* We just use the same warp speed as configured
+        * for the windowlist */
+       spd = e_config->winlist_warp_speed;
+       x = warp_x;
+       y = warp_y;
+       warp_x = (x * (1.0 - spd)) + (warp_to_x * spd);
+       warp_y = (y * (1.0 - spd)) + (warp_to_y * spd);
+       if (warp_x == x && warp_y == y)
+         {
+            warp_x = warp_to_x;
+            warp_y = warp_to_y;
+            warp_to = 0;
+            goto cleanup;
+         }
+       ecore_x_pointer_warp(warp_to_win, warp_x, warp_y);
+       return 1;
+     }
+   cleanup:
+   ecore_timer_del(warp_timer);
+   warp_timer = NULL;
+   return 0;
+}
+
+EAPI int
+e_border_pointer_warp_to_center(E_Border *bd)
+{
+   int x, y;
+
+   /* Only warp the pointer if it is not already in the area of
+    * the given border */
+   ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
+   if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
+       (y >= bd->y) && (y <= (bd->y + bd->h)))
+     return 0;
+
+   warp_to_x = bd->x + (bd->w / 2); 
+   if (warp_to_x < (bd->zone->x + 1))
+     warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
+   else if (warp_to_x > (bd->zone->x + bd->zone->w))
+     warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2; 
+
+   warp_to_y = bd->y + (bd->h / 2);
+   if (warp_to_y < (bd->zone->y + 1))
+     warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
+   else if (warp_to_y > (bd->zone->y + bd->zone->h))
+     warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2; 
+
+   warp_to = 1;
+   warp_to_win = bd->zone->container->win;
+   ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x, &warp_y);
+   warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, 
(const void*)bd);
+   return 1;
 }
===================================================================
RCS file: /cvs/e/e17/apps/e/src/bin/e_border.h,v
retrieving revision 1.166
retrieving revision 1.167
diff -u -3 -r1.166 -r1.167
--- e_border.h  11 Nov 2007 11:48:40 -0000      1.166
+++ e_border.h  26 Nov 2007 21:33:23 -0000      1.167
@@ -546,6 +546,8 @@
 EAPI void      e_border_stack_above(E_Border *bd, E_Border *above);
 EAPI void      e_border_stack_below(E_Border *bd, E_Border *below);
 EAPI void      e_border_focus_latest_set(E_Border *bd);
+EAPI void      e_border_raise_latest_set(E_Border *bd);
+EAPI void      e_border_focus_set_with_pointer(E_Border *bd);
 EAPI void      e_border_focus_set(E_Border *bd, int focus, int set);
 EAPI void      e_border_shade(E_Border *bd, E_Direction dir);
 EAPI void      e_border_unshade(E_Border *bd, E_Direction dir);
@@ -604,6 +606,9 @@
 EAPI void e_border_hook_del(E_Border_Hook *bh);
 EAPI void e_border_focus_track_freeze(void);
 EAPI void e_border_focus_track_thaw(void);
+
+EAPI E_Border *e_border_under_pointer_get(E_Desk *desk, E_Border *exclude);
+EAPI int e_border_pointer_warp_to_center(E_Border *bd);
 
 extern EAPI int E_EVENT_BORDER_RESIZE;
 extern EAPI int E_EVENT_BORDER_MOVE;



-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to