Move and Resize using keyboard.

These new shortcuts will trigger move and resize modes that are
interactive using keyboard. Use arrows to move or resize (left/top =
shrink, right/bottom = enlarge), presse Escape to abort, Return or
mouse click or timeout to confirm.

This should work like WindowMaker or Kwin.

TODO:
 - add customizable thresholds.
 - figure out what to do with the old action "Move" and "Resize",
   they're really useless for keyboard, just works with mouse.




SVN revision: 36010
This commit is contained in:
Gustavo Sverzut Barbieri 2008-09-16 00:11:26 +00:00
parent 35b67bef0b
commit ba3e4fc00d
3 changed files with 317 additions and 0 deletions

View File

@ -123,6 +123,19 @@ ACT_FN_END_MOUSE(window_move)
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 @@ ACT_FN_END_MOUSE(window_resize)
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 @@ e_actions_init(void)
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 @@ e_actions_init(void)
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"),

View File

@ -2608,6 +2608,285 @@ e_border_client_list()
return borders;
}
static Ecore_X_Window action_input_win = 0;
static E_Border *action_border = NULL;
static Ecore_Event_Handler *action_handler_key = NULL;
static Ecore_Event_Handler *action_handler_mouse = 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_key)
{
ecore_event_handler_del(action_handler_key);
action_handler_key = NULL;
}
if (action_handler_mouse)
{
ecore_event_handler_del(action_handler_mouse);
action_handler_mouse = 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)
{
fputs("ERROR: no action_border!\n", stderr);
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_border_action_timeout_add();
return 1;
stop:
_e_border_move_end(action_border);
_e_border_action_finish();
return 0;
}
static int
_e_border_move_mouse_down(void *data, int type, void *event)
{
Ecore_X_Event_Mouse_Button_Down *ev = event;
if (ev->event_win != action_input_win)
return 1;
if (!action_border)
fputs("ERROR: no action_border!\n", stderr);
_e_border_move_end(action_border);
_e_border_action_finish();
return 0;
}
EAPI void
e_border_act_move_keyboard(E_Border *bd)
{
if (!bd)
return;
if (!_e_border_move_begin(bd))
return;
if (!_e_border_action_input_win_new(bd))
{
_e_border_move_end(bd);
return;
}
_e_border_action_init(bd);
if (action_handler_key)
ecore_event_handler_del(action_handler_key);
action_handler_key = ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
if (action_handler_mouse)
ecore_event_handler_del(action_handler_mouse);
action_handler_mouse = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_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)
{
fputs("ERROR: no action_border!\n", stderr);
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_border_action_timeout_add();
return 1;
stop:
_e_border_resize_end(action_border);
_e_border_action_finish();
return 0;
}
static int
_e_border_resize_mouse_down(void *data, int type, void *event)
{
Ecore_X_Event_Mouse_Button_Down *ev = event;
if (ev->event_win != action_input_win)
return 1;
if (!action_border)
fputs("ERROR: no action_border!\n", stderr);
_e_border_resize_end(action_border);
_e_border_action_finish();
return 0;
}
EAPI void
e_border_act_resize_keyboard(E_Border *bd)
{
if (!bd)
return;
if (!_e_border_resize_begin(bd))
return;
if (!_e_border_action_input_win_new(bd))
{
_e_border_resize_end(bd);
return;
}
_e_border_action_init(bd);
if (action_handler_key)
ecore_event_handler_del(action_handler_key);
action_handler_key = ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
if (action_handler_mouse)
ecore_event_handler_del(action_handler_mouse);
action_handler_mouse = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
}
EAPI void
e_border_act_move_begin(E_Border *bd, Ecore_X_Event_Mouse_Button_Down *ev)
{

View File

@ -598,6 +598,9 @@ EAPI void e_border_idler_before(void);
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);