diff options
author | Vincent Torri <vincent.torri@gmail.com> | 2012-12-02 22:35:45 +0000 |
---|---|---|
committer | Vincent Torri <vincent.torri@gmail.com> | 2012-12-02 22:35:45 +0000 |
commit | 7d6010b12c47a20e492da808e3192c3f87dab619 (patch) | |
tree | 26c6fd189e046a76560c0bc740b85f4d767ae399 /src/lib/ecore_fb | |
parent | 53fc441d5475155965d92da89502fe4634a561b2 (diff) | |
download | efl-7d6010b12c47a20e492da808e3192c3f87dab619.tar.gz |
merge: add escape ecore, fix several bugs
SVN revision: 79995
Diffstat (limited to 'src/lib/ecore_fb')
-rw-r--r-- | src/lib/ecore_fb/Ecore_Fb.h | 100 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb.c | 129 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_kbd.c | 326 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_keytable.h | 129 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_li.c | 721 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_private.h | 94 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_ps2.c | 223 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_ts.c | 362 | ||||
-rw-r--r-- | src/lib/ecore_fb/ecore_fb_vt.c | 322 |
9 files changed, 2406 insertions, 0 deletions
diff --git a/src/lib/ecore_fb/Ecore_Fb.h b/src/lib/ecore_fb/Ecore_Fb.h new file mode 100644 index 0000000000..069cccdff9 --- /dev/null +++ b/src/lib/ecore_fb/Ecore_Fb.h @@ -0,0 +1,100 @@ +#ifndef _ECORE_FB_H +#define _ECORE_FB_H + +#include <Eina.h> + +#ifdef EAPI +# undef EAPI +#endif + +#ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#else +# define EAPI +#endif + +/* FIXME: + * maybe a new module? + * - code to get battery info + * - code to get thermal info + * ecore evas fb isn't good enough for weird things, like multiple fb's, same happens here. + * backlight support using new kernel interface + * absolute axis + * joystick + * ecore_fb_li_device_close_all ? or a shutdown of the subsystem? + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions. + * + * Functions used to set up and shut down the Ecore_Framebuffer functions. + * + * @{ + */ + +/** + * @typedef Ecore_Fb_Input_Device + * Input device handler. + */ +typedef struct _Ecore_Fb_Input_Device Ecore_Fb_Input_Device; + +/** + * @enum _Ecore_Fb_Input_Device_Cap + * Device capabilities. + */ +enum _Ecore_Fb_Input_Device_Cap +{ + ECORE_FB_INPUT_DEVICE_CAP_NONE = 0x00000000, + ECORE_FB_INPUT_DEVICE_CAP_RELATIVE = 0x00000001, + ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE = 0x00000002, + ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS = 0x00000004 +}; + +/** + * @typedef Ecore_Fb_Input_Device_Cap + * Device capabilities. + */ +typedef enum _Ecore_Fb_Input_Device_Cap Ecore_Fb_Input_Device_Cap; + +/* ecore_fb_vt.c */ +EAPI void ecore_fb_callback_gain_set(void (*func) (void *data), void *data); +EAPI void ecore_fb_callback_lose_set(void (*func) (void *data), void *data); + +/* ecore_fb_li.c */ +EAPI Ecore_Fb_Input_Device *ecore_fb_input_device_open(const char *dev); +EAPI void ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev); +EAPI void ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, Eina_Bool listen); +EAPI const char *ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev); +EAPI Ecore_Fb_Input_Device_Cap ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev); +EAPI void ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h); +EAPI void ecore_fb_input_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold); +EAPI double ecore_fb_input_threshold_click_get(Ecore_Fb_Input_Device *dev); +EAPI void ecore_fb_input_device_window_set(Ecore_Fb_Input_Device *dev, void *window); + +/* ecore_fb.c */ + +EAPI int ecore_fb_init(const char *name); +EAPI int ecore_fb_shutdown(void); +EAPI void ecore_fb_size_get(int *w, int *h); + +EAPI void ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap); +EAPI void ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/ecore_fb/ecore_fb.c b/src/lib/ecore_fb/ecore_fb.c new file mode 100644 index 0000000000..ff96ac8a77 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb.c @@ -0,0 +1,129 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "Ecore_Fb.h" +#include "ecore_fb_private.h" + +static void _ecore_fb_size_get(int *w, int *h); + +static int _ecore_fb_init_count = 0; +static int _ecore_fb_console_w = 0; +static int _ecore_fb_console_h = 0; + +/** + * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions. + * + * @{ + */ + +static sighandler_t oldhand = NULL; + +static void +nosigint(int val EINA_UNUSED) +{ +} + +/** + * @brief Initialize the Ecore_Fb library. + * + * @param name Device target name. + * @return 1 or greater on success, 0 on error. + * + * This function sets up all the Ecore_Fb library. It returns 0 on + * failure, otherwise it returns the number of times it has already + * been called. + * + * When Ecore_Fb is not used anymore, call ecore_fb_shutdown() to shut down + * the Ecore_Fb library. + */ +EAPI int +ecore_fb_init(const char *name EINA_UNUSED) +{ + if (++_ecore_fb_init_count != 1) + return _ecore_fb_init_count; + + if (!ecore_fb_vt_init()) + return --_ecore_fb_init_count; + + if (!oldhand) + { + oldhand = signal(SIGINT, nosigint); + } + + _ecore_fb_size_get(&_ecore_fb_console_w, &_ecore_fb_console_h); + + return _ecore_fb_init_count; +} + +/** + * @brief Shut down the Ecore_Fb library. + * + * @return 0 when the library is completely shut down, 1 or + * greater otherwise. + * + * This function shuts down the Ecore_Fb library. It returns 0 when it has + * been called the same number of times than ecore_fb_init(). + */ +EAPI int +ecore_fb_shutdown(void) +{ + if (--_ecore_fb_init_count != 0) + return _ecore_fb_init_count; + + if (oldhand) + { + signal(SIGINT, oldhand); + oldhand = NULL; + } + + ecore_fb_vt_shutdown(); + + return _ecore_fb_init_count; +} + + +/** + * @brief Retrieve the width and height of the current frame buffer in + * pixels. + * + * @param w Pointer to an integer in which to store the width. + * @param h Pointer to an interge in which to store the height. + * + * This function retrieves the size of the current frame buffer in + * pixels. @p w and @p h can be buffers that will be filled with the + * corresponding values. If one of them is @c NULL, nothing will be + * done for that parameter. + */ +EAPI void +ecore_fb_size_get(int *w, int *h) +{ + if (w) *w = _ecore_fb_console_w; + if (h) *h = _ecore_fb_console_h; +} + +static void +_ecore_fb_size_get(int *w, int *h) +{ + struct fb_var_screeninfo fb_var; + int fb; + + fb = open("/dev/fb0", O_RDWR); + if (fb < 0) + goto exit; + + if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1) + goto err_ioctl; + + *w = fb_var.xres; + *h = fb_var.yres; + +err_ioctl: + close(fb); +exit: + return; +} + +/** + * @} + */ diff --git a/src/lib/ecore_fb/ecore_fb_kbd.c b/src/lib/ecore_fb/ecore_fb_kbd.c new file mode 100644 index 0000000000..fd111db04d --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_kbd.c @@ -0,0 +1,326 @@ +static void _ecore_fb_event_free_key_down(void *data, void *ev); +static void _ecore_fb_event_free_key_up(void *data, void *ev); + +static const char *_ecore_fb_kbd_syms[128 * 7] = +{ +#include "ecore_fb_keytable.h" +}; + +static const char *_ecore_fb_btn_syms[128] = +{ + "0x00", + "Escape", + "F1", + "F2", + "F3", + "F4", + "Up", + "Right", + "Left", + "Down", + "Return", + "0x1b", + "0x1c", + "0x1d", + "0x1e", + "0x1f", + "0x20", + "0x21", + "0x22", + "0x23", + "0x24", + "0x25", + "0x26", + "0x27", + "0x28", + "0x29", + "0x2a", + "0x2b", + "0x2c", + "0x2d", + "0x2e", + "0x2f", + "0x30", + "0x31", + "0x32", + "0x33", + "0x34", + "0x35", + "0x36", + "0x37", + "0x38", + "0x39", + "0x3a", + "0x3b", + "0x3c", + "0x3d", + "0x3e", + "0x3f", + "0x40", + "0x41", + "0x42", + "0x43", + "0x44", + "0x45", + "0x46", + "0x47", + "0x48", + "0x49", + "0x4a", + "0x4b", + "0x4c", + "0x4d", + "0x4e", + "0x4f", + "0x50", + "0x51", + "0x52", + "0x53", + "0x54", + "0x55", + "0x56", + "0x57", + "0x58", + "0x59", + "0x5a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0x5f", + "0x60", + "0x61", + "0x62", + "0x63", + "0x64", + "0x65", + "0x66", + "0x67", + "0x68", + "0x69", + "0x6a", + "0x6b", + "0x6c", + "0x6d", + "0x6e", + "0x6f", + "0x70", + "0x71", + "0x72", + "0x73", + "0x74", + "0x75", + "0x76", + "0x77", + "0x78", + "0x79", + "0x7a", + "0x7b", + "0x7c", + "0x7d", + "0x7e", + "0x7f" +}; +static int _ecore_fb_kbd_fd = -1; +static int _ecore_fb_ctrl = 0; +static int _ecore_fb_alt = 0; +static int _ecore_fb_shift = 0; +static int _ecore_fb_lock = 0; + +static Ecore_Fd_Handler *_ecore_fb_kbd_fd_handler_handle = NULL; +static Eina_Bool _ecore_fb_kbd_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); + +static void +_ecore_fb_event_free_key_down(void *data EINA_UNUSED, void *ev) +{ + Ecore_Fb_Event_Key_Down *e; + e = ev; + free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static void +_ecore_fb_event_free_key_up(void *data EINA_UNUSED, void *ev) +{ + Ecore_Fb_Event_Key_Up *e; + + e = ev; + free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static Eina_Bool +_ecore_fb_kbd_fd_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + int v = 0; + + do + { + unsigned char buf; + + v = read(_ecore_fb_kbd_fd, &buf, 1); + if (v < 0) return EINA_TRUE; + if (v < 1) return EINA_TRUE; + if (!(buf & 0x80)) + { + /* DOWN */ + int vt_switch = -1; + Ecore_Fb_Event_Key_Down *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Key_Down)); + if (!e) goto retry; + if (_ecore_fb_kbd_fd == _ecore_fb_tty_fd) + { + int add = 0; + + if (_ecore_fb_shift) add = 1; + else if (_ecore_fb_lock) add = 2; + e->keyname = strdup(_ecore_fb_kbd_syms[(buf & 0x7f) * 7]); + e->keysymbol = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 7) + add]); + e->key_compose = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 7) + 3 + add]); + } + else + e->keyname = strdup(_ecore_fb_btn_syms[buf & 0x7f]); + if (!e->keyname) + { + free(e); + goto retry; + } + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + if (!strcmp(e->keyname, "Control_L")) + _ecore_fb_ctrl++; + else if (!strcmp(e->keyname, "Control_R")) + _ecore_fb_ctrl++; + else if (!strcmp(e->keyname, "Alt_L")) + _ecore_fb_alt++; + else if (!strcmp(e->keyname, "Alt_R")) + _ecore_fb_alt++; + else if (!strcmp(e->keyname, "Shift_L")) + _ecore_fb_shift++; + else if (!strcmp(e->keyname, "Shift_R")) + _ecore_fb_shift++; + else if (!strcmp(e->keyname, "Caps_Lock")) + _ecore_fb_lock++; + else if (!strcmp(e->keyname, "F1")) vt_switch = 0; + else if (!strcmp(e->keyname, "F2")) vt_switch = 1; + else if (!strcmp(e->keyname, "F3")) vt_switch = 2; + else if (!strcmp(e->keyname, "F4")) vt_switch = 3; + else if (!strcmp(e->keyname, "F5")) vt_switch = 4; + else if (!strcmp(e->keyname, "F6")) vt_switch = 5; + else if (!strcmp(e->keyname, "F7")) vt_switch = 6; + else if (!strcmp(e->keyname, "F8")) vt_switch = 7; + else if (!strcmp(e->keyname, "F9")) vt_switch = 8; + else if (!strcmp(e->keyname, "F10")) vt_switch = 9; + else if (!strcmp(e->keyname, "F11")) vt_switch = 10; + else if (!strcmp(e->keyname, "F12")) vt_switch = 11; + if (_ecore_fb_ctrl > 2) _ecore_fb_ctrl = 2; + if (_ecore_fb_alt > 2) _ecore_fb_alt = 2; + if ((_ecore_fb_kbd_fd == _ecore_fb_tty_fd) && + (_ecore_fb_ctrl)) + { + const char *ts = _ecore_fb_kbd_syms[(buf & 0x7f) + 3 + 3]; + + if (ts) + { + if (e->key_compose) free(e->key_compose); + e->key_compose = strdup(ts); + } + } + if ((vt_switch >= 0) && + (_ecore_fb_ctrl) && + (_ecore_fb_alt)) + _ecore_fb_vt_switch(vt_switch); + ecore_event_add(ECORE_FB_EVENT_KEY_DOWN, e, _ecore_fb_event_free_key_down, NULL); + } + else + { + /* UP */ + Ecore_Fb_Event_Key_Up *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Key_Up)); + if (!e) goto retry; + if (_ecore_fb_kbd_fd == _ecore_fb_tty_fd) + { + int add = 0; + + if (_ecore_fb_shift) add = 1; + else if (_ecore_fb_lock) add = 2; + e->keyname = strdup(_ecore_fb_kbd_syms[(buf & 0x7f) * 7]); + e->keysymbol = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 7) + add]); + e->key_compose = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 7) + 3 + add]); + } + else + e->keyname = strdup(_ecore_fb_btn_syms[buf & 0x7f]); + if (!e->keyname) + { + free(e); + goto retry; + } + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_FB_EVENT_KEY_UP, e, _ecore_fb_event_free_key_up, NULL); + if (!strcmp(e->keyname, "Control_L")) + _ecore_fb_ctrl--; + else if (!strcmp(e->keyname, "Control_R")) + _ecore_fb_ctrl--; + else if (!strcmp(e->keyname, "Alt_L")) + _ecore_fb_alt--; + else if (!strcmp(e->keyname, "Alt_R")) + _ecore_fb_alt--; + else if (!strcmp(e->keyname, "Shift_L")) + _ecore_fb_shift--; + else if (!strcmp(e->keyname, "Shift_R")) + _ecore_fb_shift--; + else if (!strcmp(e->keyname, "Caps_Lock")) + _ecore_fb_lock--; + if (_ecore_fb_ctrl < 0) _ecore_fb_ctrl = 0; + if (_ecore_fb_alt < 0) _ecore_fb_alt = 0; + if (_ecore_fb_shift < 0) _ecore_fb_shift = 0; + if (_ecore_fb_lock < 0) _ecore_fb_lock = 0; + } +retry: + ; + } + while (v > 0); + return EINA_TRUE; +} + +int +ecore_fb_kbd_init(void) +{ + int prev_flags; + + prev_flags = fcntl(_ecore_fb_kbd_fd, F_GETFL); + fcntl(_ecore_fb_kbd_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_kbd_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_kbd_fd, + ECORE_FD_READ, + _ecore_fb_kbd_fd_handler, NULL, + NULL, NULL); + if(!_ecore_fb_kbd_fd_handler_handle) return 0; + return 1; +} + +void +ecore_fb_kbd_shutdown(void) +{ + if (_ecore_fb_kbd_fd_handler_handle) + ecore_main_fd_handler_del(_ecore_fb_kbd_fd_handler_handle); + if (_ecore_fb_kbd_fd >= 0) close(_ecore_fb_kbd_fd); + _ecore_fb_kbd_fd = -1; + _ecore_fb_kbd_fd_handler_handle = NULL; + _ecore_fb_ctrl = 0; + _ecore_fb_lock = 0; + _ecore_fb_shift = 0; + _ecore_fb_alt = 0; +} diff --git a/src/lib/ecore_fb/ecore_fb_keytable.h b/src/lib/ecore_fb/ecore_fb_keytable.h new file mode 100644 index 0000000000..70bf6b9689 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_keytable.h @@ -0,0 +1,129 @@ +/* this table was taken from ecore_fb, is the default en layout */ + "0x00", "0x00", "0x00", /**/"", "", "", NULL,/***/ + "Escape", "Escape", "Escape", /**/"", "", "", "\x1b",/***/ + "1", "exclam", "1", /**/"1", "!", "1", NULL,/***/ + "2", "at", "2", /**/"2", "@", "2", "",/***/ + "3", "numbersign", "3", /**/"3", "#", "3", "\x1b",/***/ + "4", "dollar", "4", /**/"4", "$", "4", "\x1c",/***/ + "5", "percent", "5", /**/"5", "%", "5", "\x1d",/***/ + "6", "asciicircumm", "6", /**/"6", "^", "6", "\x1e",/***/ + "7", "ampersand", "7", /**/"7", "&", "7", "\x1f",/***/ + "8", "asterisk", "8", /**/"8", "*", "8", "\x7f",/***/ + "9", "parenleft", "9", /**/"9", "(", "9", NULL,/***/ + "0", "parenright", "0", /**/"0", ")", "0", NULL,/***/ + "minus", "underscore", "minus", /**/"-", "_", "-", NULL,/***/ + "equal", "plus", "equal", /**/"=", "+", "=", NULL,/***/ + "BackSpace", "BackSpace", "BackSpace", /**/"\010","\010","\010", NULL,/***/ + "Tab", "ISO_Left_Tab", "Tab", /**/"\011","", "\011", NULL,/***/ + "q", "Q", "Q", /**/"q", "Q", "Q", "\x11",/***/ + "w", "W", "W", /**/"w", "W", "W", "\x17",/***/ + "e", "E", "E", /**/"e", "E", "E", "\x05",/***/ + "r", "R", "R", /**/"r", "R", "R", "\x12",/***/ + "t", "T", "T", /**/"t", "T", "T", "\x14",/***/ + "y", "Y", "Y", /**/"y", "Y", "Y", "\x19",/***/ + "u", "U", "U", /**/"u", "U", "U", "\x15",/***/ + "i", "I", "I", /**/"i", "I", "I", "\x09",/***/ + "o", "O", "O", /**/"o", "O", "O", "\x0f",/***/ + "p", "P", "P", /**/"p", "P", "P", "\x10",/***/ + "bracketleft", "braceleft", "bracketleft", /**/"[", "{", "[", "\x1b",/***/ + "bracketright", "braceright", "bracketright", /**/"]", "}", "]", "\x1d",/***/ + "Return", "Return", "Return", /**/"\015","\015","\015", NULL,/***/ + "Control_L", "Control_L", "Control_L", /**/"", "", "", NULL,/***/ + "a", "A", "A", /**/"a", "A", "A", "\x01",/***/ + "s", "S", "S", /**/"s", "S", "S", "\x13",/***/ + "d", "D", "D", /**/"d", "D", "D", "\x04",/***/ + "f", "F", "F", /**/"f", "F", "F", "\x06",/***/ + "g", "G", "G", /**/"g", "G", "G", "\x07",/***/ + "h", "h", "H", /**/"h", "H", "H", "\x08",/***/ + "j", "J", "J", /**/"j", "J", "J", "\x0a",/***/ + "k", "K", "K", /**/"k", "K", "K", "\x0b",/***/ + "l", "L", "L", /**/"l", "L", "L", "\x0c",/***/ + "semicolon", "colon", "semicolon", /**/";", ":", ";", NULL,/***/ + "apostrophe", "quotedbl", "apostrophe", /**/"'", "\"", "'", NULL,/***/ + "grave", "asciitilde", "grave", /**/"`", "~", "`", "",/***/ + "Shift_L", "Shift_L", "Shift_L", /**/"", "", "", NULL,/***/ + "backslash", "bar", "backslash", /**/"\\", "|", "\\", "\x1c",/***/ + "z", "Z", "Z", /**/"z", "Z", "Z", "\x1a",/***/ + "x", "X", "X", /**/"x", "X", "X", "\x18",/***/ + "c", "C", "C", /**/"c", "C", "C", "\x03",/***/ + "v", "V", "V", /**/"v", "V", "V", "\x16",/***/ + "b", "B", "B", /**/"b", "B", "B", "\x02",/***/ + "n", "N", "N", /**/"n", "N", "N", "\x0e",/***/ + "m", "M", "M", /**/"m", "M", "M", "\x0d",/***/ + "comma", "less", "comma", /**/",", "<", ",", NULL,/***/ + "period", "greater", "period", /**/".", ">", ".", NULL,/***/ + "slash", "question", "slash", /**/"/", "?", "/", "",/***/ + "Shift_R", "Shift_R", "Shift_R", /**/"", "", "", NULL,/***/ + "KP_Multiply", "KP_Multiply", "KP_Multiply", /**/"", "*", "", NULL,/***/ + "Alt_L", "Alt_L", "Alt_L", /**/"", "", "", NULL,/***/ + "space", "space", "space", /**/" ", " ", " ", "",/***/ + "Caps_Lock", "Caps_Lock", "Caps_Lock", /**/"", "", "", NULL,/***/ + "F1", "F1", "F1", /**/"", "", "", NULL,/***/ + "F2", "F2", "F2", /**/"", "", "", NULL,/***/ + "F3", "F3", "F3", /**/"", "", "", NULL,/***/ + "F4", "F4", "F4", /**/"", "", "", NULL,/***/ + "F5", "F5", "F5", /**/"", "", "", NULL,/***/ + "F6", "F6", "F6", /**/"", "", "", NULL,/***/ + "F7", "F7", "F7", /**/"", "", "", NULL,/***/ + "F8", "F8", "F8", /**/"", "", "", NULL,/***/ + "F9", "F9", "F9", /**/"", "", "", NULL,/***/ + "F10", "F10", "F10", /**/"", "", "", NULL,/***/ + "Num_Lock", "Num_Lock", "Num_Lock", /**/"", "", "", NULL,/***/ + "Scroll_Lock", "Scroll_Lock", "Scroll_Lock", /**/"", "", "", NULL,/***/ + "KP_Home", "KP_7", "KP_Home", /**/"", "7", "", NULL,/***/ + "KP_Up", "KP_8", "KP_Up", /**/"", "8", "", NULL,/***/ + "KP_Prior", "KP_9", "KP_Prior", /**/"", "9", "", NULL,/***/ + "KP_Subtract", "KP_Subtract", "KP_Subtract", /**/"", "", "", NULL,/***/ + "KP_Left", "KP_4", "KP_Left", /**/"", "4", "", NULL,/***/ + "KP_Begin", "KP_5", "KP_Begin", /**/"", "5", "", NULL,/***/ + "KP_Right", "KP_6", "KP_Right", /**/"", "6", "", NULL,/***/ + "KP_Add", "KP_Add", "KP_Add", /**/"", "", "", NULL,/***/ + "KP_End", "KP_1", "KP_End", /**/"", "1", "", NULL,/***/ + "KP_Down", "KP_2", "KP_Down", /**/"", "2", "", NULL,/***/ + "KP_Next", "KP_3", "KP_Next", /**/"", "3", "", NULL,/***/ + "KP_Insert", "KP_0", "KP_Insert", /**/"", "0", "", NULL,/***/ + "KP_Delete", "KP_Decimal", "KP_Delete", /**/"", ".", "", NULL,/***/ + "0x54", "0x54", "0x54", /**/"", "", "", NULL,/***/ + "0x55", "0x55", "0x55", /**/"", "", "", NULL,/***/ + "0x56", "0x56", "0x56", /**/"", "", "", NULL,/***/ + "F11", "F11", "F11", /**/"", "", "", NULL,/***/ + "F12", "F12", "F12", /**/"", "", "", NULL,/***/ + "0x59", "0x59", "0x59", /**/"", "", "", NULL,/***/ + "0x5a", "0x5a", "0x5a", /**/"", "", "", NULL,/***/ + "0x5b", "0x5b", "0x5b", /**/"", "", "", NULL,/***/ + "0x5c", "0x5c", "0x5c", /**/"", "", "", NULL,/***/ + "0x5d", "0x5d", "0x5d", /**/"", "", "", NULL,/***/ + "0x5e", "0x5e", "0x5e", /**/"", "", "", NULL,/***/ + "0x5f", "0x5f", "0x5f", /**/"", "", "", NULL,/***/ + "KP_Enter", "KP_Enter", "KP_Enter", /**/"\015", "\015", "\015", NULL,/***/ + "Control_R", "Control_R", "Control_R", /**/"", "", "", NULL,/***/ + "KP_Divide", "KP_Divide", "KP_Divide", /**/"", "", "", NULL,/***/ + "Print", "Print", "Print", /**/"", "", "", NULL,/***/ + "Alt_R", "Alt_R", "Alt_R", /**/"", "", "", NULL,/***/ + "0x65", "0x65", "0x65", /**/"", "", "", NULL,/***/ + "Home", "Home", "Home", /**/"", "", "", NULL,/***/ + "Up", "Up", "Up", /**/"", "", "", NULL,/***/ + "Prior", "Prior", "Prior", /**/"", "", "", NULL,/***/ + "Left", "Left", "Left", /**/"", "", "", NULL,/***/ + "Right", "Right", "Right", /**/"", "", "", NULL,/***/ + "End", "End", "End", /**/"", "", "", NULL,/***/ + "Down", "Down", "Down", /**/"", "", "", NULL,/***/ + "Next", "Next", "Next", /**/"", "", "", NULL,/***/ + "Insert", "Insert", "Insert", /**/"", "", "", NULL,/***/ + "Delete", "Delete", "Delete", /**/"\177","\177","\177", NULL,/***/ + "0x70", "0x70", "0x70", /**/"", "", "", NULL,/***/ + "0x71", "0x71", "0x71", /**/"", "", "", NULL,/***/ + "0x72", "0x72", "0x72", /**/"", "", "", NULL,/***/ + "0x73", "0x73", "0x73", /**/"", "", "", NULL,/***/ + "0x74", "0x74", "0x74", /**/"", "", "", NULL,/***/ + "0x75", "0x75", "0x75", /**/"", "", "", NULL,/***/ + "0x76", "0x76", "0x76", /**/"", "", "", NULL,/***/ + "Pause", "Pause", "Pause", /**/"", "", "", NULL,/***/ + "0x78", "0x78", "0x78", /**/"", "", "", NULL,/***/ + "0x79", "0x79", "0x79", /**/"", "", "", NULL,/***/ + "0x7a", "0x7a", "0x7a", /**/"", "", "", NULL,/***/ + "0x7b", "0x7b", "0x7b", /**/"", "", "", NULL,/***/ + "0x7c", "0x7c", "0x7c", /**/"", "", "", NULL,/***/ + "Super_L", "Super_L", "Super_L", /**/"", "", "", NULL,/***/ + "Super_R", "Super_R", "Super_R", /**/"", "", "", NULL,/***/ + "0x7f", "0x7f", "0x7f", /**/"", "", "", NULL, /***/ diff --git a/src/lib/ecore_fb/ecore_fb_li.c b/src/lib/ecore_fb/ecore_fb_li.c new file mode 100644 index 0000000000..0ea0549f92 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_li.c @@ -0,0 +1,721 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> + +#include "Ecore_Fb.h" +#include "ecore_fb_private.h" + +#define CLICK_THRESHOLD_DEFAULT 0.25 + +static Eina_List *_ecore_fb_li_devices = NULL; + +static const char *_ecore_fb_li_kbd_syms[128 * 7] = +{ +#include "ecore_fb_keytable.h" +}; + +/* Initial Copyright (C) Brad Hards (1999-2002), + * this function is used to tell if "bit" is set in "array" + * it selects a byte from the array, and does a boolean AND + * operation with a byte that only has the relevant bit set. + * eg. to check for the 12th bit, we do (array[1] & 1<<4). + * Moved to static inline in order to force compiler to otimized + * the unsued part away or force a link error if long has an unexpected + * size. + * - bigeasy + */ +extern int long_has_neither_32_nor_64_bits(void); +static inline int +test_bit(int bit, unsigned long *array) +{ + if (sizeof(long) == 4) + return array[bit / 32] & (1 << (bit % 32)); + else if (sizeof(long) == 8) + return array[bit / 64] & (1 << (bit % 64)); + else long_has_neither_32_nor_64_bits(); +} + +static void +_ecore_fb_li_device_event_key(Ecore_Fb_Input_Device *dev, struct input_event *iev) +{ + if (!dev->listen) return; + + /* check for basic keyboard keys */ + if ((iev->code >= KEY_ESC) && (iev->code <= KEY_COMPOSE)) + { + int offset = 0; + const char *keyname = _ecore_fb_li_kbd_syms[iev->code * 7]; + + /* check the key table */ + if (iev->value) + { + /* its a repeated key, dont increment */ + if (iev->value != 2) + { + if (!strcmp(keyname, "Control_L")) + dev->keyboard.ctrl++; + else if (!strcmp(keyname, "Control_R")) + dev->keyboard.ctrl++; + else if (!strcmp(keyname, "Alt_L")) + dev->keyboard.alt++; + else if (!strcmp(keyname, "Alt_R")) + dev->keyboard.alt++; + else if (!strcmp(keyname, "Shift_L")) + dev->keyboard.shift++; + else if (!strcmp(keyname, "Shift_R")) + dev->keyboard.shift++; + else if (!strcmp(keyname, "Caps_Lock")) + dev->keyboard.lock = !dev->keyboard.lock; + if (dev->keyboard.ctrl > 2) dev->keyboard.ctrl = 2; + if (dev->keyboard.alt > 2) dev->keyboard.alt = 2; + if (dev->keyboard.shift > 2) dev->keyboard.shift = 2; + if (dev->keyboard.lock > 1) dev->keyboard.lock = 1; + } + } + else + { + if (!strcmp(keyname, "Control_L")) + dev->keyboard.ctrl--; + else if (!strcmp(keyname, "Control_R")) + dev->keyboard.ctrl--; + else if (!strcmp(keyname, "Alt_L")) + dev->keyboard.alt--; + else if (!strcmp(keyname, "Alt_R")) + dev->keyboard.alt--; + else if (!strcmp(keyname, "Shift_L")) + dev->keyboard.shift--; + else if (!strcmp(keyname, "Shift_R")) + dev->keyboard.shift--; + if (dev->keyboard.ctrl < 0) dev->keyboard.ctrl = 0; + if (dev->keyboard.alt < 0) dev->keyboard.alt = 0; + if (dev->keyboard.shift < 0) dev->keyboard.shift = 0; + if (dev->keyboard.lock < 0) dev->keyboard.lock = 0; + } + + /* sending ecore_input_evas events */ + Ecore_Event_Key *e; + + if (dev->keyboard.shift) offset = 1; + else if (dev->keyboard.lock) offset = 2; + + const char *key = _ecore_fb_li_kbd_syms[(iev->code * 7) + offset]; + const char *compose = _ecore_fb_li_kbd_syms[(iev->code * 7) + 3 + offset]; + + if (dev->keyboard.ctrl) + { + const char *ts = _ecore_fb_li_kbd_syms[(iev->code * 7) + 3 + 3]; + + if (ts) compose = ts; + } + + e = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + + strlen(keyname) + (compose ? strlen(compose) : 0) + 3); + e->keyname = (char *)(e + 1); + e->key = e->keyname + strlen(keyname) + 1; + e->compose = (compose) ? e->key + strlen(key) + 1 : NULL; + e->string = e->compose; + + strcpy((char *)e->keyname, keyname); + strcpy((char *)e->key, key); + if (compose) + strcpy((char *)e->compose, compose); + + e->modifiers = 0; + if (dev->keyboard.shift) + e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL; + if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS; + + e->timestamp = ecore_loop_time_get() * 1000.0; + e->window = (Ecore_Window)dev->window; + e->event_window = (Ecore_Window)dev->window; + e->root_window = (Ecore_Window)dev->window; + e->same_screen = 1; + + if (iev->value) + ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL); + else + ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL); + } + /* check for mouse button events */ + else if ((iev->code >= BTN_MOUSE) && (iev->code < BTN_JOYSTICK)) + { + int button; + Ecore_Event_Mouse_Button *e; + double current = ecore_loop_time_get(); + + button = ((iev->code & 0x00F) + 1); + // swap 2 and 3 to make middle and right butotn work right. + if (button == 3) button = 2; + else if (button == 2) button = 3; + if (iev->value) + { + dev->mouse.did_double = EINA_FALSE; + dev->mouse.did_triple = EINA_FALSE; + + if (((current - dev->mouse.prev) <= dev->mouse.threshold) && + (button == dev->mouse.prev_button)) + { + dev->mouse.did_double = EINA_TRUE; + if (((current - dev->mouse.last) <= (2 * dev->mouse.threshold)) && + (button == dev->mouse.last_button)) + { + dev->mouse.did_triple = EINA_TRUE; + /* reset */ + dev->mouse.prev = 0; + dev->mouse.last = 0; + current = 0; + } + } + dev->mouse.last = dev->mouse.prev; + dev->mouse.prev = current; + dev->mouse.last_button = dev->mouse.prev_button; + dev->mouse.prev_button = button; + } + + e = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!e) + return; + + e->timestamp = current * 1000.0; + e->window = (Ecore_Window)dev->window; + e->event_window = (Ecore_Window)dev->window; + e->root_window = (Ecore_Window)dev->window; + e->same_screen = 1; + + e->modifiers = 0; + if (dev->keyboard.shift) + e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL; + if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS; + + e->x = dev->mouse.x; + e->y = dev->mouse.y; + e->root.x = e->x; + e->root.y = e->y; + e->buttons = button; + + if (dev->mouse.did_double) + e->double_click = 1; + if (dev->mouse.did_triple) + e->triple_click = 1; + + if (iev->value) + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL); + else + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL); + } +} + +static void +_ecore_fb_li_device_event_rel(Ecore_Fb_Input_Device *dev, struct input_event *iev) +{ + if (!dev->listen) return; + /* dispatch the button events if they are queued */ + switch (iev->code) + { + case REL_X: + case REL_Y: + { + Ecore_Event_Mouse_Move *e; + if (iev->code == REL_X) + { + dev->mouse.x += iev->value; + if (dev->mouse.x > dev->mouse.w - 1) + dev->mouse.x = dev->mouse.w; + else if(dev->mouse.x < 0) + dev->mouse.x = 0; + } + else + { + dev->mouse.y += iev->value; + if (dev->mouse.y > dev->mouse.h - 1) + dev->mouse.y = dev->mouse.h; + else if(dev->mouse.y < 0) + dev->mouse.y = 0; + } + + e = calloc(1, sizeof(Ecore_Event_Mouse_Move)); + if (!e) + return; + + e->window = (Ecore_Window)dev->window; + e->event_window = (Ecore_Window)dev->window; + e->root_window = (Ecore_Window)dev->window; + e->same_screen = 1; + + e->modifiers = 0; + if (dev->keyboard.shift) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL; + if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS; + + e->x = dev->mouse.x; + e->y = dev->mouse.y; + e->root.x = e->x; + e->root.y = e->y; + + e->timestamp = ecore_loop_time_get() * 1000.0; + + ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL); + + break; + } + case REL_WHEEL: + case REL_HWHEEL: + { + Ecore_Event_Mouse_Wheel *e; + + e = calloc(1, sizeof(Ecore_Event_Mouse_Wheel)); + if (!e) + return; + + e->x = dev->mouse.x; + e->y = dev->mouse.y; + if (iev->code == REL_HWHEEL) e->direction = 1; + e->z = iev->value; + e->root.x = dev->mouse.x; + e->root.y = dev->mouse.y; + + e->window = (Ecore_Window)dev->window; + e->event_window = (Ecore_Window)dev->window; + e->root_window = (Ecore_Window)dev->window; + e->same_screen = 1; + + e->modifiers = 0; + if (dev->keyboard.shift) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.ctrl) e->modifiers |= ECORE_EVENT_MODIFIER_CTRL; + if (dev->keyboard.alt) e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (dev->keyboard.lock) e->modifiers |= ECORE_EVENT_LOCK_CAPS; + + e->timestamp = ecore_loop_time_get() * 1000.0; + + ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL); + + break; + } + default: + break; + } +} + +static void +_ecore_fb_li_device_event_abs(Ecore_Fb_Input_Device *dev, struct input_event *iev) +{ + static int prev_pressure = 0; + int pressure; + + if (!dev->listen) return; + switch (iev->code) + { + case ABS_X: + if (dev->mouse.w != 0) + { + int tmp; + + tmp = (int)((double)(iev->value - dev->mouse.min_w) / dev->mouse.rel_w); + if (tmp < 0) dev->mouse.x = 0; + else if (tmp > dev->mouse.w) dev->mouse.x = dev->mouse.w; + else dev->mouse.x = tmp; + dev->mouse.event = ECORE_EVENT_MOUSE_MOVE; + } + break; + + case ABS_Y: + if (dev->mouse.h != 0) + { + int tmp; + + tmp = (int)((double)(iev->value - dev->mouse.min_h) / dev->mouse.rel_h); + if (tmp < 0) dev->mouse.y = 0; + else if (tmp > dev->mouse.h) dev->mouse.y = dev->mouse.h; + else dev->mouse.y = tmp; + dev->mouse.event = ECORE_EVENT_MOUSE_MOVE; + } + break; + + case ABS_PRESSURE: + pressure = iev->value; + if ((pressure) && (!prev_pressure)) + { + /* DOWN: mouse is down, but was not before */ + dev->mouse.event = ECORE_EVENT_MOUSE_BUTTON_DOWN; + } + else if ((!pressure) && (prev_pressure)) + { + /* UP: mouse was down, but is not now */ + dev->mouse.event = ECORE_EVENT_MOUSE_BUTTON_UP; + } + prev_pressure = pressure; + break; + } +} + +static void +_ecore_fb_li_device_event_syn(Ecore_Fb_Input_Device *dev, struct input_event *iev EINA_UNUSED) +{ + if (!dev->listen) return; + + if (dev->mouse.event == ECORE_EVENT_MOUSE_MOVE) + { + Ecore_Event_Mouse_Move *ev; + ev = calloc(1,sizeof(Ecore_Event_Mouse_Move)); + ev->x = dev->mouse.x; + ev->y = dev->mouse.y; + ev->root.x = ev->x; + ev->root.y = ev->y; + ev->timestamp = ecore_loop_time_get() * 1000.0; + } + else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_DOWN) + { + Ecore_Event_Mouse_Button *ev; + ev = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + ev->x = dev->mouse.x; + ev->y = dev->mouse.y; + ev->root.x = ev->x; + ev->root.y = ev->y; + ev->buttons = 1; + ev->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL); + } + else if (dev->mouse.event == ECORE_EVENT_MOUSE_BUTTON_UP) + { + Ecore_Event_Mouse_Button *ev; + ev = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + ev->x = dev->mouse.x; + ev->y = dev->mouse.y; + ev->root.x = ev->x; + ev->root.y = ev->y; + ev->buttons = 1; + ev->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL); + } +} + +static Eina_Bool +_ecore_fb_li_device_fd_callback(void *data, Ecore_Fd_Handler *fdh EINA_UNUSED) +{ + Ecore_Fb_Input_Device *dev; + struct input_event ev[64]; + int len; + int i; + + dev = (Ecore_Fb_Input_Device*)data; + /* read up to 64 events at once */ + len = read(dev->fd, &ev, sizeof(ev)); + for(i = 0; i < (int)(len / sizeof(ev[0])); i++) + { + switch(ev[i].type) + { + case EV_SYN: + _ecore_fb_li_device_event_syn(dev, &ev[i]); + break; + case EV_ABS: + _ecore_fb_li_device_event_abs(dev, &ev[i]); + break; + case EV_REL: + _ecore_fb_li_device_event_rel(dev, &ev[i]); + break; + case EV_KEY: + _ecore_fb_li_device_event_key(dev, &ev[i]); + break; + default: + break; + } + } + return EINA_TRUE; +} + +/** + * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions. + * + * @{ + */ + +/** + * @brief Set the listen mode for an input device . + * + * @param dev The device to set the mode of. + * @param listen @c EINA_FALSE to disable listening mode, @c EINA_TRUE to + * enable it. + * + * This function enables or disables listening on the input device @p dev. + * If @p listen is @c EINA_FALSE, listening mode is disabled, if it is + * @c EINA_TRUE, it is enabled. + */ +EAPI void +ecore_fb_input_device_listen(Ecore_Fb_Input_Device *dev, Eina_Bool listen) +{ + if (!dev) return; + if ((listen && dev->listen) || (!listen && !dev->listen)) return; + if (listen) + { + /* if the device already had a handler */ + if (!dev->handler) + dev->handler = ecore_main_fd_handler_add(dev->fd, ECORE_FD_READ, _ecore_fb_li_device_fd_callback, dev, NULL, NULL); + + } + dev->listen = listen; +} + +#ifndef EV_CNT +# define EV_CNT (EV_MAX+1) +#endif + +/** + * @brief Associates an input device with the given @ref Ecore_Evas_Group. + * + * @param dev The input being associated with an @ref Ecore_Evas_Group (not @c NULL). + * @param window The window which this input is being associated to. + * @c NULL will remove any previous association. + * + * Events generated by this device will have a pointer to @p window. If this @p + * window is registered with ecore_event_window_register() or + * ecore_evas_input_event_register(), respective evas events will be delivered + * by the ecore_input_evas system. An example can be seen in the following code: + * + * @code + * Ecore_Evas *ee = ecore_evas_new(NULL, 0, 0, 800, 600, NULL); + * + * ecore_evas_input_event_register(ee); + * + * device = ecore_fb_input_device_open(device_path); + * if (device) + * ecore_fb_input_device_window_set(device, ee); + * + * @endcode + * + * On the previous code, all input captured on the mentioned device will be + * delivered to the @c Ecore_Evas @c ee. + * + * @since 1.1 + */ +EAPI void +ecore_fb_input_device_window_set(Ecore_Fb_Input_Device *dev, void *window) +{ + if (!dev) return; + + dev->window = window; +} + +/** + * @brief Open an input device. + * + * @param dev The device to open. + * @return The @ref Ecore_Fb_Input_Device object that has been opened. + * + * This function opens the input device named @p dev and returns the + * object for it, or returns @c NULL on failure. + */ +EAPI Ecore_Fb_Input_Device * +ecore_fb_input_device_open(const char *dev) +{ + Ecore_Fb_Input_Device *device; + unsigned long event_type_bitmask[EV_CNT / 32 + 1]; + int event_type; + int fd; + + if (!dev) return NULL; + device = calloc(1, sizeof(Ecore_Fb_Input_Device)); + if (!device) return NULL; + + if ((fd = open(dev, O_RDONLY, O_NONBLOCK)) < 0) + { + fprintf(stderr, "[ecore_fb_li:device_open] %s %s", dev, strerror(errno)); + goto error_open; + } + /* query capabilities */ + if (ioctl(fd, EVIOCGBIT(0, EV_MAX), event_type_bitmask) < 0) + { + fprintf(stderr,"[ecore_fb_li:device_open] query capabilities %s %s", dev, strerror(errno)); + goto error_caps; + } + /* query name */ + device->info.name = calloc(256, sizeof(char)); + if (ioctl(fd, EVIOCGNAME(sizeof(char) * 256), device->info.name) < 0) + { + fprintf(stderr, "[ecore_fb_li:device_open] get name %s %s", dev, strerror(errno)); + strcpy(device->info.name, "Unknown"); + } + device->fd = fd; + device->info.dev = strdup(dev); + /* common */ + device->mouse.threshold = CLICK_THRESHOLD_DEFAULT; + + /* set info */ + for (event_type = 0; event_type < EV_MAX; event_type++) + { + if (!test_bit(event_type, event_type_bitmask)) + continue; + switch (event_type) + { + case EV_SYN: + break; + case EV_KEY: + device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_KEYS_OR_BUTTONS; + break; + case EV_REL: + device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_RELATIVE; + break; + case EV_ABS: + device->info.cap |= ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE; + break; + case EV_MSC: + case EV_LED: + case EV_SND: + case EV_REP: + case EV_FF : + case EV_FF_STATUS: + case EV_PWR: + default: + break; + } + } + + _ecore_fb_li_devices = eina_list_append(_ecore_fb_li_devices, device); + return device; + +error_caps: + close(fd); +error_open: + free(device); + return NULL; +} + +/** + * @brief Close the given device. + * + * @param dev The device to close + * + * This function closes the device @p dev. If @p dev is @c NULL, this + * function does nothing. + */ +EAPI void +ecore_fb_input_device_close(Ecore_Fb_Input_Device *dev) +{ + if (!dev || dev->fd < 0) return; + /* close the fd */ + close(dev->fd); + /* remove the element from the list */ + _ecore_fb_li_devices = eina_list_remove(_ecore_fb_li_devices, dev); + free(dev); +} + + +/** + * @brief Set the axis size of the given device. + * + * @param dev The device to set the axis size to. + * @param w The width of the axis. + * @param h The height of the axis. + * + * This function sets set the width @p w and height @p h of the axis + * of device @p dev. If @p dev is a relative input device, a width and + * height must set for it. If its absolute set the ioctl correctly, if + * not, unsupported device. + */ +EAPI void +ecore_fb_input_device_axis_size_set(Ecore_Fb_Input_Device *dev, int w, int h) +{ + if (!dev) return; + if ((w < 0) || (h < 0)) return; + /* FIXME + * this code is for a touchscreen device, + * make it configurable (ABSOLUTE | RELATIVE) + */ + if (dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_ABSOLUTE) + { + /* FIXME looks like some kernels dont include this struct */ + struct input_absinfo abs_features; + + ioctl(dev->fd, EVIOCGABS(ABS_X), &abs_features); + dev->mouse.min_w = abs_features.minimum; + dev->mouse.rel_w = (double)(abs_features.maximum - abs_features.minimum)/(double)(w); + + ioctl(dev->fd, EVIOCGABS(ABS_Y), &abs_features); + dev->mouse.min_h = abs_features.minimum; + dev->mouse.rel_h = (double)(abs_features.maximum - abs_features.minimum)/(double)(h); + } + else if (!(dev->info.cap & ECORE_FB_INPUT_DEVICE_CAP_RELATIVE)) + return; + + /* update the local values */ + if (dev->mouse.x > w - 1) dev->mouse.x = w -1; + if (dev->mouse.y > h - 1) dev->mouse.y = h -1; + dev->mouse.w = w; + dev->mouse.h = h; +} + +/** + * @brief Retrieve the name of the given device. + * + * @param dev The device to get the name from. + * @return The name of the device. + * + * This function returns the name of the device @p dev. If @p dev is + * @c NULL, this function returns @c NULL. + */ +EAPI const char * +ecore_fb_input_device_name_get(Ecore_Fb_Input_Device *dev) +{ + if (!dev) return NULL; + return dev->info.name; +} + +/** + * @brief Retrieve the capability of the given device. + * + * @param dev The device to get the name from. + * @return The capability of the device. + * + * This function returns the capability of the device @p dev. If @p dev is + * @c NULL, this function returns ECORE_FB_INPUT_DEVICE_CAP_NONE. + */ +EAPI Ecore_Fb_Input_Device_Cap +ecore_fb_input_device_cap_get(Ecore_Fb_Input_Device *dev) +{ + if (!dev) return ECORE_FB_INPUT_DEVICE_CAP_NONE; + return dev->info.cap; +} + +/** + * @brief Set the threshold of mouse clicks of the given device. + * + * @param dev The device to set the threshodl mouse click to. + * @param threshold The threshold value. + * + * This function sets the threshold of mouse clicks of the device + * @p dev to @p threshold. If @p dev is @c NULL, this function does + * nothing. + */ +EAPI void +ecore_fb_input_device_threshold_click_set(Ecore_Fb_Input_Device *dev, double threshold) +{ + if (!dev) return; + if ((threshold == dev->mouse.threshold) || (threshold == 0)) return; + dev->mouse.threshold = threshold; +} + +/** + * @brief Get the threshold of mouse clicks of the given device. + * + * @param dev The device to set the threshodl mouse click from. + * @return The threshold value. + * + * This function returns the threshold of mouse clicks of the device + * @p dev. If @p dev is @c NULL, this function returns 0.0. + */ +EAPI double +ecore_fb_input_device_threshold_click_get(Ecore_Fb_Input_Device *dev) +{ + if (!dev) return 0; + return dev->mouse.threshold; +} + +/** + * @} + */ diff --git a/src/lib/ecore_fb/ecore_fb_private.h b/src/lib/ecore_fb/ecore_fb_private.h new file mode 100644 index 0000000000..797f86305f --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_private.h @@ -0,0 +1,94 @@ +#ifndef _ECORE_FB_PRIVATE_H +#define _ECORE_FB_PRIVATE_H + +#include "Ecore.h" +#include "ecore_private.h" +#include "Ecore_Input.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <termios.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/version.h> +#include <linux/kd.h> +#include <linux/vt.h> +#include <linux/fb.h> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) + #define kernel_ulong_t unsigned long + #define BITS_PER_LONG 32 + #include <linux/input.h> + #undef kernel_ulong_t + #undef BITS_PER_LONG +#else + #include <linux/input.h> +#endif + +#include <signal.h> +#include <fcntl.h> +#include <errno.h> + +#include <Ecore_Fb.h> + +/* ecore_fb_li.c */ +struct _Ecore_Fb_Input_Device +{ + int fd; + Ecore_Fd_Handler *handler; + int listen; + struct { + Ecore_Fb_Input_Device_Cap cap; + char *name; + char *dev; + } info; + struct + { + /* common mouse */ + int x,y; + int w,h; + + double last; + double prev; + double threshold; + Eina_Bool did_double; + Eina_Bool did_triple; + /* absolute axis */ + int min_w, min_h; + double rel_w, rel_h; + int event; + int prev_button; + int last_button; + } mouse; + struct + { + int shift; + int ctrl; + int alt; + int lock; + } keyboard; + void *window; +}; + +/* ecore_fb_ts.c */ +EAPI int ecore_fb_ts_init(void); +EAPI void ecore_fb_ts_shutdown(void); +EAPI void ecore_fb_ts_events_window_set(void *window); +EAPI void *ecore_fb_ts_events_window_get(void); +EAPI void ecore_fb_ts_event_window_set(void *window); + +/* ecore_fb_vt.c */ +int ecore_fb_vt_init(void); +void ecore_fb_vt_shutdown(void); + +/* hacks to stop people NEEDING #include <linux/h3600_ts.h> */ +#ifndef TS_SET_CAL +#define TS_SET_CAL 0x4014660b +#endif +#ifndef TS_GET_CAL +#define TS_GET_CAL 0x8014660a +#endif + +#endif diff --git a/src/lib/ecore_fb/ecore_fb_ps2.c b/src/lib/ecore_fb/ecore_fb_ps2.c new file mode 100644 index 0000000000..53aa302fef --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_ps2.c @@ -0,0 +1,223 @@ +typedef struct _Ecore_Fb_Ps2_Event Ecore_Fb_Ps2_Event; +struct _Ecore_Fb_Ps2_Event +{ + unsigned char button; + unsigned char x; + unsigned char y; + unsigned char z; +}; + +static int _ecore_fb_ps2_event_byte_count = 0; +static Ecore_Fb_Ps2_Event _ecore_fb_ps2_event; +static int _ecore_fb_ps2_fd = 0; +static Eina_Bool _ecore_fb_ps2_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); + +int +ecore_fb_ps2_init(void) +{ + _ecore_fb_ps2_fd = open("/dev/psaux", O_RDWR); + if (_ecore_fb_ps2_fd >= 0) + { + prev_flags = fcntl(_ecore_fb_ps2_fd, F_GETFL); + fcntl(_ecore_fb_ps2_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ps2_fd, + ECORE_FD_READ, + _ecore_fb_ps2_fd_handler, NULL, NULL, NULL); + if (!_ecore_fb_ts_fd_handler_handle) + { + close(_ecore_fb_ps2_fd); + return 0; + } + return 1; + } + return 0; +} + +void +ecore_fb_ps2_shutdown(void) +{ + if (_ecore_fb_ps2_fd > 0) close(_ecore_fb_ps2_fd); + _ecore_fb_ps2_fd = 0; +} + +static Eina_Bool +_ecore_fb_ps2_fd_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + static int prev_x = 0, prev_y = 0, prev_button = 0; + static double last_time = 0; + static double last_last_time = 0; + int v = 0; + + do + { + int x, y, button, i; + int num; + char *ptr; + double t; + static int did_double = 0; + static int did_triple = 0; + + ptr = (char *)&(_ecore_fb_ps2_event); + ptr += _ecore_fb_ps2_event_byte_count; + num = sizeof(Ecore_Fb_Ps2_Event) - _ecore_fb_ps2_event_byte_count; + v = read(_ecore_fb_ps2_fd, ptr, num); + if (v < 0) return EINA_TRUE; + _ecore_fb_ps2_event_byte_count += v; + if (v < num) return EINA_TRUE; + t = ecore_loop_time_get(); + _ecore_fb_ps2_event_byte_count = 0; + if (_ecore_fb_ps2_event.button & 0x10) + x = prev_x + (0xffffff00 | _ecore_fb_ps2_event.x); + else + x = prev_x + _ecore_fb_ps2_event.x; + if (_ecore_fb_ps2_event.button & 0x20) + y = prev_y - (0xffffff00 | _ecore_fb_ps2_event.y); + else + y = prev_y - _ecore_fb_ps2_event.y; + button = _ecore_fb_ps2_event.button & 0x7; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x >= _ecore_fb_console_w) x = _ecore_fb_console_w - 1; + if (y >= _ecore_fb_console_h) y = _ecore_fb_console_h - 1; + /* add event to queue */ + /* always add a move event */ + if (1) + { + /* MOVE: mouse is down and was */ + Ecore_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Move)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->root.x = e->x; + e->root.y = e->y; + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + for (i = 1; i <= 3; i++) + { + int mask; + + mask = 1 << (i - 1); + if (((button & mask)) && (!(prev_button & mask))) + { + /* DOWN: mouse is down, but was not now */ + Ecore_Event_Mouse_Button *e; + + e = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->root.x = e->x; + e->root.y = e->y; + e->button = i; + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + if ((t - last_time) <= _ecore_fb_double_click_time) + { + e->double_click = 1; + did_double = 1; + } + else + { + did_double = 0; + did_triple = 0; + } + if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time)) + { + did_triple = 1; + e->triple_click = 1; + } + else + { + did_triple = 0; + } + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL); + } + else if ((!(button & mask)) && ((prev_button & mask))) + { + /* UP: mouse was down, but is not now */ + Ecore_Event_Mouse_Button *e; + + e = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->root.x = e->x; + e->root.y = e->y; + e->button = i; + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + if (did_double) + e->double_click = 1; + if (did_triple) + e->triple_click = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL); + } + } + if (did_triple) + { + last_time = 0; + last_last_time = 0; + } + else + { + last_last_time = last_time; + last_time = t; + } + retry: + prev_x = x; + prev_y = y; + prev_button = button; + } + while (v > 0); + return EINA_TRUE; +} +/** + * @defgroup Ecore_FB_Click_Group Framebuffer Double Click Functions + * + * Functions that deal with the double click time of the framebuffer. + */ + +/** + * Sets the timeout for a double and triple clicks to be flagged. + * + * This sets the time between clicks before the double_click flag is + * set in a button down event. If 3 clicks occur within double this + * time, the triple_click flag is also set. + * + * @param t The time in seconds + * @ingroup Ecore_FB_Click_Group + */ +EAPI void +ecore_fb_double_click_time_set(double t) +{ + if (t < 0.0) t = 0.0; + _ecore_fb_double_click_time = t; +} + +/** + * Retrieves the double and triple click flag timeout. + * + * See @ref ecore_x_double_click_time_set for more information. + * + * @return The timeout for double clicks in seconds. + * @ingroup Ecore_FB_Click_Group + */ +EAPI double +ecore_fb_double_click_time_get(void) +{ + return _ecore_fb_double_click_time; +} + diff --git a/src/lib/ecore_fb/ecore_fb_ts.c b/src/lib/ecore_fb/ecore_fb_ts.c new file mode 100644 index 0000000000..ce9c733c3e --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_ts.c @@ -0,0 +1,362 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_TSLIB +# include <tslib.h> +# include <errno.h> +#endif + +#include "Ecore_Fb.h" +#include "ecore_fb_private.h" + +typedef struct _Ecore_Fb_Ts_Event Ecore_Fb_Ts_Event; +typedef struct _Ecore_Fb_Ts_Calibrate Ecore_Fb_Ts_Calibrate; +typedef struct _Ecore_Fb_Ts_Backlight Ecore_Fb_Ts_Backlight; +typedef struct _Ecore_Fb_Ts_Contrast Ecore_Fb_Ts_Contrast; +typedef struct _Ecore_Fb_Ts_Led Ecore_Fb_Ts_Led; +typedef struct _Ecore_Fb_Ts_Flite Ecore_Fb_Ts_Flite; + +struct _Ecore_Fb_Ts_Event +{ + unsigned short pressure; + unsigned short x; + unsigned short y; + unsigned short _unused; +}; + +struct _Ecore_Fb_Ts_Calibrate +{ + int xscale; + int xtrans; + int yscale; + int ytrans; + int xyswap; +}; + +struct _Ecore_Fb_Ts_Backlight +{ + int on; + unsigned char brightness; +}; + +struct _Ecore_Fb_Ts_Contrast +{ + unsigned char contrast; +}; + +struct _Ecore_Fb_Ts_Led +{ + unsigned char on; + unsigned char blink_time; + unsigned char on_time; + unsigned char off_time; +}; + +struct _Ecore_Fb_Ts_Flite +{ + unsigned char mode; + unsigned char pwr; + unsigned char brightness; +}; + +static Eina_Bool _ecore_fb_ts_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_fb_ts_fd = -1; +static int _ecore_fb_ts_event_byte_count = 0; +static int _ecore_fb_ts_apply_cal = 0; +static Ecore_Fb_Ts_Event _ecore_fb_ts_event; +static Ecore_Fb_Ts_Calibrate _ecore_fb_ts_cal = {1,1,0,0,0}; +static Ecore_Fd_Handler *_ecore_fb_ts_fd_handler_handle = NULL; + +#ifdef HAVE_TSLIB +struct tsdev *_ecore_fb_tslib_tsdev = NULL; +struct ts_sample _ecore_fb_tslib_event; +#endif + +static double _ecore_fb_double_click_time = 0.25; +static void *_ecore_fb_ts_event_window = NULL; + +EAPI int +ecore_fb_ts_init(void) +{ +#ifdef HAVE_TSLIB + char *tslib_tsdevice = NULL; + if ( (tslib_tsdevice = getenv("TSLIB_TSDEVICE")) ) + { + printf( "ECORE_FB: TSLIB_TSDEVICE = '%s'\n", tslib_tsdevice ); + _ecore_fb_tslib_tsdev = ts_open( tslib_tsdevice, 1 ); /* 1 = nonblocking, 0 = blocking */ + + if ( !_ecore_fb_tslib_tsdev ) + { + printf( "ECORE_FB: Can't ts_open (%s)\n", strerror( errno ) ); + return 0; + } + + if ( ts_config( _ecore_fb_tslib_tsdev ) ) + { + printf( "ECORE_FB: Can't ts_config (%s)\n", strerror( errno ) ); + return 0; + } + _ecore_fb_ts_fd = ts_fd( _ecore_fb_tslib_tsdev ); + if ( _ecore_fb_ts_fd < 0 ) + { + printf( "ECORE_FB: Can't open touchscreen (%s)\n", strerror( errno ) ); + return 0; + } + } +#else + _ecore_fb_ts_fd = open("/dev/touchscreen/0", O_RDONLY); +#endif + if (_ecore_fb_ts_fd >= 0) + { + _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ts_fd, + ECORE_FD_READ, + _ecore_fb_ts_fd_handler, NULL, + NULL, NULL); + if (!_ecore_fb_ts_fd_handler_handle) + { + close(_ecore_fb_ts_fd); + return 0; + } + // FIXME _ecore_fb_kbd_fd = open("/dev/touchscreen/key", O_RDONLY); + return 1; + } + return 0; +} + +EAPI void +ecore_fb_ts_shutdown(void) +{ + if (_ecore_fb_ts_fd_handler_handle) + ecore_main_fd_handler_del(_ecore_fb_ts_fd_handler_handle); + if (_ecore_fb_ts_fd >= 0) close(_ecore_fb_ts_fd); + _ecore_fb_ts_fd = -1; + _ecore_fb_ts_fd_handler_handle = NULL; + _ecore_fb_ts_event_window = NULL; +} + +EAPI void +ecore_fb_ts_event_window_set(void *window) +{ + _ecore_fb_ts_event_window = window; +} + +EAPI void * +ecore_fb_ts_event_window_get(void) +{ + return _ecore_fb_ts_event_window; +} + +/** + * @defgroup Ecore_FB_Calibrate_Group Framebuffer Calibration Functions + * + * Functions that calibrate the screen. + */ + + +/** + * Calibrates the touschreen using the given parameters. + * @param xscale X scaling, where 256 = 1.0 + * @param xtrans X translation. + * @param yscale Y scaling. + * @param ytrans Y translation. + * @param xyswap Swap X & Y flag. + * @ingroup Ecore_FB_Calibrate_Group + */ +EAPI void +ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap) +{ + Ecore_Fb_Ts_Calibrate cal; + + if (_ecore_fb_ts_fd < 0) return; + cal.xscale = xscale; + cal.xtrans = xtrans; + cal.yscale = yscale; + cal.ytrans = ytrans; + cal.xyswap = xyswap; + if (ioctl(_ecore_fb_ts_fd, TS_SET_CAL, (void *)&cal)) + { + _ecore_fb_ts_cal = cal; + _ecore_fb_ts_apply_cal = 1; + } +} + +/** + * Retrieves the calibration parameters of the touchscreen. + * @param xscale Pointer to an integer in which to store the X scaling. + * Note that 256 = 1.0. + * @param xtrans Pointer to an integer in which to store the X translation. + * @param yscale Pointer to an integer in which to store the Y scaling. + * @param ytrans Pointer to an integer in which to store the Y translation. + * @param xyswap Pointer to an integer in which to store the Swap X & Y flag. + * @ingroup Ecore_FB_Calibrate_Group + */ +EAPI void +ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap) +{ + Ecore_Fb_Ts_Calibrate cal; + + if (_ecore_fb_ts_fd < 0) return; + if (!_ecore_fb_ts_apply_cal) + { + if (ioctl(_ecore_fb_ts_fd, TS_GET_CAL, (void *)&cal)) + _ecore_fb_ts_cal = cal; + } + else + cal = _ecore_fb_ts_cal; + if (xscale) *xscale = cal.xscale; + if (xtrans) *xtrans = cal.xtrans; + if (yscale) *yscale = cal.yscale; + if (ytrans) *ytrans = cal.ytrans; + if (xyswap) *xyswap = cal.xyswap; +} + +static Eina_Bool +_ecore_fb_ts_fd_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + static int prev_x = 0, prev_y = 0, prev_pressure = 0; + static double last_time = 0; + static double last_last_time = 0; + int v = 0; + + do + { + int x, y, pressure; + int num; + char *ptr; + double t = 0.0; + static int did_double = 0; + static int did_triple = 0; + +#ifdef HAVE_TSLIB + if (_ecore_fb_ts_apply_cal) + num = ts_read_raw(_ecore_fb_tslib_tsdev, &_ecore_fb_tslib_event, 1); + else + num = ts_read(_ecore_fb_tslib_tsdev, &_ecore_fb_tslib_event, 1); + if (num != 1) return 1; /* no more samples at this time */ + x = _ecore_fb_tslib_event.x; + y = _ecore_fb_tslib_event.y; + pressure = _ecore_fb_tslib_event.pressure; + v = 1; /* loop, there might be more samples */ +#else + ptr = (char *)&(_ecore_fb_ts_event); + ptr += _ecore_fb_ts_event_byte_count; + num = sizeof(Ecore_Fb_Ts_Event) - _ecore_fb_ts_event_byte_count; + v = read(_ecore_fb_ts_fd, ptr, num); + if (v < 0) return 1; + _ecore_fb_ts_event_byte_count += v; + if (v < num) return 1; + _ecore_fb_ts_event_byte_count = 0; + if (_ecore_fb_ts_apply_cal) + { + x = ((_ecore_fb_ts_cal.xscale * _ecore_fb_ts_event.x) >> 8) + _ecore_fb_ts_cal.xtrans; + y = ((_ecore_fb_ts_cal.yscale * _ecore_fb_ts_event.y) >> 8) + _ecore_fb_ts_cal.ytrans; + } + else + { + x = _ecore_fb_ts_event.x; + y = _ecore_fb_ts_event.y; + } + pressure = _ecore_fb_ts_event.pressure; +#endif + t = ecore_loop_time_get(); + /* add event to queue */ + /* always add a move event */ + if ((pressure) || (prev_pressure)) + { + /* MOVE: mouse is down and was */ + Ecore_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_Event_Mouse_Move)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->root.x = e->x; + e->root.y = e->y; + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + if ((pressure) && (!prev_pressure)) + { + /* DOWN: mouse is down, but was not now */ + Ecore_Event_Mouse_Button *e; + + e = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->root.x = e->x; + e->root.y = e->y; + e->buttons = 1; + if ((t - last_time) <= _ecore_fb_double_click_time) + { + e->double_click = 1; + did_double = 1; + } + else + { + did_double = 0; + did_triple = 0; + } + if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time)) + { + did_triple = 1; + e->triple_click = 1; + } + else + { + did_triple = 0; + } + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL); + } + else if ((!pressure) && (prev_pressure)) + { + /* UP: mouse was down, but is not now */ + Ecore_Event_Mouse_Button *e; + + e = calloc(1, sizeof(Ecore_Event_Mouse_Button)); + if (!e) goto retry; + e->x = prev_x; + e->y = prev_y; + e->root.x = e->x; + e->root.y = e->y; + e->buttons = 1; + if (did_double) + e->double_click = 1; + if (did_triple) + e->triple_click = 1; + e->window = 1; + e->event_window = e->window; + e->root_window = e->window; + e->same_screen = 1; + e->timestamp = ecore_loop_time_get() * 1000.0; + ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL); + } + if (did_triple) + { + last_time = 0; + last_last_time = 0; + } + else + { + last_last_time = last_time; + last_time = t; + } +retry: + prev_x = x; + prev_y = y; + prev_pressure = pressure; + } + while (v > 0); + return 1; +} + diff --git a/src/lib/ecore_fb/ecore_fb_vt.c b/src/lib/ecore_fb/ecore_fb_vt.c new file mode 100644 index 0000000000..c92c087336 --- /dev/null +++ b/src/lib/ecore_fb/ecore_fb_vt.c @@ -0,0 +1,322 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "Ecore_Fb.h" +#include "ecore_fb_private.h" + +static int _ecore_fb_vt_do_switch = 0; + +static int _ecore_fb_vt_tty0_fd = -1; +static int _ecore_fb_vt_tty_fd = -1; +static int _ecore_fb_vt_current_vt = 0; +static int _ecore_fb_vt_prev_vt = 0; + +static struct termios _ecore_fb_tty_prev_tio_mode; +static struct vt_mode _ecore_fb_vt_prev_mode; + +static Eina_Bool _ecore_fb_signal_usr_handler(void *data, int type, void *ev); +static Ecore_Event_Handler *_ecore_fb_user_handler = NULL; +static int _ecore_fb_tty_prev_mode = 0; +static int _ecore_fb_tty_prev_kd_mode = 0; + +/* callbacks for an attach/release of a vt */ +static void (*_ecore_fb_func_fb_lost) (void *data) = NULL; +static void *_ecore_fb_func_fb_lost_data = NULL; +static void (*_ecore_fb_func_fb_gain) (void *data) = NULL; +static void *_ecore_fb_func_fb_gain_data = NULL; + +/* FIXME what is the filter for? */ +static Ecore_Event_Filter *_ecore_fb_filter_handler = NULL; + +/* prototypes */ +/* XXX: unused +static void _ecore_fb_vt_switch(int vt); +static void *_ecore_fb_event_filter_start(void *data); +static Eina_Bool _ecore_fb_event_filter_filter(void *data, void *loop_data, int type, void *event); +static void _ecore_fb_event_filter_end(void *data, void *loop_data); +*/ + +static Eina_Bool +_ecore_fb_signal_usr_handler(void *data EINA_UNUSED, int type EINA_UNUSED, void *ev) +{ + Ecore_Event_Signal_User *e; + + e = (Ecore_Event_Signal_User *)ev; + if (e->number == 1) + { + /* release vt */ + if (_ecore_fb_func_fb_lost) _ecore_fb_func_fb_lost(_ecore_fb_func_fb_lost_data); + /* TODO stop listening from the devices? let the callback do it? */ + ioctl(_ecore_fb_vt_tty_fd, VT_RELDISP, 1); + } + else if (e->number == 2) + { + /* attach vt */ + if (_ecore_fb_func_fb_gain) _ecore_fb_func_fb_gain(_ecore_fb_func_fb_gain_data); + /* TODO reattach all devices */ + } + return 1; +} + +/* XXX: unused +static void +_ecore_fb_vt_switch(int vt) +{ + vt++; + if (_ecore_fb_vt_tty_fd != 0) + { + if (vt != _ecore_fb_vt_current_vt) + { + tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); + } + } + ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, vt); +} +*/ + +static int +_ecore_fb_vt_setup(void) +{ + char buf[64]; +// XXX: unused +// struct termios tio; + struct vt_mode new_vtmode; + + if (_ecore_fb_vt_current_vt != _ecore_fb_vt_prev_vt) + { + snprintf(buf, sizeof(buf), "/dev/tty%i", _ecore_fb_vt_current_vt); + if ((_ecore_fb_vt_tty_fd = open(buf, O_RDWR)) < 0) + { + printf("[ecore_fb:vt_setup] can't open tty %d\n", _ecore_fb_vt_current_vt); + return 0; + } + close(_ecore_fb_vt_tty0_fd); + _ecore_fb_vt_tty0_fd = -1; + /* FIXME detach the process from current tty ? */ + } + else + _ecore_fb_vt_tty_fd = _ecore_fb_vt_tty0_fd; + /* for backup */ + tcgetattr(_ecore_fb_vt_tty_fd, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_vt_tty_fd, KDGETMODE, &_ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_vt_tty_fd, VT_GETMODE, &_ecore_fb_vt_prev_mode); + + if (ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) + { + perror("[ecore_fb:vt_setup] can't set the mode to KD_GRAPHICS"); + close(_ecore_fb_vt_tty_fd); + _ecore_fb_vt_tty_fd = -1; + return 0; + } + ioctl(_ecore_fb_vt_tty_fd, KDGKBMODE, &_ecore_fb_tty_prev_mode); + + /* support of switching */ + new_vtmode.mode = VT_PROCESS; + new_vtmode.waitv = 0; + new_vtmode.relsig = SIGUSR1; + new_vtmode.acqsig = SIGUSR2; + if (ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &new_vtmode) < 0) + { + perror("[ecore_fb:vt_setup] can't set the tty mode"); + close(_ecore_fb_vt_tty_fd); + _ecore_fb_vt_tty_fd = -1; + return 0; + } + /* register signal handlers when alloc/detach of vt */ + _ecore_fb_user_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, + _ecore_fb_signal_usr_handler, + NULL); + /* What does this do? */ + /* + _ecore_fb_filter_handler = ecore_event_filter_add(_ecore_fb_event_filter_start, _ecore_fb_event_filter_filter, _ecore_fb_event_filter_end, NULL); + */ + + usleep(40000); + if (ioctl(_ecore_fb_vt_tty_fd, VT_ACTIVATE, _ecore_fb_vt_current_vt) < 0) + { + perror("[ecore_fb:vt_setup] error on VT_ACTIVATE"); + close(_ecore_fb_vt_tty_fd); + _ecore_fb_vt_tty_fd = -1; + return 0; + } + if(ioctl(_ecore_fb_vt_tty_fd, VT_WAITACTIVE, _ecore_fb_vt_current_vt) < 0) + { + perror("[ecore_fb:vt_setup] error on VT_WAITACTIVE"); + close(_ecore_fb_vt_tty_fd); + _ecore_fb_vt_tty_fd = -1; + return 0; + } + /* FIXME assign the fb to the tty in case isn't setup */ + return 1; +} + +int +ecore_fb_vt_init(void) +{ + struct vt_stat vtstat; + + /* as root you can allocate another tty */ + if (!geteuid()) + _ecore_fb_vt_do_switch = 1; + if ((_ecore_fb_vt_tty0_fd = open("/dev/tty0", O_RDONLY)) < 0) + { + printf("[ecore_fb:init] can't open /dev/tty0\n"); + return 0; + } + /* query current vt state */ + if ((ioctl(_ecore_fb_vt_tty0_fd, VT_GETSTATE, &vtstat)) < 0) + { + printf("[ecore_fb:init] can't get current tty state\n"); + return 0; + } + _ecore_fb_vt_prev_vt = vtstat.v_active; + /* switch to another tty */ + if (_ecore_fb_vt_do_switch) + { + int vtno; + + if ((ioctl(_ecore_fb_vt_tty0_fd, VT_OPENQRY, &vtno) < 0)) + { + printf("[ecore_fb:init] can't query for a vt\n"); + return 0; + } + _ecore_fb_vt_current_vt = vtno; + } + /* use current tty */ + else + _ecore_fb_vt_current_vt = _ecore_fb_vt_prev_vt; + if (!_ecore_fb_vt_setup()) + { + printf("[ecore_fb:init] can't setup the vt, restoring previous mode...\n"); + /* TODO finish this */ + if (_ecore_fb_vt_do_switch) + { + printf("[ecore_fb:init] switching back to vt %d\n", _ecore_fb_vt_prev_vt); + } + return 0; + } + return 1; +} + +void +ecore_fb_vt_shutdown(void) +{ + /* restore the previous mode */ + if (_ecore_fb_vt_tty_fd != -1) + { + tcsetattr(_ecore_fb_vt_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_vt_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_vt_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); + ioctl(_ecore_fb_vt_tty_fd, VT_SETMODE, &_ecore_fb_vt_prev_mode); + /* go back to previous vt */ + close(_ecore_fb_vt_tty_fd); + _ecore_fb_vt_tty_fd = -1; + } + + if (_ecore_fb_user_handler) ecore_event_handler_del(_ecore_fb_user_handler); + _ecore_fb_user_handler = NULL; + + if (_ecore_fb_filter_handler) ecore_event_filter_del(_ecore_fb_filter_handler); + _ecore_fb_filter_handler = NULL; +} + +/** + * @addtogroup Ecore_FB_Group Ecore_FB - Frame buffer convenience functions. + * + * @{ + */ + +/** + * @brief Set a callback called when a virtual terminal is gained. + * + * @param func The callback called when vt is gained. + * @param data The data to pass to the callback. + * + * This function sets the callback @p func which will be called when a + * virtual terminal is gained (for example you press Ctrl-Alt-F1 to go + * to vt1 and your app was using vt1). @p data will be pass to @p func if + * the callback is called. + */ +EAPI void +ecore_fb_callback_gain_set(void (*func) (void *data), void *data) +{ + _ecore_fb_func_fb_gain = func; + _ecore_fb_func_fb_gain_data = data; +} + +/** + * @brief Set a callback called when a virtual terminal is lost. + * + * @param func The callback called when vt is lost. + * @param data The data to pass to the callback. + * + * This function sets the callback @p func which will be called when a + * virtual terminal is lost (someone wants the tv from you and you + * want to give up that vt). @p data will be pass to @p func if the + * callback is called. + */ +EAPI void +ecore_fb_callback_lose_set(void (*func) (void *data), void *data) +{ + _ecore_fb_func_fb_lost = func; + _ecore_fb_func_fb_lost_data = data; + +} + +/** + * @} + */ + +/* + * This filter should take into account that the MOUSE_MOVE event can be + * triggered by a mouse, not just a touchscreen device, so you can't discard + * them (only those generated by a device that sends events with absolute + * coordinates). + +typedef struct _Ecore_Fb_Filter_Data Ecore_Fb_Filter_Data; + +struct _Ecore_Fb_Filter_Data +{ + int last_event_type; +}; + +static void * +_ecore_fb_event_filter_start(void *data EINA_UNUSED) +{ + Ecore_Fb_Filter_Data *filter_data; + + filter_data = calloc(1, sizeof(Ecore_Fb_Filter_Data)); + return filter_data; +} + +static Eina_Bool +_ecore_fb_event_filter_filter(void *data EINA_UNUSED, void *loop_data,int type, void *event EINA_UNUSED) +{ + Ecore_Fb_Filter_Data *filter_data; + + filter_data = loop_data; + if (!filter_data) return EINA_TRUE; + if (type == ECORE_EVENT_MOUSE_MOVE) + { + if ((filter_data->last_event_type) == ECORE_EVENT_MOUSE_MOVE) + { + filter_data->last_event_type = type; + return EINA_FALSE; + } + } + filter_data->last_event_type = type; + return EINA_TRUE; +} + +static void +_ecore_fb_event_filter_end(void *data EINA_UNUSED, void *loop_data) +{ + Ecore_Fb_Filter_Data *filter_data; + + filter_data = loop_data; + if (filter_data) free(filter_data); +} +*/ |