From 4d8b3bea449b1b2fc5b4d5e11b7003b389cc83f0 Mon Sep 17 00:00:00 2001 From: Kim Shinwoo Date: Mon, 3 Sep 2012 04:06:02 +0000 Subject: [PATCH] From: Kim Shinwoo i have revised the access module and attached. you can find the following in the patch. - mouse double tap and move gesture for each direction - two finger flicking for each direction - two finger panning SVN revision: 75945 --- AUTHORS | 1 + src/modules/access/e_mod_main.c | 269 +++++++++++++++++++++++++++++--- 2 files changed, 245 insertions(+), 25 deletions(-) diff --git a/AUTHORS b/AUTHORS index 85ffc91e4..338116677 100644 --- a/AUTHORS +++ b/AUTHORS @@ -36,3 +36,4 @@ q66 Tom Hacohen (TAsn) Maxime Villard Jeremy Zurcher +Shinwoo Kim diff --git a/src/modules/access/e_mod_main.c b/src/modules/access/e_mod_main.c index 3a966b512..b12fc89b7 100644 --- a/src/modules/access/e_mod_main.c +++ b/src/modules/access/e_mod_main.c @@ -1,18 +1,31 @@ #include "e.h" #include "e_mod_main.h" +#define HISTORY_MAX 8 typedef struct { E_Zone *zone; Ecore_X_Window win; Ecore_Timer *timer; - int x, y, dx, dy; + Ecore_Timer *double_down_timer; + int x, y, dx, dy, mx, my; + int mouse_history[HISTORY_MAX]; unsigned int dt; + Eina_Inlist *history; Eina_Bool down : 1; + Eina_Bool two_finger_down : 1; + Eina_Bool mouse_double_down : 1; } Cover; +typedef struct +{ + EINA_INLIST; + int device; +} Multi; + static Eina_List *covers = NULL; static Eina_List *handlers = NULL; +static int multi_device[3]; static Ecore_X_Window _mouse_win_in_get(Cover *cov, int x, int y) @@ -21,7 +34,7 @@ _mouse_win_in_get(Cover *cov, int x, int y) Ecore_X_Window *skip, inwin; Cover *cov2; int i; - + skip = alloca(sizeof(Ecore_X_Window) * eina_list_count(covers)); i = 0; EINA_LIST_FOREACH(covers, l, cov2) @@ -31,6 +44,7 @@ _mouse_win_in_get(Cover *cov, int x, int y) } inwin = ecore_x_window_shadow_tree_at_xy_with_skip_get (cov->zone->container->manager->root, x, y, skip, i); + return inwin; } @@ -39,8 +53,9 @@ _mouse_win_fake_tap(Cover *cov, Ecore_Event_Mouse_Button *ev) { Ecore_X_Window inwin; int x, y; - + inwin = _mouse_win_in_get(cov, ev->root.x, ev->root.y); + ecore_x_pointer_xy_get(inwin, &x, &y); ecore_x_mouse_in_send(inwin, x, y); ecore_x_mouse_move_send(inwin, x, y); @@ -49,20 +64,59 @@ _mouse_win_fake_tap(Cover *cov, Ecore_Event_Mouse_Button *ev) ecore_x_mouse_out_send(inwin, x, y); } +static void +_record_mouse_history(Cover *cov, void *event) +{ + Ecore_Event_Mouse_Move *ev = event; + int i = 0; + + for (i = 0; i < HISTORY_MAX; i++) + { + if (cov->mouse_history[i] == -1) + { + cov->mouse_history[i] = ev->multi.device; + break; + } + } + + // if there is not enough space to save device number, shift! + if (i == HISTORY_MAX) + { + for (i = 0; i < (HISTORY_MAX - 1); i++) + cov->mouse_history[i] = cov->mouse_history[i + 1]; + cov->mouse_history[HISTORY_MAX - 1] = ev->multi.device; + } +} + +static Eina_Bool +_check_mouse_history(Cover *cov) +{ + int i = 0; + + for (i = 0; i < HISTORY_MAX; i++) + { + if ((cov->mouse_history[i] != multi_device[0]) && + (cov->mouse_history[i] != -1)) + return EINA_FALSE; + } + + return EINA_TRUE; +} + static Eina_Bool _mouse_longpress(void *data) { Cover *cov = data; int distance = 40; int dx, dy; - + cov->timer = NULL; dx = cov->x - cov->dx; dy = cov->y - cov->dy; if (((dx * dx) + (dy * dy)) < (distance * distance)) { E_Border *bd = e_border_focused_get(); - + cov->down = EINA_FALSE; printf("longpress\n"); if (bd) @@ -71,18 +125,76 @@ _mouse_longpress(void *data) return EINA_FALSE; } +static Eina_Bool +_mouse_double_down(void *data) +{ + Cover *cov = data; + + ecore_timer_del(cov->double_down_timer); + cov->double_down_timer = NULL; + return EINA_FALSE; +} + +static void +_mouse_double_down_timeout(Cover *cov) +{ + double short_time = 0.3; + int distance = 40; + int dx, dy; + + dx = cov->x - cov->dx; + dy = cov->y - cov->dy; + + if ((cov->double_down_timer) && + (((dx * dx) + (dy * dy)) < (distance * distance))) + { + // start double tap and move from here + cov->mouse_double_down = EINA_TRUE; + + if (cov->timer) + { + ecore_timer_del(cov->timer); + cov->timer = NULL; + } + } + + if (cov->double_down_timer) + { + ecore_timer_del(cov->double_down_timer); + cov->double_down_timer = NULL; + return; + } + + cov->double_down_timer = ecore_timer_add(short_time, _mouse_double_down, + cov); +} + static void _mouse_down(Cover *cov, Ecore_Event_Mouse_Button *ev) { + int x, y; + E_Border *bd; double longtime = 0.5; - + cov->dx = ev->x; cov->dy = ev->y; + cov->mx = ev->x; + cov->my = ev->y; cov->x = ev->x; cov->y = ev->y; cov->dt = ev->timestamp; cov->down = EINA_TRUE; cov->timer = ecore_timer_add(longtime, _mouse_longpress, cov); + + // 2nd finger comes... + _mouse_double_down_timeout(cov); + + // mouse in should be here + bd = e_border_focused_get(); + if (!bd) return; + + ecore_x_pointer_xy_get(bd->client.win, &x, &y); + ecore_x_mouse_in_send(bd->client.win, x, y); } static void @@ -91,8 +203,22 @@ _mouse_up(Cover *cov, Ecore_Event_Mouse_Button *ev) double timeout = 0.15; int distance = 40; int dx, dy; + int x, y; + E_Border *bd = e_border_focused_get(); - + + // for two finger panning + if (cov->two_finger_down) + { + ecore_x_pointer_xy_get(bd->client.win, &x, &y); + ecore_x_mouse_up_send(bd->client.win, x, y, 1); + cov->two_finger_down = EINA_FALSE; + ecore_x_mouse_out_send(bd->client.win, x, y); + } + + // reset double down and moving + cov->mouse_double_down = EINA_FALSE; + if (cov->timer) { ecore_timer_del(cov->timer); @@ -115,19 +241,26 @@ _mouse_up(Cover *cov, Ecore_Event_Mouse_Button *ev) ecore_x_e_illume_access_action_activate_send(bd->client.win); } } - else + else if (((dx * dx) + (dy * dy)) > (4 * distance * distance) + && ((ev->timestamp - cov->dt) < (timeout * 1000))) { if (abs(dx) > abs(dy)) // left or right { if (dx > 0) // right { - printf("right\n"); + if (_check_mouse_history(cov)) + printf("single flick right\n"); + else + printf("double flick right\n"); if (bd) ecore_x_e_illume_access_action_read_next_send(bd->client.win); } else // left { - printf("left\n"); + if (_check_mouse_history(cov)) + printf("single flick left\n"); + else + printf("double flick left\n"); if (bd) ecore_x_e_illume_access_action_read_prev_send(bd->client.win); } @@ -136,13 +269,20 @@ _mouse_up(Cover *cov, Ecore_Event_Mouse_Button *ev) { if (dy > 0) // down { - printf("down\n"); + if (_check_mouse_history(cov)) + printf("single flick down\n"); + else + printf("double flick down\n"); + if (bd) ecore_x_e_illume_access_action_next_send(bd->client.win); } else // up { - printf("up\n"); + if (_check_mouse_history(cov)) + printf("single flick up\n"); + else + printf("double flick up\n"); if (bd) ecore_x_e_illume_access_action_prev_send(bd->client.win); } @@ -154,9 +294,50 @@ _mouse_up(Cover *cov, Ecore_Event_Mouse_Button *ev) static void _mouse_move(Cover *cov, Ecore_Event_Mouse_Move *ev) { - if (!cov->down) return; + int distance = 5; + int x, y; + int dx, dy; + E_Border *bd; + + //FIXME: why here.. after long press you cannot go below.. + //if (!cov->down) return; cov->x = ev->x; cov->y = ev->y; + + bd = e_border_focused_get(); + if (!bd) return; + + _record_mouse_history(cov, ev); + + ecore_x_pointer_xy_get(bd->client.win, &x, &y); + ecore_x_mouse_move_send(bd->client.win, x, y); + + // for panning, without check two_finger_down, there will be several down_send() + if ((ev->multi.device == multi_device[0]) && (cov->mouse_double_down)) + { + dx = ev->x - cov->mx; + dy = ev->y - cov->my; + if (((dx * dx) + (dy * dy)) > (distance * distance)) + { + + if (abs(dx) > abs(dy)) // left or right + { + if (dx > 0) // right + printf("mouse double down and moving - right\n"); + else // left + printf("mouse double down and moving - left\n"); + } + else // up or down + { + if (dy > 0) // down + printf("mouse double down and moving - down\n"); + else // up + printf("mouse double down and moving - up\n"); + } + cov->mx = ev->x; + cov->my = ev->y; + } + } } static void @@ -173,13 +354,38 @@ _cb_mouse_down(void *data __UNUSED__, Ecore_Event_Mouse_Button *ev = event; Eina_List *l; Cover *cov; - + int i = 0; + E_Border *bd; + int x, y; + + for (i = 0; i < 3; i++) + { + if (multi_device[i] == -1) + { + multi_device[i] = ev->multi.device; + break; + } + else if (multi_device[i] == ev->multi.device) break; + } + EINA_LIST_FOREACH(covers, l, cov) { if (ev->window == cov->win) { - if ((ev->buttons == 1) && (ev->multi.device == 0)) + // XXX change specific number + if (ev->multi.device == multi_device[0]) _mouse_down(cov, ev); + + if ((ev->multi.device == multi_device[1]) && + (!cov->two_finger_down)) + { + bd = e_border_focused_get(); + if (!bd) return ECORE_CALLBACK_PASS_ON; + ecore_x_pointer_xy_get(bd->client.win, &x, &y); + ecore_x_mouse_move_send(bd->client.win, x, y); + ecore_x_mouse_down_send(bd->client.win, x, y, 1); + cov->two_finger_down = EINA_TRUE; + } return ECORE_CALLBACK_PASS_ON; } } @@ -194,12 +400,12 @@ _cb_mouse_up(void *data __UNUSED__, Ecore_Event_Mouse_Button *ev = event; Eina_List *l; Cover *cov; - + EINA_LIST_FOREACH(covers, l, cov) { if (ev->window == cov->win) { - if ((ev->buttons == 1) && (ev->multi.device == 0)) + if (ev->buttons == 1) _mouse_up(cov, ev); return ECORE_CALLBACK_PASS_ON; } @@ -215,12 +421,12 @@ _cb_mouse_move(void *data __UNUSED__, Ecore_Event_Mouse_Move *ev = event; Eina_List *l; Cover *cov; - EINA_LIST_FOREACH(covers, l, cov) { if (ev->window == cov->win) { - if (ev->multi.device == 0) + if ((ev->multi.device == multi_device[0]) || + (ev->multi.device == multi_device[1])) _mouse_move(cov, ev); return ECORE_CALLBACK_PASS_ON; } @@ -236,7 +442,7 @@ _cb_mouse_wheel(void *data __UNUSED__, Ecore_Event_Mouse_Wheel *ev = event; Eina_List *l; Cover *cov; - + EINA_LIST_FOREACH(covers, l, cov) { if (ev->window == cov->win) @@ -252,7 +458,7 @@ static Cover * _cover_new(E_Zone *zone) { Cover *cov; - + cov = E_NEW(Cover, 1); if (!cov) return NULL; cov->zone = zone; @@ -260,6 +466,9 @@ _cover_new(E_Zone *zone) zone->container->x + zone->x, zone->container->y + zone->y, zone->w, zone->h); + + ecore_x_input_multi_select(cov->win); + ecore_x_window_ignore_set(cov->win, 1); ecore_x_window_configure(cov->win, ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING | @@ -268,6 +477,8 @@ _cover_new(E_Zone *zone) zone->container->layers[8].win, ECORE_X_WINDOW_STACK_ABOVE); ecore_x_window_show(cov->win); + ecore_x_window_raise(cov->win); + return cov; } @@ -276,19 +487,23 @@ _covers_init(void) { Eina_List *l, *l2, *l3; E_Manager *man; + int i = 0; EINA_LIST_FOREACH(e_manager_list(), l, man) { E_Container *con; - EINA_LIST_FOREACH(man->containers, l2, con) { E_Zone *zone; - EINA_LIST_FOREACH(con->zones, l3, zone) { Cover *cov = _cover_new(zone); - if (cov) covers = eina_list_append(covers, cov); + if (cov) + { + covers = eina_list_append(covers, cov); + for (i = 0; i < HISTORY_MAX; i++) + cov->mouse_history[i] = -1; + } } } } @@ -298,7 +513,7 @@ static void _covers_shutdown(void) { Cover *cov; - + EINA_LIST_FREE(covers, cov) { ecore_x_window_ignore_set(cov->win, 0); @@ -345,6 +560,8 @@ _cb_zone_move_resize(void *data __UNUSED__, static void _events_init(void) { + int i = 0; + handlers = eina_list_append (handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _cb_mouse_down, NULL)); @@ -366,6 +583,8 @@ _events_init(void) handlers = eina_list_append (handlers, ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE, _cb_zone_move_resize, NULL)); + + for (i = 0; i < 3; i++) multi_device[i] = -1; } static void