// Virtual-pointer injector mode for the F16 demo:
//
// f16_clipboard_dnd inject click <x> <y> <btn> one click (btn is the
// evdev code: 272 left,
// 273 right)
// f16_clipboard_dnd inject drag <x1> <y1> <x2> <y2>
//
// `drag` plugs ONE `zwlr_virtual_pointer_v1` device in, presses BTN_LEFT at
// (x1,y1) and HOLDS it through an 8-step motion_absolute sweep to (x2,y2)
// before releasing — wl_data_device.start_drag is only valid against the
// serial of an implicit (button-down) grab, so the press, the demo's
// start_drag, the sweep and the drop all have to live inside one device
// session. Coordinates are global against ./run.sh's 1280x720 sway layout
// (window A at (0,120), window B at (640,120), both 640x480).
module (module) injectinject;
import c; // ImportC shim — wsi_vpm_* / wsi_vptr_* are hand-marshalled (see ./c.c)
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stdioD header file for C99 <stdio.h>
pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h
Source
core/stdc/stdio.d
stdio : (alias) inject.fprintf = int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogcfprintf, (alias) inject.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf, (alias shared global) inject.stderr = shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderrstderr;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.stringD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html, string.h
Source
core/stdc/string.d
string : (alias) inject.strcmp = int core.stdc.string.strcmp(scope const(char*) s1, scope const(char*) s2) pure nothrow @nogcstrcmp;
__gshared wl_proxy* _error_ inject.gi_mgrgi_mgr;
__gshared wl_seat* _error_ inject.gi_seatgi_seat;
__gshared wl_display* _error_ inject.gi_dpygi_dpy;
__gshared wl_proxy* _error_ inject.gi_ptrgi_ptr;
extern (C) void inject.injGlobalinjGlobal(void* data, wl_registry* (parameter) wl_registry* regreg, uint name,
const(char)* iface, uint ver) nothrow @nogc
{
if (strcmp(iface, "zwlr_virtual_pointer_manager_v1") == 0)
gi_mgr = cast(wl_proxy*) wsi_registry_bind(reg, name,
&wsi_virtual_pointer_manager_interface, 1);
else if (strcmp(iface, wl_seat_interface.name) == 0 && gi_seat is null)
gi_seat = cast(wl_seat*) wsi_registry_bind(reg, name, &wl_seat_interface, 1);
}
extern (C) void inject.injGlobalRemoveinjGlobalRemove(void* data, wl_registry* (parameter) wl_registry* regreg, uint name) nothrow @nogc
{
}
__gshared wl_registry_listener _error_ inject.gi_registryListenergi_registryListener = {&injGlobal, &injGlobalRemove};
enum uint (constant) uint inject.BTN_LEFT = 272uBTN_LEFT = 0x110;
void void inject.absMove(uint x, uint y) nothrow @nogcabsMove(uint (parameter) uint xx, uint (parameter) uint yy) nothrow @nogc
{
wsi_vptr_motion_absolute(gi_ptr, 0, x, y, 1280, 720);
wsi_vptr_frame(gi_ptr);
wl_display_flush(gi_dpy);
}
void void inject.btn(uint button, uint state) nothrow @nogcbtn(uint (parameter) uint buttonbutton, uint (parameter) uint statestate) nothrow @nogc
{
wsi_vptr_button(gi_ptr, 0, button, state);
wsi_vptr_frame(gi_ptr);
wl_display_flush(gi_dpy);
}
void void inject.pause(uint ms) nothrow @nogcpause(uint (parameter) uint msms) nothrow @nogc
{
usleep(ms * 1000);
}
int int inject.devicePlug()devicePlug() // returns 0 on success
{
gi_dpy = wl_display_connect(null);
if (gi_dpy is null)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("SKIP: inject: no Wayland compositor\n");
return 1;
}
wl_registry* (local variable) _error_ regreg = wsi_display_get_registry(gi_dpy);
wsi_registry_add_listener(reg, &gi_registryListener, null);
wl_display_roundtrip(gi_dpy);
if (gi_mgr is null)
{
int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogcprintf("SKIP: inject: no zwlr_virtual_pointer_manager_v1\n");
wl_display_disconnect(gi_dpy);
return 1;
}
gi_ptr = wsi_vpm_create_virtual_pointer(gi_mgr, gi_seat);
wl_display_roundtrip(gi_dpy); // device plugged → seat gains the capability
void inject.pause(uint ms) nothrow @nogcpause(400); // demo (re)creates its wl_pointer
return 0;
}
void void inject.deviceUnplug()deviceUnplug()
{
wsi_vptr_destroy(gi_ptr);
wsi_vpm_destroy(gi_mgr);
wl_display_roundtrip(gi_dpy);
wl_display_disconnect(gi_dpy);
}
int int inject.injectClick(int x, int y, int button)injectClick(int (parameter) int xx, int (parameter) int yy, int (parameter) int buttonbutton)
{
if (int inject.devicePlug()devicePlug() != 0)
return 0;
void inject.absMove(uint x, uint y) nothrow @nogcabsMove((parameter) int xx, (parameter) int yy);
void inject.pause(uint ms) nothrow @nogcpause(250);
void inject.btn(uint button, uint state) nothrow @nogcbtn((parameter) int buttonbutton, 1);
void inject.pause(uint ms) nothrow @nogcpause(100);
void inject.btn(uint button, uint state) nothrow @nogcbtn((parameter) int buttonbutton, 0);
void inject.pause(uint ms) nothrow @nogcpause(400);
void inject.deviceUnplug()deviceUnplug();
int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogcfprintf((shared global) shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderrstderr, "inject: click done x=%d y=%d btn=0x%x\n", (parameter) int xx, (parameter) int yy, (parameter) int buttonbutton);
return 0;
}
int int inject.injectDrag(int x1, int y1, int x2, int y2)injectDrag(int (parameter) int x1x1, int (parameter) int y1y1, int (parameter) int x2x2, int (parameter) int y2y2)
{
if (int inject.devicePlug()devicePlug() != 0)
return 0;
void inject.absMove(uint x, uint y) nothrow @nogcabsMove((parameter) int x1x1, (parameter) int y1y1);
void inject.pause(uint ms) nothrow @nogcpause(300);
void inject.btn(uint button, uint state) nothrow @nogcbtn((constant) uint inject.BTN_LEFT = 272uBTN_LEFT, 1); // implicit grab — the demo's start_drag serial
void inject.pause(uint ms) nothrow @nogcpause(400); // the demo calls start_drag inside this hold
foreach ((local variable) int ii; 1 .. 9)
{
void inject.absMove(uint x, uint y) nothrow @nogcabsMove((parameter) int x1x1 + ((parameter) int x2x2 - (parameter) int x1x1) * (local variable) int ii / 8, (parameter) int y1y1 + ((parameter) int y2y2 - (parameter) int y1y1) * (local variable) int ii / 8);
void inject.pause(uint ms) nothrow @nogcpause(90);
}
void inject.pause(uint ms) nothrow @nogcpause(300);
void inject.btn(uint button, uint state) nothrow @nogcbtn((constant) uint inject.BTN_LEFT = 272uBTN_LEFT, 0); // drop
void inject.pause(uint ms) nothrow @nogcpause(800); // receive pipe + finish round-trips
void inject.deviceUnplug()deviceUnplug();
int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogcfprintf((shared global) shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderrstderr, "inject: drag done %d,%d -> %d,%d\n", (parameter) int x1x1, (parameter) int y1y1, (parameter) int x2x2, (parameter) int y2y2);
return 0;
}