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:
oldosfan 2022-10-16 11:35:56 +00:00
parent 297c79d600
commit c1959e5f22
7 changed files with 168 additions and 15 deletions

View file

@ -235,6 +235,7 @@ XLMain (int argc, char **argv)
XLInitSinglePixelBuffer ();
XLInitDrmLease ();
XLInitPointerConstraints ();
XLInitRelativePointer ();
/* This has to come after the rest of the initialization. */
DetermineServerTime ();

View file

@ -202,6 +202,7 @@ zxdg_decoration_manager_v1 1
zwp_text_input_manager_v3 1
wp_single_pixel_buffer_manager_v1 1
zwp_pointer_constraints_v1 1
zwp_relative_pointer_manager 1
.TE
.PP
When the protocol translator is built with EGL support, the following
@ -235,11 +236,6 @@ size. Setting the
.B APPLY_STATE_WORKAROUND
environment variable may help.
.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
least support the
.B _NET_WM_SYNC_REQUEST

View file

@ -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 \
wp_viewporter.c decoration.c text_input.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 \
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 \
wp_viewporter.o decoration.o text_input.o \
single_pixel_buffer.o drm_lease.o pointer_constraints.o \
time.o
time.o relative_pointer.o
GENHEADERS = transfer_atoms.h
@ -120,6 +120,7 @@ ScannerTarget(text-input-unstable-v3)
ScannerTarget(single-pixel-buffer-v1)
ScannerTarget(drm-lease-v1)
ScannerTarget(pointer-constraints-unstable-v1)
ScannerTarget(relative-pointer-unstable-v1)
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
$(OBJS): $(GENHEADERS)

1
README
View file

@ -66,6 +66,7 @@ complete degree:
'zwp_text_input_manager_v3', version: 1
'wp_single_pixel_buffer_manager_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:

View file

@ -90,6 +90,7 @@ struct _Compositor
typedef struct _Seat Seat;
typedef struct _Pointer Pointer;
typedef struct _RelativePointer RelativePointer;
/* Forward declarations from primary_selection.c. */
@ -1444,6 +1445,8 @@ extern void XLSeatGetMouseData (Seat *, Surface **, double *, double *,
double *, double *);
extern void XLSeatLockPointer (Seat *);
extern void XLSeatUnlockPointer (Seat *);
extern RelativePointer *XLSeatGetRelativePointer (Seat *, struct wl_resource *);
extern void XLSeatDestroyRelativePointer (RelativePointer *);
extern Cursor InitDefaultCursor (void);
@ -1611,6 +1614,12 @@ extern void XLPointerConstraintsSurfaceMovedTo (Surface *, int, int);
extern void XLPointerConstraintsSubsurfaceMoved (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. */
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])

View file

@ -905,6 +905,7 @@ HandleResourceDestroy (struct wl_resource *resource)
confinement->surface = NULL;
/* Remove the commit callback. */
if (confinement->commit_callback)
XLSurfaceCancelCommitCallback (confinement->commit_callback);
confinement->commit_callback = NULL;
}
@ -961,6 +962,7 @@ HandleSeatDestroyed (void *data)
confinement->surface = NULL;
/* Cancel the commit callback. */
if (confinement->commit_callback)
XLSurfaceCancelCommitCallback (confinement->commit_callback);
confinement->commit_callback = NULL;
}

155
seat.c
View file

@ -88,6 +88,7 @@ enum
IsDropped = (1 << 4),
IsTextInputSeat = (1 << 5),
IsPointerLocked = (1 << 6),
IsSurfaceCoordSet = (1 << 7),
};
enum
@ -105,6 +106,7 @@ typedef struct _Seat Seat;
typedef struct _SeatClientInfo SeatClientInfo;
typedef struct _Pointer Pointer;
typedef struct _Keyboard Keyboard;
typedef struct _RelativePointer RelativePointer;
typedef struct _SeatCursor SeatCursor;
typedef struct _ResizeDoneCallback ResizeDoneCallback;
typedef struct _ScrollValuator ScrollValuator;
@ -288,7 +290,7 @@ struct _Pointer
struct _Keyboard
{
/* The keyboard this pointer object refers to. */
/* The seat this keyboard object refers to. */
Seat *seat;
/* The struct wl_resource associated with this keyboard. */
@ -302,25 +304,45 @@ struct _Keyboard
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
{
/* Number of references to this seat client information. */
int refcount;
/* The next and last structures in the client info chain. */
SeatClientInfo *next, *last;
/* The client corresponding to this object. */
struct wl_client *client;
/* List of pointer objects on this seat for this client. */
Pointer pointers;
/* Number of references to this seat client information. */
int refcount;
/* The serial of the last enter event sent. */
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. */
Keyboard keyboards;
/* List of relative pointers on this seat for this client. */
RelativePointer relative_pointers;
};
struct _ModifierChangeCallback
@ -653,6 +675,8 @@ CreateSeatClientInfo (Seat *seat, struct wl_client *client)
info->pointers.last = &info->pointers;
info->keyboards.next = &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. */
@ -671,6 +695,7 @@ ReleaseSeatClientInfo (SeatClientInfo *info)
/* Assert that there are no more keyboards or pointers attached. */
XLAssert (info->keyboards.next == &info->keyboards);
XLAssert (info->pointers.next == &info->pointers);
XLAssert (info->relative_pointers.next == &info->relative_pointers);
/* Unlink the client info structure if it is still linked. */
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
SendLeave (Seat *seat, Surface *surface)
{
@ -3333,6 +3392,9 @@ EnteredSurface (Seat *seat, Surface *surface, Time time,
XLSurfaceCancelRunOnFree (seat->last_seen_surface_callback);
seat->last_seen_surface = NULL;
seat->last_seen_surface_callback = NULL;
/* Mark the last surface motion coords as no longer set. */
seat->flags &= ~IsSurfaceCoordSet;
}
if (surface)
@ -3811,6 +3873,16 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
/* Send the motion event. */
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
activate. */
CheckPointerBarrier (seat, dispatch, x, y, xev->root_x,
@ -3820,6 +3892,7 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
/* Set the last movement location. */
seat->last_surface_x = x;
seat->last_surface_y = y;
seat->flags |= IsSurfaceCoordSet;
}
/* 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
WriteKeymap (void)
{
@ -4614,6 +4708,7 @@ XLGetGEWindowForSeats (XEvent *event)
XIFocusInEvent *focusin;
XIEnterEvent *enter;
XIDeviceEvent *xev;
XIBarrierEvent *barrier;
if (event->type == GenericEvent
&& event->xgeneric.extension == xi2_opcode)
@ -4637,6 +4732,10 @@ XLGetGEWindowForSeats (XEvent *event)
case XI_Leave:
enter = event->xcookie.data;
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_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_BarrierHit);
XISelectEvents (compositor.display, window, &mask, 1);
}
@ -4688,6 +4788,8 @@ XLDispatchGEForSeats (XEvent *event, Surface *surface,
else if (event->xgeneric.evtype == XI_KeyPress
|| event->xgeneric.evtype == XI_KeyRelease)
DispatchKey (event->xcookie.data);
else if (event->xgeneric.evtype == XI_BarrierHit)
DispatchBarrierHit (event->xcookie.data);
}
Cursor
@ -5589,3 +5691,44 @@ XLSeatUnlockPointer (Seat *seat)
{
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);
}