On Thu, Jun 23, 2011 at 11:48:22AM -0700, Jason Gerecke wrote:
> On Wed, Jun 22, 2011 at 6:27 PM, Peter Hutterer
> <peter.hutte...@who-t.net> wrote:
> > The NVIDIA binary driver doesn't support RandR 1.2 but it does support
> > Xinerama. Test for RandR and then fall back to Xinerama if we need to.
> >
> > User commands:
> >    xsetwacom set "device name" MapToOutput HEAD-0
> >    xsetwacom set "device name" MapToOutput HEAD-1
> >
> > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
> > ---
> > Changes to v1:
> > - rename set_output_twinview to set_output_xinerama
> > - test for RandR first, fall back to Xinerama if it fails. Only test for
> >  NVidia for tracing/debugging purposes
> > - use convert_value_from_user for arg parsing
> >
> >  configure.ac      |    2 +-
> >  man/xsetwacom.man |    3 +-
> >  tools/xsetwacom.c |   91 
> > ++++++++++++++++++++++++++++++++++++++++++----------
> >  3 files changed, 76 insertions(+), 20 deletions(-)
> >
> > diff --git a/configure.ac b/configure.ac
> > index 408e75f..c151e54 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -53,7 +53,7 @@ AC_CHECK_LIB([m], [rint])
> >  PKG_CHECK_MODULES(XORG, [xorg-server >= 1.7.0] xproto xext kbproto 
> > inputproto randrproto)
> >
> >  # Obtain compiler/linker options for the xsetwacom tool
> > -PKG_CHECK_MODULES(X11, x11 xi xrandr)
> > +PKG_CHECK_MODULES(X11, x11 xi xrandr xinerama)
> >
> >  # Obtain compiler/linker options for libudev used by ISDV4 code
> >  PKG_CHECK_MODULES(UDEV, libudev)
> > diff --git a/man/xsetwacom.man b/man/xsetwacom.man
> > index 3a5fa40..564e1d0 100644
> > --- a/man/xsetwacom.man
> > +++ b/man/xsetwacom.man
> > @@ -126,7 +126,8 @@ outputs may be obtained with the xrandr tool. The 
> > output mapping
> >  configuration is a onetime setting and does not track output
> >  reconfigurations; the command needs to be re-run whenever the output
> >  configuration changes. When used with tablet rotation, the tablet must be
> > -rotated before it is mapped to the new screen.
> > +rotated before it is mapped to the new screen. When running the NVIDIA
> > +binary driver, the output names are "HEAD-0" and "HEAD-1".
> >  This parameter is write-only and cannot be queried.
> >  .TP
> >  \fBMode\fR Absolute|Relative
> > diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c
> > index c0cf707..9f75e83 100644
> > --- a/tools/xsetwacom.c
> > +++ b/tools/xsetwacom.c
> > @@ -37,6 +37,7 @@
> >  #include <X11/Xatom.h>
> >  #include <X11/extensions/XInput.h>
> >  #include <X11/extensions/Xrandr.h>
> > +#include <X11/extensions/Xinerama.h>
> >  #include <X11/XKBlib.h>
> >
> >  #define TRACE(...) \
> > @@ -57,6 +58,7 @@ enum prop_flags {
> >        PROP_FLAG_READONLY = 2,
> >        PROP_FLAG_WRITEONLY = 4,
> >        PROP_FLAG_INVERTED = 8, /* only valid with PROP_FLAG_BOOLEAN */
> > +       PROP_FLAG_OUTPUT = 16,
> >  };
> >
> >
> > @@ -416,7 +418,7 @@ static param_t parameters[] =
> >                .desc = "Map the device to the given output. ",
> >                .set_func = set_output,
> >                .arg_count = 1,
> > -               .prop_flags = PROP_FLAG_WRITEONLY
> > +               .prop_flags = PROP_FLAG_WRITEONLY | PROP_FLAG_OUTPUT,
> >        },
> >        {
> >                .name = "all",
> > @@ -1483,7 +1485,16 @@ static Bool convert_value_from_user(const param_t 
> > *param, const char *value, int
> >                if (param->prop_flags & PROP_FLAG_INVERTED)
> >                        *return_value = !(*return_value);
> >        }
> > -       else
> > +       else if (param->prop_flags & PROP_FLAG_OUTPUT)
> > +       {
> > +               const char *prefix = "HEAD-";
> > +               /* We currently support HEAD-X, where X is 0-9 */
> > +               if (strlen(value) != strlen(prefix) + 1 ||
> > +                   strncasecmp(value, prefix, strlen(prefix)) != 0)
> > +                       return False;
> > +
> > +               *return_value = value[strlen(prefix)] - '0';
> > +       } else
> >        {
> >                char *end;
> >                long conversion = strtol(value, &end, 10);
> > @@ -2000,7 +2011,6 @@ static void _set_matrix(Display *dpy, XDevice *dev,
> >
> >  static void set_output_xrandr(Display *dpy, XDevice *dev, param_t *param, 
> > int argc, char **argv)
> >  {
> > -       int min, maj;
> >        int i, found = 0;
> >        char *output_name;
> >        XRRScreenResources *res;
> > @@ -2009,20 +2019,6 @@ static void set_output_xrandr(Display *dpy, XDevice 
> > *dev, param_t *param, int ar
> >
> >        output_name = argv[0];
> >
> > -       if (!XRRQueryExtension(dpy, &maj, &min)) /* using min/maj as dummy 
> > */
> > -       {
> > -               fprintf(stderr, "Server does not support RandR");
> > -               return;
> > -       }
> > -
> > -       if (!XRRQueryVersion(dpy, &maj, &min) ||
> > -           (maj * 1000 + min) < 1002)
> > -       {
> > -               fprintf(stderr, "Server does not support RandR 1.2");
> > -               return;
> > -       }
> > -
> > -
> >        res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
> >
> >        for (i = 0; i < res->noutput && !found; i++)
> > @@ -2058,8 +2054,58 @@ static void set_output_xrandr(Display *dpy, XDevice 
> > *dev, param_t *param, int ar
> >        XRRFreeScreenResources(res);
> >  }
> >
> > +/**
> > + * Adjust the transformation matrix based on the Xinerama settings. For
> > + * TwinView This would better be done with libXNVCtrl but until they learn
> > + * to package it properly, rely on Xinerama. Besides, libXNVCtrl isn't
> > + * available on RHEL, so we'd have to do it through Xinerama there anyway.
> > + */
> > +static void set_output_xinerama(Display *dpy, XDevice *dev, param_t 
> > *param, int argc, char **argv)
> > +{
> > +       int event, error;
> > +       XineramaScreenInfo *screens;
> > +       int nscreens;
> > +       int head;
> > +
> > +       if (!XineramaQueryExtension(dpy, &event, &error))
> > +       {
> > +               fprintf(stderr, "Unable to set screen mapping. Xinerama 
> > extension not found\n");
> > +               return;
> > +       }
> > +
> > +       if (!convert_value_from_user(param, argv[0], &head))
> > +       {
> > +               fprintf(stderr, "Please specify the output name as HEAD-X,"
> > +                               "where X is the screen number\n");
> > +               return;
> > +       }
> > +
> > +       screens = XineramaQueryScreens(dpy, &nscreens);
> > +
> > +       if (nscreens == 0)
> > +       {
> > +               fprintf(stderr, "Xinerama failed to query screens.\n");
> > +               goto out;
> > +       } else if (nscreens <= head)
> > +       {
> > +               fprintf(stderr, "Found %d screens, but you requested %s.\n",
> > +                               nscreens, argv[0]);
> > +               goto out;
> > +       }
> > +
> > +       _set_matrix(dpy, dev,
> > +                   screens[head].x_org, screens[head].y_org,
> > +                   screens[head].width, screens[head].height);
> > +
> > +out:
> > +       XFree(screens);
> > +}
> > +
> >  static void set_output(Display *dpy, XDevice *dev, param_t *param, int 
> > argc, char **argv)
> >  {
> > +       int opcode, event, error;
> > +       int maj, min;
> > +
> >        if (argc != param->arg_count)
> >        {
> >                fprintf(stderr, "'%s' requires exactly %d value(s).\n", 
> > param->name,
> > @@ -2067,7 +2113,16 @@ static void set_output(Display *dpy, XDevice *dev, 
> > param_t *param, int argc, cha
> >                return;
> >        }
> >
> > -       set_output_xrandr(dpy, dev, param, argc, argv);
> > +       /* Check for RandR 1.2 */
> > +       if (!XQueryExtension(dpy, "RANDR", &opcode, &event, &error) ||
> > +           !XRRQueryVersion(dpy, &maj, &min) || (maj * 1000 + min) < 1002)
> > +       {
> > +               if (XQueryExtension(dpy, "NV-CONTROL", &opcode, &event, 
> > &error))
> > +                       TRACE("Nvidia binary driver detected.\n");
> > +               set_output_xinerama(dpy, dev, param, argc, argv);
> > +       } else {
> > +               set_output_xrandr(dpy, dev, param, argc, argv);
> > +       }
> >  }
> >
> >
> > --
> > 1.7.5.4
> >
> >
> 
> Xinerama code works properly, but set_output isn't executing it. It
> looks like my nVidia driver (173.14.30-3) is actually reporting the
> entire desktop as a single screen through xrandr:

urgh. this seems to be a server bug that it reports the version _it_
supports, not the driver. at least with the nvidia driver not sure about
others. easy enough to work around for our use-case, we can just check for
NV-CONTROL first.

Patch coming up in a tick.

> xrandr: Failed to get size of gamma for output default
> Screen 0: minimum 2880 x 1200, current 2880 x 1200, maximum 2880 x 1200
> default connected 2880x1200+0+0 0mm x 0mm
>    2880x1200      50.0*
> 
> A number of solutions exist, though I like checking
> convert_value_from_user (in addition to the existing RandR checks) for
> its trivial implementation and ability to allow 'HEAD-N' to override
> the RandR codepath.
> 
> That aside,
> 
> Tested-by: Jason Gerecke <killert...@gmail.com>

Thanks.

Cheers,
  Peter

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a 
definitive record of customers, application performance, security 
threats, fraudulent activity and more. Splunk takes this data and makes 
sense of it. Business sense. IT sense. Common sense.. 
http://p.sf.net/sfu/splunk-d2d-c1
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to