On Sun, Sep 14, 2008 at 1:53 AM, Gustavo Sverzut Barbieri
<[EMAIL PROTECTED]> wrote:
> Guys,
>
> I really miss a feature from other window managers, at least KWin and
> WindowMaker, that is the option to move and resize windows using just
> the keyboard. Basically you activate a shortcut to enter the "action
> mode", in which you use the keyboard arrows to move or resize the
> window and then you hit "Enter" to confirm or "Escape" to rollback, if
> you wait some seconds it will also confirm, since it's not a dangerous
> option, it is more intuitive (you don't even need to know you need to
> confirm)... if you say "Oh, sh*t" then you usually hit Escape and
> you'll learn it will rollback.
>
> This is implemented in the attached patch. It's very rough and needs
> some review, but it works nicely, except:
>  - we'll have 2 items in the bindings for each action: "Move" and
> "Move with keyboard", etc.
>  - offsets are not configurable, they're fixed in 5px in each
> direction for each operation;
>  - timeout is not configurable, it's 5s;
>  - no geometry window while moving or resizing windows.
>
> The first point is really easy to remove, but then I guess it would
> impact the mouse bindings, anyone with more experience in that can
> confirm?
>
> The second and third are easy to add, but maybe it's too much. I'll
> add if required, but I want to avoid too much useless options going
> in.
>
> The last point I haven't looked at it, but I guess i can learn it from
> existing code. hints are welcome, of course.

Ok, 4th point done, also fixed the check for locks (was using stack
due copy&paste) and added that check on the api entrance as well.

PS: funny that in less than 15min after mailing this at least 2 guys
replied to me on IRC saying they liked the idea! Awesome :-)

-- 
Gustavo Sverzut Barbieri
http://profusion.mobi embedded systems
--------------------------------------
MSN: [EMAIL PROTECTED]
Skype: gsbarbieri
Mobile: +55 (19) 9225-2202
Index: src/bin/e_border.c
===================================================================
--- src/bin/e_border.c	(revision 35979)
+++ src/bin/e_border.c	(working copy)
@@ -2607,7 +2607,231 @@
    return borders;
 }
 
+static Ecore_X_Window action_input_win = 0;
+static E_Border *action_border = NULL;
+static Ecore_Event_Handler *action_handler = NULL;
+static Ecore_Timer *action_timer = NULL;
+static Ecore_X_Rectangle action_orig;
+
+static int
+_e_border_action_input_win_del(void)
+{
+   if (!action_input_win)
+     return 0;
+
+   e_grabinput_release(action_input_win, action_input_win);
+   ecore_x_window_del(action_input_win);
+   action_input_win = 0;
+   return 1;
+}
+
+static int
+_e_border_action_input_win_new(E_Border *bd)
+{
+   if (!action_input_win)
+     {
+	Ecore_X_Window parent = bd->zone->container->win;
+	action_input_win = ecore_x_window_input_new(parent, 0, 0, 1, 1);
+	if (!action_input_win)
+	  return 0;
+     }
+
+   ecore_x_window_show(action_input_win);
+   if (e_grabinput_get(action_input_win, 0, action_input_win))
+     return 1;
+
+   _e_border_action_input_win_del();
+   return 0;
+}
+
+static int
+_e_border_action_finish(void)
+{
+   _e_border_action_input_win_del();
+
+   if (action_timer)
+     ecore_timer_del(action_timer);
+   action_timer = NULL;
+
+   if (action_handler)
+     ecore_event_handler_del(action_handler);
+   action_handler = NULL;
+
+   action_border = NULL;
+}
+
+static int
+_e_border_action_timeout(void *data)
+{
+   _e_border_action_finish();
+   return 0;
+}
+
+static void
+_e_border_action_timeout_add(void)
+{
+   if (action_timer)
+     ecore_timer_del(action_timer);
+   action_timer = ecore_timer_add(5.0, _e_border_action_timeout, NULL);
+}
+
+static void
+_e_border_action_init(E_Border *bd)
+{
+   action_orig.x = bd->x;
+   action_orig.y = bd->y;
+   action_orig.width = bd->w;
+   action_orig.height = bd->h;
+
+   action_border = bd;
+
+   _e_border_action_timeout_add();
+}
+
+static void
+_e_border_action_restore_orig(E_Border *bd)
+{
+   if (action_border != bd)
+     return;
+
+   e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
+}
+
+#define E_BORDER_MOVE_KEY_DX 5
+#define E_BORDER_MOVE_KEY_DY 5
+static int
+_e_border_move_key_down(void *data, int type, void *event)
+{
+   Ecore_X_Event_Key_Down *ev = event;
+   int x, y;
+
+   if (ev->event_win != action_input_win)
+     return 1;
+   if (!action_border)
+     {
+	fprintf(stderr, "ERROR: no action_border!\n");
+	goto stop;
+     }
+
+   x = action_border->x;
+   y = action_border->y;
+
+   if (strcmp(ev->keysymbol, "Up") == 0)
+     y -= E_BORDER_MOVE_KEY_DY;
+   else if (strcmp(ev->keysymbol, "Down") == 0)
+     y += E_BORDER_MOVE_KEY_DY;
+   else if (strcmp(ev->keysymbol, "Left") == 0)
+     x -= E_BORDER_MOVE_KEY_DX;
+   else if (strcmp(ev->keysymbol, "Right") == 0)
+     x += E_BORDER_MOVE_KEY_DX;
+   else if (strcmp(ev->keysymbol, "Return") == 0)
+     goto stop;
+   else if (strcmp(ev->keysymbol, "Escape") == 0)
+     {
+	_e_border_action_restore_orig(action_border);
+	goto stop;
+     }
+
+   e_border_move(action_border, x, y);
+   e_move_update(x, y);
+   _e_border_action_timeout_add();
+
+   return 1;
+
+ stop:
+   _e_border_action_finish();
+   e_move_end();
+   return 0;
+}
+
 EAPI void
+e_border_act_move_keyboard(E_Border *bd)
+{
+   if (!bd)
+     return;
+   if (bd->lock_user_location)
+     return;
+
+   if (!_e_border_action_input_win_new(bd))
+     return;
+
+   e_move_begin(bd->zone, bd->x, bd->y);
+   _e_border_action_init(bd);
+
+   if (action_handler)
+     ecore_event_handler_del(action_handler);
+   action_handler = ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
+}
+
+#define E_BORDER_RESIZE_KEY_DX 5
+#define E_BORDER_RESIZE_KEY_DY 5
+static int
+_e_border_resize_key_down(void *data, int type, void *event)
+{
+   Ecore_X_Event_Key_Down *ev = event;
+   int w, h;
+
+   if (ev->event_win != action_input_win)
+     return 1;
+   if (!action_border)
+     {
+	fprintf(stderr, "ERROR: no action_border!\n");
+	goto stop;
+     }
+
+   w = action_border->w;
+   h = action_border->h;
+
+   if (strcmp(ev->keysymbol, "Up") == 0)
+     h -= E_BORDER_RESIZE_KEY_DY;
+   else if (strcmp(ev->keysymbol, "Down") == 0)
+     h += E_BORDER_RESIZE_KEY_DY;
+   else if (strcmp(ev->keysymbol, "Left") == 0)
+     w -= E_BORDER_RESIZE_KEY_DX;
+   else if (strcmp(ev->keysymbol, "Right") == 0)
+     w += E_BORDER_RESIZE_KEY_DX;
+   else if (strcmp(ev->keysymbol, "Return") == 0)
+     goto stop;
+   else if (strcmp(ev->keysymbol, "Escape") == 0)
+     {
+	_e_border_action_restore_orig(action_border);
+	goto stop;
+     }
+   else
+     goto stop;
+
+   e_border_resize(action_border, w, h);
+   e_resize_update(w, h);
+   _e_border_action_timeout_add();
+
+   return 1;
+
+ stop:
+   _e_border_action_finish();
+   e_resize_end();
+   return 0;
+}
+
+EAPI void
+e_border_act_resize_keyboard(E_Border *bd)
+{
+   if (!bd)
+     return;
+   if (bd->lock_user_size)
+     return;
+
+   if (!_e_border_action_input_win_new(bd))
+     return;
+
+   e_resize_begin(bd->zone, bd->w, bd->h);
+   _e_border_action_init(bd);
+
+   if (action_handler)
+     ecore_event_handler_del(action_handler);
+   action_handler = ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
+}
+
+EAPI void
 e_border_act_move_begin(E_Border *bd, Ecore_X_Event_Mouse_Button_Down *ev)
 {
    E_OBJECT_CHECK(bd);
Index: src/bin/e_border.h
===================================================================
--- src/bin/e_border.h	(revision 35979)
+++ src/bin/e_border.h	(working copy)
@@ -598,6 +598,9 @@
 
 EAPI Evas_List *e_border_client_list(void);
 
+EAPI void e_border_act_move_keyboard(E_Border *bd);
+EAPI void e_border_act_resize_keyboard(E_Border *bd);
+
 EAPI void e_border_act_move_begin(E_Border *bd, Ecore_X_Event_Mouse_Button_Down *ev);
 EAPI void e_border_act_move_end(E_Border *bd, Ecore_X_Event_Mouse_Button_Up *ev);
 EAPI void e_border_act_resize_begin(E_Border *bd, Ecore_X_Event_Mouse_Button_Down *ev);
Index: src/bin/e_actions.c
===================================================================
--- src/bin/e_actions.c	(revision 35979)
+++ src/bin/e_actions.c	(working copy)
@@ -123,6 +123,19 @@
    e_border_act_move_end((E_Border *)obj, ev);
 }
 
+ACT_FN_GO(window_move_keyboard)
+{
+   if (!obj) obj = E_OBJECT(e_border_focused_get());
+   if (!obj) return;
+   if (obj->type != E_BORDER_TYPE)
+     {
+	obj = E_OBJECT(e_border_focused_get());
+	if (!obj) return;
+     }
+   if (!((E_Border *)obj)->lock_user_location)
+     e_border_act_move_keyboard((E_Border *)obj);
+}
+
 /***************************************************************************/
 ACT_FN_GO(window_resize)
 {
@@ -174,6 +187,19 @@
    e_border_act_resize_end((E_Border *)obj, ev);
 }
 
+ACT_FN_GO(window_resize_keyboard)
+{
+   if (!obj) obj = E_OBJECT(e_border_focused_get());
+   if (!obj) return;
+   if (obj->type != E_BORDER_TYPE)
+     {
+	obj = E_OBJECT(e_border_focused_get());
+	if (!obj) return;
+     }
+   if (!((E_Border *)obj)->lock_user_size)
+     e_border_act_resize_keyboard((E_Border *)obj);
+}
+
 /***************************************************************************/
 ACT_FN_GO(window_menu)
 {
@@ -2254,6 +2280,11 @@
    ACT_GO_SIGNAL(window_move);
    ACT_END(window_move);
    ACT_END_MOUSE(window_move);
+
+   ACT_GO(window_move_keyboard);
+   e_action_predef_name_set(_("Window : Actions"), _("Move with Keyboard"),
+			    "window_move_keyboard", NULL, NULL, 0);
+
    
    /* window_resize */
    ACT_GO(window_resize);
@@ -2265,6 +2296,10 @@
    ACT_END(window_resize);
    ACT_END_MOUSE(window_resize);
 
+   ACT_GO(window_resize_keyboard);
+   e_action_predef_name_set(_("Window : Actions"), _("Resize with Keyboard"),
+			    "window_resize_keyboard", NULL, NULL, 0);
+
    /* window_menu */
    ACT_GO(window_menu);
    e_action_predef_name_set(_("Menu"), _("Window Menu"), 
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to