forked from 12to11/12to11
Implement support for pointer-gestures-unstable-v1
* 12to11.c (XLMain): Initialize pointer gestures. * 12to11.man (supported): Document that pointer gestures are now supported. * Imakefile (SRCS): Add pointer_gestures.c. (OBJS): Add pointer_gestures.o. (pointer-gestures-unstable-v1): New scanner target. * README (supported): Documentation changes. * compositor.h: Update prototypes. Export xi2_major and xi2_minor from seat.c. * seat.c (struct _SwipeGesture, struct _PinchGesture): New structures. (struct _SeatClientInfo, CreateSeatClientInfo): Initialize those structures in the seat client info. (EnteredSurface): Clear any gestures if the surface changed. (SendGesturePinchBegin, SendGesturePinchUpdate) (SendGesturePinchEnd, DispatchGesturePinch, SendGestureSwipeBegin) (SendGestureSwipeUpdate, SendGestureSwipeEnd, DispatchGestureEnd): New functions. (XLGetGEWindowForSeats, XLSelectStandardEvents) (XLDispatchGEForSeats): Handle and select for various kinds of XI events. (XLInitSeats): Ask for XI 2.4. (XLSeatGetSwipeGesture, XLSeatGetPinchGesture) (XLSeatDestroySwipeGesture, XLSeatDestroyPinchGesture): New functions.
This commit is contained in:
parent
000231fbb2
commit
168ce048be
6 changed files with 569 additions and 4 deletions
1
12to11.c
1
12to11.c
|
@ -244,6 +244,7 @@ XLMain (int argc, char **argv)
|
||||||
XLInitRelativePointer ();
|
XLInitRelativePointer ();
|
||||||
XLInitKeyboardShortcutsInhibit ();
|
XLInitKeyboardShortcutsInhibit ();
|
||||||
XLInitIdleInhibit ();
|
XLInitIdleInhibit ();
|
||||||
|
XLInitPointerGestures ();
|
||||||
|
|
||||||
/* This has to come after the rest of the initialization. */
|
/* This has to come after the rest of the initialization. */
|
||||||
DetermineServerTime ();
|
DetermineServerTime ();
|
||||||
|
|
|
@ -293,6 +293,15 @@ Protocol Version
|
||||||
wp_drm_lease_device_v1 1
|
wp_drm_lease_device_v1 1
|
||||||
.TE
|
.TE
|
||||||
.PP
|
.PP
|
||||||
|
When the X server supports version 2.4 or later of the X Input
|
||||||
|
Extension, the following Wayland protocol is also supported:
|
||||||
|
.TS H
|
||||||
|
lb lb
|
||||||
|
lb n .
|
||||||
|
Protocol Version
|
||||||
|
zwp_pointer_gestures_v1 3
|
||||||
|
.TE
|
||||||
|
.PP
|
||||||
However, Wayland clients are allowed to continue to access data from
|
However, Wayland clients are allowed to continue to access data from
|
||||||
the \fBCLIPBOARD\fP and \fBPRIMARY\fP selections even when they do not
|
the \fBCLIPBOARD\fP and \fBPRIMARY\fP selections even when they do not
|
||||||
have the keyboard focus, against the restrictions put out in the
|
have the keyboard focus, against the restrictions put out in the
|
||||||
|
|
|
@ -25,7 +25,7 @@ SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.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 relative_pointer.c keyboard_shortcuts_inhibit.c \
|
time.c relative_pointer.c keyboard_shortcuts_inhibit.c \
|
||||||
idle_inhibit.c process.c fence_ring.c
|
idle_inhibit.c process.c fence_ring.c pointer_gestures.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 \
|
||||||
|
@ -37,7 +37,7 @@ OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.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 relative_pointer.o keyboard_shortcuts_inhibit.o \
|
time.o relative_pointer.o keyboard_shortcuts_inhibit.o \
|
||||||
idle_inhibit.o process.o fence_ring.o
|
idle_inhibit.o process.o fence_ring.o pointer_gestures.o
|
||||||
|
|
||||||
GENHEADERS = transfer_atoms.h drm_modifiers.h
|
GENHEADERS = transfer_atoms.h drm_modifiers.h
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@ ScannerTarget(pointer-constraints-unstable-v1)
|
||||||
ScannerTarget(relative-pointer-unstable-v1)
|
ScannerTarget(relative-pointer-unstable-v1)
|
||||||
ScannerTarget(keyboard-shortcuts-inhibit-unstable-v1)
|
ScannerTarget(keyboard-shortcuts-inhibit-unstable-v1)
|
||||||
ScannerTarget(idle-inhibit-unstable-v1)
|
ScannerTarget(idle-inhibit-unstable-v1)
|
||||||
|
ScannerTarget(pointer-gestures-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)
|
||||||
|
|
5
README
5
README
|
@ -79,6 +79,11 @@ supported:
|
||||||
|
|
||||||
'wp_drm_lease_device_v1', version: 1
|
'wp_drm_lease_device_v1', version: 1
|
||||||
|
|
||||||
|
When the X server supports version 2.4 or later of the X Input
|
||||||
|
Extension, the following Wayland protocol is also supported:
|
||||||
|
|
||||||
|
'zwp_pointer_gestures_v1', version: 3
|
||||||
|
|
||||||
With the main caveat being that zwp_linux_dmabuf_v1 has no real
|
With the main caveat being that zwp_linux_dmabuf_v1 has no real
|
||||||
support for multiple-provider setups (help wanted).
|
support for multiple-provider setups (help wanted).
|
||||||
|
|
||||||
|
|
12
compositor.h
12
compositor.h
|
@ -94,6 +94,8 @@ struct _Compositor
|
||||||
typedef struct _Seat Seat;
|
typedef struct _Seat Seat;
|
||||||
typedef struct _Pointer Pointer;
|
typedef struct _Pointer Pointer;
|
||||||
typedef struct _RelativePointer RelativePointer;
|
typedef struct _RelativePointer RelativePointer;
|
||||||
|
typedef struct _SwipeGesture SwipeGesture;
|
||||||
|
typedef struct _PinchGesture PinchGesture;
|
||||||
|
|
||||||
/* Forward declarations from primary_selection.c. */
|
/* Forward declarations from primary_selection.c. */
|
||||||
|
|
||||||
|
@ -1522,6 +1524,8 @@ extern void XLInitTextInput (void);
|
||||||
extern int xi2_opcode;
|
extern int xi2_opcode;
|
||||||
extern int xi_first_event;
|
extern int xi_first_event;
|
||||||
extern int xi_first_error;
|
extern int xi_first_error;
|
||||||
|
extern int xi2_major;
|
||||||
|
extern int xi2_minor;
|
||||||
|
|
||||||
extern XLList *live_seats;
|
extern XLList *live_seats;
|
||||||
|
|
||||||
|
@ -1570,6 +1574,10 @@ extern RelativePointer *XLSeatGetRelativePointer (Seat *, struct wl_resource *);
|
||||||
extern void XLSeatDestroyRelativePointer (RelativePointer *);
|
extern void XLSeatDestroyRelativePointer (RelativePointer *);
|
||||||
extern Bool XLSeatApplyExternalGrab (Seat *, Surface *);
|
extern Bool XLSeatApplyExternalGrab (Seat *, Surface *);
|
||||||
extern void XLSeatCancelExternalGrab (Seat *);
|
extern void XLSeatCancelExternalGrab (Seat *);
|
||||||
|
extern SwipeGesture *XLSeatGetSwipeGesture (Seat *, struct wl_resource *);
|
||||||
|
extern PinchGesture *XLSeatGetPinchGesture (Seat *, struct wl_resource *);
|
||||||
|
extern void XLSeatDestroySwipeGesture (SwipeGesture *);
|
||||||
|
extern void XLSeatDestroyPinchGesture (PinchGesture *);
|
||||||
|
|
||||||
extern Cursor InitDefaultCursor (void);
|
extern Cursor InitDefaultCursor (void);
|
||||||
|
|
||||||
|
@ -1783,6 +1791,10 @@ extern void FenceAwait (Fence *);
|
||||||
extern void FenceRelease (Fence *);
|
extern void FenceRelease (Fence *);
|
||||||
extern XSyncFence FenceToXFence (Fence *);
|
extern XSyncFence FenceToXFence (Fence *);
|
||||||
|
|
||||||
|
/* Defined in pointer_gestures.c. */
|
||||||
|
|
||||||
|
extern void XLInitPointerGestures (void);
|
||||||
|
|
||||||
/* 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])
|
||||||
|
|
541
seat.c
541
seat.c
|
@ -41,6 +41,7 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
#include "xdg-shell.h"
|
#include "xdg-shell.h"
|
||||||
|
#include "pointer-gestures-unstable-v1.h"
|
||||||
|
|
||||||
/* X11 event opcode, event base, and error base for the input
|
/* X11 event opcode, event base, and error base for the input
|
||||||
extension. */
|
extension. */
|
||||||
|
@ -49,7 +50,7 @@ int xi2_opcode, xi_first_event, xi_first_error;
|
||||||
|
|
||||||
/* The version of the input extension in use. */
|
/* The version of the input extension in use. */
|
||||||
|
|
||||||
static int xi2_major, xi2_minor;
|
int xi2_major, xi2_minor;
|
||||||
|
|
||||||
/* The current keymap file descriptor. */
|
/* The current keymap file descriptor. */
|
||||||
|
|
||||||
|
@ -91,6 +92,8 @@ enum
|
||||||
IsPointerLocked = (1 << 6),
|
IsPointerLocked = (1 << 6),
|
||||||
IsSurfaceCoordSet = (1 << 7),
|
IsSurfaceCoordSet = (1 << 7),
|
||||||
IsExternalGrabApplied = (1 << 8),
|
IsExternalGrabApplied = (1 << 8),
|
||||||
|
IsInPinchGesture = (1 << 9),
|
||||||
|
IsInSwipeGesture = (1 << 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -323,6 +326,39 @@ struct _RelativePointer
|
||||||
RelativePointer *next, *last;
|
RelativePointer *next, *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _SwipeGesture
|
||||||
|
{
|
||||||
|
/* The seat this swipe gesture refers to. */
|
||||||
|
Seat *seat;
|
||||||
|
|
||||||
|
/* The struct wl_resource associated with this swipe gesture. */
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
/* The seat client info associated with this swipe gesture
|
||||||
|
resource. */
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
/* The next and last swipe gestures attached to the seat client
|
||||||
|
info. */
|
||||||
|
SwipeGesture *next, *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PinchGesture
|
||||||
|
{
|
||||||
|
/* The seat this pinch gesture refers to. */
|
||||||
|
Seat *seat;
|
||||||
|
|
||||||
|
/* The struct wl_resource associated with this pinch gesture. */
|
||||||
|
struct wl_resource *resource;
|
||||||
|
|
||||||
|
/* The seat client info associated with this pinch gesture. */
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
/* The next and last pinch gestures attached to the seat client
|
||||||
|
info. */
|
||||||
|
PinchGesture *next, *last;
|
||||||
|
};
|
||||||
|
|
||||||
struct _SeatClientInfo
|
struct _SeatClientInfo
|
||||||
{
|
{
|
||||||
/* The next and last structures in the client info chain. */
|
/* The next and last structures in the client info chain. */
|
||||||
|
@ -345,6 +381,12 @@ struct _SeatClientInfo
|
||||||
|
|
||||||
/* List of relative pointers on this seat for this client. */
|
/* List of relative pointers on this seat for this client. */
|
||||||
RelativePointer relative_pointers;
|
RelativePointer relative_pointers;
|
||||||
|
|
||||||
|
/* List of swipe gestures on this seat for this client. */
|
||||||
|
SwipeGesture swipe_gestures;
|
||||||
|
|
||||||
|
/* List of pinch gestures on this seat for this client. */
|
||||||
|
PinchGesture pinch_gestures;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ModifierChangeCallback
|
struct _ModifierChangeCallback
|
||||||
|
@ -685,6 +727,10 @@ CreateSeatClientInfo (Seat *seat, struct wl_client *client)
|
||||||
info->keyboards.last = &info->keyboards;
|
info->keyboards.last = &info->keyboards;
|
||||||
info->relative_pointers.next = &info->relative_pointers;
|
info->relative_pointers.next = &info->relative_pointers;
|
||||||
info->relative_pointers.last = &info->relative_pointers;
|
info->relative_pointers.last = &info->relative_pointers;
|
||||||
|
info->swipe_gestures.next = &info->swipe_gestures;
|
||||||
|
info->swipe_gestures.last = &info->swipe_gestures;
|
||||||
|
info->pinch_gestures.next = &info->pinch_gestures;
|
||||||
|
info->pinch_gestures.last = &info->pinch_gestures;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increase the reference count of info. */
|
/* Increase the reference count of info. */
|
||||||
|
@ -3357,10 +3403,17 @@ UndefineCursorOn (Seat *seat, Surface *surface)
|
||||||
XUndefineCursor (compositor.display, window);
|
XUndefineCursor (compositor.display, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Forward declaration. */
|
||||||
|
|
||||||
|
static void SendGesturePinchEnd (Seat *, Surface *, Time, int);
|
||||||
|
static void SendGestureSwipeEnd (Seat *, Surface *, Time, int);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
EnteredSurface (Seat *seat, Surface *surface, Time time,
|
EnteredSurface (Seat *seat, Surface *surface, Time time,
|
||||||
double x, double y, Bool preserve_cursor)
|
double x, double y, Bool preserve_cursor)
|
||||||
{
|
{
|
||||||
|
Time gesture_time;
|
||||||
|
|
||||||
if (seat->grab_held && surface != seat->last_seen_surface)
|
if (seat->grab_held && surface != seat->last_seen_surface)
|
||||||
{
|
{
|
||||||
/* If the seat is grabbed, delay this for later. */
|
/* If the seat is grabbed, delay this for later. */
|
||||||
|
@ -3371,6 +3424,41 @@ EnteredSurface (Seat *seat, Surface *surface, Time time,
|
||||||
if (seat->last_seen_surface == surface)
|
if (seat->last_seen_surface == surface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* The surface currently entered changed (or will change). Cancel
|
||||||
|
any ongoing gestures. */
|
||||||
|
|
||||||
|
if (seat->flags & IsInPinchGesture
|
||||||
|
/* Not sure if this can actually be NULL here. */
|
||||||
|
&& seat->last_seen_surface)
|
||||||
|
{
|
||||||
|
/* If time is 0 (CurrentTime), then just use the last user
|
||||||
|
time. */
|
||||||
|
gesture_time = time ? time : seat->last_user_time.milliseconds;
|
||||||
|
|
||||||
|
/* Send the gesture end event. */
|
||||||
|
SendGesturePinchEnd (seat, seat->last_seen_surface,
|
||||||
|
gesture_time, 1);
|
||||||
|
|
||||||
|
/* And clear the flag so further updates are not sent. */
|
||||||
|
seat->flags &= ~IsInPinchGesture;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seat->flags & IsInSwipeGesture
|
||||||
|
/* Not sure if this can actually be NULL here. */
|
||||||
|
&& seat->last_seen_surface)
|
||||||
|
{
|
||||||
|
/* If time is 0 (CurrentTime), then just use the last user
|
||||||
|
time. */
|
||||||
|
gesture_time = time ? time : seat->last_user_time.milliseconds;
|
||||||
|
|
||||||
|
/* Send the gesture end event. */
|
||||||
|
SendGestureSwipeEnd (seat, seat->last_seen_surface,
|
||||||
|
gesture_time, 1);
|
||||||
|
|
||||||
|
/* And clear the flag so further updates are not sent. */
|
||||||
|
seat->flags &= ~IsInSwipeGesture;
|
||||||
|
}
|
||||||
|
|
||||||
if (seat->last_seen_surface)
|
if (seat->last_seen_surface)
|
||||||
{
|
{
|
||||||
if (seat->flags & IsDragging)
|
if (seat->flags & IsDragging)
|
||||||
|
@ -4296,6 +4384,343 @@ DispatchBarrierHit (XIBarrierEvent *barrier)
|
||||||
seat->last_user_time = TimestampFromServerTime (barrier->time);
|
seat->last_user_time = TimestampFromServerTime (barrier->time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendGesturePinchBegin (Seat *seat, Surface *dispatch, Time time,
|
||||||
|
int detail)
|
||||||
|
{
|
||||||
|
PinchGesture *gesture;
|
||||||
|
uint32_t serial;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
info = ClientInfoForResource (seat, dispatch->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gesture = info->pinch_gestures.next;
|
||||||
|
|
||||||
|
for (; gesture != &info->pinch_gestures; gesture = gesture->next)
|
||||||
|
zwp_pointer_gesture_pinch_v1_send_begin (gesture->resource,
|
||||||
|
serial, time,
|
||||||
|
dispatch->resource,
|
||||||
|
detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendGesturePinchUpdate (Seat *seat, Surface *dispatch, Time time,
|
||||||
|
double dx, double dy, double scale, double rotation)
|
||||||
|
{
|
||||||
|
PinchGesture *gesture;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
info = ClientInfoForResource (seat, dispatch->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gesture = info->pinch_gestures.next;
|
||||||
|
|
||||||
|
for (; gesture != &info->pinch_gestures; gesture = gesture->next)
|
||||||
|
zwp_pointer_gesture_pinch_v1_send_update (gesture->resource,
|
||||||
|
time,
|
||||||
|
wl_fixed_from_double (dx),
|
||||||
|
wl_fixed_from_double (dy),
|
||||||
|
wl_fixed_from_double (scale),
|
||||||
|
wl_fixed_from_double (rotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendGesturePinchEnd (Seat *seat, Surface *dispatch, Time time, int cancelled)
|
||||||
|
{
|
||||||
|
PinchGesture *gesture;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
|
info = ClientInfoForResource (seat, dispatch->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gesture = info->pinch_gestures.next;
|
||||||
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
|
||||||
|
for (; gesture != &info->pinch_gestures; gesture = gesture->next)
|
||||||
|
zwp_pointer_gesture_pinch_v1_send_end (gesture->resource,
|
||||||
|
serial, time, cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DispatchGesturePinch (Subcompositor *subcompositor, XIGesturePinchEvent *pinch)
|
||||||
|
{
|
||||||
|
Seat *seat;
|
||||||
|
Surface *dispatch, *actual_dispatch;
|
||||||
|
double x, y, event_x, event_y;
|
||||||
|
|
||||||
|
seat = XLLookUpAssoc (seats, pinch->deviceid);
|
||||||
|
|
||||||
|
if (!seat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Move the icon surface. */
|
||||||
|
if (seat->icon_surface)
|
||||||
|
XLMoveIconSurface (seat->icon_surface, pinch->root_x,
|
||||||
|
pinch->root_y);
|
||||||
|
|
||||||
|
/* Update information used for resize tracking. */
|
||||||
|
seat->its_root_x = pinch->root_x;
|
||||||
|
seat->its_root_y = pinch->root_y;
|
||||||
|
seat->its_press_time = pinch->time;
|
||||||
|
|
||||||
|
/* Update the last user time. */
|
||||||
|
seat->last_user_time = TimestampFromServerTime (pinch->time);
|
||||||
|
|
||||||
|
/* Now find the dispatch surface so we can enter it if required.
|
||||||
|
Most of this code is copied from DispatchMotion; it should
|
||||||
|
probably be moved to a separate function. */
|
||||||
|
actual_dispatch = FindSurfaceUnder (subcompositor, pinch->event_x,
|
||||||
|
pinch->event_y);
|
||||||
|
|
||||||
|
if (seat->grab_held)
|
||||||
|
{
|
||||||
|
/* If the grab is held, make the surface underneath the pointer
|
||||||
|
the pending unlock surface. */
|
||||||
|
SwapUnlockSurface (seat, actual_dispatch);
|
||||||
|
dispatch = seat->last_seen_surface;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dispatch = actual_dispatch;
|
||||||
|
|
||||||
|
event_x = pinch->event_y;
|
||||||
|
event_y = pinch->event_y;
|
||||||
|
|
||||||
|
if (!dispatch)
|
||||||
|
{
|
||||||
|
if (seat->grab_surface)
|
||||||
|
{
|
||||||
|
/* If the grab surface is set, translate the coordinates to
|
||||||
|
it and use it instead. */
|
||||||
|
TranslateGrabPosition (seat, pinch->event,
|
||||||
|
&event_x, &event_y);
|
||||||
|
dispatch = seat->grab_surface;
|
||||||
|
|
||||||
|
goto after_dispatch_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnteredSurface (seat, dispatch, pinch->time, 0, 0, False);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
after_dispatch_set:
|
||||||
|
TransformToSurface (dispatch, event_x, event_y, &x, &y);
|
||||||
|
EnteredSurface (seat, dispatch, pinch->time, x, y, False);
|
||||||
|
|
||||||
|
/* Now do the actual event dispatch. */
|
||||||
|
switch (pinch->evtype)
|
||||||
|
{
|
||||||
|
case XI_GesturePinchBegin:
|
||||||
|
/* Send a motion event, in case the position changed. */
|
||||||
|
SendMotion (seat, dispatch, x, y, pinch->time);
|
||||||
|
|
||||||
|
/* Send a begin event. */
|
||||||
|
SendGesturePinchBegin (seat, dispatch, pinch->time, pinch->detail);
|
||||||
|
|
||||||
|
/* Say that the seat is in the middle of a pinch gesture, so it
|
||||||
|
can be cancelled should the pointer move out of this
|
||||||
|
surface. */
|
||||||
|
seat->flags |= IsInPinchGesture;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XI_GesturePinchUpdate:
|
||||||
|
/* The gesture sequence was cancelled for some other reason. */
|
||||||
|
if (!(seat->flags & IsInPinchGesture))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Send an update event. */
|
||||||
|
SendGesturePinchUpdate (seat, dispatch, pinch->time,
|
||||||
|
pinch->delta_x, pinch->delta_y,
|
||||||
|
pinch->scale, pinch->delta_angle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XI_GesturePinchEnd:
|
||||||
|
/* The gesture sequence was cancelled for some other reason. */
|
||||||
|
if (!(seat->flags & IsInPinchGesture))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Send an end event. */
|
||||||
|
SendGesturePinchEnd (seat, dispatch, pinch->time,
|
||||||
|
pinch->flags & XIGesturePinchEventCancelled);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendGestureSwipeBegin (Seat *seat, Surface *dispatch, Time time,
|
||||||
|
int detail)
|
||||||
|
{
|
||||||
|
SwipeGesture *gesture;
|
||||||
|
uint32_t serial;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
info = ClientInfoForResource (seat, dispatch->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gesture = info->swipe_gestures.next;
|
||||||
|
|
||||||
|
for (; gesture != &info->swipe_gestures; gesture = gesture->next)
|
||||||
|
zwp_pointer_gesture_swipe_v1_send_begin (gesture->resource,
|
||||||
|
serial, time,
|
||||||
|
dispatch->resource,
|
||||||
|
detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendGestureSwipeUpdate (Seat *seat, Surface *dispatch, Time time,
|
||||||
|
double dx, double dy)
|
||||||
|
{
|
||||||
|
SwipeGesture *gesture;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
info = ClientInfoForResource (seat, dispatch->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gesture = info->swipe_gestures.next;
|
||||||
|
|
||||||
|
for (; gesture != &info->swipe_gestures; gesture = gesture->next)
|
||||||
|
zwp_pointer_gesture_swipe_v1_send_update (gesture->resource,
|
||||||
|
time,
|
||||||
|
wl_fixed_from_double (dx),
|
||||||
|
wl_fixed_from_double (dy));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SendGestureSwipeEnd (Seat *seat, Surface *dispatch, Time time, int cancelled)
|
||||||
|
{
|
||||||
|
SwipeGesture *gesture;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
uint32_t serial;
|
||||||
|
|
||||||
|
info = ClientInfoForResource (seat, dispatch->resource);
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gesture = info->swipe_gestures.next;
|
||||||
|
serial = wl_display_next_serial (compositor.wl_display);
|
||||||
|
|
||||||
|
for (; gesture != &info->swipe_gestures; gesture = gesture->next)
|
||||||
|
zwp_pointer_gesture_swipe_v1_send_end (gesture->resource,
|
||||||
|
serial, time, cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DispatchGestureSwipe (Subcompositor *subcompositor, XIGestureSwipeEvent *swipe)
|
||||||
|
{
|
||||||
|
Seat *seat;
|
||||||
|
Surface *dispatch, *actual_dispatch;
|
||||||
|
double x, y, event_x, event_y;
|
||||||
|
|
||||||
|
seat = XLLookUpAssoc (seats, swipe->deviceid);
|
||||||
|
|
||||||
|
if (!seat)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Move the icon surface. */
|
||||||
|
if (seat->icon_surface)
|
||||||
|
XLMoveIconSurface (seat->icon_surface, swipe->root_x,
|
||||||
|
swipe->root_y);
|
||||||
|
|
||||||
|
/* Update information used for resize tracking. */
|
||||||
|
seat->its_root_x = swipe->root_x;
|
||||||
|
seat->its_root_y = swipe->root_y;
|
||||||
|
seat->its_press_time = swipe->time;
|
||||||
|
|
||||||
|
/* Update the last user time. */
|
||||||
|
seat->last_user_time = TimestampFromServerTime (swipe->time);
|
||||||
|
|
||||||
|
/* Now find the dispatch surface so we can enter it if required.
|
||||||
|
Most of this code is copied from DispatchMotion; it should
|
||||||
|
probably be moved to a separate function. */
|
||||||
|
actual_dispatch = FindSurfaceUnder (subcompositor, swipe->event_x,
|
||||||
|
swipe->event_y);
|
||||||
|
|
||||||
|
if (seat->grab_held)
|
||||||
|
{
|
||||||
|
/* If the grab is held, make the surface underneath the pointer
|
||||||
|
the pending unlock surface. */
|
||||||
|
SwapUnlockSurface (seat, actual_dispatch);
|
||||||
|
dispatch = seat->last_seen_surface;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dispatch = actual_dispatch;
|
||||||
|
|
||||||
|
event_x = swipe->event_y;
|
||||||
|
event_y = swipe->event_y;
|
||||||
|
|
||||||
|
if (!dispatch)
|
||||||
|
{
|
||||||
|
if (seat->grab_surface)
|
||||||
|
{
|
||||||
|
/* If the grab surface is set, translate the coordinates to
|
||||||
|
it and use it instead. */
|
||||||
|
TranslateGrabPosition (seat, swipe->event,
|
||||||
|
&event_x, &event_y);
|
||||||
|
dispatch = seat->grab_surface;
|
||||||
|
|
||||||
|
goto after_dispatch_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnteredSurface (seat, dispatch, swipe->time, 0, 0, False);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
after_dispatch_set:
|
||||||
|
TransformToSurface (dispatch, event_x, event_y, &x, &y);
|
||||||
|
EnteredSurface (seat, dispatch, swipe->time, x, y, False);
|
||||||
|
|
||||||
|
/* Now do the actual event dispatch. */
|
||||||
|
switch (swipe->evtype)
|
||||||
|
{
|
||||||
|
case XI_GestureSwipeBegin:
|
||||||
|
/* Send a motion event, in case the position changed. */
|
||||||
|
SendMotion (seat, dispatch, x, y, swipe->time);
|
||||||
|
|
||||||
|
/* Send a begin event. */
|
||||||
|
SendGestureSwipeBegin (seat, dispatch, swipe->time, swipe->detail);
|
||||||
|
|
||||||
|
/* Say that the seat is in the middle of a swipe gesture, so it
|
||||||
|
can be cancelled should the pointer move out of this
|
||||||
|
surface. */
|
||||||
|
seat->flags |= IsInSwipeGesture;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XI_GestureSwipeUpdate:
|
||||||
|
/* The gesture sequence was cancelled for some other reason. */
|
||||||
|
if (!(seat->flags & IsInSwipeGesture))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Send an update event. */
|
||||||
|
SendGestureSwipeUpdate (seat, dispatch, swipe->time,
|
||||||
|
swipe->delta_x, swipe->delta_y);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XI_GestureSwipeEnd:
|
||||||
|
/* The gesture sequence was cancelled for some other reason. */
|
||||||
|
if (!(seat->flags & IsInSwipeGesture))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Send an end event. */
|
||||||
|
SendGestureSwipeEnd (seat, dispatch, swipe->time,
|
||||||
|
swipe->flags & XIGestureSwipeEventCancelled);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
WriteKeymap (void)
|
WriteKeymap (void)
|
||||||
{
|
{
|
||||||
|
@ -4773,6 +5198,8 @@ XLGetGEWindowForSeats (XEvent *event)
|
||||||
XIEnterEvent *enter;
|
XIEnterEvent *enter;
|
||||||
XIDeviceEvent *xev;
|
XIDeviceEvent *xev;
|
||||||
XIBarrierEvent *barrier;
|
XIBarrierEvent *barrier;
|
||||||
|
XIGesturePinchEvent *pinch;
|
||||||
|
XIGestureSwipeEvent *swipe;
|
||||||
|
|
||||||
if (event->type == GenericEvent
|
if (event->type == GenericEvent
|
||||||
&& event->xgeneric.extension == xi2_opcode)
|
&& event->xgeneric.extension == xi2_opcode)
|
||||||
|
@ -4800,6 +5227,18 @@ XLGetGEWindowForSeats (XEvent *event)
|
||||||
case XI_BarrierHit:
|
case XI_BarrierHit:
|
||||||
barrier = event->xcookie.data;
|
barrier = event->xcookie.data;
|
||||||
return barrier->event;
|
return barrier->event;
|
||||||
|
|
||||||
|
case XI_GesturePinchBegin:
|
||||||
|
case XI_GesturePinchEnd:
|
||||||
|
case XI_GesturePinchUpdate:
|
||||||
|
pinch = event->xcookie.data;
|
||||||
|
return pinch->event;
|
||||||
|
|
||||||
|
case XI_GestureSwipeBegin:
|
||||||
|
case XI_GestureSwipeEnd:
|
||||||
|
case XI_GestureSwipeUpdate:
|
||||||
|
swipe = event->xcookie.data;
|
||||||
|
return swipe->event;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4830,6 +5269,18 @@ XLSelectStandardEvents (Window window)
|
||||||
XISetMask (mask.mask, XI_KeyRelease);
|
XISetMask (mask.mask, XI_KeyRelease);
|
||||||
XISetMask (mask.mask, XI_BarrierHit);
|
XISetMask (mask.mask, XI_BarrierHit);
|
||||||
|
|
||||||
|
if (xi2_major > 2 || xi2_minor >= 4)
|
||||||
|
{
|
||||||
|
/* Select for gesture events whenever supported. */
|
||||||
|
|
||||||
|
XISetMask (mask.mask, XI_GesturePinchBegin);
|
||||||
|
XISetMask (mask.mask, XI_GesturePinchUpdate);
|
||||||
|
XISetMask (mask.mask, XI_GesturePinchEnd);
|
||||||
|
XISetMask (mask.mask, XI_GestureSwipeBegin);
|
||||||
|
XISetMask (mask.mask, XI_GestureSwipeUpdate);
|
||||||
|
XISetMask (mask.mask, XI_GestureSwipeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
XISelectEvents (compositor.display, window, &mask, 1);
|
XISelectEvents (compositor.display, window, &mask, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4854,6 +5305,14 @@ XLDispatchGEForSeats (XEvent *event, Surface *surface,
|
||||||
DispatchKey (event->xcookie.data);
|
DispatchKey (event->xcookie.data);
|
||||||
else if (event->xgeneric.evtype == XI_BarrierHit)
|
else if (event->xgeneric.evtype == XI_BarrierHit)
|
||||||
DispatchBarrierHit (event->xcookie.data);
|
DispatchBarrierHit (event->xcookie.data);
|
||||||
|
else if (event->xgeneric.evtype == XI_GesturePinchBegin
|
||||||
|
|| event->xgeneric.evtype == XI_GesturePinchUpdate
|
||||||
|
|| event->xgeneric.evtype == XI_GesturePinchEnd)
|
||||||
|
DispatchGesturePinch (subcompositor, event->xcookie.data);
|
||||||
|
else if (event->xgeneric.evtype == XI_GestureSwipeBegin
|
||||||
|
|| event->xgeneric.evtype == XI_GestureSwipeUpdate
|
||||||
|
|| event->xgeneric.evtype == XI_GestureSwipeEnd)
|
||||||
|
DispatchGestureSwipe (subcompositor, event->xcookie.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cursor
|
Cursor
|
||||||
|
@ -5555,7 +6014,7 @@ XLInitSeats (void)
|
||||||
|
|
||||||
/* This is the version of the input extension that we want. */
|
/* This is the version of the input extension that we want. */
|
||||||
xi2_major = 2;
|
xi2_major = 2;
|
||||||
xi2_minor = 3;
|
xi2_minor = 4;
|
||||||
|
|
||||||
if (XQueryExtension (compositor.display, "XInputExtension",
|
if (XQueryExtension (compositor.display, "XInputExtension",
|
||||||
&xi2_opcode, &xi_first_event, &xi_first_error))
|
&xi2_opcode, &xi_first_event, &xi_first_error))
|
||||||
|
@ -5804,6 +6263,84 @@ XLSeatDestroyRelativePointer (RelativePointer *relative_pointer)
|
||||||
XLFree (relative_pointer);
|
XLFree (relative_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwipeGesture *
|
||||||
|
XLSeatGetSwipeGesture (Seat *seat, struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
SwipeGesture *swipe_gesture;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
/* Create a swipe gesture object for the resource RESOURCE. */
|
||||||
|
swipe_gesture = XLCalloc (1, sizeof *swipe_gesture);
|
||||||
|
|
||||||
|
/* Obtain or create the seat client info. */
|
||||||
|
info = CreateSeatClientInfo (seat, wl_resource_get_client (resource));
|
||||||
|
|
||||||
|
/* Link the gesture onto it. */
|
||||||
|
swipe_gesture->next = info->swipe_gestures.next;
|
||||||
|
swipe_gesture->last = &info->swipe_gestures;
|
||||||
|
info->swipe_gestures.next->last = swipe_gesture;
|
||||||
|
info->swipe_gestures.next = swipe_gesture;
|
||||||
|
swipe_gesture->info = info;
|
||||||
|
|
||||||
|
/* Set the seat and resource. */
|
||||||
|
swipe_gesture->seat = seat;
|
||||||
|
swipe_gesture->resource = resource;
|
||||||
|
RetainSeat (seat);
|
||||||
|
|
||||||
|
return swipe_gesture;
|
||||||
|
}
|
||||||
|
|
||||||
|
PinchGesture *
|
||||||
|
XLSeatGetPinchGesture (Seat *seat, struct wl_resource *resource)
|
||||||
|
{
|
||||||
|
PinchGesture *pinch_gesture;
|
||||||
|
SeatClientInfo *info;
|
||||||
|
|
||||||
|
/* Create a pinch gesture object for the resource RESOURCE. */
|
||||||
|
pinch_gesture = XLCalloc (1, sizeof *pinch_gesture);
|
||||||
|
|
||||||
|
/* Obtain or create the seat client info. */
|
||||||
|
info = CreateSeatClientInfo (seat, wl_resource_get_client (resource));
|
||||||
|
|
||||||
|
/* Link the gesture onto it. */
|
||||||
|
pinch_gesture->next = info->pinch_gestures.next;
|
||||||
|
pinch_gesture->last = &info->pinch_gestures;
|
||||||
|
info->pinch_gestures.next->last = pinch_gesture;
|
||||||
|
info->pinch_gestures.next = pinch_gesture;
|
||||||
|
pinch_gesture->info = info;
|
||||||
|
|
||||||
|
/* Set the seat and resource. */
|
||||||
|
pinch_gesture->seat = seat;
|
||||||
|
pinch_gesture->resource = resource;
|
||||||
|
RetainSeat (seat);
|
||||||
|
|
||||||
|
return pinch_gesture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSeatDestroySwipeGesture (SwipeGesture *swipe_gesture)
|
||||||
|
{
|
||||||
|
swipe_gesture->last->next = swipe_gesture->next;
|
||||||
|
swipe_gesture->next->last = swipe_gesture->last;
|
||||||
|
|
||||||
|
ReleaseSeatClientInfo (swipe_gesture->info);
|
||||||
|
ReleaseSeat (swipe_gesture->seat);
|
||||||
|
|
||||||
|
XLFree (swipe_gesture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XLSeatDestroyPinchGesture (PinchGesture *pinch_gesture)
|
||||||
|
{
|
||||||
|
pinch_gesture->last->next = pinch_gesture->next;
|
||||||
|
pinch_gesture->next->last = pinch_gesture->last;
|
||||||
|
|
||||||
|
ReleaseSeatClientInfo (pinch_gesture->info);
|
||||||
|
ReleaseSeat (pinch_gesture->seat);
|
||||||
|
|
||||||
|
XLFree (pinch_gesture);
|
||||||
|
}
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
XLSeatApplyExternalGrab (Seat *seat, Surface *surface)
|
XLSeatApplyExternalGrab (Seat *seat, Surface *surface)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue