forked from enlightenment/enlightenment
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:
parent
7bac5692b1
commit
3fd7095f05
|
@ -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
|
||||
|
|
|
@ -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.
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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.
|
Loading…
Reference in New Issue