clients: Add API for pointer locking and pointer confinement

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
dev
Jonas Ådahl 10 years ago
parent d3414f23c3
commit e5a1bb4be2
  1. 6
      Makefile.am
  2. 318
      clients/window.c
  3. 55
      clients/window.h

@ -581,7 +581,11 @@ nodist_libtoytoolkit_la_SOURCES = \
protocol/xdg-shell-unstable-v5-protocol.c \
protocol/xdg-shell-unstable-v5-client-protocol.h \
protocol/ivi-application-protocol.c \
protocol/ivi-application-client-protocol.h
protocol/ivi-application-client-protocol.h \
protocol/pointer-constraints-unstable-v1-protocol.c \
protocol/pointer-constraints-unstable-v1-client-protocol.h \
protocol/relative-pointer-unstable-v1-protocol.c \
protocol/relative-pointer-unstable-v1-client-protocol.h
BUILT_SOURCES += $(nodist_libtoytoolkit_la_SOURCES)

@ -24,6 +24,7 @@
#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -72,6 +73,8 @@ typedef void *EGLContext;
#include "shared/zalloc.h"
#include "xdg-shell-unstable-v5-client-protocol.h"
#include "text-cursor-position-client-protocol.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
#include "shared/os-compatibility.h"
#include "window.h"
@ -80,6 +83,9 @@ typedef void *EGLContext;
#include "ivi-application-client-protocol.h"
#define IVI_SURFACE_ID 9000
#define ZWP_RELATIVE_POINTER_MANAGER_V1_VERSION 1
#define ZWP_POINTER_CONSTRAINTS_V1_VERSION 1
struct shm_pool;
struct global {
@ -99,6 +105,8 @@ struct display {
struct text_cursor_position *text_cursor_position;
struct xdg_shell *xdg_shell;
struct ivi_application *ivi_application; /* ivi style shell */
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
EGLDisplay dpy;
EGLConfig argb_config;
EGLContext argb_ctx;
@ -247,6 +255,8 @@ struct window {
window_output_handler_t output_handler;
window_state_changed_handler_t state_changed_handler;
window_locked_pointer_motion_handler_t locked_pointer_motion_handler;
struct surface *main_surface;
struct xdg_surface *xdg_surface;
struct xdg_popup *xdg_popup;
@ -261,6 +271,19 @@ struct window {
/* struct surface::link, contains also main_surface */
struct wl_list subsurface_list;
struct zwp_relative_pointer_v1 *relative_pointer;
struct zwp_locked_pointer_v1 *locked_pointer;
struct input *locked_input;
bool pointer_locked;
locked_pointer_locked_handler_t pointer_locked_handler;
locked_pointer_unlocked_handler_t pointer_unlocked_handler;
confined_pointer_confined_handler_t pointer_confined_handler;
confined_pointer_unconfined_handler_t pointer_unconfined_handler;
struct zwp_confined_pointer_v1 *confined_pointer;
struct widget *confined_widget;
bool confined;
void *user_data;
struct wl_list link;
};
@ -4056,6 +4079,22 @@ window_do_resize(struct window *window)
if (!window->fullscreen && !window->maximized)
window->saved_allocation = window->pending_allocation;
if (window->confined && window->confined_widget) {
struct wl_compositor *compositor = window->display->compositor;
struct wl_region *region;
struct widget *widget = window->confined_widget;
region = wl_compositor_create_region(compositor);
wl_region_add(region,
widget->allocation.x,
widget->allocation.y,
widget->allocation.width,
widget->allocation.height);
zwp_confined_pointer_v1_set_region(window->confined_pointer,
region);
wl_region_destroy(region);
}
}
static void
@ -4584,6 +4623,31 @@ window_set_state_changed_handler(struct window *window,
window->state_changed_handler = handler;
}
void
window_set_pointer_locked_handler(struct window *window,
locked_pointer_locked_handler_t locked,
locked_pointer_unlocked_handler_t unlocked)
{
window->pointer_unlocked_handler = unlocked;
window->pointer_locked_handler = locked;
}
void
window_set_pointer_confined_handler(struct window *window,
confined_pointer_confined_handler_t confined,
confined_pointer_unconfined_handler_t unconfined)
{
window->pointer_confined_handler = confined;
window->pointer_unconfined_handler = unconfined;
}
void
window_set_locked_pointer_motion_handler(struct window *window,
window_locked_pointer_motion_handler_t handler)
{
window->locked_pointer_motion_handler = handler;
}
void
window_set_title(struct window *window, const char *title)
{
@ -4618,6 +4682,248 @@ window_set_text_cursor_position(struct window *window, int32_t x, int32_t y)
wl_fixed_from_int(y));
}
static void
relative_pointer_handle_motion(void *data, struct zwp_relative_pointer_v1 *pointer,
uint32_t utime_hi,
uint32_t utime_lo,
wl_fixed_t dx,
wl_fixed_t dy,
wl_fixed_t dx_unaccel,
wl_fixed_t dy_unaccel)
{
struct input *input = data;
struct window *window = input->pointer_focus;
uint32_t ms = (((uint64_t) utime_hi) << 32 | utime_lo) / 1000;
if (window->locked_pointer_motion_handler &&
window->pointer_locked) {
window->locked_pointer_motion_handler(
window, input, ms,
wl_fixed_to_double(dx),
wl_fixed_to_double(dy),
window->user_data);
}
}
static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
relative_pointer_handle_motion,
};
static void
locked_pointer_locked(void *data,
struct zwp_locked_pointer_v1 *locked_pointer)
{
struct input *input = data;
struct window *window = input->pointer_focus;
window->pointer_locked = true;
if (window->pointer_locked_handler) {
window->pointer_locked_handler(window,
input,
window->user_data);
}
}
static void
locked_pointer_unlocked(void *data,
struct zwp_locked_pointer_v1 *locked_pointer)
{
struct input *input = data;
struct window *window = input->pointer_focus;
window_unlock_pointer(window);
if (window->pointer_unlocked_handler) {
window->pointer_unlocked_handler(window,
input,
window->user_data);
}
}
static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
locked_pointer_locked,
locked_pointer_unlocked,
};
int
window_lock_pointer(struct window *window, struct input *input)
{
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager =
window->display->relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints =
window->display->pointer_constraints;
struct zwp_relative_pointer_v1 *relative_pointer;
struct zwp_locked_pointer_v1 *locked_pointer;
if (!window->display->relative_pointer_manager)
return -1;
if (!window->display->pointer_constraints)
return -1;
if (window->locked_pointer)
return -1;
if (window->confined_pointer)
return -1;
if (!input->pointer)
return -1;
relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(
relative_pointer_manager, input->pointer);
zwp_relative_pointer_v1_add_listener(relative_pointer,
&relative_pointer_listener,
input);
locked_pointer =
zwp_pointer_constraints_v1_lock_pointer(pointer_constraints,
window->main_surface->surface,
input->pointer,
NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT);
zwp_locked_pointer_v1_add_listener(locked_pointer,
&locked_pointer_listener,
input);
window->locked_input = input;
window->locked_pointer = locked_pointer;
window->relative_pointer = relative_pointer;
return 0;
}
void
window_unlock_pointer(struct window *window)
{
if (!window->locked_pointer)
return;
zwp_locked_pointer_v1_destroy(window->locked_pointer);
zwp_relative_pointer_v1_destroy(window->relative_pointer);
window->locked_pointer = NULL;
window->relative_pointer = NULL;
window->pointer_locked = false;
window->locked_input = NULL;
}
void
widget_set_locked_pointer_cursor_hint(struct widget *widget,
float x, float y)
{
struct window *window = widget->window;
if (!window->locked_pointer)
return;
zwp_locked_pointer_v1_set_cursor_position_hint(window->locked_pointer,
wl_fixed_from_double(x),
wl_fixed_from_double(y));
wl_surface_commit(window->main_surface->surface);
}
static void
confined_pointer_confined(void *data,
struct zwp_confined_pointer_v1 *confined_pointer)
{
struct input *input = data;
struct window *window = input->pointer_focus;
window->confined = true;
if (window->pointer_confined_handler) {
window->pointer_confined_handler(window,
input,
window->user_data);
}
}
static void
confined_pointer_unconfined(void *data,
struct zwp_confined_pointer_v1 *confined_pointer)
{
struct input *input = data;
struct window *window = input->pointer_focus;
window_unconfine_pointer(window);
window->confined = false;
if (window->pointer_unconfined_handler) {
window->pointer_unconfined_handler(window,
input,
window->user_data);
}
}
static const struct zwp_confined_pointer_v1_listener confined_pointer_listener = {
confined_pointer_confined,
confined_pointer_unconfined,
};
int
window_confine_pointer_to_widget(struct window *window,
struct widget *widget,
struct input *input)
{
struct zwp_pointer_constraints_v1 *pointer_constraints =
window->display->pointer_constraints;
struct zwp_confined_pointer_v1 *confined_pointer;
struct wl_compositor *compositor = window->display->compositor;
struct wl_region *region = NULL;
if (!window->display->pointer_constraints)
return -1;
if (window->locked_pointer)
return -1;
if (window->confined_pointer)
return -1;
if (!input->pointer)
return -1;
if (widget) {
region = wl_compositor_create_region(compositor);
wl_region_add(region,
widget->allocation.x,
widget->allocation.y,
widget->allocation.width,
widget->allocation.height);
}
confined_pointer =
zwp_pointer_constraints_v1_confine_pointer(pointer_constraints,
window->main_surface->surface,
input->pointer,
region,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT);
if (region)
wl_region_destroy(region);
zwp_confined_pointer_v1_add_listener(confined_pointer,
&confined_pointer_listener,
input);
window->confined_pointer = confined_pointer;
window->confined_widget = widget;
return 0;
}
void
window_unconfine_pointer(struct window *window)
{
if (!window->confined_pointer)
return;
zwp_confined_pointer_v1_destroy(window->confined_pointer);
window->confined_pointer = NULL;
window->confined = false;
}
static void
surface_enter(void *data,
struct wl_surface *wl_surface, struct wl_output *wl_output)
@ -5459,6 +5765,18 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
display_add_output(d, id);
} else if (strcmp(interface, "wl_seat") == 0) {
display_add_input(d, id, version);
} else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0 &&
version == ZWP_RELATIVE_POINTER_MANAGER_V1_VERSION) {
d->relative_pointer_manager =
wl_registry_bind(registry, id,
&zwp_relative_pointer_manager_v1_interface,
1);
} else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0 &&
version == ZWP_POINTER_CONSTRAINTS_V1_VERSION) {
d->pointer_constraints =
wl_registry_bind(registry, id,
&zwp_pointer_constraints_v1_interface,
1);
} else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
wl_shm_add_listener(d->shm, &shm_listener, d);

@ -213,6 +213,29 @@ typedef void (*window_output_handler_t)(struct window *window, struct output *ou
typedef void (*window_state_changed_handler_t)(struct window *window,
void *data);
typedef void (*window_locked_pointer_motion_handler_t)(struct window *window,
struct input *input,
uint32_t time,
float x, float y,
void *data);
typedef void (*locked_pointer_locked_handler_t)(struct window *window,
struct input *input,
void *data);
typedef void (*locked_pointer_unlocked_handler_t)(struct window *window,
struct input *input,
void *data);
typedef void (*confined_pointer_confined_handler_t)(struct window *window,
struct input *input,
void *data);
typedef void (*confined_pointer_unconfined_handler_t)(struct window *window,
struct input *input,
void *data);
typedef void (*widget_resize_handler_t)(struct widget *widget,
int32_t width, int32_t height,
void *data);
@ -359,6 +382,24 @@ window_schedule_redraw(struct window *window);
void
window_schedule_resize(struct window *window, int width, int height);
int
window_lock_pointer(struct window *window, struct input *input);
void
window_unlock_pointer(struct window *window);
void
widget_set_locked_pointer_cursor_hint(struct widget *widget,
float x, float y);
int
window_confine_pointer_to_widget(struct window *window,
struct widget *widget,
struct input *input);
void
window_unconfine_pointer(struct window *window);
cairo_surface_t *
window_get_surface(struct window *window);
@ -436,6 +477,20 @@ void
window_set_state_changed_handler(struct window *window,
window_state_changed_handler_t handler);
void
window_set_pointer_locked_handler(struct window *window,
locked_pointer_locked_handler_t locked,
locked_pointer_unlocked_handler_t unlocked);
void
window_set_pointer_confined_handler(struct window *window,
confined_pointer_confined_handler_t confined,
confined_pointer_unconfined_handler_t unconfined);
void
window_set_locked_pointer_motion_handler(
struct window *window, window_locked_pointer_motion_handler_t handler);
void
window_set_title(struct window *window, const char *title);

Loading…
Cancel
Save