Last active
October 19, 2020 10:22
-
-
Save osnr/42468c00a2471853112e872d43408358 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local ffi = require 'ffi' | |
ffi.cdef[[ | |
typedef struct _XDisplay Display; | |
typedef struct Screen Screen; | |
extern Display *XOpenDisplay( | |
const char* /* display_name */ | |
); | |
extern int XDefaultScreen( | |
Display* /* display */ | |
); | |
typedef unsigned long XID; | |
typedef XID Window; | |
typedef unsigned long Atom; | |
typedef XID Drawable; | |
typedef XID Colormap; | |
extern Window XCreateSimpleWindow( | |
Display* /* display */, | |
Window /* parent */, | |
int /* x */, | |
int /* y */, | |
unsigned int /* width */, | |
unsigned int /* height */, | |
unsigned int /* border_width */, | |
unsigned long /* border */, | |
unsigned long /* background */ | |
); | |
extern Window XRootWindow( | |
Display* /* display */, | |
int /* screen_number */ | |
); | |
extern unsigned long XBlackPixel( | |
Display* /* display */, | |
int /* screen_number */ | |
); | |
extern unsigned long XWhitePixel( | |
Display* /* display */, | |
int /* screen_number */ | |
); | |
extern int XSelectInput( | |
Display* /* display */, | |
Window /* w */, | |
long /* event_mask */ | |
); | |
extern int XMapWindow( | |
Display* /* display */, | |
Window /* w */ | |
); | |
typedef int Bool; | |
typedef unsigned long Time; | |
/* | |
* Definitions of specific events. | |
*/ | |
typedef struct { | |
int type; /* of event */ | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; /* "event" window it is reported relative to */ | |
Window root; /* root window that the event occurred on */ | |
Window subwindow; /* child window */ | |
Time time; /* milliseconds */ | |
int x, y; /* pointer x, y coordinates in event window */ | |
int x_root, y_root; /* coordinates relative to root */ | |
unsigned int state; /* key or button mask */ | |
unsigned int keycode; /* detail */ | |
Bool same_screen; /* same screen flag */ | |
} XKeyEvent; | |
typedef XKeyEvent XKeyPressedEvent; | |
typedef XKeyEvent XKeyReleasedEvent; | |
typedef struct { | |
int type; /* of event */ | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; /* "event" window it is reported relative to */ | |
Window root; /* root window that the event occurred on */ | |
Window subwindow; /* child window */ | |
Time time; /* milliseconds */ | |
int x, y; /* pointer x, y coordinates in event window */ | |
int x_root, y_root; /* coordinates relative to root */ | |
unsigned int state; /* key or button mask */ | |
unsigned int button; /* detail */ | |
Bool same_screen; /* same screen flag */ | |
} XButtonEvent; | |
typedef XButtonEvent XButtonPressedEvent; | |
typedef XButtonEvent XButtonReleasedEvent; | |
typedef struct { | |
int type; /* of event */ | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; /* "event" window reported relative to */ | |
Window root; /* root window that the event occurred on */ | |
Window subwindow; /* child window */ | |
Time time; /* milliseconds */ | |
int x, y; /* pointer x, y coordinates in event window */ | |
int x_root, y_root; /* coordinates relative to root */ | |
unsigned int state; /* key or button mask */ | |
char is_hint; /* detail */ | |
Bool same_screen; /* same screen flag */ | |
} XMotionEvent; | |
typedef XMotionEvent XPointerMovedEvent; | |
typedef struct { | |
int type; /* of event */ | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; /* "event" window reported relative to */ | |
Window root; /* root window that the event occurred on */ | |
Window subwindow; /* child window */ | |
Time time; /* milliseconds */ | |
int x, y; /* pointer x, y coordinates in event window */ | |
int x_root, y_root; /* coordinates relative to root */ | |
int mode; /* NotifyNormal, NotifyGrab, NotifyUngrab */ | |
int detail; | |
/* | |
* NotifyAncestor, NotifyVirtual, NotifyInferior, | |
* NotifyNonlinear,NotifyNonlinearVirtual | |
*/ | |
Bool same_screen; /* same screen flag */ | |
Bool focus; /* boolean focus */ | |
unsigned int state; /* key or button mask */ | |
} XCrossingEvent; | |
typedef XCrossingEvent XEnterWindowEvent; | |
typedef XCrossingEvent XLeaveWindowEvent; | |
typedef struct { | |
int type; /* FocusIn or FocusOut */ | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; /* window of event */ | |
int mode; /* NotifyNormal, NotifyWhileGrabbed, | |
NotifyGrab, NotifyUngrab */ | |
int detail; | |
/* | |
* NotifyAncestor, NotifyVirtual, NotifyInferior, | |
* NotifyNonlinear,NotifyNonlinearVirtual, NotifyPointer, | |
* NotifyPointerRoot, NotifyDetailNone | |
*/ | |
} XFocusChangeEvent; | |
typedef XFocusChangeEvent XFocusInEvent; | |
typedef XFocusChangeEvent XFocusOutEvent; | |
/* generated on EnterWindow and FocusIn when KeyMapState selected */ | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
char key_vector[32]; | |
} XKeymapEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
int x, y; | |
int width, height; | |
int count; /* if non-zero, at least this many more */ | |
} XExposeEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Drawable drawable; | |
int x, y; | |
int width, height; | |
int count; /* if non-zero, at least this many more */ | |
int major_code; /* core is CopyArea or CopyPlane */ | |
int minor_code; /* not defined in the core */ | |
} XGraphicsExposeEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Drawable drawable; | |
int major_code; /* core is CopyArea or CopyPlane */ | |
int minor_code; /* not defined in the core */ | |
} XNoExposeEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
int state; /* Visibility state */ | |
} XVisibilityEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window parent; /* parent of the window */ | |
Window window; /* window id of window created */ | |
int x, y; /* window location */ | |
int width, height; /* size of window */ | |
int border_width; /* border width */ | |
Bool override_redirect; /* creation should be overridden */ | |
} XCreateWindowEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
} XDestroyWindowEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
Bool from_configure; | |
} XUnmapEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
Bool override_redirect; /* boolean, is override set... */ | |
} XMapEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window parent; | |
Window window; | |
} XMapRequestEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
Window parent; | |
int x, y; | |
Bool override_redirect; | |
} XReparentEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
int x, y; | |
int width, height; | |
int border_width; | |
Window above; | |
Bool override_redirect; | |
} XConfigureEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
int x, y; | |
} XGravityEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
int width, height; | |
} XResizeRequestEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window parent; | |
Window window; | |
int x, y; | |
int width, height; | |
int border_width; | |
Window above; | |
int detail; /* Above, Below, TopIf, BottomIf, Opposite */ | |
unsigned long value_mask; | |
} XConfigureRequestEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window event; | |
Window window; | |
int place; /* PlaceOnTop, PlaceOnBottom */ | |
} XCirculateEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window parent; | |
Window window; | |
int place; /* PlaceOnTop, PlaceOnBottom */ | |
} XCirculateRequestEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
Atom atom; | |
Time time; | |
int state; /* NewValue, Deleted */ | |
} XPropertyEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
Atom selection; | |
Time time; | |
} XSelectionClearEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window owner; | |
Window requestor; | |
Atom selection; | |
Atom target; | |
Atom property; | |
Time time; | |
} XSelectionRequestEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window requestor; | |
Atom selection; | |
Atom target; | |
Atom property; /* ATOM or None */ | |
Time time; | |
} XSelectionEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
Colormap colormap; /* COLORMAP or None */ | |
Bool new; | |
int state; /* ColormapInstalled, ColormapUninstalled */ | |
} XColormapEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; | |
Atom message_type; | |
int format; | |
union { | |
char b[20]; | |
short s[10]; | |
long l[5]; | |
} data; | |
} XClientMessageEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
Window window; /* unused */ | |
int request; /* one of MappingModifier, MappingKeyboard, | |
MappingPointer */ | |
int first_keycode; /* first keycode */ | |
int count; /* defines range of change w. first_keycode*/ | |
} XMappingEvent; | |
typedef struct { | |
int type; | |
Display *display; /* Display the event was read from */ | |
XID resourceid; /* resource id */ | |
unsigned long serial; /* serial number of failed request */ | |
unsigned char error_code; /* error code of failed request */ | |
unsigned char request_code; /* Major op-code of failed request */ | |
unsigned char minor_code; /* Minor op-code of failed request */ | |
} XErrorEvent; | |
typedef struct { | |
int type; | |
unsigned long serial; /* # of last request processed by server */ | |
Bool send_event; /* true if this came from a SendEvent request */ | |
Display *display;/* Display the event was read from */ | |
Window window; /* window on which event was requested in event mask */ | |
} XAnyEvent; | |
typedef struct | |
{ | |
int type; /* of event. Always GenericEvent */ | |
unsigned long serial; /* # of last request processed */ | |
Bool send_event; /* true if from SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
int extension; /* major opcode of extension that caused the event */ | |
int evtype; /* actual event type. */ | |
} XGenericEvent; | |
typedef struct { | |
int type; /* of event. Always GenericEvent */ | |
unsigned long serial; /* # of last request processed */ | |
Bool send_event; /* true if from SendEvent request */ | |
Display *display; /* Display the event was read from */ | |
int extension; /* major opcode of extension that caused the event */ | |
int evtype; /* actual event type. */ | |
unsigned int cookie; | |
void *data; | |
} XGenericEventCookie; | |
typedef union _XEvent { | |
int type; /* must not be changed; first element */ | |
XAnyEvent xany; | |
XKeyEvent xkey; | |
XButtonEvent xbutton; | |
XMotionEvent xmotion; | |
XCrossingEvent xcrossing; | |
XFocusChangeEvent xfocus; | |
XExposeEvent xexpose; | |
XGraphicsExposeEvent xgraphicsexpose; | |
XNoExposeEvent xnoexpose; | |
XVisibilityEvent xvisibility; | |
XCreateWindowEvent xcreatewindow; | |
XDestroyWindowEvent xdestroywindow; | |
XUnmapEvent xunmap; | |
XMapEvent xmap; | |
XMapRequestEvent xmaprequest; | |
XReparentEvent xreparent; | |
XConfigureEvent xconfigure; | |
XGravityEvent xgravity; | |
XResizeRequestEvent xresizerequest; | |
XConfigureRequestEvent xconfigurerequest; | |
XCirculateEvent xcirculate; | |
XCirculateRequestEvent xcirculaterequest; | |
XPropertyEvent xproperty; | |
XSelectionClearEvent xselectionclear; | |
XSelectionRequestEvent xselectionrequest; | |
XSelectionEvent xselection; | |
XColormapEvent xcolormap; | |
XClientMessageEvent xclient; | |
XMappingEvent xmapping; | |
XErrorEvent xerror; | |
XKeymapEvent xkeymap; | |
XGenericEvent xgeneric; | |
XGenericEventCookie xcookie; | |
long pad[24]; | |
} XEvent; | |
extern int XNextEvent( | |
Display* /* display */, | |
XEvent* /* event_return */ | |
); | |
typedef struct _XGC *GC; | |
extern int XDrawLine( | |
Display* /* display */, | |
Drawable /* d */, | |
GC /* gc */, | |
int /* x1 */, | |
int /* y1 */, | |
int /* x2 */, | |
int /* y2 */ | |
); | |
extern GC XDefaultGC( | |
Display* /* display */, | |
int /* screen_number */ | |
); | |
extern int XCloseDisplay( | |
Display* /* display */ | |
); | |
]] | |
local X = ffi.load('X11') | |
local ExposureMask = bit.lshift(1, 15) | |
local KeyPressMask = bit.lshift(1, 0) | |
local PointerMotionMask = bit.lshift(1, 6) | |
local KeyPress = 2 | |
local MotionNotify = 6 | |
local Expose = 12 | |
local bit = require 'bit' | |
local function new_point(x, y) | |
return {x=x, y=y} | |
end | |
local function load_points() | |
local f = loadfile('./save.txt') | |
if f == nil then | |
return {new_point(-1, -1)} | |
end | |
return f() | |
end | |
local function save_points(ll) | |
local fptr = io.open('./save.txt', 'w') | |
fptr:write('return {\n') | |
for _, head in ipairs(ll) do | |
fptr:write(string.format('{x=%i, y=%i},\n', head.x, head.y)) | |
end | |
fptr:write('}') | |
fptr:close() | |
end | |
local ll = load_points() | |
local doRefresh | |
local display = X.XOpenDisplay(nil) | |
if display == nil then | |
error("Cannot open display") | |
end | |
local s = X.XDefaultScreen(display) | |
local window = X.XCreateSimpleWindow(display, X.XRootWindow(display, s), 10, 10, 200, 200, 1, X.XBlackPixel(display, s), X.XWhitePixel(display, s)) | |
X.XSelectInput(display, window, bit.bor(ExposureMask, KeyPressMask, PointerMotionMask)) | |
X.XMapWindow(display, window) | |
local event = ffi.new('XEvent[1]') -- https://stackoverflow.com/a/24113572 | |
while true do | |
X.XNextEvent(display, event) | |
if event[0].type == MotionNotify then | |
local points_tip_new = new_point(ffi.cast('XMotionEvent*', event).x, ffi.cast('XMotionEvent*', event).y) | |
table.insert(ll, points_tip_new) | |
doRefresh = true | |
end | |
if event[0].type == Expose then | |
local points_tip_new = new_point(-1, -1) | |
table.insert(ll, points_tip_new) | |
doRefresh = true | |
end | |
if event[0].type == KeyPress and (event[0].xkey.keycode == 0x09 or event[0].xkey.keycode == 61) then -- diff keycodes on diff OSes? | |
break | |
end | |
if doRefresh then | |
local lastX = -1 | |
local lastY = -1 | |
for _, p in ipairs(ll) do | |
if p.x ~= -1 and lastX ~= -1 then | |
X.XDrawLine(display, window, X.XDefaultGC(display, s), p.x, p.y, lastX, lastY) | |
end | |
lastX = p.x | |
lastY = p.y | |
end | |
doRefresh = false | |
end | |
end | |
save_points(ll) | |
X.XCloseDisplay(display) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment