E20 clamps the pointer position inside the boundary of a screen.
If there is a client requesting to grab relative motion, E20 sends
relative motion events when pointer is restricted at the edges
of the output.
Change-Id: Ic8a613681c81927c194ad88d34a2ed7971757f05
src/bin/inputmgr/e_input_thread_client.c \
src/bin/inputmgr/e_device.c \
src/bin/inputmgr/e_devicemgr_keyboard_grab.c \
+src/bin/inputmgr/e_devicemgr_relative_motion_grab.c \
src/bin/inputmgr/e_devicemgr.c \
src/bin/inputmgr/e_devicemgr_conf.c \
src/bin/inputmgr/e_devicemgr_block.c \
EINTERN int e_devicemgr_keyboard_ungrab(struct wl_client *client, struct wl_resource *surface);
EINTERN int e_devicemgr_keyboard_grab(struct wl_client *client, struct wl_resource *surface, uint32_t subclas);
+EINTERN int e_devicemgr_relative_motion_grab(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t boundary);
+EINTERN int e_devicemgr_relative_motion_ungrab(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface);
+EINTERN Eina_Bool e_devicemgr_relative_motion_is_grabbed(unsigned int boundaries);
EINTERN void e_devicemgr_conf_init(E_Devicemgr_Config_Data *dconfig);
EINTERN void e_devicemgr_conf_fini(E_Devicemgr_Config_Data *dconfig);
--- /dev/null
+#include "e_devicemgr_intern.h"
+#include "e_input_log.h"
+
+#include <tizen-extension-server-protocol.h>
+
+EINTERN Eina_Bool
+e_devicemgr_relative_motion_is_grabbed(unsigned int boundaries)
+{
+ if (e_devicemgr->relative_motion_grab.grabbed_boundaries & boundaries)
+ {
+ DMINF("e_devicemgr_relative_motion_is_grabbed() grabbed:%d, boundaries:%d",
+ e_devicemgr->relative_motion_grab.grabbed_boundaries, boundaries);
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+static unsigned int
+_e_devicemgr_relative_motion_grabbed_boundary_get(struct wl_client *client, E_Client *ec)
+{
+ unsigned int boundary = 0;
+
+ for (int i = 1; i < E_DEVICEMGR_BOUNDARY_MAX + 1; i++)
+ {
+ if (e_devicemgr->relative_motion_grab.boundaries[i].client == client &&
+ e_devicemgr->relative_motion_grab.boundaries[i].ec == ec)
+ {
+ boundary = i;
+ break;
+ }
+ }
+
+ return boundary;
+}
+
+static Eina_Bool
+_e_devicemgr_relative_motion_grab_surface_remove(E_Client *ec,
+ unsigned int boundary)
+{
+ if (ec != e_devicemgr->relative_motion_grab.boundaries[boundary].ec)
+ return EINA_FALSE;
+
+ e_devicemgr->relative_motion_grab.boundaries[boundary].client = NULL;
+ e_devicemgr->relative_motion_grab.boundaries[boundary].ec = NULL;
+ e_devicemgr->relative_motion_grab.boundaries[boundary].resource = NULL;
+ e_devicemgr->relative_motion_grab.grabbed_boundaries &= ~(1 << boundary);
+ e_devicemgr->relative_motion_grab.last_event_boundary = 0;
+
+ return EINA_TRUE;
+}
+
+static void
+_e_devicemgr_relative_motion_grab_surface_cb_destroy(struct wl_listener *l, void *data)
+{
+ struct wl_resource *surface = (struct wl_resource *)data;
+ E_Client *ec;
+
+ DMINF("Listener(%p) called: surface: %p is died", l, surface);
+
+ wl_list_remove(&l->link);
+ E_FREE(l);
+
+ ec = e_client_from_surface_resource(surface);
+
+ for (int i = 1; i < E_DEVICEMGR_BOUNDARY_MAX + 1; i++)
+ {
+ if (e_devicemgr->relative_motion_grab.boundaries[i].ec == ec)
+ {
+ _e_devicemgr_relative_motion_grab_surface_remove(ec, i);
+ }
+ }
+}
+
+static Eina_Bool
+_e_devicemgr_relative_motion_grab_surface_add(E_Client *ec, uint32_t boundary,
+ struct wl_client *client,
+ struct wl_resource *resource)
+{
+ if (ec == e_devicemgr->relative_motion_grab.boundaries[boundary].ec)
+ return EINA_TRUE;
+
+ e_devicemgr->relative_motion_grab.boundaries[boundary].client = client;
+ e_devicemgr->relative_motion_grab.boundaries[boundary].ec = ec;
+ e_devicemgr->relative_motion_grab.boundaries[boundary].resource = resource;
+ e_devicemgr->relative_motion_grab.grabbed_boundaries |= (1 << boundary);
+
+ return EINA_TRUE;
+}
+
+int
+e_devicemgr_relative_motion_grab(struct wl_client *client, struct wl_resource *resource,
+ struct wl_resource *surface, uint32_t boundary)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ E_Client *ec;
+ struct wl_listener *destroy_listener = NULL;
+
+ if (boundary <= 0 || boundary > E_DEVICEMGR_BOUNDARY_MAX)
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_PARAMETER;
+
+ if (e_devicemgr->relative_motion_grab.boundaries[boundary].client &&
+ e_devicemgr->relative_motion_grab.boundaries[boundary].client != client)
+ {
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+ }
+
+ ec = e_client_from_surface_resource(surface);
+ if (!ec)
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_SURFACE;
+
+ destroy_listener = E_NEW(struct wl_listener, 1);
+ if (!destroy_listener)
+ {
+ DMERR("Failed to allocate memory for wl_client destroy listener !");
+ return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
+ }
+ destroy_listener->notify = _e_devicemgr_relative_motion_grab_surface_cb_destroy;
+ wl_resource_add_destroy_listener(surface, destroy_listener);
+
+ if (!_e_devicemgr_relative_motion_grab_surface_add(ec, boundary, client, resource))
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+
+ return ret;
+}
+
+int
+e_devicemgr_relative_motion_ungrab(struct wl_client *client, struct wl_resource *resource,
+ struct wl_resource *surface)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+ E_Client *ec;
+ unsigned int boundary;
+
+ ec = e_client_from_surface_resource(surface);
+ if (!ec)
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_INVALID_SURFACE;
+
+ boundary = _e_devicemgr_relative_motion_grabbed_boundary_get(client, ec);
+ if (boundary == 0)
+ return TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+
+ if (!_e_devicemgr_relative_motion_grab_surface_remove(ec, boundary))
+ ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NOT_ALLOWED;
+
+ return ret;
+}
Ecore_Event_Mouse_Move *ev;
Ecore_Device *ecore_dev = NULL, *data, *detent_data = NULL;
Eina_List *l;
- int x = 0, y = 0, w = 0, h = 0;
const char *device_name = NULL;
uint32_t timestamp = 0;
if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)))) return;
- _device_configured_size_get(evdev, &x, &y, &w, &h);
-
- if (evdev->seat->ptr.ix < x)
- evdev->seat->ptr.dx = evdev->seat->ptr.ix = x;
- else if (evdev->seat->ptr.ix >= (x + w))
- evdev->seat->ptr.dx = evdev->seat->ptr.ix = (x + w - 1);
-
- if (evdev->seat->ptr.iy < y)
- evdev->seat->ptr.dy = evdev->seat->ptr.iy = y;
- else if (evdev->seat->ptr.iy >= (y + h))
- evdev->seat->ptr.dy = evdev->seat->ptr.iy = (y + h - 1);
-
evdev->mouse.dx = evdev->seat->ptr.dx;
evdev->mouse.dy = evdev->seat->ptr.dy;
comp_conf = e_comp_config_get();
if (comp_conf && comp_conf->input_log_enable)
- ELOGF("Mouse", "Relative Move (time: %d, dx: %d, dy: %d, unaccel(%d, %d) device: %s)", NULL, ev->timestamp, ev->dx, ev->dy, ev->dx_unaccel, ev->dy_unaccel, ecore_device_name_get(ev->dev));
+ ELOGF("Mouse", "Relative Move (time: %d, dx: %.2f, dy: %.2f, unaccel(%.2f, %.2f) device: %s)", NULL, ev->timestamp, dx[0], dy[0], dx[1], dy[1], ecore_device_name_get(ev->dev));
ecore_event_add(ECORE_EVENT_MOUSE_RELATIVE_MOVE, ev, _e_input_event_mouse_relative_move_cb_free, NULL);
ecore_thread_main_loop_end();
}
+static unsigned int
+_device_pointer_motion_clamp_for_output(E_Input_Evdev *evdev)
+{
+ int x = 0, y = 0, w = 0, h = 0;
+ unsigned int ret = 0;
+
+ _device_configured_size_get(evdev, &x, &y, &w, &h);
+
+ if (evdev->seat->ptr.dx < x)
+ {
+ evdev->seat->ptr.dx = x;
+ ret |= (1 << (unsigned int)E_DEVICEMGR_BOUNDARY_LEFT);
+ }
+ else if (evdev->seat->ptr.dx >= (x + w))
+ {
+ evdev->seat->ptr.dx = (x + w - 1);
+ ret |= (1 << (unsigned int)E_DEVICEMGR_BOUNDARY_RIGHT);
+ }
+
+ if (evdev->seat->ptr.dy < y)
+ {
+ evdev->seat->ptr.dy = y;
+ ret |= (1 << (unsigned int)E_DEVICEMGR_BOUNDARY_TOP);
+ }
+ else if (evdev->seat->ptr.dy >= (y + h))
+ {
+ evdev->seat->ptr.dy = (y + h - 1);
+ ret |= (1 << (unsigned int)E_DEVICEMGR_BOUNDARY_BOTTOM);
+ }
+
+ return ret;
+}
+
static void
_device_pointer_motion_send(E_Input_Evdev *evdev, struct libinput_event_pointer *event, double dx[2], double dy[2])
{
+ static unsigned int clamped_boundaries = 0;
+ unsigned int boundaries;
+
e_input_relative_motion_cb func = e_input_relative_motion_handler_get();
+
if (func)
{
//func(dx, dy, time_us);
return;
}
+ boundaries = _device_pointer_motion_clamp_for_output(evdev);
+ if (boundaries != 0)
+ {
+ clamped_boundaries = boundaries;
+ if (e_devicemgr_relative_motion_is_grabbed(boundaries))
+ {
+ e_devicemgr->relative_motion_grab.prev_boundaries = e_devicemgr->relative_motion_grab.curr_boundaries;
+ e_devicemgr->relative_motion_grab.curr_boundaries = boundaries;
+ _device_pointer_relative_motion(evdev, event, dx, dy);
+ }
+ }
+ else if (clamped_boundaries != 0)
+ {
+ if (e_devicemgr_relative_motion_is_grabbed(clamped_boundaries))
+ _device_pointer_relative_motion(evdev, event, dx, dy);
+
+ e_devicemgr->relative_motion_grab.prev_boundaries = e_devicemgr->relative_motion_grab.curr_boundaries;
+ e_devicemgr->relative_motion_grab.curr_boundaries = (unsigned int)E_DEVICEMGR_BOUNDARY_NONE;
+ clamped_boundaries = 0;
+ }
+
evdev->seat->ptr.ix = evdev->seat->ptr.dx;
evdev->seat->ptr.iy = evdev->seat->ptr.dy;
#include "e_input_thread_client_intern.h"
#include "e_display_intern.h"
#include "e_view_client_intern.h"
+#include "e_devicemgr_wl_intern.h"
#include <tizen-extension-server-protocol.h>
#include <relative-pointer-unstable-v1-server-protocol.h>
return ECORE_CALLBACK_RENEW;
}
-static Eina_Bool
-_e_comp_wl_cb_mouse_relative_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Relative_Move *ev)
+static void
+_e_comp_wl_send_mouse_relative_move(E_Client *ec, int dx, int dy,
+ int dx_unaccel, int dy_unaccel,
+ unsigned int timestamp)
{
- E_Client *ec;
struct wl_resource *surface;
struct wl_resource *res;
struct wl_client *wc;
Eina_List *l;
E_Comp_Config *comp_conf;
- ec = e_comp_wl->ptr_constraints.ec;
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_RENEW);
-
+ if (!ec) return;
+ if (e_object_is_del(E_OBJECT(ec))) return;
surface = e_comp_wl_client_surface_get(ec);
- EINA_SAFETY_ON_NULL_RETURN_VAL(surface, ECORE_CALLBACK_RENEW);
+ if (!surface) return;
wc = wl_resource_get_client(surface);
-
comp_conf = e_comp_config_get();
EINA_LIST_FOREACH(e_comp_wl->relative_ptr.resources, l, res)
if (comp_conf && comp_conf->input_log_enable)
ELOGF("Mouse", "Relative Move (time: %d, dx:%d dy:%d, unaccel(%d, %d) name:%20s)",
- ec, ev->timestamp, ev->dx, ev->dy, ev->dx_unaccel, ev->dy_unaccel,
+ ec, timestamp, dx, dy, dx_unaccel, dy_unaccel,
e_client_util_name_get(ec));
zwp_relative_pointer_v1_send_relative_motion(res,
0,
- (uint32_t)(ev->timestamp),
- wl_fixed_from_int(ev->dx),
- wl_fixed_from_int(ev->dy),
- wl_fixed_from_int(ev->dx_unaccel),
- wl_fixed_from_int(ev->dy_unaccel));
+ (uint32_t)(timestamp),
+ wl_fixed_from_int(dx),
+ wl_fixed_from_int(dy),
+ wl_fixed_from_int(dx_unaccel),
+ wl_fixed_from_int(dy_unaccel));
+ }
+}
+
+static Eina_Bool
+_e_comp_wl_cb_mouse_relative_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Relative_Move *ev)
+{
+ E_Client *ec;
+
+ ec = e_comp_wl->ptr_constraints.ec;
+ if (!ec)
+ {
+ for (int i = 1; i < E_DEVICEMGR_BOUNDARY_MAX + 1; i++)
+ {
+ if ((e_devicemgr->relative_motion_grab.curr_boundaries & (1 << i)))
+ {
+ if (e_devicemgr->relative_motion_grab.last_event_boundary != i)
+ {
+ e_devicemgr->relative_motion_grab.last_event_boundary = i;
+ e_devicemgr_wl_event_boundary_send(e_devicemgr->relative_motion_grab.boundaries[i].resource, i);
+ }
+ ec = e_devicemgr->relative_motion_grab.boundaries[i].ec;
+ if (ec)
+ {
+ ELOGF("Mouse", "Relative Move. Clamped boundary:%d", ec, i);
+ _e_comp_wl_send_mouse_relative_move(ec, ev->dx, ev->dy, ev->dx_unaccel, ev->dy_unaccel, ev->timestamp);
+ }
+ }
+ else if ((e_devicemgr->relative_motion_grab.prev_boundaries & (1 << i)))
+ {
+ if (e_devicemgr->relative_motion_grab.last_event_boundary != i)
+ {
+ e_devicemgr->relative_motion_grab.last_event_boundary = i;
+ e_devicemgr_wl_event_boundary_send(e_devicemgr->relative_motion_grab.boundaries[i].resource, i);
+ }
+ ec = e_devicemgr->relative_motion_grab.boundaries[i].ec;
+ if (ec)
+ {
+ ELOGF("Mouse", "Relative Move. Prev Clamped boundary:%d", ec, i);
+ _e_comp_wl_send_mouse_relative_move(ec, ev->dx, ev->dy, ev->dx_unaccel, ev->dy_unaccel, ev->timestamp);
+
+ e_devicemgr->relative_motion_grab.prev_boundaries &= ~(1 << i);
+ }
+ }
+ }
+ }
+ else
+ {
+ _e_comp_wl_send_mouse_relative_move(ec, ev->dx, ev->dy, ev->dx_unaccel, ev->dy_unaccel, ev->timestamp);
}
return ECORE_CALLBACK_DONE;
tizen_input_device_manager_send_error(resource, result);
}
+void
+e_devicemgr_wl_event_boundary_send(struct wl_resource *resource, unsigned int boundary)
+{
+ uint32_t serial;
+
+ if(!resource) return;
+
+ DMINF("Relative Move. Event Boundary: %d", boundary);
+
+ serial = wl_display_next_serial(e_comp_wl->wl.disp);
+ tizen_input_device_manager_send_event_boundary(resource, serial, boundary);
+}
+
static void
_e_devicemgr_wl_cb_block_events(struct wl_client *client, struct wl_resource *resource, uint32_t serial, uint32_t clas, uint32_t duration)
{
tizen_input_device_manager_send_error(resource, ret);
}
+static void
+_e_devicemgr_wl_cb_grab_relative_motion(struct wl_client *client, struct wl_resource *resource,
+ struct wl_resource *surface, uint32_t boundary)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+ if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client,
+ E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM))
+ {
+ DMERR("grab relative motion request:priv check failed");
+ tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+ return;
+ }
+#endif
+
+ ret = e_devicemgr_relative_motion_grab(client, resource, surface, boundary);
+ tizen_input_device_manager_send_error(resource, ret);
+}
+
+static void
+_e_devicemgr_wl_cb_ungrab_relative_motion(struct wl_client *client, struct wl_resource *resource,
+ struct wl_resource *surface)
+{
+ int ret = TIZEN_INPUT_DEVICE_MANAGER_ERROR_NONE;
+
+#ifdef HAVE_CYNARA
+ if (EINA_FALSE == _e_devicemgr_util_do_privilege_check(client,
+ E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM))
+ {
+ DMERR("ungrab relative motion request:priv check failed");
+ tizen_input_device_manager_send_error(resource, TIZEN_INPUT_DEVICE_MANAGER_ERROR_NO_PERMISSION);
+ return;
+ }
+#endif
+
+ ret = e_devicemgr_relative_motion_ungrab(client, resource, surface);
+ tizen_input_device_manager_send_error(resource, ret);
+}
static const struct tizen_input_device_manager_interface _e_devicemgr_wl_implementation = {
_e_devicemgr_wl_cb_block_events,
_e_devicemgr_wl_cb_set_touch_count,
_e_devicemgr_wl_cb_init_generator_with_sync,
_e_devicemgr_wl_cb_keyboard_grab,
- _e_devicemgr_wl_cb_keyboard_ungrab
+ _e_devicemgr_wl_cb_keyboard_ungrab,
+ _e_devicemgr_wl_cb_grab_relative_motion,
+ _e_devicemgr_wl_cb_ungrab_relative_motion
};
static void
/* try to add tizen_input_device_manager to wayland globals */
g_tizen_devicemgr->global = wl_global_create(display,
- &tizen_input_device_manager_interface, 6,
+ &tizen_input_device_manager_interface, 7,
NULL, _e_devicemgr_wl_cb_bind);
if (!g_tizen_devicemgr->global)
{
EINTERN void e_devicemgr_wl_detent_send_event(int detent);
EINTERN void e_devicemgr_wl_touch_max_count_send(int slot, struct wl_resource *res, struct wl_resource *seat_res);
EINTERN void e_devicemgr_wl_generator_with_sync_send_event(struct wl_resource *resource, int error);
+EINTERN void e_devicemgr_wl_event_boundary_send(struct wl_resource *resource, unsigned int boundary);
#endif
#include <glib.h>
+#define E_DEVICEMGR_BOUNDARY_MAX 4
+
typedef struct _E_Devicemgr E_Devicemgr;
typedef struct _E_Devicemgr_Conf_Edd E_Devicemgr_Conf_Edd;
typedef struct _E_Devicemgr_Config_Data E_Devicemgr_Config_Data;
typedef void (*E_Devicemgr_Block_Expire_Cb) (void *data);
+typedef struct _E_Devicemgr_Pointer_Boundary
+{
+ struct wl_client *client;
+ E_Client *ec;
+ struct wl_resource *resource;
+} E_Devicemgr_Pointer_Boundary;
+
+typedef enum _E_Devicemgr_Boundary
+{
+ E_DEVICEMGR_BOUNDARY_NONE = 0,
+ E_DEVICEMGR_BOUNDARY_TOP,
+ E_DEVICEMGR_BOUNDARY_RIGHT,
+ E_DEVICEMGR_BOUNDARY_BOTTOM,
+ E_DEVICEMGR_BOUNDARY_LEFT
+} E_Devicemgr_Boundary_Type;
+
struct _E_Devicemgr
{
E_Devicemgr_Config_Data *dconfig;
E_Client *ec;
unsigned int subtype;
} keyboard_grab;
+
+ struct
+ {
+ E_Devicemgr_Pointer_Boundary boundaries[E_DEVICEMGR_BOUNDARY_MAX + 1];
+ unsigned int grabbed_boundaries;
+ unsigned int curr_boundaries;
+ unsigned int prev_boundaries;
+ unsigned int last_event_boundary;
+ } relative_motion_grab;
};
extern E_API E_Devicemgr *e_devicemgr;