Package: xwit
Version: 3.4-16+b1
Severity: wishlist

Dear Maintainer,

xwit should support the Multi Pointer X system that comes with the
current Xorg server. It should have options to run

- XISetClientPointer because window managers 
  don't bother to run it.
- XISetFocus for the same reason.
- XIWarpPointer in addition to XWarpPointer

Having these options in xwit will enable users to do many multi pointer
things that otherwise would require patching many applications.
It enables running multiple programs or program instances simultaneously
that each want to grab the pointer or have some unwanted effect when
losing focus.

Examples:

Running multiple instances of minetest on same Xorg server is normally 
not possible, because each instance will want to grab the pointer. After
running XISetClientPointer on them, each instance will grab only the
designated pointer and all instances can be used simultanously.

Running koules with a gamepad while doing something else with a mouse 
and keyboard is normally not possible, because koules will pause when
losing focus. Running XISetClientPointer and XISetFocus can prevent
it form losing focus.

I wrote a patch to add these options to xwit.
diff -u -r a/Makefile b/Makefile
--- a/Makefile  2022-09-05 20:51:10.000000000 +0300
+++ b/Makefile  2022-06-07 23:55:47.933537017 +0300
@@ -1,6 +1,6 @@
 CFLAGS ?= -Wall -O2 -g -Wstrict-prototypes -Wmissing-prototypes
 LDFLAGS ?= -Wl,-z,defs
-LIBRARIES = -lX11
+LIBRARIES = -lX11 -lXi
 
 all: xwit
 
diff -u -r a/xwit.c b/xwit.c
--- a/xwit.c    2022-09-05 20:51:10.000000000 +0300
+++ b/xwit.c    2022-09-05 21:22:06.414875202 +0300
@@ -31,6 +31,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xproto.h>
+#include <X11/extensions/XInput2.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <limits.h>
@@ -66,11 +67,12 @@
        -pop -focus -iconify -unmap -print \n\
        -raise -lower -opposite -[un]circulate\n\
        -resize w h -rows r -columns c -[r]move x y\n\
-       -[r]warp x y -colormap <colormapid> -[no]save\n\
+       -[xi][r]warp x y -colormap <colormapid> -[no]save\n\
        -name <name> -iconname <name> -property <lookfor>\n\
        -bitmap <file> -mask <file> -[r]iconmove x y\n\
        -[no]backingstore -[no]saveunder\n\
        -[no]keyrepeat keycode ... keycode - keycode\n\
+       -keyboard n -pointer n -xifocus -xisetpointer\n\
        -id <windowid> -root -current -select -all\n\
        -names <initialsubstrings>... [must be last]\n",
                program_name);
@@ -78,26 +80,28 @@
 }
 
 enum functions {
-    pop, focus, icon, unmap, colormap,
+    pop, focus, xifocus, icon, unmap, colormap,
     print,
     raise, lower, opposite, circulate, uncirculate,
-    move, rmove, warp, rwarp,
+    move, rmove, warp, rwarp, xiwarp, xirwarp,
     resize, save, nosave,
     keyrepeat, nokeyrepeat,
     name, iconname,
     rows, columns,
     iconbitmap, iconmove, riconmove,
+    xisetpointer,
     F_winattr,
     lastfunc
 };
 static long function;
-#define        FBIT(func)      (1 << (func))
+#define        FBIT(func)      (1ll << (func))
 
 /* options that don't need a window */
 #define        NOWINDOW \
        (FBIT(save) | FBIT(nosave) | \
        FBIT(keyrepeat) | FBIT(nokeyrepeat) | \
-       FBIT(rwarp))
+       FBIT(rwarp) | \
+       FBIT(xirwarp))
 
 static enum winidmode {
        WID_none,
@@ -126,6 +130,8 @@
 static char *bitmapname;
 static char *maskname;
 static int Gbs, Gsu;
+static int clientpointer;
+static int clientkeyboard;
 
 /* set if we found a window to act on*/
 static int Gwinfound;
@@ -562,10 +568,18 @@
                        XWarpPointer(dpy, None, window, 0, 0, 0, 0,
                                warpx, warpy);
                        break;
+               case xiwarp:
+                       XIWarpPointer(dpy, clientpointer, None, window, 0, 0, 
0, 0,
+                               warpx, warpy);
+                       break;
                case rwarp:
                        XWarpPointer(dpy, None, None, 0, 0, 0, 0,
                                warpx, warpy);
                        break;
+               case xirwarp:
+                       XIWarpPointer(dpy, clientpointer, None, None, 0, 0, 0, 
0,
+                               warpx, warpy);
+                       break;
                case move:
                        domove(window, tox, toy, Gright, Gbottom);
                        break;
@@ -616,6 +630,14 @@
                        }
                        break;
                }
+               case xifocus: {
+                       XISetFocus(dpy, clientkeyboard, window, CurrentTime);
+                       break;
+               }
+               case xisetpointer: {
+                       XISetClientPointer(dpy, window, clientpointer);
+                       break;
+               }
                case raise:
                        values.stack_mode = Above;
                        value_mask = CWStackMode;
@@ -1028,6 +1050,9 @@
                else if (matchopt("f*ocus", 0, pargc, argv)) {
                        function |= FBIT(focus);
                }
+               else if (matchopt("xifocus", 0, pargc, argv)) {
+                       function |= FBIT(xifocus);
+               }
                else if (matchopt("ra*ise", 0, pargc, argv)) {
                        function |= FBIT(raise);
                }
@@ -1068,6 +1093,29 @@
                        warpy = atoi(argv[2]);
                        argv += 2;
                }
+               else if (matchopt("xiwarp", 2, pargc, argv)) {
+                       function |= FBIT(xiwarp);
+                       warpx = atoi(argv[1]);
+                       warpy = atoi(argv[2]);
+                       argv += 2;
+               }
+               else if (matchopt("xirwarp", 2, pargc, argv)) {
+                       function |= FBIT(xirwarp);
+                       warpx = atoi(argv[1]);
+                       warpy = atoi(argv[2]);
+                       argv += 2;
+               }
+               else if (matchopt("xisetpointer", 0, pargc, argv)) {
+                       function |= FBIT(xisetpointer);
+               }
+               else if (matchopt("pointer", 1, pargc, argv)) {
+                       clientpointer = atoi(argv[1]);
+                       argv += 1;
+               }
+               else if (matchopt("keyboard", 1, pargc, argv)) {
+                       clientkeyboard = atoi(argv[1]);
+                       argv += 1;
+               }
                else if (matchopt("r*esize", 2, pargc, argv)) {
                        function |= FBIT(resize);
                        towidth = atoi(argv[1]);
diff -u -r a/xwit.man b/xwit.man
--- a/xwit.man  2022-09-05 20:51:10.000000000 +0300
+++ b/xwit.man  2022-09-05 20:49:32.107400495 +0300
@@ -51,6 +51,16 @@
 .RB [ \- [ no ] keyrepeat
 .IR "keycode ... keycode \- keycode ..." ]
 .br
+.RB [ \-keyboard
+.IR deviceid ]
+.RB [ \-pointer
+.IR deviceid ]
+.RB [ \-xi [ r ] warp
+.IR x\ y ]
+.br
+.RB [ \-xifocus ]
+.RB [ \-xisetpointer ]
+.br
 .RB [ \-id
 .IR windowid ]
 .RB [ \-root ]
@@ -182,6 +192,25 @@
 selected windows.
 If \-property is given, that one will be printed instead of the name.
 .TP
+\-keyboard n
+use keyboard n with xifocus
+.TP
+\-pointer n
+use pointer n with xiwarp, xirwarp and xifocus
+.TP
+\-xiwarp x y
+warp the specified pointer to the given position relative to the specified
+window. Add -root to rasp to and absolut position
+.TP
+\-xirwarp x y
+move the specified pointer by the given relative amount.
+.TP
+\-xifocus
+will give the input focus of the specified keyboard to the specified window
+.TP
+\-xisetpointer
+calls XISetClientPointer on the specified window with the specified pointer
+.TP
 Window Selection
 .br
 If no window is specified, $WINDOWID will be used if set;

Reply via email to