[PATCH libXi] Added XIGrabDeviceWithConfine.

Peter Hutterer peter.hutterer at who-t.net
Wed May 18 21:32:16 PDT 2011


On Wed, May 18, 2011 at 06:29:44PM +0200, Philipp Reh wrote:
> The new function is like XIGrabDevice but it takes an
> additional confine_to parameter. This functionality is important
> for programs that need relative mouse movement but also need
> the cursor to stay in their window (like games, for example).
> 
> The confine_to value is put after the variable length
> mask, so the protocol doesn't need a completely new request.
> To make this possible, it is first checked if the server supports
> version 2.1 or greater, in which case it will expect the new
> parameter. Otherwise the new WithConfine is unsupported.
> ---
>  include/X11/extensions/XInput2.h |   13 ++++++++++
>  man/XIGrabDevice.txt             |   18 +++++++++++++
>  src/XExtInt.c                    |    3 +-
>  src/XIGrabDevice.c               |   50 +++++++++++++++++++++++++++++++++----
>  4 files changed, 77 insertions(+), 7 deletions(-)
> 
> diff --git a/include/X11/extensions/XInput2.h b/include/X11/extensions/XInput2.h
> index 3fcf083..1ae818b 100644
> --- a/include/X11/extensions/XInput2.h
> +++ b/include/X11/extensions/XInput2.h
> @@ -402,6 +402,19 @@ extern Status XIGrabDevice(
>       XIEventMask        *mask
>  );
>  
> +extern Status XIGrabDeviceWithConfine(
> +     Display*           dpy,
> +     int                deviceid,
> +     Window             grab_window,
> +     Window             confine_to,
> +     Time               time,
> +     Cursor             cursor,
> +     int                grab_mode,
> +     int                paired_device_mode,
> +     Bool               owner_events,
> +     XIEventMask        *mask
> +);
> +
>  extern Status XIUngrabDevice(
>       Display*           dpy,
>       int                deviceid,
> diff --git a/man/XIGrabDevice.txt b/man/XIGrabDevice.txt
> index bd749b7..c6db809 100644
> --- a/man/XIGrabDevice.txt
> +++ b/man/XIGrabDevice.txt
> @@ -20,6 +20,17 @@ SYNOPSIS
>                          int paired_device_mode,
>                          Bool owner_events,
>                          XIEventMask *mask);
> +
> +    Status XIGrabDeviceWithConfine( Display *display,
> +                                    int deviceid,
> +                                    Window grab_window,
> +                                    Window confine_to,
> +                                    Time time,
> +                                    Cursor cursor,
> +                                    int grab_mode,
> +                                    int paired_device_mode,
> +                                    Bool owner_events,
> +                                    XIEventMask *mask);
>     
>     Status XIUngrabDevice( Display *display,
>                            int deviceid,
> @@ -43,6 +54,10 @@ SYNOPSIS
>     grab_window
>            The grab window.
>  
> +   confine_to
> +          The window to confine this device to if it is a
> +          master pointer. Can be None.
> +
>     mask
>            Event mask.
>  
> @@ -112,6 +127,9 @@ DESCRIPTION
>     XIGrabDevice can generate BadDevice, BadValue, and BadWindow
>     errors.
>  
> +   XIGrabDeviceWithConfine with confine_to set to None has the
> +   same behaviour as XIGrabDevice.
> +
>     The XIUngrabDevice request releases the device and any queued
>     events if this client has it actively grabbed from either
>     XIGrabDevice or XIGrabKey or XIGrabButton. If other devices are
> diff --git a/src/XExtInt.c b/src/XExtInt.c
> index 55144c6..97b0d96 100644
> --- a/src/XExtInt.c
> +++ b/src/XExtInt.c
> @@ -268,7 +268,8 @@ static XExtensionVersion versions[] = { {XI_Absent, 0, 0},
>   XI_Add_DevicePresenceNotify_Minor},
>  {XI_Present, XI_Add_DeviceProperties_Major,
>   XI_Add_DeviceProperties_Minor},
> -{XI_Present, XI_2_Major, XI_2_Minor}
> +{XI_Present, XI_2_Major, XI_2_Minor},
> +{XI_Present, XI_2_1_Major, XI_2_1_Minor}
>  };
>  
>  /***********************************************************************
> diff --git a/src/XIGrabDevice.c b/src/XIGrabDevice.c
> index 94feaee..d943ca6 100644
> --- a/src/XIGrabDevice.c
> +++ b/src/XIGrabDevice.c
> @@ -29,11 +29,11 @@
>  #include <X11/extensions/extutil.h>
>  #include "XIint.h"
>  
> -
> -Status
> -XIGrabDevice(Display* dpy, int deviceid, Window grab_window, Time time,
> -             Cursor cursor, int grab_mode, int paired_device_mode,
> -             Bool owner_events, XIEventMask *mask)
> +static Status
> +_XIGrabDevice(Display* dpy, int deviceid, Window grab_window,
> +              Window confine_to, Time time, Cursor cursor,
> +              int grab_mode, int paired_device_mode,
> +              Bool owner_events, XIEventMask *mask, int version)

I don't think version is actually needed here, you can get around it by
simply appending the confine_to window each time. If it is None, nothing
happens anyway and it doesn't matter which version the server supports. XI
2.0 servers will take longer requests, just ignore data at the end.

If contine_to is not None, then you need to check for XInput_2_1 and can
return BadRequest/NoSuchExtension. But confine_to can only happen with the
new function, so you can put the check there.

see my comments below:

>  {
>      xXIGrabDeviceReq *req;
>      xXIGrabDeviceReply reply;
> @@ -43,7 +43,7 @@ XIGrabDevice(Display* dpy, int deviceid, Window grab_window, Time time,
>      XExtDisplayInfo *extinfo = XInput_find_display(dpy);
>  
>      LockDisplay(dpy);
> -    if (_XiCheckExtInit(dpy, XInput_2_0, extinfo) == -1)
> +    if (_XiCheckExtInit(dpy, version, extinfo) == -1)
>  	return (NoSuchExtension);

this code would remain on the current XInput_2_0 check.

>  
>      GetReq(XIGrabDevice, req);
> @@ -61,10 +61,18 @@ XIGrabDevice(Display* dpy, int deviceid, Window grab_window, Time time,
>  
>      /* mask->mask_len is in bytes, but we need 4-byte units on the wire,
>       * and they need to be padded with 0 */
> +    /* If the version is not XInput_2_0 (which means it is greater)
> +     * we allocate one more word for the confine_to parameter */
>      len = req->mask_len;
> +    if(version != XInput_2_0)
> +       ++len;
>      buff = calloc(1, len * 4);
>      memcpy(buff, mask->mask, mask->mask_len);
>  
> +    /* put the confine_to window at the end */
> +    if(version != XInput_2_0)
> +        memcpy(buff + mask->mask_len, (unsigned char *)&confine_to, 4);
> +

you can skip the version != XInput_2_0 checks here and just append the
confine_to window anyway.

>      SetReqLen(req, len, len);
>      Data(dpy, buff, len * 4);
>      free(buff);
> @@ -79,6 +87,36 @@ XIGrabDevice(Display* dpy, int deviceid, Window grab_window, Time time,
>  }
>  
>  Status
> +XIGrabDevice(Display* dpy, int deviceid, Window grab_window, Time time,
> +             Cursor cursor, int grab_mode, int paired_device_mode,
> +             Bool owner_events, XIEventMask *mask)
> +{
> +    /* The server either expects a 2_0 or a 2_1 request
> +     * depending on which version it has available */
> +    int version = XInput_2_1;
> +    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
> +
> +    LockDisplay(dpy);
> +    if (_XiCheckExtInit(dpy, XInput_2_1, extinfo) == -1)
> +        version = XInput_2_0;

just make this call _XIGrabDevice(...,  None);

> +
> +    return _XIGrabDevice(dpy, deviceid, grab_window, None, time,
> +                         cursor, grab_mode, paired_device_mode,
> +                         owner_events, mask, version);
> +}
> +
> +Status
> +XIGrabDeviceWithConfine(Display* dpy, int deviceid, Window grab_window,
> +                        Window confine_to, Time time, Cursor cursor,
> +                        int grab_mode, int paired_device_mode,
> +                        Bool owner_events, XIEventMask *mask)
> +{

have a check for XInput_2_1 here.

> +    return _XIGrabDevice(dpy, deviceid, grab_window, confine_to, time,
> +                         cursor, grab_mode, paired_device_mode,
> +                         owner_events, mask, XInput_2_1);
> +}
> +
> +Status
>  XIUngrabDevice(Display* dpy, int deviceid, Time time)
>  {
>      xXIUngrabDeviceReq *req;
> -- 
> 1.7.5.rc3
 


More information about the xorg-devel mailing list