add access module - bare bones, but intercepts all mouse events and

handles gestures and passes on commands to the focused app or maybe
fakes a tap event on the screen location - depending. things that
could be done here:

1. config to select which actions happen as a result of which
events/gestures
2. config to determine which zones get this access setup and whihc
don't.



SVN revision: 71323
This commit is contained in:
Carsten Haitzler 2012-05-22 12:13:18 +00:00
parent 7bac5692b1
commit 3fd7095f05
7 changed files with 533 additions and 0 deletions

View File

@ -199,6 +199,10 @@ if USE_MODULE_TILING
SUBDIRS += tiling
endif
if USE_MODULE_ACCESS
SUBDIRS += access
endif
#if HAVE_WAYLAND_DRM
# SUBDIRS += wl_drm
#endif

View File

@ -0,0 +1,29 @@
MAINTAINERCLEANFILES = Makefile.in
MODULE = access
# data files for the module
filesdir = $(libdir)/enlightenment/modules/$(MODULE)
files_DATA = \
e-module-$(MODULE).edj module.desktop
EXTRA_DIST = $(files_DATA)
# the module .so file
INCLUDES = -I. \
-I$(top_srcdir) \
-I$(top_srcdir)/src/modules/$(MODULE) \
-I$(top_srcdir)/src/bin \
-I$(top_builddir)/src/bin \
-I$(top_srcdir)/src/modules \
@e_cflags@
pkgdir = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH)
pkg_LTLIBRARIES = module.la
module_la_SOURCES = e_mod_main.c \
e_mod_main.h \
e_mod_config.c
module_la_LIBADD = @e_libs@ @dlopen_libs@
module_la_LDFLAGS = -module -avoid-version
module_la_DEPENDENCIES = $(top_builddir)/config.h
uninstall:
rm -rf $(DESTDIR)$(libdir)/enlightenment/modules/$(MODULE)

Binary file not shown.

View File

@ -0,0 +1,80 @@
#include "e.h"
#include "e_mod_main.h"
struct _E_Config_Dialog_Data
{
int dummy;
};
/* local function prototypes */
static void *_create_data (E_Config_Dialog *cfd);
static void _fill_data (E_Config_Dialog_Data *cfdata);
static void _free_data (E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata);
static Evas_Object *_basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data *cfdata);
static int _basic_apply (E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata);
void
_config_pager_module(void)
{
E_Config_Dialog *cfd;
E_Config_Dialog_View *v;
E_Container *con;
if (e_config_dialog_find("E", "_e_mod_access_config_dialog"))
return;
v = E_NEW(E_Config_Dialog_View, 1);
if (!v) return;
v->create_cfdata = _create_data;
v->free_cfdata = _free_data;
v->basic.create_widgets = _basic_create;
v->basic.apply_cfdata = _basic_apply;
con = e_container_current_get(e_manager_current_get());
cfd = e_config_dialog_new(con, _("Access Settings"), "E",
"_e_mod_access_config_dialog",
"preferences-desktop-access", 0, v, NULL);
}
/* local function prototypes */
static void *
_create_data(E_Config_Dialog *cfd __UNUSED__)
{
E_Config_Dialog_Data *cfdata;
cfdata = E_NEW(E_Config_Dialog_Data, 1);
_fill_data(cfdata);
return cfdata;
}
static void
_fill_data(E_Config_Dialog_Data *cfdata)
{
cfdata->dummy = 1;
}
static void
_free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
{
E_FREE(cfdata);
}
static Evas_Object *
_basic_create(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data *cfdata)
{
Evas_Object *ol, *of;
ol = e_widget_list_add(evas, 0, 0);
of = e_widget_framelist_add(evas, _("General"), 0);
e_widget_list_object_append(ol, of, 1, 0, 0.5);
return ol;
}
static int
_basic_apply(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
{
e_config_save_queue();
return 1;
}

View File

@ -0,0 +1,404 @@
#include "e.h"
#include "e_mod_main.h"
typedef struct
{
E_Zone *zone;
Ecore_X_Window win;
Ecore_Timer *timer;
int x, y, dx, dy;
unsigned int dt;
Eina_Bool down : 1;
} Cover;
static Eina_List *covers = NULL;
static Eina_List *handlers = NULL;
static Ecore_X_Window
_mouse_win_in_get(Cover *cov, int x, int y)
{
Eina_List *l;
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)
{
skip[i] = cov2->win;
i++;
}
inwin = ecore_x_window_shadow_tree_at_xy_with_skip_get
(cov->zone->container->manager->root, x, y, skip, i);
return inwin;
}
static void
_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);
ecore_x_mouse_down_send(inwin, x, y, 1);
ecore_x_mouse_up_send(inwin, x, y, 1);
ecore_x_mouse_out_send(inwin, x, y);
}
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)
ecore_x_e_illume_access_action_read_send(bd->client.win);
}
return EINA_FALSE;
}
static void
_mouse_down(Cover *cov, Ecore_Event_Mouse_Button *ev)
{
double longtime = 0.5;
cov->dx = ev->x;
cov->dy = 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);
}
static void
_mouse_up(Cover *cov, Ecore_Event_Mouse_Button *ev)
{
double timeout = 0.15;
int distance = 40;
int dx, dy;
E_Border *bd = e_border_focused_get();
if (cov->timer)
{
ecore_timer_del(cov->timer);
cov->timer = NULL;
}
if (!cov->down) return;
dx = ev->x - cov->dx;
dy = ev->y - cov->dy;
if (((dx * dx) + (dy * dy)) < (distance * distance))
{
if ((ev->timestamp - cov->dt) > (timeout * 1000))
{
printf("tap\n");
_mouse_win_fake_tap(cov, ev);
}
else if (ev->double_click)
{
printf("double click\n");
if (bd)
ecore_x_e_illume_access_action_activate_send(bd->client.win);
}
}
else
{
if (abs(dx) > abs(dy)) // left or right
{
if (dx > 0) // right
{
printf("right\n");
if (bd)
ecore_x_e_illume_access_action_read_next_send(bd->client.win);
}
else // left
{
printf("left\n");
if (bd)
ecore_x_e_illume_access_action_read_prev_send(bd->client.win);
}
}
else // up or down
{
if (dy > 0) // down
{
printf("down\n");
if (bd)
ecore_x_e_illume_access_action_next_send(bd->client.win);
}
else // up
{
printf("up\n");
if (bd)
ecore_x_e_illume_access_action_prev_send(bd->client.win);
}
}
}
cov->down = EINA_FALSE;
}
static void
_mouse_move(Cover *cov, Ecore_Event_Mouse_Move *ev)
{
if (!cov->down) return;
cov->x = ev->x;
cov->y = ev->y;
}
static void
_mouse_wheel(Cover *cov __UNUSED__, Ecore_Event_Mouse_Wheel *ev __UNUSED__)
{
// XXX: fake wheel?
}
static Eina_Bool
_cb_mouse_down(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
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))
_mouse_down(cov, ev);
return ECORE_CALLBACK_PASS_ON;
}
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_cb_mouse_up(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
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))
_mouse_up(cov, ev);
return ECORE_CALLBACK_PASS_ON;
}
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_cb_mouse_move(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
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)
_mouse_move(cov, ev);
return ECORE_CALLBACK_PASS_ON;
}
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_cb_mouse_wheel(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_Event_Mouse_Wheel *ev = event;
Eina_List *l;
Cover *cov;
EINA_LIST_FOREACH(covers, l, cov)
{
if (ev->window == cov->win)
{
_mouse_wheel(cov, ev);
return ECORE_CALLBACK_PASS_ON;
}
}
return ECORE_CALLBACK_PASS_ON;
}
static Cover *
_cover_new(E_Zone *zone)
{
Cover *cov;
cov = E_NEW(Cover, 1);
if (!cov) return NULL;
cov->zone = zone;
cov->win = ecore_x_window_input_new(zone->container->manager->root,
zone->container->x + zone->x,
zone->container->y + zone->y,
zone->w, zone->h);
ecore_x_window_ignore_set(cov->win, 1);
ecore_x_window_configure(cov->win,
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
zone->container->layers[8].win,
ECORE_X_WINDOW_STACK_ABOVE);
ecore_x_window_show(cov->win);
return cov;
}
static void
_covers_init(void)
{
Eina_List *l, *l2, *l3;
E_Manager *man;
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);
}
}
}
}
static void
_covers_shutdown(void)
{
Cover *cov;
EINA_LIST_FREE(covers, cov)
{
ecore_x_window_ignore_set(cov->win, 0);
ecore_x_window_free(cov->win);
if (cov->timer)
{
ecore_timer_del(cov->timer);
cov->timer = NULL;
}
free(cov);
}
}
static Eina_Bool
_cb_zone_add(void *data __UNUSED__,
int type __UNUSED__,
void *event __UNUSED__)
{
_covers_init();
_covers_shutdown();
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_cb_zone_del(void *data __UNUSED__,
int type __UNUSED__,
void *event __UNUSED__)
{
_covers_init();
_covers_shutdown();
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_cb_zone_move_resize(void *data __UNUSED__,
int type __UNUSED__,
void *event __UNUSED__)
{
_covers_init();
_covers_shutdown();
return ECORE_CALLBACK_PASS_ON;
}
static void
_events_init(void)
{
handlers = eina_list_append
(handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
_cb_mouse_down, NULL));
handlers = eina_list_append
(handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
_cb_mouse_up, NULL));
handlers = eina_list_append
(handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
_cb_mouse_move, NULL));
handlers = eina_list_append
(handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
_cb_mouse_wheel, NULL));
handlers = eina_list_append
(handlers, ecore_event_handler_add(E_EVENT_ZONE_ADD,
_cb_zone_add, NULL));
handlers = eina_list_append
(handlers, ecore_event_handler_add(E_EVENT_ZONE_DEL,
_cb_zone_del, NULL));
handlers = eina_list_append
(handlers, ecore_event_handler_add(E_EVENT_ZONE_MOVE_RESIZE,
_cb_zone_move_resize, NULL));
}
static void
_events_shutdown(void)
{
E_FREE_LIST(handlers, ecore_event_handler_del);
}
/***************************************************************************/
/* module setup */
EAPI E_Module_Api e_modapi =
{
E_MODULE_API_VERSION, "Access"
};
EAPI void *
e_modapi_init(E_Module *m)
{
_events_init();
_covers_init();
return m;
}
EAPI int
e_modapi_shutdown(E_Module *m __UNUSED__)
{
_covers_shutdown();
_events_shutdown();
return 1;
}
EAPI int
e_modapi_save(E_Module *m __UNUSED__)
{
return 1;
}

View File

@ -0,0 +1,10 @@
#ifndef E_MOD_MAIN_H
#define E_MOD_MAIN_H
EAPI extern E_Module_Api e_modapi;
EAPI void *e_modapi_init(E_Module *m);
EAPI int e_modapi_shutdown(E_Module *m);
EAPI int e_modapi_save(E_Module *m);
#endif

View File

@ -0,0 +1,6 @@
[Desktop Entry]
Type=Link
Name=Access
Icon=e-module-access
X-Enlightenment-ModuleType=utils
Comment=Accessibility module designed to improve ease of use for the vision impaired and the blind.