7

The two main utilities to configure and test X input devices are xinput and xset.

The main difference between the two (for what I understand) is that xinput allows a more fine-grained control over the (possibly device-dependent) properties. On the other hand, sometimes the settings given via xset are a pretty good starting point.

What I would like to do is to start from the settings given by xset and apply some fine-tuning from there via xinput.

The problem is that it seems that the configurations obtained via xset are not registered by xinput, and the xset man page does not give the exact details of the settings it produces.

For example, say I want to change the speed of my touchpad. I know from xinput --list that the relevant device id is 15, so that I can use xinput --list-props 15 to list all the touchpad properties. I could now go and change some property, say the constant deceleration (which in this case has ID 276) to the value 1.5, using xinput --set-prop 15 276 1.5.

However, xset mouse 5 5 also gives a pretty good speed setting for me. I want to understand what exact configurations are being configured with this command, but running xinput --list-props 15 after xset mouse 5 5 does not register any difference. How can I get this information?

1 Answer 1

2

Not a complete answer, but I figured out some details by looking at the source code.

I had a look at the source code of xset in the file xset.c, which comes from the package x11-xserver-utils. The code in the file downloaded on my system (Ubuntu 16.04) by apt-get source x11-xserver-utils is more or less the same as the code found here, so I will use the code on that page as reference.

What happens when the mouse option is given can be seen at L475-502 (EDIT: in the updated ref L450-475):

/*  Set pointer (mouse) settings:  Acceleration and Threshold. */
  else if (strcmp(arg, "m") == 0 || strcmp(arg, "mouse") == 0) {
    acc_num = SERVER_DEFAULT;             /* restore server defaults */
    acc_denom = SERVER_DEFAULT;
    threshold = SERVER_DEFAULT;
    if (i >= argc){
      set_mouse(dpy, acc_num, acc_denom, threshold);
      break;
    }
    arg = argv[i];
    if (strcmp(arg, "default") == 0) {
      i++;
    } 
    else if (*arg >= '0' && *arg <= '9') {
      acc_denom = 1;
      sscanf(arg, "%d/%d", &acc_num, &acc_denom);
      i++;
      if (i >= argc) {
       set_mouse(dpy, acc_num, acc_denom, threshold);
       break;
      }
      arg = argv[i];
      if (*arg >= '0' && *arg <= '9') {
       threshold = atoi(arg);  /* Set threshold as user specified.  */
       i++;
      }
    }
    set_mouse(dpy, acc_num, acc_denom, threshold);
  }

where SERVER_DEFAULT is set as -1. This just reads the arguments and calls set_mouse. Notably, if no additional arguments are given (command called as xset mouse) the defaults are xset mouse -1/-1 -1. Also, acc_num and threshold must be between 0 and 9, otherwise the default value -1 is used, and the default value for acc_denom is 1.

The function set_mouse is again just a bunch of checks for illegal input values:

set_mouse(Display *dpy, int acc_num, int acc_denom, int threshold)
{
int do_accel = True, do_threshold = True;

if (acc_num == DONT_CHANGE)        /* what an incredible crock... */
  do_accel = False;
if (threshold == DONT_CHANGE)
  do_threshold = False;
if (acc_num < 0)                   /* shouldn't happen */
  acc_num = SERVER_DEFAULT;
if (acc_denom <= 0)                /* prevent divide by zero */
  acc_denom = SERVER_DEFAULT;
if (threshold < 0) threshold = SERVER_DEFAULT;
XChangePointerControl(dpy, do_accel, do_threshold, acc_num,
                    acc_denom, threshold);
return;
}

The ball is now passed to XChangePointerControl. This function is however not defined in this package. Some searching through the included dependencies brought me to the libx11 package, containing the file ChPntCont.c (source code here), which defines this function:

int
XChangePointerControl(
     register Display *dpy,
     Bool do_acc,
     Bool do_thresh,
     int acc_numerator,
     int acc_denominator,
     int threshold)

{
    register xChangePointerControlReq *req;

    LockDisplay(dpy);
    GetReq(ChangePointerControl, req);
    req->doAccel = do_acc;
    req->doThresh = do_thresh;
    req->accelNum = acc_numerator;
    req->accelDenum = acc_denominator;
    req->threshold = threshold;
    UnlockDisplay(dpy);
    SyncHandle();
    return 1;
}

I didn't really manage to understand much beyond this point. GetReq is defined by a macro in the file Xlibint.h in the libx11 package and we get bounced around between several different functions. At the end of the day we probably have enough information from the above functions though, in that the input values seem to be directly fed as new values for similarly named properties of the touchpad device.

The above at least tells us something about the default and accepted values of xset.

I didn't manage to figure out why the output of xinput list-props is not updated after the properties are changed with xset though.

2
  • Hi @gIS thanks for this. The code ref is broken; I found salsa.debian.org/xorg-team/app/x11-xserver-utils/blob/… Not sure if it is right to drop in this href?
    – Rob
    Nov 24, 2018 at 12:01
  • 1
    @Rob glad it helped. Thanks for the catch, I updated the link. It's probably a different version of the package, as the line numbers are different, but the code block is identical, so it should be fine (and I don't really remember the exact version of the library I was referring to here)
    – glS
    Nov 24, 2018 at 12:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .