app.dhover×441 error×74all
// X11 F10 demo — pointer: relative/raw motion, lock & confine (the feature
// contract: ../../../features/f10-pointer-capture.md; findings:
// ../../f10-pointer-capture.md). Built on the scaffold (../scaffold/app.d),
// drawing reduced to server-side lines so the pointer machinery is the subject.
//
// Scripted phases (WSI_AUTO_EXIT=1):
//   1 unlocked          XI_Motion abs + XI_RawMotion raw-vs-accelerated pairs
//   2 locked            mouselook: XIGrabDevice + XFixesHideCursor + warp-to-
//                       center; deltas from raw motion; unlock warps back to
//                       the saved position (X11 *can* warp — Wayland can only
//                       hint via set_cursor_position_hint)
//   3 confine_grab      modal: XGrabPointer confine_to = InputOnly child over
//                       the center half (+ second-client AlreadyGrabbed probe)
//   4 confine_barrier   ambient: XFixesCreatePointerBarrier on the rect edges
//   5 barrier_plus_grab grab without confine_to on top of live barriers
// Each confine phase warps to the window corners and reports XQueryPointer
// (`confine_probe target=… actual=… inside_rect=…`). Interactive keys:
// l=lock c=confine-grab b=barriers q=quit.
//
// WSI_DRIVEN=1 stretches each phase to 2 s and suppresses the self-warp
// probes so an external driver (xdotool, see ./run.sh) owns the pointer.
// Headless-safe: no display, or no XInputExtension -> prints `SKIP:`, exit 0.
module 
(module) app
app
;
import
(module) c
c
; // ImportC: Xlib + Xutil + XInput2 + Xfixes + poll
C preprocess command `cpp` failed for file `/home/runner/work/sparkles/sparkles/docs/research/window-system-integration/os-apis/x11/examples/f10-pointer-capture/c.c`, exit status 1
import
(module) instrument
instrument
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.config

D compatible types that correspond to various basic types in associated C and C++ compilers.

Source

core/stdc/config.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
config
: c_long, c_ulong;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) app.getenv = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
;
// --------------------------------------------------------------------------- // Constants ImportC cannot export (all #defines): core masks/types, the // whole of <X11/extensions/XI2.h>, and the XFixes barrier directions from // <X11/extensions/xfixeswire.h>. Re-declared per the scaffold gotcha. enum : c_long {
(enum value) app.KeyPressMask = 1L
KeyPressMask
= 1L << 0,
(enum value) app.ExposureMask = 32768L
ExposureMask
= 1L << 15,
(enum value) app.StructureNotifyMask = 131072L
StructureNotifyMask
= 1L << 17,
} enum // core XEvent.type discriminators; GenericEvent carries all XI2 events {
(enum value) app.KeyPress = 2
KeyPress
= 2,
(enum value) app.Expose = 12
Expose
= 12,
(enum value) app.MapNotify = 19
MapNotify
= 19,
(enum value) app.ClientMessage = 33
ClientMessage
= 33,
(enum value) app.GenericEvent = 35
GenericEvent
= 35,
} enum
(constant) int app.False = 0
False
= 0;
enum
(constant) int app.True = 1
True
= 1;
enum
(constant) int app.None = 0
None
= 0;
enum
(constant) int app.CurrentTime = 0
CurrentTime
= 0;
enum
(constant) int app.GrabModeAsync = 1
GrabModeAsync
= 1;
enum
(constant) int app.InputOnly = 2
InputOnly
= 2;
enum
(constant) int app.POLLIN = 1
POLLIN
= 0x001;
immutable
(alias) object.string = string
string
[5]
(immutable global) immutable(string[5]) app.grabStatusName
grabStatusName
=
["GrabSuccess", "AlreadyGrabbed", "GrabInvalidTime", "GrabNotViewable", "GrabFrozen"]; enum // XI2.h; XI_BarrierHit/Leave require announcing XI >= 2.3 {
(enum value) app.XIAllDevices = 0
XIAllDevices
= 0,
(enum value) app.XIAllMasterDevices = 1
XIAllMasterDevices
= 1,
(enum value) app.XIMasterPointer = 1
XIMasterPointer
= 1,
(enum value) app.XIMasterKeyboard = 2
XIMasterKeyboard
= 2,
(enum value) app.XISlavePointer = 3
XISlavePointer
= 3,
(enum value) app.XISlaveKeyboard = 4
XISlaveKeyboard
= 4,
(enum value) app.XIFloatingSlave = 5
XIFloatingSlave
= 5,
(enum value) app.XI_ButtonPress = 4
XI_ButtonPress
= 4,
(enum value) app.XI_Motion = 6
XI_Motion
= 6,
(enum value) app.XI_RawMotion = 17
XI_RawMotion
= 17,
(enum value) app.XI_BarrierHit = 25
XI_BarrierHit
= 25,
(enum value) app.XI_BarrierLeave = 26
XI_BarrierLeave
= 26,
} enum // xfixeswire.h: directions a barrier is *transparent* in {
(enum value) app.BarrierPositiveX = 1
BarrierPositiveX
= 1,
(enum value) app.BarrierPositiveY = 2
BarrierPositiveY
= 2,
(enum value) app.BarrierNegativeX = 4
BarrierNegativeX
= 4,
(enum value) app.BarrierNegativeY = 8
BarrierNegativeY
= 8,
} immutable
(alias) object.string = string
string
[5]
(immutable global) immutable(string[5]) app.useName
useName
=
["MasterPointer", "MasterKeyboard", "SlavePointer", "SlaveKeyboard", "FloatingSlave"]; /// XISetMask is a macro; same bit math, D-side. void
void app.xiSetMask(scope ubyte[] mask, int event) nothrow @nogc

XISetMask is a macro; same bit math, D-side.

xiSetMask
(scope ubyte[]
(parameter) ubyte[] mask
mask
, int
(parameter) int event
event
) @nogc nothrow
{
(parameter) ubyte[] mask
mask
[
(parameter) int event
event
>> 3] |= cast(ubyte)(1 << (
(parameter) int event
event
& 7));
} /// Select XI2 `events` for `deviceid` on `w` (one XIEventMask, one request). void
app.xiSelect

Select XI2 events for deviceid on w (one XIEventMask, one request).

xiSelect
(Display*
(parameter) Display* dpy
dpy
, Window w, int deviceid, scope const int[] events) @nogc nothrow
undefined identifier `Display`
undefined identifier `Window`
{ ubyte[4]
_error_ bits
bits
= 0;
foreach (
(parameter) e
e
; events)
xiSetMask(bits[], e); XIEventMask
_error_ m
m
;
m.deviceid = deviceid; m.mask_len = bits.length; m.
m.mask
mask
= bits.
bits.ptr
ptr
;
XISelectEvents(dpy, w, &m, 1); } int
int D main()
main
()
{
void instrument.initInstrument(const(char)* demoName) nothrow @nogc

Names the demo, starts the monotonic clock, and emits init_start. Call this first, before any platform API call.

initInstrument
("x11_f10");
const
(local variable) const(bool) autoExit
autoExit
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_AUTO_EXIT") !is null;
const
(local variable) const(bool) driven
driven
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_DRIVEN") !is null; // xdotool owns the pointer
const
(local variable) const(int) unitUs
unitUs
=
(local variable) const(bool) driven
driven
? 2_000_000 : 420_000; // per-phase duration
Display*
(local variable) _error_ dpy
dpy
= XOpenDisplay(null);
undefined identifier `Display`
undefined identifier `XOpenDisplay`
if (dpy is null) {
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: no X11 display (XOpenDisplay returned null)\n");
return 0; } const
(local variable) const(_error_) screen
screen
= XDefaultScreen(dpy);
undefined identifier `XDefaultScreen`
const
(local variable) const(_error_) root
root
= XRootWindow(dpy, screen);
undefined identifier `XRootWindow`
// -- Extension handshakes ------------------------------------------------- int
(local variable) int xiOpcode
xiOpcode
,
(local variable) int xiEventBase
xiEventBase
,
(local variable) int xiErrorBase
xiErrorBase
;
if (!XQueryExtension(dpy, "XInputExtension", &xiOpcode, &xiEventBase, &xiErrorBase))
undefined identifier `XQueryExtension`
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: no XInputExtension on this display\n");
XCloseDisplay(dpy);
undefined identifier `XCloseDisplay`
return 0; } int
(local variable) int xiMajor
xiMajor
= 2,
(local variable) int xiMinor
xiMinor
= 3; // 2.3: raw events during grabs + barrier events
const
(local variable) const(_error_) xiStatus
xiStatus
= XIQueryVersion(dpy, &xiMajor, &xiMinor);
undefined identifier `XIQueryVersion`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("step", "name=XIQueryVersion status=%d server=%d.%d opcode=%d",
xiStatus,
(local variable) int xiMajor
xiMajor
,
(local variable) int xiMinor
xiMinor
,
(local variable) int xiOpcode
xiOpcode
);
if (xiStatus != 0 /* Success */ ||
(local variable) int xiMajor
xiMajor
< 2)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
("SKIP: server does not speak XI2 (got %d.%d)\n",
(local variable) int xiMajor
xiMajor
,
(local variable) int xiMinor
xiMinor
);
XCloseDisplay(dpy);
undefined identifier `XCloseDisplay`
return 0; } int
(local variable) int fixMajor
fixMajor
,
(local variable) int fixMinor
fixMinor
,
(local variable) int fixEventBase
fixEventBase
,
(local variable) int fixErrorBase
fixErrorBase
;
const
(local variable) const(_error_) haveFixes
haveFixes
= XFixesQueryExtension(dpy, &fixEventBase, &fixErrorBase) != 0
undefined identifier `XFixesQueryExtension`
&& XFixesQueryVersion(dpy, &fixMajor, &fixMinor) != 0;
undefined identifier `XFixesQueryVersion`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("step", "name=XFixesQueryVersion server=%d.%d barriers=%d",
(local variable) int fixMajor
fixMajor
,
(local variable) int fixMinor
fixMinor
, cast(int)(haveFixes &&
(local variable) int fixMajor
fixMajor
>= 5));
// -- Device dump + master pointer id -------------------------------------- int
(local variable) int masterPtr
masterPtr
= 2; // conventional VCP id; replaced by the query below
int
(local variable) int nDevs
nDevs
;
XIDeviceInfo*
(local variable) _error_ devs
devs
= XIQueryDevice(dpy, XIAllDevices, &nDevs);
undefined identifier `XIDeviceInfo`
undefined identifier `XIQueryDevice`
foreach (
(local variable) int i
i
; 0 ..
(local variable) int nDevs
nDevs
)
{ const
(local variable) const(_error_) d
d
= devs +
(local variable) int i
i
;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("device", "id=%d use=%s attachment=%d name=%s", d.deviceid,
(immutable global) immutable(string[5]) app.useName
useName
[d.use - 1].
(field) _error_ useName[d.use - 1].ptr
ptr
, d.attachment, d.name);
if (d.use ==
(enum value) app.XIMasterPointer = 1
XIMasterPointer
)
(local variable) int masterPtr
masterPtr
= d.deviceid;
} XIFreeDeviceInfo(devs);
undefined identifier `XIFreeDeviceInfo`
// -- Window ---------------------------------------------------------------- const int
(local variable) const(int) width
width
= 480,
(local variable) const(int) height
height
= 320;
Window
(local variable) _error_ win
win
= XCreateSimpleWindow(dpy, root, 20, 20, width, height, 1,
undefined identifier `Window`
undefined identifier `XCreateSimpleWindow`
XBlackPixel(dpy, screen), XWhitePixel(dpy, screen)); XStoreName(dpy, win, "Sparkles · X11 F10 pointer capture");
undefined identifier `XStoreName`
Atom
(local variable) _error_ wmDelete
wmDelete
= XInternAtom(dpy, "WM_DELETE_WINDOW", False);
undefined identifier `Atom`
undefined identifier `XInternAtom`
XSetWMProtocols(dpy, win, &wmDelete, 1);
undefined identifier `XSetWMProtocols`
XSelectInput(dpy, win, ExposureMask | KeyPressMask | StructureNotifyMask);
undefined identifier `XSelectInput`
XMapWindow(dpy, win);
undefined identifier `XMapWindow`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("window_created", "xid=0x%lx size=%dx%d", win,
(local variable) const(int) width
width
,
(local variable) const(int) height
height
);
// XI2 selections: raw motion is root-window-only by spec; abs motion + // barrier events ride the same root/window split. static immutable int[]
(immutable global) immutable(int[]) app.main.rootEvents
rootEvents
= [
(enum value) app.XI_RawMotion = 17
XI_RawMotion
,
(enum value) app.XI_BarrierHit = 25
XI_BarrierHit
,
(enum value) app.XI_BarrierLeave = 26
XI_BarrierLeave
];
static immutable int[]
(immutable global) immutable(int[]) app.main.winEvents
winEvents
= [
(enum value) app.XI_Motion = 6
XI_Motion
,
(enum value) app.XI_ButtonPress = 4
XI_ButtonPress
];
xiSelect(dpy, root, XIAllMasterDevices, rootEvents); xiSelect(dpy, win, XIAllMasterDevices, winEvents);
void instrument.emit(scope const(char)* kind) nothrow @nogc

Emit an event with no key=value payload.

emit
("step name=XISelectEvents root=RawMotion,BarrierHit/Leave win=Motion,ButtonPress");
GC
(local variable) _error_ gc
gc
= XDefaultGC(dpy, screen);
undefined identifier `GC`
undefined identifier `XDefaultGC`
// Window origin in root coordinates (no WM under Xvfb, but don't assume). int
(local variable) int orgX
orgX
,
(local variable) int orgY
orgY
;
{ Window
(local variable) _error_ dummy
dummy
;
undefined identifier `Window`
XTranslateCoordinates(dpy, win, root, 0, 0, &orgX, &orgY, &dummy);
undefined identifier `XTranslateCoordinates`
} // The confine region: center half of the window (window + root coords). const
(local variable) const(int) rx
rx
=
(local variable) const(int) width
width
/ 4,
(local variable) const(int) ry
ry
=
(local variable) const(int) height
height
/ 4,
(local variable) const(int) rw
rw
=
(local variable) const(int) width
width
/ 2,
(local variable) const(int) rh
rh
=
(local variable) const(int) height
height
/ 2;
const
(local variable) const(int) cx
cx
=
(local variable) const(int) width
width
/ 2,
(local variable) const(int) cy
cy
=
(local variable) const(int) height
height
/ 2; // lock center (window coords)
// -- Demo state ------------------------------------------------------------ Display*
(local variable) _error_ dpy2
dpy2
= null; // second client, for the AlreadyGrabbed probe
undefined identifier `Display`
Window
(local variable) _error_ confineChild
confineChild
= None;
undefined identifier `Window`
PointerBarrier[4]
(local variable) _error_ barriers
barriers
;
undefined identifier `PointerBarrier`
bool
(local variable) bool locked
locked
,
(local variable) bool confineGrabbed
confineGrabbed
,
(local variable) bool barriersUp
barriersUp
,
(local variable) bool plainGrabbed
plainGrabbed
;
int
(local variable) int savedX
savedX
= -1,
(local variable) int savedY
savedY
= -1; // root coords to restore on unlock
double
(local variable) double yaw
yaw
= 0,
(local variable) double pitch
pitch
= 0; // accumulated raw deltas while locked
int
(local variable) int rawWhileLocked
rawWhileLocked
,
(local variable) int jitterWarps
jitterWarps
,
(local variable) int recenterWarps
recenterWarps
;
void
void app.main.queryPtr(out int rootX, out int rootY, out int winX, out int winY) pure nothrow @nogc @safe
queryPtr
(out int
(parameter) int rootX
rootX
, out int
(parameter) int rootY
rootY
, out int
(parameter) int winX
winX
, out int
(parameter) int winY
winY
)
{ Window
(local variable) _error_ r
r
,
(local variable) _error_ ch
ch
;
undefined identifier `Window`
undefined identifier `Window`
uint
(local variable) uint mods
mods
;
XQueryPointer(dpy, win, &r, &ch, &rootX, &rootY, &winX, &winY, &mods);
undefined identifier `XQueryPointer`
} void
void app.main.redraw() pure nothrow @nogc @safe
redraw
()
{ XClearWindow(dpy, win);
undefined identifier `XClearWindow`
if (
(local variable) bool confineGrabbed
confineGrabbed
||
(local variable) bool barriersUp
barriersUp
)
XDrawRectangle(dpy, win, gc, rx, ry, rw, rh);
undefined identifier `XDrawRectangle`
if (
(local variable) bool locked
locked
)
{ const
(local variable) const(int) px
px
=
(local variable) const(int) cx
cx
+ cast(int)
(local variable) double yaw
yaw
/ 4,
(local variable) const(int) py
py
=
(local variable) const(int) cy
cy
+ cast(int)
(local variable) double pitch
pitch
/ 4;
XDrawLine(dpy, win, gc, px - 8, py, px + 8, py);
undefined identifier `XDrawLine`
XDrawLine(dpy, win, gc, px, py - 8, px, py + 8);
undefined identifier `XDrawLine`
} XFlush(dpy);
undefined identifier `XFlush`
} void
void app.main.setLock(bool on) nothrow @nogc @system
setLock
(bool
(parameter) bool on
on
)
{ if (
(parameter) bool on
on
==
(local variable) bool locked
locked
)
return; if (
(parameter) bool on
on
)
{ int
(local variable) int wx
wx
,
(local variable) int wy
wy
;
void app.main.queryPtr(out int rootX, out int rootY, out int winX, out int winY) pure nothrow @nogc @safe
queryPtr
(
(local variable) int savedX
savedX
,
(local variable) int savedY
savedY
,
(local variable) int wx
wx
,
(local variable) int wy
wy
);
XFixesHideCursor(dpy, win);
undefined identifier `XFixesHideCursor`
ubyte[4]
(local variable) ubyte[4] bits
bits
= 0;
void app.xiSetMask(scope ubyte[] mask, int event) nothrow @nogc

XISetMask is a macro; same bit math, D-side.

xiSetMask
(
(local variable) ubyte[4] bits
bits
[],
(enum value) app.XI_Motion = 6
XI_Motion
);
void app.xiSetMask(scope ubyte[] mask, int event) nothrow @nogc

XISetMask is a macro; same bit math, D-side.

xiSetMask
(
(local variable) ubyte[4] bits
bits
[],
(enum value) app.XI_ButtonPress = 4
XI_ButtonPress
);
XIEventMask
(local variable) _error_ m
m
;
undefined identifier `XIEventMask`
m.deviceid = masterPtr; m.mask_len = bits.length; m.
m.mask
mask
= bits.
bits.ptr
ptr
;
const
(local variable) const(_error_) st
st
= XIGrabDevice(dpy, masterPtr, win, CurrentTime, None,
undefined identifier `XIGrabDevice`
GrabModeAsync, GrabModeAsync, True, &m); XWarpPointer(dpy, None, win, 0, 0, 0, 0, cx, cy);
undefined identifier `XWarpPointer`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("lock", "state=on grab=XIGrabDevice status=%s saved=%d,%d",
(immutable global) immutable(string[5]) app.grabStatusName
grabStatusName
[st].
(field) _error_ grabStatusName[st].ptr
ptr
,
(local variable) int savedX
savedX
,
(local variable) int savedY
savedY
);
(local variable) double yaw
yaw
=
(local variable) double pitch
pitch
= 0;
(local variable) int rawWhileLocked
rawWhileLocked
=
(local variable) int jitterWarps
jitterWarps
=
(local variable) int recenterWarps
recenterWarps
= 0;
} else { XIUngrabDevice(dpy, masterPtr, CurrentTime);
undefined identifier `XIUngrabDevice`
XFixesShowCursor(dpy, win);
undefined identifier `XFixesShowCursor`
XWarpPointer(dpy, None, root, 0, 0, 0, 0, savedX, savedY); // X11 can warp
undefined identifier `XWarpPointer`
XSync(dpy, False);
undefined identifier `XSync`
int
(local variable) int rxp
rxp
,
(local variable) int ryp
ryp
,
(local variable) int wx
wx
,
(local variable) int wy
wy
;
void app.main.queryPtr(out int rootX, out int rootY, out int winX, out int winY) pure nothrow @nogc @safe
queryPtr
(
(local variable) int rxp
rxp
,
(local variable) int ryp
ryp
,
(local variable) int wx
wx
,
(local variable) int wy
wy
);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("lock", "state=off restored=%d,%d wanted=%d,%d match=%d",
(local variable) int rxp
rxp
,
(local variable) int ryp
ryp
,
(local variable) int savedX
savedX
,
(local variable) int savedY
savedY
, cast(int)(
(local variable) int rxp
rxp
==
(local variable) int savedX
savedX
&&
(local variable) int ryp
ryp
==
(local variable) int savedY
savedY
));
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("lock_stats", "raw_events=%d jitter_warps=%d recenter_warps=%d "
~ "yaw=%.1f pitch=%.1f",
(local variable) int rawWhileLocked
rawWhileLocked
,
(local variable) int jitterWarps
jitterWarps
,
(local variable) int recenterWarps
recenterWarps
,
(local variable) double yaw
yaw
,
(local variable) double pitch
pitch
);
}
(local variable) bool locked
locked
=
(parameter) bool on
on
;
void app.main.redraw() pure nothrow @nogc @safe
redraw
();
} void
void app.main.setConfineGrab(bool on) nothrow @nogc @system
setConfineGrab
(bool
(parameter) bool on
on
)
{ if (
(parameter) bool on
on
==
(local variable) bool confineGrabbed
confineGrabbed
)
return; if (
(parameter) bool on
on
)
{ if (confineChild == None) { // InputOnly child over the center half: invisible, events-only — // it exists purely to be a confine_to target. WSI_CONFINE_IO=1 // swaps in an InputOutput child to probe whether the window // class changes the confinement behavior. const
(local variable) const(bool) inputOutput
inputOutput
=
char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
("WSI_CONFINE_IO") !is null;
XSetWindowAttributes
(local variable) _error_ attrs
attrs
;
undefined identifier `XSetWindowAttributes`
confineChild = XCreateWindow(dpy, win, rx, ry, rw, rh, 0, 0, inputOutput ? 1 : InputOnly, null, 0, &attrs); XMapWindow(dpy, confineChild);
undefined identifier `XMapWindow`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("step", "name=XCreateWindow class=%s xid=0x%lx",
(local variable) const(bool) inputOutput
inputOutput
? "InputOutput".
(constant) immutable(char)* "InputOutput".ptr = "InputOutput"
ptr
: "InputOnly".
(constant) immutable(char)* "InputOnly".ptr = "InputOnly"
ptr
, confineChild);
} const
(local variable) const(_error_) st
st
= XGrabPointer(dpy, win, True, 0, GrabModeAsync,
undefined identifier `XGrabPointer`
GrabModeAsync, confineChild, None, CurrentTime);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("confine", "mode=grab rect=%dx%d+%d+%d confine_to=0x%lx status=%s",
(local variable) const(int) rw
rw
,
(local variable) const(int) rh
rh
,
(local variable) const(int) rx
rx
,
(local variable) const(int) ry
ry
, confineChild,
(immutable global) immutable(string[5]) app.grabStatusName
grabStatusName
[st].
(field) _error_ grabStatusName[st].ptr
ptr
);
// Failure probe: a *second client* grabbing while we hold the grab. if (dpy2 is null) dpy2 = XOpenDisplay(null); if (dpy2 !is null) { const
(local variable) const(_error_) st2
st2
= XGrabPointer(dpy2, win, True, 0, GrabModeAsync,
undefined identifier `XGrabPointer`
GrabModeAsync, None, None, CurrentTime); if (st2 == 0) XUngrabPointer(dpy2, CurrentTime);
undefined identifier `XUngrabPointer`
ubyte[4]
(local variable) ubyte[4] bits
bits
= 0;
XIEventMask
(local variable) _error_ m
m
;
undefined identifier `XIEventMask`
m.deviceid = masterPtr; m.mask_len = bits.length; m.
m.mask
mask
= bits.
bits.ptr
ptr
;
const
(local variable) const(_error_) st3
st3
= XIGrabDevice(dpy2, masterPtr, win, CurrentTime, None,
undefined identifier `XIGrabDevice`
GrabModeAsync, GrabModeAsync, True, &m); if (st3 == 0) XIUngrabDevice(dpy2, masterPtr, CurrentTime);
undefined identifier `XIUngrabDevice`
XFlush(dpy2);
undefined identifier `XFlush`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("grab_probe", "client=second XGrabPointer=%s XIGrabDevice=%s",
(immutable global) immutable(string[5]) app.grabStatusName
grabStatusName
[st2].
(field) _error_ grabStatusName[st2].ptr
ptr
,
(immutable global) immutable(string[5]) app.grabStatusName
grabStatusName
[st3].
(field) _error_ grabStatusName[st3].ptr
ptr
);
} } else { XUngrabPointer(dpy, CurrentTime);
undefined identifier `XUngrabPointer`
void instrument.emit(scope const(char)* kind) nothrow @nogc

Emit an event with no key=value payload.

emit
("confine mode=grab state=off");
}
(local variable) bool confineGrabbed
confineGrabbed
=
(parameter) bool on
on
;
void app.main.redraw() pure nothrow @nogc @safe
redraw
();
} void
void app.main.setBarriers(bool on) nothrow @nogc @system
setBarriers
(bool
(parameter) bool on
on
)
{ if (
(parameter) bool on
on
==
(local variable) bool barriersUp
barriersUp
|| !haveFixes ||
(local variable) int fixMajor
fixMajor
< 5)
return; if (
(parameter) bool on
on
)
{ // Four barriers boxing the region (root coords). Each is transparent // *inward* only, so the pointer can enter but relative motion cannot // leave. Non-modal: no grab, event delivery is untouched. const
(local variable) const(int) x1
x1
=
(local variable) int orgX
orgX
+
(local variable) const(int) rx
rx
,
(local variable) const(int) y1
y1
=
(local variable) int orgY
orgY
+
(local variable) const(int) ry
ry
,
(local variable) const(int) x2
x2
=
(local variable) const(int) x1
x1
+
(local variable) const(int) rw
rw
,
(local variable) const(int) y2
y2
=
(local variable) const(int) y1
y1
+
(local variable) const(int) rh
rh
;
barriers[0] = XFixesCreatePointerBarrier(dpy, root, x1, y1, x1, y2, BarrierPositiveX, 0, null); // left edge: only +x passes barriers[1] = XFixesCreatePointerBarrier(dpy, root, x2, y1, x2, y2, BarrierNegativeX, 0, null); // right edge: only -x passes barriers[2] = XFixesCreatePointerBarrier(dpy, root, x1, y1, x2, y1, BarrierPositiveY, 0, null); // top edge: only +y passes barriers[3] = XFixesCreatePointerBarrier(dpy, root, x1, y2, x2, y2, BarrierNegativeY, 0, null); // bottom edge: only -y passes XWarpPointer(dpy, None, win, 0, 0, 0, 0, cx, cy); // start inside
undefined identifier `XWarpPointer`
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("confine", "mode=barrier rect=%dx%d+%d+%d root_rect=%d,%d..%d,%d "
~ "ids=%lu,%lu,%lu,%lu",
(local variable) const(int) rw
rw
,
(local variable) const(int) rh
rh
,
(local variable) const(int) rx
rx
,
(local variable) const(int) ry
ry
,
(local variable) const(int) x1
x1
,
(local variable) const(int) y1
y1
,
(local variable) const(int) x2
x2
,
(local variable) const(int) y2
y2
,
barriers[0], barriers[1], barriers[2], barriers[3]); } else { foreach (
(parameter) b
b
; barriers)
XFixesDestroyPointerBarrier(dpy, b);
void instrument.emit(scope const(char)* kind) nothrow @nogc

Emit an event with no key=value payload.

emit
("confine mode=barrier state=off");
}
(local variable) bool barriersUp
barriersUp
=
(parameter) bool on
on
;
void app.main.redraw() pure nothrow @nogc @safe
redraw
();
} void
void app.main.setPlainGrab(bool on) pure nothrow @nogc @safe
setPlainGrab
(bool
(parameter) bool on
on
) // grab-on-top-of-barriers interaction probe
{ if (
(parameter) bool on
on
==
(local variable) bool plainGrabbed
plainGrabbed
)
return; if (
(parameter) bool on
on
)
{ const
(local variable) const(_error_) st
st
= XGrabPointer(dpy, win, True, 0, GrabModeAsync,
undefined identifier `XGrabPointer`
GrabModeAsync, None, None, CurrentTime);
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("grab_probe", "client=first XGrabPointer=%s confine_to=None "
~ "barriers_active=%d",
(immutable global) immutable(string[5]) app.grabStatusName
grabStatusName
[st].
(field) _error_ grabStatusName[st].ptr
ptr
, cast(int)
(local variable) bool barriersUp
barriersUp
);
} else XUngrabPointer(dpy, CurrentTime);
undefined identifier `XUngrabPointer`
(local variable) bool plainGrabbed
plainGrabbed
=
(parameter) bool on
on
;
} /// Warp to a window-local target, round-trip, report where the pointer /// actually ended up relative to the confine region. void
void app.main.confineProbe(const(char)* mode, int tx, int ty) nothrow @nogc @system

Warp to a window-local target, round-trip, report where the pointer actually ended up relative to the confine region.

confineProbe
(const(char)*
(parameter) const(char)* mode
mode
, int
(parameter) int tx
tx
, int
(parameter) int ty
ty
)
{ XWarpPointer(dpy, None, win, 0, 0, 0, 0, tx, ty);
undefined identifier `XWarpPointer`
XSync(dpy, False);
undefined identifier `XSync`
int
(local variable) int rxp
rxp
,
(local variable) int ryp
ryp
,
(local variable) int wx
wx
,
(local variable) int wy
wy
;
void app.main.queryPtr(out int rootX, out int rootY, out int winX, out int winY) pure nothrow @nogc @safe
queryPtr
(
(local variable) int rxp
rxp
,
(local variable) int ryp
ryp
,
(local variable) int wx
wx
,
(local variable) int wy
wy
);
const
(local variable) const(bool) inside
inside
=
(local variable) int wx
wx
>=
(local variable) const(int) rx
rx
&&
(local variable) int wx
wx
<
(local variable) const(int) rx
rx
+
(local variable) const(int) rw
rw
&&
(local variable) int wy
wy
>=
(local variable) const(int) ry
ry
&&
(local variable) int wy
wy
<
(local variable) const(int) ry
ry
+
(local variable) const(int) rh
rh
;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("confine_probe", "mode=%s target=%d,%d actual=%d,%d inside_rect=%d",
(parameter) const(char)* mode
mode
,
(parameter) int tx
tx
,
(parameter) int ty
ty
,
(local variable) int wx
wx
,
(local variable) int wy
wy
, cast(int)
(local variable) const(bool) inside
inside
);
} // -- Scripted phases (auto mode) ------------------------------------------- static immutable
(alias) object.string = string
string
[6]
(immutable global) immutable(string[6]) app.main.phaseNames
phaseNames
= [
"unlocked", "locked", "confine_grab", "confine_barrier", "barrier_plus_grab", "done" ]; int
(local variable) int phase
phase
= -1;
long
(local variable) long phaseStartUs
phaseStartUs
;
long
(local variable) long nextProbeUs
nextProbeUs
;
int
(local variable) int probeIdx
probeIdx
;
bool
(local variable) bool sawExpose
sawExpose
,
(local variable) bool running
running
= true;
static immutable int[2][4]
(immutable global) immutable(int[2][4]) app.main.corners
corners
= [[8, 8], [471, 8], [8, 311], [471, 311]];
void
void app.main.enterPhase(int p) nothrow @nogc @system
enterPhase
(int
(parameter) int p
p
)
{
(local variable) int phase
phase
=
(parameter) int p
p
;
(local variable) long phaseStartUs
phaseStartUs
=
long instrument.nowUs() nothrow @nogc

Microseconds elapsed since initInstrument.

nowUs
();
(local variable) long nextProbeUs
nextProbeUs
=
(local variable) long phaseStartUs
phaseStartUs
+ 60_000;
(local variable) int probeIdx
probeIdx
= 0;
void instrument.emitf(scope const(char)* kind, scope const(char)* fmt, ...) nothrow @nogc

Emit an event with a printf-formatted key=value ... payload.

emitf
("phase", "name=%s",
(immutable global) immutable(string[6]) app.main.phaseNames
phaseNames
[
(parameter) int p
p
].
(field) immutable(char)* immutable(string).ptr
ptr
);
final switch (
(parameter) int p
p
)
{ case 0: break; case 1:
void app.main.setLock(bool on) nothrow @nogc @system
setLock
(true);
break; case 2:
void app.main.setLock(bool on) nothrow @nogc @system
setLock
(false);
void app.main.setConfineGrab(bool on) nothrow @nogc @system
setConfineGrab
(true);
break; case 3:
void app.main.setConfineGrab(bool on) nothrow @nogc @system
setConfineGrab
(false);
void app.main.setBarriers(bool on) nothrow @nogc @system
setBarriers
(true);
break; case 4:
void app.main.setPlainGrab(bool on) pure nothrow @nogc @safe
setPlainGrab
(true);
break; case 5:
void app.main.setPlainGrab(bool on) pure nothrow @nogc @safe
setPlainGrab
(false);
void app.main.setBarriers(bool on) nothrow @nogc @system
setBarriers
(false);
(local variable) bool running
running
= false;
void instrument.emit(scope const(char)* kind) nothrow @nogc

Emit an event with no key=value payload.

emit
("auto_exit");
break; } } void
void app.main.runProbe() nothrow @nogc @system
runProbe
() // self-warp choreography; suppressed when xdotool drives
{ static immutable
(alias) object.string = string
string
[3]
(immutable global) immutable(string[3]) app.main.runProbe.probeMode
probeMode
= ["grab", "barrier", "barrier_grab"];
if (
(local variable) int phase
phase
== 0) // diagonal sweep: feeds abs motion + raw-vs-accel pairs
XWarpPointer(dpy, None, win, 0, 0, 0, 0,
undefined identifier `XWarpPointer`
40 + probeIdx * 80, 40 + probeIdx * 48); else if (
(local variable) int phase
phase
== 1) // mouselook jitter: warp off-center, handler re-centers
{ XWarpPointer(dpy, None, win, 0, 0, 0, 0,
undefined identifier `XWarpPointer`
cx + (probeIdx % 2 == 0 ? 24 : -16), cy + 10 - probeIdx * 4); ++
(local variable) int jitterWarps
jitterWarps
;
} else if (
(local variable) int phase
phase
>= 2 &&
(local variable) int phase
phase
<= 4)
void app.main.confineProbe(const(char)* mode, int tx, int ty) nothrow @nogc @system

Warp to a window-local target, round-trip, report where the pointer actually ended up relative to the confine region.

confineProbe
(
(immutable global) immutable(string[3]) app.main.runProbe.probeMode
probeMode
[
(local variable) int phase
phase
- 2].
(field) immutable(char)* immutable(string).ptr
ptr
,
(immutable global) immutable(int[2][4]) app.main.corners
corners
[
(local variable) int probeIdx
probeIdx
& 3][0],
(immutable global) immutable(int[2][4]) app.main.corners
corners
[
(local variable) int probeIdx
probeIdx
& 3][1]);
++
(local variable) int probeIdx
probeIdx
;
} // -- Event loop -------------------------------------------------------------- const
(local variable) const(_error_) fd
fd
= XConnectionNumber(dpy);
undefined identifier `XConnectionNumber`
while (
(local variable) bool running
running
)
{ while (XPending(dpy) > 0)
undefined identifier `XPending`
{ XEvent
(local variable) _error_ ev
ev
;
undefined identifier `XEvent`
XNextEvent(dpy, &ev);
undefined identifier `XNextEvent`
switch (ev.type) { case Expose: if (ev.xexpose.count == 0) { redraw(); if (!sawExpose) { sawExpose = true; if (autoExit) enterPhase(0); } } break; case KeyPress: // interactive toggles const
_error_ ks
ks
= XLookupKeysym(&ev.xkey, 0);
if (ks == 'l') setLock(!locked); else if (ks == 'c') setConfineGrab(!confineGrabbed); else if (ks == 'b') setBarriers(!barriersUp); else if (ks == 'q' || ks == 0xff1b /* XK_Escape */ ) running = false; break; case ClientMessage: if (cast(Atom) ev.xclient.data.l[0] == wmDelete) running = false; break; case GenericEvent: auto
_error_ cookie
cookie
= &ev.xcookie;
if (XGetEventData(dpy, cookie) && cookie.extension == xiOpcode) { switch (cookie.evtype) { case XI_RawMotion: // One event, both flavors: values = post-acceleration/ // transform, raw_values = device deltas untouched. const
_error_ re
re
= cast(const(XIRawEvent)*) cookie.data;
double
_error_ dx
dx
= 0,
_error_ dy
dy
= 0,
_error_ rdx
rdx
= 0,
_error_ rdy
rdy
= 0;
int
_error_ idx
idx
;
foreach (
(parameter) i
i
; 0 .. re.valuators.mask_len * 8)
{ if (!(re.valuators.
re.valuators.mask
mask
[i >> 3] & (1 << (i & 7))))
continue; if (i == 0) { dx = re.valuators.values[idx]; rdx = re.raw_values[idx]; } else if (i == 1) { dy = re.valuators.values[idx]; rdy = re.raw_values[idx]; } ++idx; } const
_error_ accelEq
accelEq
= dx == rdx && dy == rdy;
if (locked) { yaw += rdx; pitch += rdy; ++rawWhileLocked; emitf("pointer", "rel dx=%.2f dy=%.2f raw=1 " ~ "accel_dx=%.2f accel_dy=%.2f accel_equal=%d " ~ "yaw=%.1f pitch=%.1f", rdx, rdy, dx, dy, cast(int) accelEq, yaw, pitch); } else emitf("raw_motion", "raw_dx=%.2f raw_dy=%.2f " ~ "accel_dx=%.2f accel_dy=%.2f accel_equal=%d device=%d", rdx, rdy, dx, dy, cast(int) accelEq, re.deviceid); break; case XI_Motion: const
_error_ de
de
= cast(const(XIDeviceEvent)*) cookie.data;
const
_error_ mx
mx
= cast(int) de.event_x,
_error_ my
my
= cast(int) de.event_y;
if (locked) { if (mx != cx || my != cy) // recenter (skip our own echo) { XWarpPointer(dpy, None, win, 0, 0, 0, 0, cx, cy); ++recenterWarps; } } else emitf("pointer", "abs x=%d y=%d root=%.0f,%.0f", mx, my, de.root_x, de.root_y); break; case XI_BarrierHit: case XI_BarrierLeave: const
_error_ be
be
= cast(const(XIBarrierEvent)*) cookie.data;
emitf(cookie.evtype == XI_BarrierHit ? "barrier_hit".
"barrier_hit".ptr
ptr
: "barrier_leave".
"barrier_leave".ptr
ptr
,
"barrier=%lu root=%.0f,%.0f blocked_dx=%.1f blocked_dy=%.1f", be.barrier, be.root_x, be.root_y, be.
be.dx
dx
, be.
be.dy
dy
);
break; default: break; } } XFreeEventData(dpy, cookie); break; default: break; } } if (
(local variable) const(bool) autoExit
autoExit
&&
(local variable) bool sawExpose
sawExpose
&&
(local variable) bool running
running
)
{ const
(local variable) const(long) now
now
=
long instrument.nowUs() nothrow @nogc

Microseconds elapsed since initInstrument.

nowUs
();
if (
(local variable) const(long) now
now
-
(local variable) long phaseStartUs
phaseStartUs
>=
(local variable) const(int) unitUs
unitUs
)
void app.main.enterPhase(int p) nothrow @nogc @system
enterPhase
(
(local variable) int phase
phase
+ 1);
else if (!
(local variable) const(bool) driven
driven
&&
(local variable) const(long) now
now
>=
(local variable) long nextProbeUs
nextProbeUs
)
{
void app.main.runProbe() nothrow @nogc @system
runProbe
();
(local variable) long nextProbeUs
nextProbeUs
=
(local variable) const(long) now
now
+ 60_000;
} if (
(local variable) bool locked
locked
)
void app.main.redraw() pure nothrow @nogc @safe
redraw
(); // keep the crosshair live while deltas accumulate
} XFlush(dpy);
undefined identifier `XFlush`
pollfd
(local variable) _error_ pfd
pfd
;
undefined identifier `pollfd`
pfd.
pfd.fd
fd
= fd;
pfd.events = POLLIN; pfd.revents = 0; poll(&pfd, 1, autoExit ? 5 : -1);
undefined identifier `poll`
} // -- Teardown ----------------------------------------------------------------
void app.main.setPlainGrab(bool on) pure nothrow @nogc @safe
setPlainGrab
(false);
void app.main.setBarriers(bool on) nothrow @nogc @system
setBarriers
(false);
void app.main.setConfineGrab(bool on) nothrow @nogc @system
setConfineGrab
(false);
if (
(local variable) bool locked
locked
)
void app.main.setLock(bool on) nothrow @nogc @system
setLock
(false);
if (dpy2 !is null) XCloseDisplay(dpy2);
undefined identifier `XCloseDisplay`
XDestroyWindow(dpy, win);
undefined identifier `XDestroyWindow`
XCloseDisplay(dpy);
undefined identifier `XCloseDisplay`
void instrument.emit(scope const(char)* kind) nothrow @nogc

Emit an event with no key=value payload.

emit
("teardown");
return 0; }