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 ();
|
||||
XLInitDrmLease ();
|
||||
XLInitPointerConstraints ();
|
||||
XLInitRelativePointer ();
|
||||
|
||||
/* This has to come after the rest of the initialization. */
|
||||
DetermineServerTime ();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1
README
|
@ -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:
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -905,7 +905,8 @@ HandleResourceDestroy (struct wl_resource *resource)
|
|||
confinement->surface = NULL;
|
||||
|
||||
/* Remove the commit callback. */
|
||||
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
||||
if (confinement->commit_callback)
|
||||
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
||||
confinement->commit_callback = NULL;
|
||||
}
|
||||
|
||||
|
@ -961,7 +962,8 @@ HandleSeatDestroyed (void *data)
|
|||
confinement->surface = NULL;
|
||||
|
||||
/* Cancel the commit callback. */
|
||||
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
||||
if (confinement->commit_callback)
|
||||
XLSurfaceCancelCommitCallback (confinement->commit_callback);
|
||||
confinement->commit_callback = NULL;
|
||||
}
|
||||
|
||||
|
|
155
seat.c
155
seat.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue