#|Use like this:
$ doas pkg_add sdl2 ecl
$ ecl
> (ext:install-c-compiler)
> (setf c:*user-ld-flags* "-lSDL2")
> (compile-file "keys.ecl.lisp" :load t)
> (sdl2-receive-keys) ; pops up a window. Use the x button or your wm to quit
Hope it helps someone. Ask jackdaniel to support you <3.
I use the undrawn window for sloppy focus. ymmv
|#
(ffi:clines "
#include <stdio.h>
#include <SDL2/SDL.h>
SDL_Renderer *renderer;
SDL_Window *window;
SDL_Event e;
")
(defun c-keyname (sdlk) "
sdlk should be an e.key.keysym.sym originating int.
"
(let ((cstring (ffi:c-inline (sdlk) (:int) :cstring "SDL_GetKeyName(#0)" :one-liner t)))
(ffi:convert-from-cstring cstring)))
(defun interpret-mods (keymod) "
keymod should be an e.key.keysym.mod originating int.
"
(let ((mods '((:lshift . #x1)
(:rshift . #x2)
(:lctrl . #x40)
(:rctrl . #x80)
(:lalt . #x100)
(:ralt . #x200)
(:lgui . #x400)
(:rgui . #x800)
(:num . #x1000)
(:caps . #x2000)
(:mode . #x4000)
(:scroll . #x8000))))
(loop :for mod :in mods
:for kw := (car mod)
:for hx := (cdr mod)
:unless (zerop (logand hx keymod))
:collect kw)))
(defun sdl2-receive-keys (&aux (keys ()))
(let ((key 0) ; int (ie default enum)
(mod 0)) ; uint16
(declare (:int key mod))
(ffi:c-progn (key mod)
"
if (SDL_Init(SDL_INIT_VIDEO) < 0)
"
(error "%s failed" 'SDL_INIT_VIDEO)
"
if (SDL_CreateWindowAndRenderer(
640, 480, SDL_WINDOW_RESIZABLE,
&window, &renderer))
"
(error "%s failed" 'SDL_WINDOW_RESIZABLE)
"
for (;;) {
SDL_SetRenderDrawColor(renderer,0,0,0,255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(25);
while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT) {
quit:
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();"
(return-from sdl2-receive-keys (nreverse keys)) "
} else if (e.type == SDL_KEYDOWN)
if (e.key.keysym.sym == SDLK_ESCAPE) goto quit;
else {
#0 = (int)(e.key.keysym.sym );
#1 = (int)(e.key.keysym.mod & 65475);"
(push (list (intern (c-keyname key) :keyword)
(interpret-mods mod)
key
mod)
keys)
"}}")))