diff --git a/configure.ac b/configure.ac index c709f7f0f3..f4b7aa57dc 100644 --- a/configure.ac +++ b/configure.ac @@ -4476,17 +4476,22 @@ if test "x${have_ecore_evas_opengl_x11}" = "xyes" || test "x${have_ecore_evas_op fi build_ecore_evas_x11="no" -build_ecore_evas_vnc="no" if test "x$have_ecore_evas_software_x11" = "xyes" || \ test "x$have_ecore_evas_opengl_x11" = "xyes"; then AC_DEFINE([BUILD_ECORE_EVAS_X11], [1], [Support for X Window Engines in Ecore_Evas]) build_ecore_evas_x11="yes" - if test "$want_vnc_server" = "yes"; then - build_ecore_evas_vnc="yes" - fi fi + AM_CONDITIONAL([BUILD_ECORE_EVAS_X11], [test "${build_ecore_evas_x11}" = "yes"]) +build_ecore_evas_vnc="no" +if test "${want_vnc_server}" = "yes" && \ + (test "${build_ecore_evas_x11}" = "yes" || \ + test "${want_fb}" = "yes"); then + AC_DEFINE([BUILD_ECORE_EVAS_VNC_SERVER], [1], [Build Ecore_Evas VNC module]) + build_ecore_evas_vnc="yes" +fi + AM_CONDITIONAL([BUILD_ECORE_EVAS_VNC_SERVER], [test "${build_ecore_evas_vnc}" = "yes"]) AC_DEFINE_IF([BUILD_ECORE_EVAS_VNC_SERVER], [test "${build_ecore_evas_vnc}" = "yes"], [1], [Build Ecore_Evas VNC module]) EFL_ADD_FEATURE([ECORE_EVAS], [vnc_server], [${build_ecore_evas_vnc}]) diff --git a/src/Makefile_Ecore_Evas.am b/src/Makefile_Ecore_Evas.am index ea854c402c..7907a67269 100644 --- a/src/Makefile_Ecore_Evas.am +++ b/src/Makefile_Ecore_Evas.am @@ -297,17 +297,25 @@ $(install_ecoreevasenginevncserverpkgLTLIBRARIES): install-libLTLIBRARIES modules_ecore_evas_vnc_server_module_la_SOURCES = $(VNCSERVERSOURCES) modules_ecore_evas_vnc_server_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ @ECORE_EVAS_CFLAGS@ \ -@LIBVNCSERVER_CFLAGS@ \ -@ECORE_X_CFLAGS@ \ --I$(top_srcdir)/src/modules/evas/engines/software_x11 +@LIBVNCSERVER_CFLAGS@ modules_ecore_evas_vnc_server_module_la_LIBADD = \ @USE_ECORE_EVAS_LIBS@ \ -@LIBVNCSERVER_LIBS@ \ -@USE_ECORE_X_LIBS@ +@LIBVNCSERVER_LIBS@ modules_ecore_evas_vnc_server_module_la_DEPENDENCIES = \ @USE_ECORE_EVAS_INTERNAL_LIBS@ modules_ecore_evas_vnc_server_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_ecore_evas_vnc_server_module_la_LIBTOOLFLAGS = --tag=disable-static +if BUILD_ECORE_EVAS_FB +modules_ecore_evas_vnc_server_module_la_CPPFLAGS += @ECORE_FB_CFLAGS@ -I$(top_srcdir)/src/modules/evas/engines/fb +modules_ecore_evas_vnc_server_module_la_LIBADD += @USE_ECORE_FB_LIBS@ +VNCSERVERSOURCES += \ +modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c \ +modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.h +endif +if BUILD_ECORE_EVAS_X11 +modules_ecore_evas_vnc_server_module_la_LIBADD += @USE_ECORE_X_LIBS@ +modules_ecore_evas_vnc_server_module_la_CPPFLAGS += @ECORE_X_CFLAGS@ -I$(top_srcdir)/src/modules/evas/engines/software_x11 +endif endif ### Binary diff --git a/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server.c b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server.c index 63df8d08b8..140a31089a 100644 --- a/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server.c +++ b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server.c @@ -11,8 +11,16 @@ #include #include #include -#include -#include + +#ifdef BUILD_ENGINE_SOFTWARE_X11 +# include +# include +#endif + +#ifdef BUILD_ENGINE_FB +# include +# include "ecore_evas_vnc_server_fb_keymap.h" +#endif #include #include @@ -57,6 +65,12 @@ static unsigned int _available_seat = 1; #endif #define DBG(...) EINA_LOG_DOM_DBG(_ecore_evas_vnc_server_log_dom, __VA_ARGS__) +typedef Eina_Bool (*Ecore_Evas_Vnc_Key_Info_Get)(rfbKeySym key, + const char **key_name, + const char **key_str, + const char **compose, + int *keycode); + typedef struct _Ecore_Evas_Vnc_Server { char *frame_buffer; rfbScreenInfoPtr vnc_screen; @@ -65,6 +79,7 @@ typedef struct _Ecore_Evas_Vnc_Server { Ecore_Evas_Vnc_Client_Accept_Cb accept_cb; void *accept_cb_data; Ecore_Evas *ee; + Ecore_Evas_Vnc_Key_Info_Get key_info_get_func; double double_click_time; int last_w; int last_h; @@ -263,6 +278,42 @@ _ecore_evas_vnc_server_ecore_event_generic_free(void *user_data, free(func_data); } +#ifdef BUILD_ENGINE_SOFTWARE_X11 +static Eina_Bool +_ecore_evas_vnc_server_x11_key_info_get(rfbKeySym key, + const char **key_name, + const char **key_str, + const char **compose, + int *keycode) +{ + *key_str = *key_name = ecore_x_keysym_string_get(key); + + if (!*key_str) + { + *keycode = 0; + return EINA_FALSE; + } + + *compose = NULL; + *keycode = ecore_x_keysym_keycode_get(*key_str); + return EINA_TRUE; +} +#endif + +#ifdef BUILD_ENGINE_FB +static Eina_Bool +_ecore_evas_vnc_server_fb_key_info_get(rfbKeySym key, + const char **key_name, + const char **key_str, + const char **compose, + int *keycode EINA_UNUSED) +{ + return ecore_evas_vnc_server_keysym_to_fb_translate(key, + key_name, key_str, + compose); +} +#endif + static void _ecore_evas_vnc_server_client_keyboard_event(rfbBool down, rfbKeySym key, @@ -272,7 +323,9 @@ _ecore_evas_vnc_server_client_keyboard_event(rfbBool down, Ecore_Evas_Vnc_Server_Client_Data *cdata = client->clientData; rfbScreenInfoPtr screen = client->screen; Ecore_Evas_Vnc_Server *server = screen->screenData; - const char *key_string; + const char *key_str, *compose, *key_name; + int keycode = 0; + Eina_Bool r; char buf[10]; if (key >= XK_Shift_L && key <= XK_Hyper_R) @@ -288,12 +341,13 @@ _ecore_evas_vnc_server_client_keyboard_event(rfbBool down, if (server->ee->ignore_events) return; - key_string = ecore_x_keysym_string_get(key); - EINA_SAFETY_ON_NULL_RETURN(key_string); + r = server->key_info_get_func(key, &key_str, &key_name, + &compose, &keycode); + EINA_SAFETY_ON_FALSE_RETURN(r); snprintf(buf, sizeof(buf), "%lc", key); - e = calloc(1, sizeof(Ecore_Event_Key) + strlen(buf) + 1); + e = calloc(1, sizeof(Ecore_Event_Key) + (compose ? 0 : strlen(buf) + 1)); EINA_SAFETY_ON_NULL_RETURN(e); e->timestamp = (unsigned int)time(NULL); @@ -303,10 +357,14 @@ _ecore_evas_vnc_server_client_keyboard_event(rfbBool down, server->ee->prop.window; e->dev = cdata->keyboard; efl_ref(cdata->keyboard); - e->keycode = ecore_x_keysym_keycode_get(key_string); - e->keyname = e->key = key_string; + e->keyname = key_name; + e->key = key_str; + e->keycode = keycode; e->compose = (char *)(e + 1); - strcpy((char *)e->compose, buf); + if (compose) + e->compose = compose; + else + strcpy((char *)e->compose, buf); e->string = e->compose; ecore_event_add(down ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP, @@ -618,18 +676,48 @@ ecore_evas_vnc_server_new(Ecore_Evas *ee, int port, const char *addr, { Ecore_Evas_Vnc_Server *server; Eina_Bool can_listen = EINA_FALSE; - Evas_Engine_Info_Software_X11 *einfo; - Eina_Bool err; + Evas_Engine_Info *engine; + Eina_Bool err, engine_set = EINA_FALSE; + Ecore_Evas_Vnc_Key_Info_Get key_info_get_func; EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL); - EINA_SAFETY_ON_TRUE_RETURN_VAL(strcmp(ee->driver, "software_x11"), NULL); + engine = evas_engine_info_get(ee->evas); - einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); - EINA_SAFETY_ON_NULL_RETURN_VAL(einfo, NULL); +#ifdef BUILD_ENGINE_SOFTWARE_X11 + if (!strcmp(ee->driver, "software_x11")) + { + Evas_Engine_Info_Software_X11 *x11_engine; + + x11_engine = (Evas_Engine_Info_Software_X11 *)engine; + x11_engine->func.region_push_hook = _ecore_evas_vnc_server_draw; + engine_set = EINA_TRUE; + key_info_get_func = _ecore_evas_vnc_server_x11_key_info_get; + } +#endif + +#ifdef BUILD_ENGINE_FB + if (!engine_set && !strcmp(ee->driver, "fb")) + { + Evas_Engine_Info_FB *fb_engine; + + fb_engine = (Evas_Engine_Info_FB *)engine; + fb_engine->func.region_push_hook = _ecore_evas_vnc_server_draw; + engine_set = EINA_TRUE; + key_info_get_func = _ecore_evas_vnc_server_fb_key_info_get; + } +#endif + + if (!engine_set) + { + WRN("The engine '%s' is not supported. Only Software X11" + " and FB are supported.", ee->driver); + return NULL; + } server = calloc(1, sizeof(Ecore_Evas_Vnc_Server)); EINA_SAFETY_ON_NULL_RETURN_VAL(server, NULL); + server->key_info_get_func = key_info_get_func; server->vnc_screen = rfbGetScreen(0, NULL, ee->w, ee->h, VNC_BITS_PER_SAMPLE, VNC_SAMPLES_PER_PIXEL, VNC_BYTES_PER_PIXEL); @@ -683,8 +771,7 @@ ecore_evas_vnc_server_new(Ecore_Evas *ee, int port, const char *addr, //rfbInitServer() failed and could not setup the sockets. EINA_SAFETY_ON_FALSE_GOTO(can_listen, err_addr); - einfo->func.region_push_hook = _ecore_evas_vnc_server_draw; - err = evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + err = evas_engine_info_set(ee->evas, (Evas_Engine_Info *)engine); EINA_SAFETY_ON_FALSE_GOTO(err, err_engine); server->vnc_screen->screenData = server; @@ -695,7 +782,6 @@ ecore_evas_vnc_server_new(Ecore_Evas *ee, int port, const char *addr, return server; err_engine: - einfo->func.region_push_hook = NULL; ecore_main_fd_handler_del(server->vnc_listen6_handler); err_listen: ecore_main_fd_handler_del(server->vnc_listen_handler); diff --git a/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c new file mode 100644 index 0000000000..33f9d2109d --- /dev/null +++ b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.c @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include + +static const char *_ecore_fb_li_kbd_syms[128 * 7] = +{ +#include +}; + +#include "ecore_evas_vnc_server_fb_keymap.h" + +static unsigned int +_x11_to_fb(rfbKeySym key, unsigned int *offset) +{ + switch (key) + { + case XK_Num_Lock: + return KEY_NUMLOCK; + case XK_KP_Delete: + return KEY_DELETE; + case XK_KP_Equal: + return KEY_KPEQUAL; + case XK_KP_Multiply: + return KEY_KPASTERISK; + case XK_KP_Add: + return KEY_KPPLUS; + case XK_KP_Subtract: + return KEY_KPMINUS; + case XK_KP_Decimal: + return KEY_KPDOT; + case XK_KP_Divide: + return KEY_KPSLASH; + case XK_plus: + *offset = 1; + case XK_equal: + return KEY_EQUAL; + case XK_underscore: + *offset = 1; + case XK_minus: + return KEY_MINUS; + case XK_quotedbl: + *offset = 1; + case XK_apostrophe: + return KEY_APOSTROPHE; + case XK_Shift_L: + return KEY_LEFTSHIFT; + case XK_Shift_R: + return KEY_RIGHTSHIFT; + case XK_Control_L: + return KEY_LEFTCTRL; + case XK_Control_R: + return KEY_RIGHTCTRL; + case XK_Caps_Lock: + return KEY_CAPSLOCK; + case XK_Meta_L: + return KEY_LEFTMETA; + case XK_Meta_R: + return KEY_RIGHTMETA; + case XK_Alt_L: + return KEY_LEFTALT; + case XK_Alt_R: + return KEY_RIGHTALT; + case XK_space: + return KEY_SPACE; + case XK_period: + *offset = 1; + case XK_greater: + return KEY_DOT; + case XK_bar: + *offset = 1; + case XK_backslash: + return KEY_BACKSLASH; + case XK_question: + *offset = 1; + case XK_slash: + return KEY_SLASH; + case XK_braceleft: + case XK_bracketleft: + return KEY_LEFTBRACE; + case XK_braceright: + case XK_bracketright: + return KEY_RIGHTBRACE; + case XK_colon: + *offset = 1; + case XK_semicolon: + return KEY_SEMICOLON; + case XK_asciitilde: + *offset = 1; + case XK_grave: + return KEY_GRAVE; + case XK_less: + *offset = 1; + case XK_comma: + return KEY_COMMA; + case XK_F1: + return KEY_F1; + case XK_F2: + return KEY_F2; + case XK_F3: + return KEY_F3; + case XK_F4: + return KEY_F4; + case XK_F5: + return KEY_F5; + case XK_F6: + return KEY_F6; + case XK_F7: + return KEY_F7; + case XK_F8: + return KEY_F8; + case XK_F9: + return KEY_F9; + case XK_F10: + return KEY_F10; + case XK_F11: + return KEY_F11; + case XK_F12: + return KEY_F12; + case XK_BackSpace: + return KEY_BACKSPACE; + case XK_Tab: + return KEY_TAB; + case XK_Return: + return KEY_ENTER; + case XK_Pause: + return KEY_PAUSE; + case XK_Escape: + return KEY_ESC; + case XK_Delete: + return KEY_DELETE; + case XK_Linefeed: + return KEY_LINEFEED; + case XK_Scroll_Lock: + return KEY_SCROLLLOCK; + case XK_Sys_Req: + return KEY_SYSRQ; + case XK_Home: + return KEY_HOME; + case XK_Left: + return KEY_LEFT; + case XK_Up: + return KEY_UP; + case XK_Right: + return KEY_RIGHT; + case XK_Down: + return KEY_DOWN; + case XK_Page_Up: + return KEY_PAGEUP; + case XK_Page_Down: + return KEY_PAGEDOWN; + case XK_End: + return KEY_END; + case XK_KP_0: + *offset = 1; + case XK_KP_Insert: + return KEY_KP0; + case XK_KP_1: + *offset = 1; + case XK_KP_End: + return KEY_KP1; + case XK_KP_2: + *offset = 1; + case XK_KP_Down: + return KEY_KP2; + case XK_KP_3: + *offset = 1; + case XK_KP_Next: + return KEY_KP3; + case XK_KP_4: + *offset = 1; + case XK_KP_Left: + return KEY_KP4; + case XK_KP_5: + *offset = 1; + case XK_KP_Begin: + return KEY_KP5; + case XK_KP_6: + *offset = 1; + case XK_KP_Right: + return KEY_KP6; + case XK_KP_7: + *offset = 1; + case XK_KP_Home: + return KEY_KP7; + case XK_KP_8: + *offset = 1; + case XK_KP_Up: + return KEY_KP8; + case XK_KP_9: + *offset = 1; + case XK_KP_Prior: + return KEY_KP9; + case XK_KP_Enter: + return KEY_KPENTER; + case XK_parenright: + *offset = 1; + case XK_0: + return KEY_0; + case XK_exclam: + *offset = 1; + case XK_1: + return KEY_1; + case XK_at: + *offset = 1; + case XK_2: + return KEY_2; + case XK_numbersign: + *offset = 1; + case XK_3: + return KEY_3; + case XK_dollar: + *offset = 1; + case XK_4: + return KEY_4; + case XK_percent: + *offset = 1; + case XK_5: + return KEY_5; + case XK_asciicircum: + *offset = 1; + case XK_6: + return KEY_6; + case XK_ampersand: + *offset = 1; + case XK_7: + return KEY_7; + case XK_asterisk: + *offset = 1; + case XK_8: + return KEY_8; + case XK_parenleft: + *offset = 1; + case XK_9: + return KEY_9; + case XK_A: + *offset = 1; + case XK_a: + return KEY_A; + case XK_B: + *offset = 1; + case XK_b: + return KEY_B; + case XK_C: + *offset = 1; + case XK_c: + return KEY_C; + case XK_D: + *offset = 1; + case XK_d: + return KEY_D; + case XK_E: + *offset = 1; + case XK_e: + return KEY_E; + case XK_F: + *offset = 1; + case XK_f: + return KEY_F; + case XK_G: + *offset = 1; + case XK_g: + return KEY_G; + case XK_H: + *offset = 1; + case XK_h: + return KEY_H; + case XK_I: + *offset = 1; + case XK_i: + return KEY_I; + case XK_J: + *offset = 1; + case XK_j: + return KEY_J; + case XK_K: + *offset = 1; + case XK_k: + return KEY_K; + case XK_L: + *offset = 1; + case XK_l: + return KEY_L; + case XK_M: + *offset = 1; + case XK_m: + return KEY_M; + case XK_N: + *offset = 1; + case XK_n: + return KEY_N; + case XK_O: + *offset = 1; + case XK_o: + return KEY_O; + case XK_P: + *offset = 1; + case XK_p: + return KEY_P; + case XK_Q: + *offset = 1; + case XK_q: + return KEY_Q; + case XK_R: + *offset = 1; + case XK_r: + return KEY_R; + case XK_S: + *offset = 1; + case XK_s: + return KEY_S; + case XK_T: + *offset = 1; + case XK_t: + return KEY_T; + case XK_U: + *offset = 1; + case XK_u: + return KEY_U; + case XK_V: + *offset = 1; + case XK_v: + return KEY_V; + case XK_W: + *offset = 1; + case XK_w: + return KEY_W; + case XK_X: + *offset = 1; + case XK_x: + return KEY_X; + case XK_Y: + *offset = 1; + case XK_y: + return KEY_Y; + case XK_Z: + *offset = 1; + case XK_z: + return KEY_Z; + default: + return UINT_MAX; + } +} + +Eina_Bool +ecore_evas_vnc_server_keysym_to_fb_translate(rfbKeySym key, + const char **key_name, + const char **key_str, + const char **compose) +{ + unsigned int offset = 0; + unsigned int id = _x11_to_fb(key, &offset); + + if (id == UINT_MAX) + return EINA_FALSE; + + *key_name = _ecore_fb_li_kbd_syms[id * 7]; + *key_str = _ecore_fb_li_kbd_syms[(id * 7) + offset]; + *compose = _ecore_fb_li_kbd_syms[(id* 7) + 3 + offset]; + return EINA_TRUE; +} + diff --git a/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.h b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.h new file mode 100644 index 0000000000..ebcfee1d33 --- /dev/null +++ b/src/modules/ecore_evas/vnc_server/ecore_evas_vnc_server_fb_keymap.h @@ -0,0 +1,12 @@ +#include +#include + +#ifndef ECORE_EVAS_VNC_SERVER_FB_KEY_MAP_H +#define ECORE_EVAS_VNC_SERVER_FB_KEY_MAP_H + +Eina_Bool ecore_evas_vnc_server_keysym_to_fb_translate(rfbKeySym key, + const char **key_name, + const char **key_str, + const char **compose); + +#endif