Merge branch 'devs/iscaro/ecore_evas_vnc_multiseat'

This series adds the Ecore_Evas multi-seat VNC support
using the software X11 backend.
This implementation tries to mimic the Wayland's multi-seat support.

This series also introduces two new kinds of EFL events, which are:
 * EFL_CANVAS_EVENT_DEVICE_ADDED - Which is emitted every
   time an Evas_Device is created.
 * EFL_CANVAS_EVENT_DEVICE_REMOVED - Which is emmited every
   time an Evas_Device is removed/deleted.

The new events are useful when one wants to monitor how many
and what kind of devices are connected to the system.

Patches by iscaro.
Differential Revision: https://phab.enlightenment.org/D4295

@feature
This commit is contained in:
Bruno Dilly 2016-09-26 22:07:13 -03:00
commit 0566abeee8
19 changed files with 1130 additions and 53 deletions

View File

@ -433,6 +433,24 @@ AC_DEFINE_IF([ENABLE_LIBLZ4], [test "${want_liblz4}" = "yes"], [1], [Use liblz4
AC_SUBST([want_liblz4])
AC_SUBST([ENABLE_LIBLZ4])
want_vnc_server="no"
AC_ARG_ENABLE([vnc-server],
[AS_HELP_STRING([--enable-vnc-server],[Enable VNC server support for Ecore_Evas_X. @<:@default=disabled@:>@])],
[
if test "x${enableval}" = "xyes" ; then
want_vnc_server="yes"
else
want_vnc_server="no"
fi
],
[want_vnc_server="no"])
AM_CONDITIONAL([ENABLE_VNC_SERVER], [test "${want_vnc_server}" = "yes"])
AC_DEFINE_IF([ENABLE_VNC_SERVER], [test "${want_vnc_server}" = "yes"], [1], [Use VNC server support for Ecore_Evas_X])
AC_SUBST([want_vnc_server])
AC_SUBST([ENABLE_VNC_SERVER])
#### Checks for header files
# Common Checks (keep names sorted for ease of use):
@ -4622,7 +4640,8 @@ AM_CONDITIONAL([BUILD_ECORE_EVAS_WIN32],
# XXX TODO: ecore_evas_x11
ECORE_EVAS_MODULE([software-x11], [${want_x11_any}])
ECORE_EVAS_MODULE([software-x11], [${want_x11_any}],
[EFL_OPTIONAL_DEPEND_PKG([ECORE_EVAS], [${want_vnc_server}], [VNC_SERVER], [libvncserver])])
have_ecore_evas_software_xlib="no"
have_ecore_evas_software_xcb="no"
@ -4645,7 +4664,8 @@ fi
# XXX TODO: ecore_evas_opengl_x11
ECORE_EVAS_MODULE([opengl-x11], [${want_x11_any_opengl}])
ECORE_EVAS_MODULE([opengl-x11], [${want_x11_any_opengl}],
[EFL_OPTIONAL_DEPEND_PKG([ECORE_EVAS], [${want_vnc_server}], [VNC_SERVER], [libvncserver])])
have_ecore_evas_opengl_xlib="no"
have_ecore_evas_opengl_xcb="no"

View File

@ -25,6 +25,7 @@
/ecore_evas_extn_socket_example
/ecore_evas_object_example
/ecore_evas_window_sizes_example
/ecore_evas_vnc
/ecore_event_example_01
/ecore_event_example_02
/ecore_exe_example

View File

@ -60,6 +60,7 @@ ecore_evas_callbacks \
ecore_evas_ews_example \
ecore_evas_object_example \
ecore_evas_window_sizes_example \
ecore_evas_vnc \
ecore_event_example_01 \
ecore_event_example_02 \
ecore_exe_example \
@ -203,6 +204,9 @@ ecore_evas_object_example_LDADD = $(ECORE_EVAS_COMMON_LDADD)
ecore_evas_window_sizes_example_SOURCES = ecore_evas_window_sizes_example.c
ecore_evas_window_sizes_example_LDADD = $(ECORE_EVAS_COMMON_LDADD)
ecore_evas_vnc_SOURCES = ecore_evas_vnc.c
ecore_evas_vnc_LDADD = $(ECORE_EVAS_COMMON_LDADD)
ecore_event_example_01_SOURCES = ecore_event_example_01.c
ecore_event_example_01_LDADD = $(ECORE_COMMON_LDADD)
@ -330,6 +334,7 @@ ecore_evas_callbacks.c \
ecore_evas_ews_example.c \
ecore_evas_object_example.c \
ecore_evas_window_sizes_example.c \
ecore_evas_vnc.c \
ecore_event_example_01.c \
ecore_event_example_02.c \
ecore_exe_example.c \

View File

@ -0,0 +1,244 @@
#define EFL_EO_API_SUPPORT
#define EFL_BETA_API_SUPPORT
#include <Efl.h>
#include <stdio.h>
#include <Ecore.h>
#include <Evas.h>
#include <Eina.h>
#include <Ecore_Evas.h>
#include <Ecore_Input.h>
static Eina_Bool
_anim(void *data)
{
static enum { RIGHT, LEFT } direction = LEFT;
static const int speed = 20;
int x, y;
Evas_Object *rect = data;
evas_object_geometry_get(rect, &x, &y, NULL, NULL);
if (direction == LEFT)
{
x -= speed;
if (x <= 0)
{
x = 0;
direction = RIGHT;
}
}
else
{
x += speed;
if (x >= 800)
{
direction = LEFT;
x = 800;
}
}
evas_object_move(rect, x, y);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_accept_cb(void *data EINA_UNUSED, Ecore_Evas *ee EINA_UNUSED, const char *client_host)
{
printf("Client %s trying to connect\n", client_host);
return EINA_TRUE;
}
static Efl_Input_Device *
_get_seat(Efl_Input_Device *dev)
{
if (!dev)
return NULL;
while ((dev = efl_input_device_parent_get(dev)))
{
if (efl_input_device_type_get(dev) == EFL_INPUT_DEVICE_CLASS_SEAT)
return dev;
}
return NULL;
}
static Eina_Bool
_keyboard_event(void *data EINA_UNUSED, int type, void *event)
{
Ecore_Event_Key *e = event;
Efl_Input_Device *seat = NULL;
if (e->dev)
seat = _get_seat(e->dev);
printf("The keyboard on seat '%s' %s the key '%s'\n", seat ?
efl_input_device_name_get(seat) : "default",
type == ECORE_EVENT_KEY_DOWN ? "pressed" : "released",
e->keyname);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_mouse_move(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Ecore_Event_Mouse_Move *e = event;
Efl_Input_Device *seat = NULL;
if (e->dev)
seat = _get_seat(e->dev);
printf("The mouse on seat '%s' is at X: %d Y:%d\n",
seat ? efl_input_device_name_get(seat) : "default", e->x, e->y);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_mouse_button(void *data EINA_UNUSED, int type, void *event)
{
Ecore_Event_Mouse_Button *e = event;
Efl_Input_Device *seat = NULL;
if (e->dev)
seat = _get_seat(e->dev);
printf("The mouse on seat '%s' %s the following button '%d'\n",
seat ? efl_input_device_name_get(seat) : "default",
type == ECORE_EVENT_MOUSE_BUTTON_DOWN ? "pressed" : "released",
e->buttons);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_mouse_wheel(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Ecore_Event_Mouse_Wheel *e = event;
Efl_Input_Device *seat = NULL;
if (e->dev)
seat = _get_seat(e->dev);
printf("The mouse on seat '%s' moved the wheel '%s'\n",
seat ? efl_input_device_name_get(seat) : "default",
e->z < 0 ? "up" : "down");
return ECORE_CALLBACK_PASS_ON;
}
static const char *
_device_type_to_string(Efl_Input_Device_Class klass)
{
switch (klass)
{
case EFL_INPUT_DEVICE_CLASS_NONE:
return "None";
case EFL_INPUT_DEVICE_CLASS_SEAT:
return "Seat";
case EFL_INPUT_DEVICE_CLASS_KEYBOARD:
return "Keyboard";
case EFL_INPUT_DEVICE_CLASS_MOUSE:
return "Mouse";
case EFL_INPUT_DEVICE_CLASS_TOUCH:
return "Touch";
case EFL_INPUT_DEVICE_CLASS_PEN:
return "Pen";
case EFL_INPUT_DEVICE_CLASS_WAND:
return "Wand";
case EFL_INPUT_DEVICE_CLASS_GAMEPAD:
return "Gamepad";
default:
return "Unknown";
}
}
static void
_dev_added_or_removed(void *data EINA_UNUSED, const Efl_Event *event)
{
Efl_Input_Device *dev = event->info;
printf("The device '%s' - class: '%s' - description: '%s' was '%s'\n",
efl_input_device_name_get(dev),
_device_type_to_string(efl_input_device_type_get(dev)),
efl_input_device_description_get(dev),
event->desc == EFL_CANVAS_EVENT_DEVICE_ADDED ? "added" : "removed");
}
int
main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
{
Ecore_Evas *ee;
Evas *evas;
Evas_Object *bg, *rect;
Ecore_Animator *animator;
Eina_Bool r;
Ecore_Event_Handler *keydown_handler, *keyup_handler, *mouse_move,
*mouse_down, *mouse_up, *mouse_wheel;
ecore_evas_init();
ee = ecore_evas_new(NULL, 0, 0, 800, 600, NULL);
if (!ee)
{
fprintf(stderr, "Could not create the ecore evas\n");
return -1;
}
evas = ecore_evas_get(ee);
bg = evas_object_rectangle_add(evas);
evas_object_color_set(bg, 255, 255, 255, 255);
evas_object_move(bg, 0, 0);
evas_object_resize(bg, 800, 600);
evas_object_show(bg);
rect = evas_object_rectangle_add(evas);
evas_object_color_set(rect, 0, 255, 0, 255);
evas_object_resize(rect, 50, 50);
evas_object_move(rect, (800 - 50) /2, (600 - 50)/2);
evas_object_show(rect);
animator = ecore_animator_add(_anim, rect);
ecore_evas_show(ee);
r = ecore_evas_vnc_start(ee, "localhost", -1, _accept_cb, NULL);
if (!r)
{
fprintf(stderr, "Could not enable the VNC support!\n");
goto exit;
}
keydown_handler = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
_keyboard_event, NULL);
keyup_handler = ecore_event_handler_add(ECORE_EVENT_KEY_UP,
_keyboard_event, NULL);
mouse_move = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _mouse_move,
NULL);
mouse_up = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
_mouse_button, NULL);
mouse_down = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
_mouse_button, NULL);
mouse_wheel = ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
_mouse_wheel, NULL);
efl_event_callback_add(evas, EFL_CANVAS_EVENT_DEVICE_ADDED,
_dev_added_or_removed, NULL);
efl_event_callback_add(evas, EFL_CANVAS_EVENT_DEVICE_REMOVED,
_dev_added_or_removed, NULL);
ecore_main_loop_begin();
ecore_event_handler_del(mouse_wheel);
ecore_event_handler_del(keydown_handler);
ecore_event_handler_del(keyup_handler);
ecore_event_handler_del(mouse_move);
ecore_event_handler_del(mouse_up);
ecore_event_handler_del(mouse_down);
exit:
ecore_evas_free(ee);
ecore_animator_del(animator);
ecore_evas_shutdown();
return 0;
}

View File

@ -2397,6 +2397,42 @@ EAPI void ecore_evas_x11_shape_input_empty(Ecore_Evas *ee);
EAPI void ecore_evas_x11_shape_input_reset(Ecore_Evas *ee);
EAPI void ecore_evas_x11_shape_input_apply(Ecore_Evas *ee);
/**
* @brief A callback used to accept a new client.
* @param data The callback data
* @param ee The Ecore_Evas
* @param client_host The address of the new client.
* @return @c EINA_TRUE to accep the client, @c EINA_FALSE otherwise.
* @see ecore_evas_vnc_start()
* @since 1.19
*/
typedef Eina_Bool (*Ecore_Evas_Vnc_Client_Accept_Cb)(void *data, Ecore_Evas *ee, const char *client_host);
/**
* @brief Starts a VNC server.
*
* @param ee The Ecore_Evas to start the VNC server
* @param addr The address that will be used to bind the VNC server. Use @c NULL to bind to any interface.
* @param port The port number to start the VNC server. Use @c -1 to set the default VNC port (5900)
* @param cb A callback used to accept a new client. If @c NULL all clients will be accepted.
* @param data Data to @a cb
* @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
* @see ecore_evas_vnc_stop()
* @see Ecore_Evas_Vnc_Client_Accept_Cb()
* @since 1.19
*/
EAPI Eina_Bool ecore_evas_vnc_start(Ecore_Evas *ee, const char *addr, int port, Ecore_Evas_Vnc_Client_Accept_Cb cb, void *data);
/**
* @brief Stop a running VNC server
*
* @param ee Ecore_Evas to stop the VNC server
* @return @c EINA_TRUE if the VNC server was stopped, @c EINA_FALSE otherwise.
* @see ecore_evas_vnc_start()
* @since 1.19
*/
EAPI Eina_Bool ecore_evas_vnc_stop(Ecore_Evas *ee);
/**
* @defgroup Ecore_Evas_Ews Ecore_Evas Single Process Windowing System.
* @ingroup Ecore_Evas_Group

View File

@ -3955,6 +3955,37 @@ ecore_evas_x11_shape_input_apply(Ecore_Evas *ee)
iface->shape_input_apply(ee);
}
EAPI Eina_Bool
ecore_evas_vnc_start(Ecore_Evas *ee, const char *addr, int port,
Ecore_Evas_Vnc_Client_Accept_Cb cb, void *data)
{
Ecore_Evas_Interface_X11 *iface;
if (strcmp(ee->driver, "software_x11"))
return EINA_FALSE;
iface = (Ecore_Evas_Interface_X11 *)_ecore_evas_interface_get(ee, "x11");
EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(iface->vnc_start, EINA_FALSE);
return iface->vnc_start(ee, addr, port, cb, data);
}
EAPI Eina_Bool
ecore_evas_vnc_stop(Ecore_Evas *ee)
{
Ecore_Evas_Interface_X11 *iface;
if (strcmp(ee->driver, "software_x11"))
return EINA_FALSE;
iface = (Ecore_Evas_Interface_X11 *)_ecore_evas_interface_get(ee, "x11");
EINA_SAFETY_ON_NULL_RETURN_VAL(iface, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(iface->vnc_stop, EINA_FALSE);
return iface->vnc_stop(ee);
}
EAPI Ecore_Evas *
ecore_evas_extn_socket_new(int w, int h)
{

View File

@ -17,6 +17,10 @@ struct _Ecore_Evas_Interface_X11 {
void (*shape_input_empty)(Ecore_Evas *ee);
void (*shape_input_reset)(Ecore_Evas *ee);
void (*shape_input_apply)(Ecore_Evas *ee);
Eina_Bool (*vnc_start)(Ecore_Evas *ee, const char *addr, int port,
Ecore_Evas_Vnc_Client_Accept_Cb cb,
void *data);
Eina_Bool (*vnc_stop)(Ecore_Evas *ee);
};
struct _Ecore_Evas_Interface_Software_X11 {

View File

@ -9,6 +9,8 @@
#include <Eina.h>
#include <Eo.h>
#ifdef EAPI
# undef EAPI
#endif
@ -209,6 +211,8 @@ extern "C" {
unsigned int keycode; /**< Key scan code numeric value @since 1.10 */
void *data; /**< User data associated with an Ecore_Event_Key @since 1.10 */
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
/**
@ -245,6 +249,8 @@ extern "C" {
double x, y;
} root; /**< same as root.x, root.y, but with sub-pixel precision, if available */
} multi;
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
/**
@ -270,6 +276,8 @@ extern "C" {
int x;
int y;
} root; /**< Coordinates relative to root window */
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
/**
@ -304,6 +312,8 @@ extern "C" {
double x, y;
} root;
} multi;
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
typedef enum _Ecore_Axis_Label
@ -344,6 +354,8 @@ extern "C" {
int naxis;
Ecore_Axis *axis;
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
/**
@ -360,6 +372,8 @@ extern "C" {
int x; /**< x coordinate relative to window where event happened */
int y; /**< y coordinate relative to window where event happened */
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
/**
@ -396,6 +410,8 @@ extern "C" {
double value; /* [0.0 .. 1.0] 0.0 == fully unpressed, 1.0 == fully pressed */
} button;
};
Eo *dev; /**< The Efl_Input_Device that originated the event @since 1.19 */
};
/**

View File

@ -155,5 +155,7 @@ interface Efl.Canvas ()
render,pre;
render,post;
device,changed: Efl.Input.Device;
device,added: Efl.Input.Device;
device,removed: Efl.Input.Device;
}
}

View File

@ -103,4 +103,23 @@ _efl_input_device_parent_get(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd)
return pd->parent;
}
EOLIAN static void
_efl_input_device_parent_set(Eo *obj, Efl_Input_Device_Data *pd, Efl_Input_Device *parent)
{
if (pd->parent == parent) return;
if (pd->parent)
{
Efl_Input_Device_Data *p = efl_data_scope_get(pd->parent, EFL_INPUT_DEVICE_CLASS);
p->children = eina_list_remove(p->children, obj);
efl_unref(obj);
}
pd->parent = parent;
if (parent)
{
Efl_Input_Device_Data *p = efl_data_scope_get(parent, EFL_INPUT_DEVICE_CLASS);
p->children = eina_list_append(p->children, obj);
efl_ref(obj);
}
}
#include "interfaces/efl_input_device.eo.c"

View File

@ -39,7 +39,7 @@ enum Efl.Input.Device.Sub_Class
/* This represents Evas_Device */
/* FIXME: no parent, no children and no Evas */
/* FIXME: no children and no Evas */
class Efl.Input.Device (Efl.Object)
{
@ -75,7 +75,7 @@ class Efl.Input.Device (Efl.Object)
}
}
@property parent {
/* set {} */
set {}
get {}
values {
parent: Efl.Input.Device;

View File

@ -338,17 +338,17 @@ typedef Efl_Input_Device_Class Evas_Device_Class;
typedef Efl_Input_Device_Sub_Class Evas_Device_Subclass;
#define EVAS_DEVICE_SUBCLASS_NONE EFL_INPUT_DEVICE_SUBCLASS_NONE /**< Not a device @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_FINGER EFL_INPUT_DEVICE_SUBCLASS_FINGER /**< The normal flat of your finger @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_FINGERNAIL EFL_INPUT_DEVICE_SUBCLASS_FINGERNAIL /**< A fingernail @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_KNUCKLE EFL_INPUT_DEVICE_SUBCLASS_KNUCKLE /**< A Knuckle @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_PALM EFL_INPUT_DEVICE_SUBCLASS_PALM /**< The palm of a users hand @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_HAND_SIZE EFL_INPUT_DEVICE_SUBCLASS_HAND_SIZE /**< The side of your hand @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_HAND_FLAT EFL_INPUT_DEVICE_SUBCLASS_HAND_FLAT /**< The flat of your hand @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_PEN_TIP EFL_INPUT_DEVICE_SUBCLASS_PEN_TIP /**< The tip of a pen @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_TRACKPAD EFL_INPUT_DEVICE_SUBCLASS_TRACKPAD /**< A trackpad style mouse @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_TRACKPOINT EFL_INPUT_DEVICE_SUBCLASS_TRACKPOINT /**< A trackpoint style mouse @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_TRACKBALL EFL_INPUT_DEVICE_SUBCLASS_TRACKBALL /**< A trackball style mouse @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_NONE EFL_INPUT_DEVICE_SUB_CLASS_NONE /**< Not a device @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_FINGER EFL_INPUT_DEVICE_SUB_CLASS_FINGER /**< The normal flat of your finger @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_FINGERNAIL EFL_INPUT_DEVICE_SUB_CLASS_FINGERNAIL /**< A fingernail @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_KNUCKLE EFL_INPUT_DEVICE_SUB_CLASS_KNUCKLE /**< A Knuckle @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_PALM EFL_INPUT_DEVICE_SUB_CLASS_PALM /**< The palm of a users hand @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_HAND_SIZE EFL_INPUT_DEVICE_SUB_CLASS_HAND_SIZE /**< The side of your hand @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_HAND_FLAT EFL_INPUT_DEVICE_SUB_CLASS_HAND_FLAT /**< The flat of your hand @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_PEN_TIP EFL_INPUT_DEVICE_SUB_CLASS_PEN_TIP /**< The tip of a pen @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_TRACKPAD EFL_INPUT_DEVICE_SUB_CLASS_TRACKPAD /**< A trackpad style mouse @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_TRACKPOINT EFL_INPUT_DEVICE_SUB_CLASS_TRACKPOINT /**< A trackpoint style mouse @since 1.8 */
#define EVAS_DEVICE_SUBCLASS_TRACKBALL EFL_INPUT_DEVICE_SUB_CLASS_TRACKBALL /**< A trackball style mouse @since 1.8 */
typedef Efl_Pointer_Flags Evas_Button_Flags;
@ -1126,10 +1126,38 @@ EAPI void evas_render_updates_free(Eina_List *updates);
* @return the device node created or NULL if an error occurred.
*
* @see evas_device_del
* @see evas_device_full_add
* @since 1.8
*/
EAPI Evas_Device *evas_device_add(Evas *e);
/**
* Add a new device type
*
* @param e The canvas to create the device node for.
* @param name The name of the device.
* @param desc The description of the device.
* @param parent_dev The parent device.
* @param emulation_dev The source device.
* @param clas The device class.
* @param sub_class The device subclass.
*
* Adds a new device node to the given canvas @p e. All devices created as
* part of the canvas @p e will automatically be deleted when the canvas
* is freed.
*
* @return the device node created or NULL if an error occurred.
*
* @see evas_device_del
* @since 1.19
*/
EAPI Evas_Device *evas_device_full_add(Evas *eo_e, const char *name,
const char *desc,
Evas_Device *parent_dev,
Evas_Device *emulation_dev,
Evas_Device_Class clas,
Evas_Device_Subclass sub_clas);
/**
* Delete a new device type
*

View File

@ -31,10 +31,22 @@ _del_cb(void *data, const Efl_Event *ev)
// can not be done in std destructor
e->devices = eina_list_remove(e->devices, ev->object);
efl_event_callback_call(e->evas, EFL_CANVAS_EVENT_DEVICE_REMOVED,
ev->object);
}
EAPI Evas_Device *
evas_device_add(Evas *eo_e)
{
return evas_device_full_add(eo_e, NULL, NULL, NULL, NULL,
EVAS_DEVICE_CLASS_NONE,
EVAS_DEVICE_SUBCLASS_NONE);
}
EAPI Evas_Device *
evas_device_full_add(Evas *eo_e, const char *name, const char *desc,
Evas_Device *parent_dev, Evas_Device *emulation_dev,
Evas_Device_Class clas, Evas_Device_Subclass sub_clas)
{
Efl_Input_Device_Data *d;
Evas_Public_Data *e;
@ -42,15 +54,24 @@ evas_device_add(Evas *eo_e)
SAFETY_CHECK(eo_e, EVAS_CANVAS_CLASS, NULL);
dev = efl_add(EFL_INPUT_DEVICE_CLASS, eo_e);
dev = efl_add(EFL_INPUT_DEVICE_CLASS, eo_e,
efl_input_device_name_set(efl_added, name),
efl_input_device_description_set(efl_added, desc),
efl_input_device_type_set(efl_added, clas),
efl_input_device_subtype_set(efl_added, sub_clas),
efl_input_device_source_set(efl_added, emulation_dev),
efl_input_device_parent_set(efl_added, parent_dev));
d = efl_data_scope_get(dev, EFL_INPUT_DEVICE_CLASS);
d->evas = eo_e;
e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
e->devices = eina_list_append(e->devices, dev);
if (!parent_dev)
e->devices = eina_list_append(e->devices, dev);
efl_event_callback_add(dev, EFL_EVENT_DEL, _del_cb, e);
efl_event_callback_call(eo_e, EFL_CANVAS_EVENT_DEVICE_ADDED, dev);
// Keeping this event to do not break things...
evas_event_callback_call(eo_e, EVAS_CALLBACK_DEVICE_CHANGED, dev);
return dev;
@ -61,7 +82,7 @@ evas_device_del(Evas_Device *dev)
{
SAFETY_CHECK(dev, EFL_INPUT_DEVICE_CLASS);
efl_unref(dev);
efl_del(dev);
}
EAPI void
@ -155,24 +176,11 @@ evas_device_parent_set(Evas_Device *dev, Evas_Device *parent)
SAFETY_CHECK(parent, EFL_INPUT_DEVICE_CLASS);
}
/* FIXME: move this to Efl.Input.Device */
if (d->parent == parent) return;
if (d->parent)
{
Efl_Input_Device_Data *p = efl_data_scope_get(d->parent, EFL_INPUT_DEVICE_CLASS);
p->children = eina_list_remove(p->children, dev);
}
else if (parent)
e->devices = eina_list_remove(e->devices, dev);
d->parent = parent;
efl_input_device_parent_set(dev, parent);
if (parent)
{
Efl_Input_Device_Data *p = efl_data_scope_get(parent, EFL_INPUT_DEVICE_CLASS);
p->children = eina_list_append(p->children, dev);
}
e->devices = eina_list_remove(e->devices, dev);
else
e->devices = eina_list_append(e->devices, dev);
evas_event_callback_call(d->evas, EVAS_CALLBACK_DEVICE_CHANGED, dev);
}

View File

@ -26,6 +26,12 @@
#include "ecore_evas_private.h"
#include "ecore_evas_x11.h"
#ifdef ENABLE_VNC_SERVER
# include <rfb/rfb.h>
# include <rfb/rfbregion.h>
# include <rfb/keysym.h>
#endif
#ifdef EAPI
# undef EAPI
#endif
@ -131,6 +137,17 @@ struct _Ecore_Evas_Engine_Data_X11 {
unsigned long colormap; // store colormap used to create pixmap
} pixmap;
Eina_Bool destroyed : 1; // X window has been deleted and cannot be used
#ifdef ENABLE_VNC_SERVER
char *frame_buffer;
rfbScreenInfoPtr vnc_screen;
Ecore_Fd_Handler *vnc_listen_handler;
Ecore_Fd_Handler *vnc_listen6_handler;
Ecore_Evas_Vnc_Client_Accept_Cb accept_cb;
void *accept_cb_data;
int last_w;
int last_h;
#endif
};
static Ecore_Evas_Interface_X11 * _ecore_evas_x_interface_x11_new(void);
@ -152,6 +169,131 @@ static void _transparent_do(Ecore_Evas *, int);
static void _avoid_damage_do(Ecore_Evas *, int);
static void _rotation_do(Ecore_Evas *, int, int);
#ifdef ENABLE_VNC_SERVER
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;
#define VNC_BITS_PER_SAMPLE (8)
#define VNC_SAMPLES_PER_PIXEL (3)
#define VNC_BYTES_PER_PIXEL (4)
static void
_ecore_evas_x11_update_vnc_clients(rfbScreenInfoPtr vnc_screen)
{
rfbClientIteratorPtr itr;
rfbClientRec *client;
itr = rfbGetClientIterator(vnc_screen);
//No clients.
if (!itr) return;
while ((client = rfbClientIteratorNext(itr))) {
rfbBool r;
r = rfbUpdateClient(client);
if (!r)
{
Ecore_Evas_X11_Vnc_Client_Data *cdata = client->clientData;
WRN("Could not update the VNC client on seat '%s'\n",
evas_device_name_get(cdata->seat));
}
//Client disconnected
if (client->sock == -1) rfbClientConnectionGone(client);
}
rfbReleaseClientIterator(itr);
}
static void
_ecore_evas_x11_vnc_server_format_setup(Ecore_Evas_Engine_Data_X11 *edata)
{
int aux;
//FIXME: Using BGR - Is there a better way to do this?
aux = edata->vnc_screen->serverFormat.redShift;
edata->vnc_screen->serverFormat.redShift = edata->vnc_screen->serverFormat.blueShift;
edata->vnc_screen->serverFormat.blueShift = aux;
}
static void
_ecore_evas_x11_region_push_hook(Evas *e, int x, int y, int w, int h,
const void *pixels)
{
Ecore_Evas *ee;
Ecore_Evas_Engine_Data_X11 *edata;
size_t size;
ee = evas_data_attach_get(e);
edata = ee->engine.data;
if (!edata->frame_buffer || edata->last_w != ee->w || edata->last_h != ee->h)
{
char *new_fb;
size = ee->w * ee->h * VNC_BYTES_PER_PIXEL;
new_fb = malloc(size);
EINA_SAFETY_ON_NULL_RETURN(new_fb);
free(edata->frame_buffer);
memcpy(new_fb, pixels, size);
edata->frame_buffer = new_fb;
edata->last_w = ee->w;
edata->last_h = ee->h;
if (edata->vnc_screen)
{
rfbNewFramebuffer(edata->vnc_screen, edata->frame_buffer, ee->w,
ee->h, VNC_BITS_PER_SAMPLE, VNC_SAMPLES_PER_PIXEL,
VNC_BYTES_PER_PIXEL);
_ecore_evas_x11_vnc_server_format_setup(edata);
}
}
else
{
//Partial update
int dy;
const int src_stride = w * VNC_BYTES_PER_PIXEL;
for (dy = 0; dy < h; dy++)
{
memcpy(edata->frame_buffer + (x * VNC_BYTES_PER_PIXEL)
+ ((dy + y) * (edata->last_w * VNC_BYTES_PER_PIXEL)),
(char *)pixels + (dy * src_stride), src_stride);
}
}
if (edata->vnc_screen)
{
rfbMarkRectAsModified(edata->vnc_screen, x, y, x+w, y+h);
_ecore_evas_x11_update_vnc_clients(edata->vnc_screen);
}
}
#else
static void
_ecore_evas_x11_region_push_hook(Evas *e EINA_UNUSED, int x EINA_UNUSED,
int y EINA_UNUSED, int w EINA_UNUSED,
int h EINA_UNUSED,
const void *pixels EINA_UNUSED)
{
}
#endif //ENABLE_VNC_SERVER
static void
_ecore_evas_x_hints_update(Ecore_Evas *ee)
{
@ -2059,6 +2201,16 @@ _ecore_evas_x_free(Ecore_Evas *ee)
ecore_timer_del(edata->outdelay);
edata->outdelay = NULL;
}
#ifdef ENABLE_VNC_SERVER
if (edata->vnc_screen)
{
ecore_main_fd_handler_del(edata->vnc_listen6_handler);
ecore_main_fd_handler_del(edata->vnc_listen_handler);
free(edata->frame_buffer);
rfbScreenCleanup(edata->vnc_screen);
edata->vnc_screen = NULL;
}
#endif
free(edata);
_ecore_evas_x_shutdown();
ecore_x_shutdown();
@ -4110,6 +4262,7 @@ ecore_evas_software_x11_new_internal(const char *disp_name, Ecore_X_Window paren
einfo->info.screen = NULL;
# endif
einfo->info.drawable = ee->prop.window;
einfo->func.region_push_hook = _ecore_evas_x11_region_push_hook;
if (argb)
{
@ -4298,6 +4451,7 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo
}
}
einfo->func.region_push_hook = _ecore_evas_x11_region_push_hook;
einfo->info.destination_alpha = argb;
if (redraw_debug < 0)
@ -5131,6 +5285,448 @@ _ecore_evas_x11_shape_input_apply(Ecore_Evas *ee)
ecore_x_window_shape_input_window_set(ee->prop.window, edata->win_shaped_input);
}
#ifdef ENABLE_VNC_SERVER
static Eina_Bool
_ecore_evas_x11_vnc_socket_listen_activity(void *data,
Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
rfbProcessNewConnection(data);
return ECORE_CALLBACK_RENEW;
}
static void
_ecore_evas_x11_client_gone(rfbClientRec *client)
{
Ecore_Evas_X11_Vnc_Client_Data *cdata = client->clientData;
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--;
}
static Eina_Bool
_ecore_evas_x11_client_activity(void *data,
Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eina_Bool r = ECORE_CALLBACK_RENEW;
rfbClientRec *client = data;
rfbProcessClientMessage(client);
//macro from rfb.h
if (FB_UPDATE_PENDING(client))
rfbSendFramebufferUpdate(client, client->modifiedRegion);
//Client disconnected.
if (client->sock == -1)
{
rfbClientConnectionGone(client);
r = ECORE_CALLBACK_DONE;
}
return r;
}
static enum rfbNewClientAction
_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);
ee = client->screen->screenData;
edata = ee->engine.data;
if (!edata->accept_cb(edata->accept_cb_data, ee, client->host))
return RFB_CLIENT_REFUSE;
cdata = calloc(1, sizeof(Ecore_Evas_X11_Vnc_Client_Data));
EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, RFB_CLIENT_REFUSE);
cdata->handler = ecore_main_fd_handler_add(client->sock, ECORE_FD_READ,
_ecore_evas_x11_client_activity,
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_ecore_event_generic_free(void *user_data,
void *func_data)
{
efl_unref(user_data);
free(func_data);
}
static void
_ecore_evas_x11_vnc_client_keyboard_event(rfbBool down,
rfbKeySym key,
rfbClientRec *client)
{
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
static Eina_Bool
_ecore_evas_x11_vnc_start(Ecore_Evas *ee, const char *addr, int port,
Ecore_Evas_Vnc_Client_Accept_Cb cb, void *data)
{
#ifdef ENABLE_VNC_SERVER
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
Eina_Bool can_listen = EINA_FALSE;
if (edata->vnc_screen)
return EINA_FALSE;
edata->vnc_screen = rfbGetScreen(0, NULL, ee->w, ee->h, VNC_BITS_PER_SAMPLE,
VNC_SAMPLES_PER_PIXEL, VNC_BYTES_PER_PIXEL);
EINA_SAFETY_ON_NULL_RETURN_VAL(edata->vnc_screen, EINA_FALSE);
edata->vnc_screen->newClientHook = _ecore_evas_x11_vnc_client_connection_new;
edata->vnc_screen->kbdAddEvent = _ecore_evas_x11_vnc_client_keyboard_event;
edata->vnc_screen->ptrAddEvent = _ecore_evas_x11_vnc_client_pointer_event;
//This enables multiple client connections at the same time.
edata->vnc_screen->alwaysShared = TRUE;
edata->vnc_screen->frameBuffer = edata->frame_buffer;
_ecore_evas_x11_vnc_server_format_setup(edata);
if (port > 0)
edata->vnc_screen->port = edata->vnc_screen->ipv6port= port;
if (addr)
{
int err;
//rfbStringToAddr() does not change the addr contents.
err = rfbStringToAddr((char *)addr, &edata->vnc_screen->listenInterface);
EINA_SAFETY_ON_TRUE_GOTO(err == 0, err_screen);
}
rfbInitServer(edata->vnc_screen);
if (edata->vnc_screen->listenSock >= 0)
{
edata->vnc_listen_handler = ecore_main_fd_handler_add(edata->vnc_screen->listenSock,
ECORE_FD_READ,
_ecore_evas_x11_vnc_socket_listen_activity,
edata->vnc_screen, NULL,
NULL);
EINA_SAFETY_ON_NULL_GOTO(edata->vnc_listen_handler, err_listen);
can_listen = EINA_TRUE;
}
if (edata->vnc_screen->listen6Sock >= 0)
{
edata->vnc_listen6_handler = ecore_main_fd_handler_add(edata->vnc_screen->listen6Sock,
ECORE_FD_READ,
_ecore_evas_x11_vnc_socket_listen_activity,
edata->vnc_screen,
NULL, NULL);
EINA_SAFETY_ON_NULL_GOTO(edata->vnc_listen6_handler, err_listen6);
can_listen = EINA_TRUE;
}
//rfbInitServer() failed and could not setup the sockets.
EINA_SAFETY_ON_FALSE_GOTO(can_listen, err_listen);
edata->vnc_screen->screenData = ee;
edata->accept_cb_data = data;
edata->accept_cb = cb;
return EINA_TRUE;
err_listen6:
ecore_main_fd_handler_del(edata->vnc_listen_handler);
edata->vnc_listen_handler = NULL;
err_listen:
rfbScreenCleanup(edata->vnc_screen);
edata->vnc_screen = NULL;
err_screen:
return EINA_FALSE;
#else
(void)ee;
(void)addr;
(void)port;
(void)cb;
(void)data;
return EINA_FALSE;
#endif
}
static Eina_Bool
_ecore_evas_x11_vnc_stop(Ecore_Evas *ee)
{
#ifdef ENABLE_VNC_SERVER
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
if (!edata->vnc_screen)
return EINA_FALSE;
ecore_main_fd_handler_del(edata->vnc_listen6_handler);
ecore_main_fd_handler_del(edata->vnc_listen_handler);
rfbScreenCleanup(edata->vnc_screen);
edata->vnc_screen = NULL;
return EINA_TRUE;
#else
(void)ee;
return EINA_FALSE;
#endif
}
static Ecore_Evas_Interface_X11 *
_ecore_evas_x_interface_x11_new(void)
{
@ -5151,6 +5747,8 @@ _ecore_evas_x_interface_x11_new(void)
iface->shape_input_empty = _ecore_evas_x11_shape_input_empty;
iface->shape_input_reset = _ecore_evas_x11_shape_input_reset;
iface->shape_input_apply = _ecore_evas_x11_shape_input_apply;
iface->vnc_start = _ecore_evas_x11_vnc_start;
iface->vnc_stop = _ecore_evas_x11_vnc_stop;
return iface;
}
@ -5205,3 +5803,4 @@ _ecore_evas_x_interface_gl_x11_new(void)
return iface;
}
#endif

View File

@ -41,6 +41,7 @@ struct _Evas_Engine_Info_Software_X11
void *(*best_visual_get) (int backend, void *connection, int screen);
unsigned int (*best_colormap_get) (int backend, void *connection, int screen);
int (*best_depth_get) (int backend, void *connection, int screen);
void (*region_push_hook)(Evas *e, int x, int y, int w, int h, const void *pixels);
} func;
unsigned char mask_changed : 1;

View File

@ -32,6 +32,8 @@
# include <dlfcn.h>
#endif
#include <Ecore.h>
Evas_Native_Tbm_Surface_Image_Set_Call glsym__evas_native_tbm_surface_image_set = NULL;
Evas_Native_Tbm_Surface_Stride_Get_Call glsym__evas_native_tbm_surface_stride_get = NULL;
int _evas_engine_soft_x11_log_dom = -1;
@ -133,6 +135,22 @@ _output_egl_setup(int w, int h, int rot, Display *disp, Drawable draw,
}
*/
void
evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, int w, int h,
const void *pixels)
{
int err;
if (!buf->region_push_hook.cb)
return;
err = ecore_thread_main_loop_begin();
EINA_SAFETY_ON_TRUE_RETURN(err == -1);
buf->region_push_hook.cb(buf->region_push_hook.evas, x, y, w, h, pixels);
ecore_thread_main_loop_end();
}
static void
_output_egl_shutdown(Render_Engine *re)
{
@ -526,6 +544,8 @@ eng_setup(Evas *eo_e, void *in)
info->info.destination_alpha);
re->outbuf_alpha_get = evas_software_xlib_outbuf_alpha_get;
}
re->generic.ob->region_push_hook.cb = info->func.region_push_hook;
re->generic.ob->region_push_hook.evas = eo_e;
}
#endif
@ -621,6 +641,8 @@ eng_setup(Evas *eo_e, void *in)
if (ob)
{
evas_render_engine_software_generic_update(&re->generic, ob, e->output.w, e->output.h);
ob->region_push_hook.cb = info->func.region_push_hook;
ob->region_push_hook.evas = eo_e;
}
/* if ((re) && (re->ob)) re->ob->onebuf = ponebuf; */

View File

@ -113,9 +113,16 @@ struct _Outbuf
unsigned char debug : 1;
unsigned char synced : 1;
} priv;
struct
{
void (*cb)(Evas *e, int x, int y, int w, int h, const void *pixels);
Evas *evas;
} region_push_hook;
};
void evas_software_xlib_x_init(void);
void evas_software_xcb_init(void);
void evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, int w, int h, const void *pixels);
#endif

View File

@ -680,9 +680,14 @@ evas_software_xcb_outbuf_flush(Outbuf *buf, Tilebuf_Rect *rects EINA_UNUSED, Eva
pixman_region_n_rects(&tmpr),
(const xcb_rectangle_t *)pixman_region_rectangles(&tmpr, NULL));
if (obr->xcbob)
evas_software_xcb_output_buffer_paste(obr->xcbob,
buf->priv.x11.xcb.win,
buf->priv.x11.xcb.gc, 0, 0, 0);
{
evas_software_x11_region_push_hook_call(buf, 0, 0, obr->xcbob->xim->width,
obr->xcbob->xim->height,
evas_software_xcb_output_buffer_data(obr->xcbob, NULL));
evas_software_xcb_output_buffer_paste(obr->xcbob,
buf->priv.x11.xcb.win,
buf->priv.x11.xcb.gc, 0, 0, 0);
}
if (obr->mask)
{
xcb_set_clip_rectangles(buf->priv.x11.xcb.conn,
@ -709,10 +714,16 @@ evas_software_xcb_outbuf_flush(Outbuf *buf, Tilebuf_Rect *rects EINA_UNUSED, Eva
evas_software_xcb_outbuf_debug_show(buf, buf->priv.x11.xcb.win,
obr->x, obr->y, obr->w, obr->h);
if (obr->xcbob)
evas_software_xcb_output_buffer_paste(obr->xcbob,
buf->priv.x11.xcb.win,
buf->priv.x11.xcb.gc,
obr->x, obr->y, 0);
{
evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
obr->xcbob->xim->width,
obr->xcbob->xim->height,
evas_software_xcb_output_buffer_data(obr->xcbob, NULL));
evas_software_xcb_output_buffer_paste(obr->xcbob,
buf->priv.x11.xcb.win,
buf->priv.x11.xcb.gc,
obr->x, obr->y, 0);
}
if (obr->mask)
evas_software_xcb_output_buffer_paste(obr->mask,
buf->priv.x11.xcb.mask,
@ -959,10 +970,16 @@ evas_software_xcb_outbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, in
evas_software_xcb_outbuf_debug_show(buf, buf->priv.x11.xcb.win,
obr->x, obr->y, obr->w, obr->h);
if (obr->xcbob)
evas_software_xcb_output_buffer_paste(obr->xcbob,
buf->priv.x11.xcb.win,
buf->priv.x11.xcb.gc,
obr->x, obr->y, 0);
{
evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
obr->xcbob->xim->width,
obr->xcbob->xim->height,
evas_software_xcb_output_buffer_data(obr->xcbob, NULL));
evas_software_xcb_output_buffer_paste(obr->xcbob,
buf->priv.x11.xcb.win,
buf->priv.x11.xcb.gc,
obr->x, obr->y, 0);
}
}
#endif
if (obr->mask)

View File

@ -818,9 +818,14 @@ evas_software_xlib_outbuf_flush(Outbuf *buf, Tilebuf_Rect *rects EINA_UNUSED, Ev
eina_array_clean(&buf->priv.onebuf_regions);
XSetRegion(buf->priv.x11.xlib.disp, buf->priv.x11.xlib.gc, tmpr);
if (obr->xob)
evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
buf->priv.x11.xlib.gc,
0, 0, 0);
{
evas_software_x11_region_push_hook_call(buf, 0, 0, obr->xob->xim->width,
obr->xob->xim->height,
evas_software_xlib_x_output_buffer_data(obr->xob, NULL));
evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
buf->priv.x11.xlib.gc,
0, 0, 0);
}
if (obr->mxob)
{
XSetRegion(buf->priv.x11.xlib.disp, buf->priv.x11.xlib.gcm, tmpr);
@ -843,9 +848,15 @@ evas_software_xlib_outbuf_flush(Outbuf *buf, Tilebuf_Rect *rects EINA_UNUSED, Ev
evas_software_xlib_outbuf_debug_show(buf, buf->priv.x11.xlib.win,
obr->x, obr->y, obr->w, obr->h);
if (obr->xob)
evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
buf->priv.x11.xlib.gc,
obr->x, obr->y, 0);
{
evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
obr->xob->xim->width,
obr->xob->xim->height,
evas_software_xlib_x_output_buffer_data(obr->xob, NULL));
evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
buf->priv.x11.xlib.gc,
obr->x, obr->y, 0);
}
if (obr->mxob)
evas_software_xlib_x_output_buffer_paste(obr->mxob,
buf->priv.x11.xlib.mask,
@ -1124,9 +1135,15 @@ evas_software_xlib_outbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, i
evas_software_xlib_outbuf_debug_show(buf, buf->priv.x11.xlib.win,
obr->x, obr->y, obr->w, obr->h);
if (obr->xob)
evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
buf->priv.x11.xlib.gc,
obr->x, obr->y, 0);
{
evas_software_x11_region_push_hook_call(buf, obr->x, obr->y,
obr->xob->xim->width,
obr->xob->xim->height,
evas_software_xlib_x_output_buffer_data(obr->xob, NULL));
evas_software_xlib_x_output_buffer_paste(obr->xob, buf->priv.x11.xlib.win,
buf->priv.x11.xlib.gc,
obr->x, obr->y, 0);
}
}
#endif
if (obr->mxob)