summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuilherme Iscaro <iscaro@profusion.mobi>2016-09-20 14:00:06 -0300
committerBruno Dilly <bdilly@profusion.mobi>2016-09-26 22:06:59 -0300
commit491fda47960ba06b1aba3b38ce154a89e1ac2fd2 (patch)
tree4a2e4935ce6b8c79597fcfbae4595620de8e3213
parentf4ff8fd4d5019503d5f50d57d357ba37048c45e0 (diff)
downloadefl-491fda47960ba06b1aba3b38ce154a89e1ac2fd2.tar.gz
Ecore_Evas_X: Dispatch Ecore_Events for VNC clients.
This patch adds the support for Ecore events from a remove VNC client. Every time it happens a VNC mouse move/click/wheel or a VNC keyboard event an Ecore event event will be created and dispatched.
-rw-r--r--src/modules/ecore_evas/engines/x/ecore_evas_x.c268
1 files changed, 257 insertions, 11 deletions
diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
index 88086e2401..75e391e3a6 100644
--- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c
+++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
@@ -29,6 +29,7 @@
#ifdef ENABLE_VNC_SERVER
# include <rfb/rfb.h>
# include <rfb/rfbregion.h>
+# include <rfb/keysym.h>
#endif
#ifdef EAPI
@@ -172,6 +173,13 @@ static void _rotation_do(Ecore_Evas *, int, int);
typedef struct _Ecore_Evas_X11_Vnc_Client_Data {
Ecore_Fd_Handler *handler;
+ unsigned int key_modifiers;
+ time_t last_mouse_button_down;
+ Eina_Bool double_click;
+ Eina_Bool triple_click;
+ Evas_Device *keyboard;
+ Evas_Device *mouse;
+ Evas_Device *seat;
} Ecore_Evas_X11_Vnc_Client_Data;
static unsigned int _available_seat = 1;
@@ -200,7 +208,8 @@ _ecore_evas_x11_update_vnc_clients(rfbScreenInfoPtr vnc_screen)
{
Ecore_Evas_X11_Vnc_Client_Data *cdata = client->clientData;
- WRN("Could not update the VNC client on seat '%p'\n", cdata);
+ WRN("Could not update the VNC client on seat '%s'\n",
+ evas_device_name_get(cdata->seat));
}
//Client disconnected
@@ -5290,9 +5299,12 @@ _ecore_evas_x11_client_gone(rfbClientRec *client)
{
Ecore_Evas_X11_Vnc_Client_Data *cdata = client->clientData;
- EDBG("VNC client on seat '%p' gone", cdata);
+ EDBG("VNC client on seat '%s' gone", evas_device_name_get(cdata->seat));
ecore_main_fd_handler_del(cdata->handler);
+ evas_device_del(cdata->keyboard);
+ evas_device_del(cdata->mouse);
+ evas_device_del(cdata->seat);
free(cdata);
_available_seat--;
}
@@ -5326,6 +5338,7 @@ _ecore_evas_x11_vnc_client_connection_new(rfbClientRec *client)
Ecore_Evas *ee;
Ecore_Evas_Engine_Data_X11 *edata;
Ecore_Evas_X11_Vnc_Client_Data *cdata;
+ char buf[32];
EINA_SAFETY_ON_TRUE_RETURN_VAL(_available_seat == UINT_MAX,
RFB_CLIENT_REFUSE);
@@ -5344,33 +5357,266 @@ _ecore_evas_x11_vnc_client_connection_new(rfbClientRec *client)
client, NULL, NULL);
EINA_SAFETY_ON_NULL_GOTO(cdata->handler, err_handler);
+ snprintf(buf, sizeof(buf), "seat-%u", _available_seat);
+
+ cdata->seat = evas_device_full_add(ee->evas, buf,
+ "A remote VNC seat",
+ NULL, NULL, EVAS_DEVICE_CLASS_SEAT,
+ EVAS_DEVICE_SUBCLASS_NONE);
+ EINA_SAFETY_ON_NULL_GOTO(cdata->seat, err_handler);
+ cdata->keyboard = evas_device_full_add(ee->evas, "Keyboard",
+ "A remote VNC keyboard",
+ cdata->seat, NULL,
+ EVAS_DEVICE_CLASS_KEYBOARD,
+ EVAS_DEVICE_SUBCLASS_NONE);
+ EINA_SAFETY_ON_NULL_GOTO(cdata->keyboard, err_dev);
+ cdata->mouse = evas_device_full_add(ee->evas, "Mouse",
+ "A remote VNC mouse",
+ cdata->seat, NULL,
+ EVAS_DEVICE_CLASS_MOUSE,
+ EVAS_DEVICE_SUBCLASS_NONE);
+ EINA_SAFETY_ON_NULL_GOTO(cdata->mouse, err_mouse);
client->clientGoneHook = _ecore_evas_x11_client_gone;
client->clientData = cdata;
EDBG("New VNC client on seat '%u'", _available_seat);
-
_available_seat++;
+
return RFB_CLIENT_ACCEPT;
+ err_mouse:
+ evas_device_del(cdata->keyboard);
+ err_dev:
+ evas_device_del(cdata->seat);
err_handler:
free(cdata);
return RFB_CLIENT_REFUSE;
}
+static unsigned int
+_ecore_evas_x11_vnc_vnc_modifier_to_ecore_x_modifier(int mod)
+{
+ if (mod == XK_Shift_L || mod == XK_Shift_R)
+ return ECORE_EVENT_MODIFIER_SHIFT;
+ if (mod == XK_Control_L || mod == XK_Control_R)
+ return ECORE_EVENT_MODIFIER_CTRL;
+ if (mod == XK_Alt_L || mod == XK_Alt_R)
+ return ECORE_EVENT_MODIFIER_ALT;
+ if (mod == XK_Super_L || mod == XK_Super_R)
+ return ECORE_EVENT_MODIFIER_WIN;
+ if (mod == XK_Scroll_Lock)
+ return ECORE_EVENT_LOCK_SCROLL;
+ if (mod == XK_Num_Lock)
+ return ECORE_EVENT_LOCK_NUM;
+ if (mod == XK_Caps_Lock)
+ return ECORE_EVENT_LOCK_CAPS;
+ if (mod == XK_Shift_Lock)
+ return ECORE_EVENT_LOCK_SHIFT;
+ return 0;
+}
+
static void
-_ecore_evas_x11_vnc_client_keyboard_event(rfbBool down EINA_UNUSED,
- rfbKeySym keySym EINA_UNUSED,
- rfbClientRec *client EINA_UNUSED)
+_ecore_evas_x11_ecore_event_generic_free(void *user_data,
+ void *func_data)
{
- EDBG("Keyboard event\n");
+ efl_unref(user_data);
+ free(func_data);
}
static void
-_ecore_evas_x11_vnc_client_pointer_event(int buttonMask EINA_UNUSED,
- int x EINA_UNUSED, int y EINA_UNUSED,
- rfbClientPtr client EINA_UNUSED)
+_ecore_evas_x11_vnc_client_keyboard_event(rfbBool down,
+ rfbKeySym key,
+ rfbClientRec *client)
{
- EDBG("Pointer event\n");
+ Ecore_Event_Key *e;
+ Ecore_Evas_X11_Vnc_Client_Data *cdata = client->clientData;
+ rfbScreenInfoPtr screen = client->screen;
+ Ecore_Evas *ee = screen->screenData;
+ const char *key_string;
+ char buf[10];
+
+ if (key >= XK_Shift_L && key <= XK_Hyper_R)
+ {
+ int mod = _ecore_evas_x11_vnc_vnc_modifier_to_ecore_x_modifier(key);
+
+ if (down)
+ cdata->key_modifiers |= mod;
+ else
+ cdata->key_modifiers &= ~mod;
+ }
+
+ if (ee->ignore_events)
+ return;
+
+ key_string = ecore_x_keysym_string_get(key);
+ EINA_SAFETY_ON_NULL_RETURN(key_string);
+
+ snprintf(buf, sizeof(buf), "%lc", key);
+
+ e = calloc(1, sizeof(Ecore_Event_Key) + strlen(buf) + 1);
+ EINA_SAFETY_ON_NULL_RETURN(e);
+
+ e->timestamp = (unsigned int)time(NULL);
+ e->modifiers = cdata->key_modifiers;
+ e->same_screen = 1;
+ e->window = e->root_window = e->event_window = 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->compose = (char *)(e + 1);
+ strcpy((char *)e->compose, buf);
+ e->string = e->compose;
+
+ ecore_event_add(down ? ECORE_EVENT_KEY_DOWN : ECORE_EVENT_KEY_UP,
+ e, _ecore_evas_x11_ecore_event_generic_free,
+ cdata->keyboard);
+}
+
+static int
+_ecore_evas_x11_vnc_pointer_button_get(int mask)
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ if (mask >> i & 1)
+ return i + 1;
+ return 0;
+}
+
+static void
+_ecore_evas_x11_vnc_client_pointer_event(int button_mask,
+ int x, int y,
+ rfbClientPtr client)
+{
+ Ecore_Evas_X11_Vnc_Client_Data *cdata = client->clientData;
+ rfbScreenInfoPtr screen = client->screen;
+ Ecore_Evas *ee = screen->screenData;
+ Ecore_Event_Mouse_Move *move_event;
+ Ecore_Event_Mouse_Button *button_event;
+ Ecore_Event_Mouse_Wheel *wheel_event;
+ int button_changed, button, event, z = 0, direction = 0;
+ time_t now = time(NULL);
+
+ if (ee->ignore_events)
+ return;
+
+ if (client->lastPtrX != x || client->lastPtrY != y)
+ {
+ move_event = calloc(1, sizeof(Ecore_Event_Mouse_Move));
+ EINA_SAFETY_ON_NULL_RETURN(move_event);
+
+ move_event->x = move_event->multi.x = x;
+ move_event->y = move_event->multi.y = y;
+ move_event->same_screen = 1;
+ move_event->timestamp = (unsigned int)now;
+ move_event->window = move_event->event_window =
+ move_event->root_window = ee->prop.window;
+ move_event->multi.pressure = 1.0;
+ move_event->modifiers = cdata->key_modifiers;
+ move_event->dev = cdata->mouse;
+ efl_ref(cdata->mouse);
+ ecore_event_add(ECORE_EVENT_MOUSE_MOVE, move_event,
+ _ecore_evas_x11_ecore_event_generic_free, cdata->mouse);
+ client->lastPtrX = x;
+ client->lastPtrY = y;
+ }
+
+ button_changed = button_mask - client->lastPtrButtons;
+
+ if (button_changed > 0)
+ {
+ button = _ecore_evas_x11_vnc_pointer_button_get(button_changed);
+
+ switch (button)
+ {
+ case 4:
+ event = ECORE_EVENT_MOUSE_WHEEL;
+ direction = 0; //Vertical
+ z = -1; //Up
+ break;
+ case 5:
+ event = ECORE_EVENT_MOUSE_WHEEL;
+ direction = 0;
+ z = 1; //Down
+ break;
+ case 6:
+ event = ECORE_EVENT_MOUSE_WHEEL;
+ direction = 1; //Horizontal
+ z = -1;
+ break;
+ case 7:
+ event = ECORE_EVENT_MOUSE_WHEEL;
+ direction = 1;
+ z = 1;
+ break;
+ default:
+ event = ECORE_EVENT_MOUSE_BUTTON_DOWN;
+ }
+
+ if (now - cdata->last_mouse_button_down <= 1000 * ecore_x_double_click_time_get())
+ cdata->double_click = EINA_TRUE;
+ else
+ cdata->double_click = cdata->triple_click = EINA_FALSE;
+
+ if (now - cdata->last_mouse_button_down <= 2000 * ecore_x_double_click_time_get())
+ cdata->triple_click = EINA_TRUE;
+ else
+ cdata->triple_click = EINA_FALSE;
+
+ cdata->last_mouse_button_down = now;
+ }
+ else if (button_changed < 0)
+ {
+ button = _ecore_evas_x11_vnc_pointer_button_get(-button_changed);
+ //Ignore, it was already report.
+ if (button > 3 && button < 8)
+ return;
+ event = ECORE_EVENT_MOUSE_BUTTON_UP;
+ }
+ else
+ return;
+
+ if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN ||
+ event == ECORE_EVENT_MOUSE_BUTTON_UP)
+ {
+ button_event = calloc(1, sizeof(Ecore_Event_Mouse_Button));
+ EINA_SAFETY_ON_NULL_RETURN(button_event);
+
+ button_event->timestamp = (unsigned int)now;
+ button_event->window = button_event->event_window =
+ button_event->root_window = ee->prop.window;
+ button_event->x = button_event->multi.x = x;
+ button_event->y = button_event->multi.y = y;
+ button_event->multi.pressure = 1.0;
+ button_event->same_screen = 1;
+ button_event->buttons = button;
+ button_event->modifiers = cdata->key_modifiers;
+ button_event->double_click = cdata->double_click ? 1 : 0;
+ button_event->triple_click = cdata->triple_click ? 1 : 0;
+ button_event->dev = cdata->mouse;
+ efl_ref(cdata->mouse);
+
+ ecore_event_add(event, button_event,
+ _ecore_evas_x11_ecore_event_generic_free, cdata->mouse);
+ return;
+ }
+
+ //Mouse wheel
+ wheel_event = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
+ EINA_SAFETY_ON_NULL_RETURN(wheel_event);
+ wheel_event->dev = cdata->mouse;
+ efl_ref(cdata->mouse);
+ wheel_event->window = wheel_event->event_window =
+ wheel_event->root_window = ee->prop.window;
+ wheel_event->same_screen = 1;
+ wheel_event->modifiers = cdata->key_modifiers;
+ wheel_event->x = x;
+ wheel_event->y = y;
+ wheel_event->direction = direction;
+ wheel_event->z = z;
+
+ ecore_event_add(event, wheel_event,
+ _ecore_evas_x11_ecore_event_generic_free, cdata->mouse);
}
#endif