forked from 12to11/12to11
Implement relative pointer protocol
* 12to11.c (XLMain): Initialize relative pointer. * 12to11.man: Document new protocol. * Imakefile (SRCS): Add relative_pointer.c. (OBJS): Add relative_pointer.o. (relative-pointer-unstable-v1): New scanner target. * README: Document support for new protocol. * compositor.h: Update prototypes. * pointer_constraints.c (HandleResourceDestroy) (HandleSeatDestroyed): Don't destroy commit callback if not attached. * seat.c (struct _Keyboard): Fix comment. (struct _RelativePointer): New structure. (struct _SeatClientInfo): Add relative pointer fields. (CreateSeatClientInfo, ReleaseSeatClientInfo): Initialize and check relative pointer list. (SendRelativeMotion): New function. (EnteredSurface): Clear surface coordinate set flag. (DispatchMotion): Dispatch relative motion if possible. (DispatchBarrierHit, XLGetGEWindowForSeats, XLSelectStandardEvents) (XLDispatchGEForSeats): Handle barrier hit events for relative motion. (XLSeatGetRelativePointer, XLSeatDestroyRelativePointer): New functions.
This commit is contained in:
parent
297c79d600
commit
c1959e5f22
7 changed files with 168 additions and 15 deletions
1
12to11.c
1
12to11.c
|
@ -235,6 +235,7 @@ XLMain (int argc, char **argv)
|
||||||
XLInitSinglePixelBuffer ();
|
XLInitSinglePixelBuffer ();
|
||||||
XLInitDrmLease ();
|
XLInitDrmLease ();
|
||||||
XLInitPointerConstraints ();
|
XLInitPointerConstraints ();
|
||||||
|
XLInitRelativePointer ();
|
||||||
|
|
||||||
/* This has to come after the rest of the initialization. */
|
/* This has to come after the rest of the initialization. */
|
||||||
DetermineServerTime ();
|
DetermineServerTime ();
|
||||||
|
|
|
@ -202,6 +202,7 @@ zxdg_decoration_manager_v1 1
|
||||||
zwp_text_input_manager_v3 1
|
zwp_text_input_manager_v3 1
|
||||||
wp_single_pixel_buffer_manager_v1 1
|
wp_single_pixel_buffer_manager_v1 1
|
||||||
zwp_pointer_constraints_v1 1
|
zwp_pointer_constraints_v1 1
|
||||||
|
zwp_relative_pointer_manager 1
|
||||||
.TE
|
.TE
|
||||||
.PP
|
.PP
|
||||||
When the protocol translator is built with EGL support, the following
|
When the protocol translator is built with EGL support, the following
|
||||||
|
@ -235,11 +236,6 @@ size. Setting the
|
||||||
.B APPLY_STATE_WORKAROUND
|
.B APPLY_STATE_WORKAROUND
|
||||||
environment variable may help.
|
environment variable may help.
|
||||||
.PP
|
.PP
|
||||||
Mozilla Firefox also does not work correctly. Resizing the Firefox
|
|
||||||
window leads to screen tearing, and Firefox often resizes its toplevel
|
|
||||||
windows outside their normal boundaries, causing invalid screen
|
|
||||||
contents to be displayed over other applications.
|
|
||||||
.PP
|
|
||||||
Using this protocol translator under a window manager that does not at
|
Using this protocol translator under a window manager that does not at
|
||||||
least support the
|
least support the
|
||||||
.B _NET_WM_SYNC_REQUEST
|
.B _NET_WM_SYNC_REQUEST
|
||||||
|
|
|
@ -24,7 +24,7 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
|
||||||
picture_renderer.c explicit_synchronization.c transform.c \
|
picture_renderer.c explicit_synchronization.c transform.c \
|
||||||
wp_viewporter.c decoration.c text_input.c \
|
wp_viewporter.c decoration.c text_input.c \
|
||||||
single_pixel_buffer.c drm_lease.c pointer_constraints.c \
|
single_pixel_buffer.c drm_lease.c pointer_constraints.c \
|
||||||
time.c
|
time.c relative_pointer.c
|
||||||
|
|
||||||
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
|
surface.o region.o shm.o atoms.o subcompositor.o positioner.o \
|
||||||
|
@ -35,7 +35,7 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
|
||||||
picture_renderer.o explicit_synchronization.o transform.o \
|
picture_renderer.o explicit_synchronization.o transform.o \
|
||||||
wp_viewporter.o decoration.o text_input.o \
|
wp_viewporter.o decoration.o text_input.o \
|
||||||
single_pixel_buffer.o drm_lease.o pointer_constraints.o \
|
single_pixel_buffer.o drm_lease.o pointer_constraints.o \
|
||||||
time.o
|
time.o relative_pointer.o
|
||||||
|
|
||||||
GENHEADERS = transfer_atoms.h
|
GENHEADERS = transfer_atoms.h
|
||||||
|
|
||||||
|
@ -120,6 +120,7 @@ ScannerTarget(text-input-unstable-v3)
|
||||||
ScannerTarget(single-pixel-buffer-v1)
|
ScannerTarget(single-pixel-buffer-v1)
|
||||||
ScannerTarget(drm-lease-v1)
|
ScannerTarget(drm-lease-v1)
|
||||||
ScannerTarget(pointer-constraints-unstable-v1)
|
ScannerTarget(pointer-constraints-unstable-v1)
|
||||||
|
ScannerTarget(relative-pointer-unstable-v1)
|
||||||
|
|
||||||
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
|
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
|
||||||
$(OBJS): $(GENHEADERS)
|
$(OBJS): $(GENHEADERS)
|
||||||
|
|
1
README
1
README
|
@ -66,6 +66,7 @@ complete degree:
|
||||||
'zwp_text_input_manager_v3', version: 1
|
'zwp_text_input_manager_v3', version: 1
|
||||||
'wp_single_pixel_buffer_manager_v1', version: 1
|
'wp_single_pixel_buffer_manager_v1', version: 1
|
||||||
'zwp_pointer_constraints_v1', version: 1
|
'zwp_pointer_constraints_v1', version: 1
|
||||||
|
'zwp_relative_pointer_manager_v1', version: 1
|
||||||
|
|
||||||
When built with EGL, the following Wayland protocol is also supported:
|
When built with EGL, the following Wayland protocol is also supported:
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct _Compositor
|
||||||
|
|
||||||
typedef struct _Seat Seat;
|
typedef struct _Seat Seat;
|
||||||
typedef struct _Pointer Pointer;
|
typedef struct _Pointer Pointer;
|
||||||
|
typedef struct _RelativePointer RelativePointer;
|
||||||
|
|
||||||
/* Forward declarations from primary_selection.c. */
|
/* Forward declarations from primary_selection.c. */
|
||||||
|
|
||||||
|
@ -1444,6 +1445,8 @@ extern void XLSeatGetMouseData (Seat *, Surface **, double *, double *,
|
||||||
double *, double *);
|
double *, double *);
|
||||||
extern void XLSeatLockPointer (Seat *);
|
extern void XLSeatLockPointer (Seat *);
|
||||||
extern void XLSeatUnlockPointer (Seat *);
|
extern void XLSeatUnlockPointer (Seat *);
|
||||||
|
extern RelativePointer *XLSeatGetRelativePointer (Seat *, struct wl_resource *);
|
||||||
|
extern void XLSeatDestroyRelativePointer (RelativePointer *);
|
||||||
|
|
||||||
extern Cursor InitDefaultCursor (void);
|
extern Cursor InitDefaultCursor (void);
|
||||||
|
|
||||||
|
@ -1611,6 +1614,12 @@ extern void XLPointerConstraintsSurfaceMovedTo (Surface *, int, int);
|
||||||
extern void XLPointerConstraintsSubsurfaceMoved (Surface *);
|
extern void XLPointerConstraintsSubsurfaceMoved (Surface *);
|
||||||
extern void XLPointerConstraintsReconfineSurface (Surface *);
|
extern void XLPointerConstraintsReconfineSurface (Surface *);
|
||||||
|
|
||||||
|
/* Defined in relative_pointer.c. */
|
||||||
|
|
||||||
|
extern void XLInitRelativePointer (void);
|
||||||
|
extern void XLRelativePointerSendRelativeMotion (struct wl_resource *,
|
||||||
|
uint64_t, double, double);
|
||||||
|
|
||||||
/* Utility functions that don't belong in a specific file. */
|
/* Utility functions that don't belong in a specific file. */
|
||||||
|
|
||||||
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
||||||
|
|
|
@ -905,6 +905,7 @@ HandleResourceDestroy (struct wl_resource *resource)
|
||||||
confinement->surface = NULL;
|
confinement->surface = NULL;
|
||||||
|
|
||||||
/* Remove the commit callback. */
|
/* Remove the commit callback. */
|
||||||
|
if (confinement->commit_callback)
|
||||||
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
||||||
confinement->commit_callback = NULL;
|
confinement->commit_callback = NULL;
|
||||||
}
|
}
|
||||||
|
@ -961,6 +962,7 @@ HandleSeatDestroyed (void *data)
|
||||||
confinement->surface = NULL;
|
confinement->surface = NULL;
|
||||||
|
|
||||||
/* Cancel the commit callback. */
|
/* Cancel the commit callback. */
|
||||||
|
if (confinement->commit_callback)
|
||||||
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
||||||
confinement->commit_callback = NULL;
|
confinement->commit_callback = NULL;
|
||||||
}
|
}
|
||||||
|
|
155
seat.c
155
seat.c
|
@ -88,6 +88,7 @@ enum
|
||||||
IsDropped = (1 << 4),
|
IsDropped = (1 << 4),
|
||||||
IsTextInputSeat = (1 << 5),
|
IsTextInputSeat = (1 << 5),
|
||||||
IsPointerLocked = (1 << 6),
|
IsPointerLocked = (1 << 6),
|
||||||
|
IsSurfaceCoordSet = (1 << 7),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -105,6 +106,7 @@ typedef struct _Seat Seat;
|
||||||
typedef struct _SeatClientInfo SeatClientInfo;
|
typedef struct _SeatClientInfo SeatClientInfo;
|
||||||
typedef struct _Pointer Pointer;
|
typedef struct _Pointer Pointer;
|
||||||
typedef struct _Keyboard Keyboard;
|
typedef struct _Keyboard Keyboard;
|
||||||
|
typedef struct _RelativePointer RelativePointer;
|
||||||
typedef struct _SeatCursor SeatCursor;
|
typedef struct _SeatCursor SeatCursor;
|
||||||
typedef struct _ResizeDoneCallback ResizeDoneCallback;
|
typedef struct _ResizeDoneCallback ResizeDoneCallback;
|
||||||
typedef struct _ScrollValuator ScrollValuator;
|
typedef struct _ScrollValuator ScrollValuator;
|
||||||
|
@ -288,7 +290,7 @@ struct _Pointer
|
||||||
|
|
||||||
struct _Keyboard
|
struct _Keyboard
|
||||||
{
|
{
|
||||||
/* The keyboard this pointer object refers to. */
|
/* The seat this keyboard object refers to. */
|
||||||
Seat *seat;
|
Seat *seat;
|
||||||
|
|
||||||
/* The struct wl_resource associated with this keyboard. */
|
/* The struct wl_resource associated with this keyboard. */
|
||||||
|
@ -302,25 +304,45 @@ struct _Keyboard
|
||||||
Keyboard *next, *next1, *last, *last1;
|
Keyboard *next, *next1, *last, *last1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _RelativePointer
|
||||||
|
{
|
||||||
|
/* The seat this relative pointer refers to. */
|
||||||
|
Seat *seat;
|
||||||
|
|
||||||
|
/* The struct wl_resource associated with this relative pointer. */
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
/* The seat client info associated with this relative pointer
|
||||||
|
resource. */
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
/* The next and last relative pointers attached to the seat client
|
||||||
|
info. */
|
||||||
|
RelativePointer *next, *last;
|
||||||
|
};
|
||||||
|
|
||||||
struct _SeatClientInfo
|
struct _SeatClientInfo
|
||||||
{
|
{
|
||||||
/* Number of references to this seat client information. */
|
|
||||||
int refcount;
|
|
||||||
|
|
||||||
/* The next and last structures in the client info chain. */
|
/* The next and last structures in the client info chain. */
|
||||||
SeatClientInfo *next, *last;
|
SeatClientInfo *next, *last;
|
||||||
|
|
||||||
/* The client corresponding to this object. */
|
/* The client corresponding to this object. */
|
||||||
struct wl_client *client;
|
struct wl_client *client;
|
||||||
|
|
||||||
/* List of pointer objects on this seat for this client. */
|
/* Number of references to this seat client information. */
|
||||||
Pointer pointers;
|
int refcount;
|
||||||
|
|
||||||
/* The serial of the last enter event sent. */
|
/* The serial of the last enter event sent. */
|
||||||
uint32_t last_enter_serial;
|
uint32_t last_enter_serial;
|
||||||
|
|
||||||
|
/* List of pointer objects on this seat for this client. */
|
||||||
|
Pointer pointers;
|
||||||
|
|
||||||
/* List of keyboard objects on this seat for this client. */
|
/* List of keyboard objects on this seat for this client. */
|
||||||
Keyboard keyboards;
|
Keyboard keyboards;
|
||||||
|
|
||||||
|
/* List of relative pointers on this seat for this client. */
|
||||||
|
RelativePointer relative_pointers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ModifierChangeCallback
|
struct _ModifierChangeCallback
|
||||||
|
@ -653,6 +675,8 @@ CreateSeatClientInfo (Seat *seat, struct wl_client *client)
|
||||||
info->pointers.last = &info->pointers;
|
info->pointers.last = &info->pointers;
|
||||||
info->keyboards.next = &info->keyboards;
|
info->keyboards.next = &info->keyboards;
|
||||||
info->keyboards.last = &info->keyboards;
|
info->keyboards.last = &info->keyboards;
|
||||||
|
info->relative_pointers.next = &info->relative_pointers;
|
||||||
|
info->relative_pointers.last = &info->relative_pointers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increase the reference count of info. */
|
/* Increase the reference count of info. */
|
||||||
|
@ -671,6 +695,7 @@ ReleaseSeatClientInfo (SeatClientInfo *info)
|
||||||
/* Assert that there are no more keyboards or pointers attached. */
|
/* Assert that there are no more keyboards or pointers attached. */
|
||||||
XLAssert (info->keyboards.next == &info->keyboards);
|
XLAssert (info->keyboards.next == &info->keyboards);
|
||||||
XLAssert (info->pointers.next == &info->pointers);
|
XLAssert (info->pointers.next == &info->pointers);
|
||||||
|
XLAssert (info->relative_pointers.next == &info->relative_pointers);
|
||||||
|
|
||||||
/* Unlink the client info structure if it is still linked. */
|
/* Unlink the client info structure if it is still linked. */
|
||||||
if (info->next)
|
if (info->next)
|
||||||
|
@ -3081,6 +3106,40 @@ SendMotion (Seat *seat, Surface *surface, double x, double y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendRelativeMotion (Seat *seat, Surface *surface, double dx, double dy,
|
||||||
|
Time time)
|
||||||
|
{
|
||||||
|
SeatClientInfo *info;
|
||||||
|
uint64_t microsecond_time;
|
||||||
|
RelativePointer *relative_pointer;
|
||||||
|
|
||||||
|
/* Unfortunately there is no way to determine whether or not a
|
||||||
|
valuator specified in a raw event really corresponds to pointer
|
||||||
|
motion, so we can't get unaccelerated deltas. It may be worth
|
||||||
|
wiring up raw events for the X.org server, since we do know how
|
||||||
|
it specifically behaves. */
|
||||||
|
|
||||||
|
info = ClientInfoForResource (seat, surface->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Hmm... */
|
||||||
|
microsecond_time = time * 1000;
|
||||||
|
|
||||||
|
relative_pointer = info->relative_pointers.next;
|
||||||
|
while (relative_pointer != &info->relative_pointers)
|
||||||
|
{
|
||||||
|
/* Send the relative deltas. */
|
||||||
|
XLRelativePointerSendRelativeMotion (relative_pointer->resource,
|
||||||
|
microsecond_time, dx, dy);
|
||||||
|
|
||||||
|
/* Move to the next relative pointer. */
|
||||||
|
relative_pointer = relative_pointer->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SendLeave (Seat *seat, Surface *surface)
|
SendLeave (Seat *seat, Surface *surface)
|
||||||
{
|
{
|
||||||
|
@ -3333,6 +3392,9 @@ EnteredSurface (Seat *seat, Surface *surface, Time time,
|
||||||
XLSurfaceCancelRunOnFree (seat->last_seen_surface_callback);
|
XLSurfaceCancelRunOnFree (seat->last_seen_surface_callback);
|
||||||
seat->last_seen_surface = NULL;
|
seat->last_seen_surface = NULL;
|
||||||
seat->last_seen_surface_callback = NULL;
|
seat->last_seen_surface_callback = NULL;
|
||||||
|
|
||||||
|
/* Mark the last surface motion coords as no longer set. */
|
||||||
|
seat->flags &= ~IsSurfaceCoordSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface)
|
if (surface)
|
||||||
|
@ -3811,6 +3873,16 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
||||||
/* Send the motion event. */
|
/* Send the motion event. */
|
||||||
SendMotion (seat, dispatch, x, y, xev->time);
|
SendMotion (seat, dispatch, x, y, xev->time);
|
||||||
|
|
||||||
|
/* Send relative motion. Relative motion is handled by
|
||||||
|
subtracting x and y from seat->last_surface_x and
|
||||||
|
seat->last_surface_y, unless pointer motion reporting is
|
||||||
|
locked, in which case XI barrier motion events are used
|
||||||
|
instead. */
|
||||||
|
if (x - seat->last_surface_x != 0.0
|
||||||
|
|| y - seat->last_surface_y != 0.0)
|
||||||
|
SendRelativeMotion (seat, dispatch, x - seat->last_surface_x,
|
||||||
|
y - seat->last_surface_y, xev->time);
|
||||||
|
|
||||||
/* Check if this motion would cause a pointer constraint to
|
/* Check if this motion would cause a pointer constraint to
|
||||||
activate. */
|
activate. */
|
||||||
CheckPointerBarrier (seat, dispatch, x, y, xev->root_x,
|
CheckPointerBarrier (seat, dispatch, x, y, xev->root_x,
|
||||||
|
@ -3820,6 +3892,7 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
||||||
/* Set the last movement location. */
|
/* Set the last movement location. */
|
||||||
seat->last_surface_x = x;
|
seat->last_surface_x = x;
|
||||||
seat->last_surface_y = y;
|
seat->last_surface_y = y;
|
||||||
|
seat->flags |= IsSurfaceCoordSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These values are for tracking the output that a cursor is in. */
|
/* These values are for tracking the output that a cursor is in. */
|
||||||
|
@ -4158,6 +4231,27 @@ DispatchKey (XIDeviceEvent *xev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DispatchBarrierHit (XIBarrierEvent *barrier)
|
||||||
|
{
|
||||||
|
Seat *seat;
|
||||||
|
|
||||||
|
seat = XLLookUpAssoc (seats, barrier->deviceid);
|
||||||
|
|
||||||
|
if (!seat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Report a barrier hit event as relative motion. */
|
||||||
|
|
||||||
|
if (seat->focus_surface)
|
||||||
|
SendRelativeMotion (seat, seat->focus_surface,
|
||||||
|
barrier->dx, barrier->dy,
|
||||||
|
barrier->time);
|
||||||
|
|
||||||
|
/* Set the last user time. */
|
||||||
|
seat->last_user_time = TimestampFromServerTime (barrier->time);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
WriteKeymap (void)
|
WriteKeymap (void)
|
||||||
{
|
{
|
||||||
|
@ -4614,6 +4708,7 @@ XLGetGEWindowForSeats (XEvent *event)
|
||||||
XIFocusInEvent *focusin;
|
XIFocusInEvent *focusin;
|
||||||
XIEnterEvent *enter;
|
XIEnterEvent *enter;
|
||||||
XIDeviceEvent *xev;
|
XIDeviceEvent *xev;
|
||||||
|
XIBarrierEvent *barrier;
|
||||||
|
|
||||||
if (event->type == GenericEvent
|
if (event->type == GenericEvent
|
||||||
&& event->xgeneric.extension == xi2_opcode)
|
&& event->xgeneric.extension == xi2_opcode)
|
||||||
|
@ -4637,6 +4732,10 @@ XLGetGEWindowForSeats (XEvent *event)
|
||||||
case XI_Leave:
|
case XI_Leave:
|
||||||
enter = event->xcookie.data;
|
enter = event->xcookie.data;
|
||||||
return enter->event;
|
return enter->event;
|
||||||
|
|
||||||
|
case XI_BarrierHit:
|
||||||
|
barrier = event->xcookie.data;
|
||||||
|
return barrier->event;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4665,6 +4764,7 @@ XLSelectStandardEvents (Window window)
|
||||||
XISetMask (mask.mask, XI_ButtonRelease);
|
XISetMask (mask.mask, XI_ButtonRelease);
|
||||||
XISetMask (mask.mask, XI_KeyPress);
|
XISetMask (mask.mask, XI_KeyPress);
|
||||||
XISetMask (mask.mask, XI_KeyRelease);
|
XISetMask (mask.mask, XI_KeyRelease);
|
||||||
|
XISetMask (mask.mask, XI_BarrierHit);
|
||||||
|
|
||||||
XISelectEvents (compositor.display, window, &mask, 1);
|
XISelectEvents (compositor.display, window, &mask, 1);
|
||||||
}
|
}
|
||||||
|
@ -4688,6 +4788,8 @@ XLDispatchGEForSeats (XEvent *event, Surface *surface,
|
||||||
else if (event->xgeneric.evtype == XI_KeyPress
|
else if (event->xgeneric.evtype == XI_KeyPress
|
||||||
|| event->xgeneric.evtype == XI_KeyRelease)
|
|| event->xgeneric.evtype == XI_KeyRelease)
|
||||||
DispatchKey (event->xcookie.data);
|
DispatchKey (event->xcookie.data);
|
||||||
|
else if (event->xgeneric.evtype == XI_BarrierHit)
|
||||||
|
DispatchBarrierHit (event->xcookie.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor
|
Cursor
|
||||||
|
@ -5589,3 +5691,44 @@ XLSeatUnlockPointer (Seat *seat)
|
||||||
{
|
{
|
||||||
seat->flags &= ~IsPointerLocked;
|
seat->flags &= ~IsPointerLocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RelativePointer *
|
||||||
|
XLSeatGetRelativePointer (Seat *seat, struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
RelativePointer *relative_pointer;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
/* Create a relative pointer object for the relative pointer
|
||||||
|
resource RESOURCE. */
|
||||||
|
|
||||||
|
relative_pointer = XLCalloc (1, sizeof *relative_pointer);
|
||||||
|
info = CreateSeatClientInfo (seat, wl_resource_get_client (resource));
|
||||||
|
|
||||||
|
/* Link the relative pointer onto the seat client info. */
|
||||||
|
relative_pointer->next = info->relative_pointers.next;
|
||||||
|
relative_pointer->last = &info->relative_pointers;
|
||||||
|
info->relative_pointers.next->last = relative_pointer;
|
||||||
|
info->relative_pointers.next = relative_pointer;
|
||||||
|
relative_pointer->info = info;
|
||||||
|
|
||||||
|
/* Then, the seat. */
|
||||||
|
relative_pointer->seat = seat;
|
||||||
|
RetainSeat (seat);
|
||||||
|
|
||||||
|
/* Add the resource. */
|
||||||
|
relative_pointer->resource = resource;
|
||||||
|
|
||||||
|
return relative_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSeatDestroyRelativePointer (RelativePointer *relative_pointer)
|
||||||
|
{
|
||||||
|
relative_pointer->last->next = relative_pointer->next;
|
||||||
|
relative_pointer->next->last = relative_pointer->last;
|
||||||
|
|
||||||
|
ReleaseSeatClientInfo (relative_pointer->info);
|
||||||
|
ReleaseSeat (relative_pointer->seat);
|
||||||
|
|
||||||
|
XLFree (relative_pointer);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue