Compare commits
No commits in common. "60d44668573a9ef44cdc7137c5f4d1e2bc7249fa" and "3628e93d1886b311fbd7a5c22bb5ff09d57d7609" have entirely different histories.
60d4466857
...
3628e93d18
6
Makefile
Normal file
6
Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
default:
|
||||||
|
|
||||||
|
install: default
|
||||||
|
|
||||||
|
run:
|
||||||
|
lua -e 'os.execute("kiwmi -c init.lua")'
|
49
README.md
49
README.md
@ -18,42 +18,35 @@ As of 2022 these principles are more aspirational than actual.
|
|||||||
|
|
||||||
## Running it
|
## Running it
|
||||||
|
|
||||||
$ nix-shell --run "kiwmi -c init.lua"
|
$ nix-shell build.nix
|
||||||
|
nix-shell$ make run
|
||||||
|
|
||||||
`shell.nix` sets `LUA_PATH` and `LUA_CPATH` settings appropriately -
|
`make run` executes `lua -e 'os.execute("kiwmi -c init.lua")'`. This
|
||||||
if you want to write a real derivation (I'll get to it eventually)
|
is suboptimally hairy, at least for the moment: Nix makes a wrapper
|
||||||
you'll need to sort that out yourself. Nix generates a wrapper script
|
script for the Lua executable that has appropriate `LUA_PATH` and
|
||||||
for the Lua interpreter itself, but it doesn't do the same for kiwmi.
|
`LUA_CPATH` settings, but it doesn't do the same for kiwmi.
|
||||||
|
|
||||||
## Connecting to the repl
|
|
||||||
|
|
||||||
If you are using the example rc.fnl, it opens a Unix socket that you
|
|
||||||
can connect to and interact with a Fennel REPL. I use
|
|
||||||
[socat](http://www.dest-unreach.org/socat/) for this purpose:
|
|
||||||
|
|
||||||
$ socat - unix-connect:${XDG_RUNTIME_DIR}/kiwmi-repl.wayland-1.socket
|
|
||||||
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
|
|
||||||
- [X] notifications (crier)
|
[X] notifications (crier)
|
||||||
- [X] web browser (just)
|
[ ] web browser (just)
|
||||||
- [ ] keyboard
|
[ ] keyboard
|
||||||
- [ ] wifi network chooser
|
[ ] wifi network chooser
|
||||||
- [ ] settings: toggle network interfaces, change volume & screen brightness
|
[ ] settings: toggle network interfaces, change volume & screen brightness
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
|
|
||||||
- [ ] better window management
|
[ ] better window management
|
||||||
- gestures to switch view
|
- gestures to switch view
|
||||||
- gesture to launch terminal?
|
- gesture to launch terminal?
|
||||||
- some way to kill an app
|
- some way to kill an app
|
||||||
- kiwmi may or may not have touch support
|
- kiwmi may or may not have touch support
|
||||||
|
|
||||||
- [ ] some way to add launcher shortcuts for Fennel functions
|
[ ] some way to add launcher shortcuts for Fennel functions
|
||||||
- [ ] hook up system to session bus, to handle incoming calls
|
[ ] hook up system to session bus, to handle incoming calls
|
||||||
- [X] kiwmi: support reloading config or otherwise making live changes
|
[ ] kiwmi: support reloading config or otherwise making live changes
|
||||||
- [ ] why are overlay windows overlapping regular view?
|
[ ] why are overlay windows overlapping regular view?
|
||||||
- [ ] screen lock
|
[ ] screen lock
|
||||||
|
@ -54,7 +54,6 @@ struct kiwmi_view {
|
|||||||
|
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
float matrix[9];
|
|
||||||
|
|
||||||
bool mapped;
|
bool mapped;
|
||||||
bool hidden;
|
bool hidden;
|
||||||
|
@ -101,36 +101,29 @@ render_surface(struct wlr_surface *surface, int sx, int sy, void *data)
|
|||||||
struct kiwmi_render_data *rdata = data;
|
struct kiwmi_render_data *rdata = data;
|
||||||
struct kiwmi_view *view = rdata->data;
|
struct kiwmi_view *view = rdata->data;
|
||||||
struct wlr_output *wlr_output = rdata->output;
|
struct wlr_output *wlr_output = rdata->output;
|
||||||
float mat[9] = { 1,0,0, 0,1,0, 0,0,1 };
|
|
||||||
|
|
||||||
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_matrix_translate(mat,
|
int ox = rdata->output_lx + sx + view->x - view->geom.x;
|
||||||
sx + view->x - view->geom.x,
|
int oy = rdata->output_ly + sy + view->y - view->geom.y;
|
||||||
sy + view->y - view->geom.y);
|
|
||||||
wlr_matrix_scale(mat, surface->current.width, surface->current.height);
|
|
||||||
wlr_matrix_multiply(mat, view->matrix, mat);
|
|
||||||
|
|
||||||
|
struct wlr_box box = {
|
||||||
|
.x = ox * wlr_output->scale,
|
||||||
|
.y = oy * wlr_output->scale,
|
||||||
|
.width = surface->current.width * wlr_output->scale,
|
||||||
|
.height = surface->current.height * wlr_output->scale,
|
||||||
|
};
|
||||||
|
|
||||||
|
float matrix[9];
|
||||||
enum wl_output_transform transform =
|
enum wl_output_transform transform =
|
||||||
wlr_output_transform_invert(surface->current.transform);
|
wlr_output_transform_invert(surface->current.transform);
|
||||||
|
wlr_matrix_project_box(
|
||||||
|
matrix, &box, transform, 0, wlr_output->transform_matrix);
|
||||||
|
|
||||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
|
wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);
|
||||||
wlr_matrix_translate(mat, 0.5, 0.5);
|
|
||||||
wlr_matrix_transform(mat, transform);
|
|
||||||
wlr_matrix_translate(mat, -0.5, -0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* looking at the definition of wlr_matrix_project_box,
|
|
||||||
* wlr_output->transform_matrix would be
|
|
||||||
* better named wlr_output->projection_matrix
|
|
||||||
*/
|
|
||||||
|
|
||||||
wlr_matrix_multiply(mat, wlr_output->transform_matrix, mat);
|
|
||||||
|
|
||||||
wlr_render_texture_with_matrix(rdata->renderer, texture, mat, 1);
|
|
||||||
|
|
||||||
wlr_surface_send_frame_done(surface, rdata->when);
|
wlr_surface_send_frame_done(surface, rdata->when);
|
||||||
}
|
}
|
||||||
|
@ -293,11 +293,6 @@ view_create(
|
|||||||
|
|
||||||
view->x = 0;
|
view->x = 0;
|
||||||
view->y = 0;
|
view->y = 0;
|
||||||
for(int r=0; r < 3; r++) {
|
|
||||||
for(int c=0; c < 3; c++) {
|
|
||||||
view->matrix[r*3+c] = (r == c) ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_init(&view->children);
|
wl_list_init(&view->children);
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
@ -209,73 +208,6 @@ l_kiwmi_server_quit(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
kiwmi_server_event_loop_fd_handler(int fd, uint32_t mask, void *data)
|
|
||||||
{
|
|
||||||
struct kiwmi_lua_callback *lc = data;
|
|
||||||
lua_State *L = lc->server->lua->L;
|
|
||||||
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
|
|
||||||
lua_pushinteger(L, fd);
|
|
||||||
lua_pushinteger(L, mask);
|
|
||||||
|
|
||||||
if (lua_pcall(L, 2, 1, 0)) {
|
|
||||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if callback returns false/nil, remove the handler */
|
|
||||||
if (! lua_toboolean(L, -1)) {
|
|
||||||
wl_event_source_remove(lc->event_source);
|
|
||||||
|
|
||||||
luaL_unref(L, LUA_REGISTRYINDEX, lc->callback_ref);
|
|
||||||
free(lc);
|
|
||||||
}
|
|
||||||
lua_pop(L, -1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
l_kiwmi_server_event_loop_add_fd(lua_State *L)
|
|
||||||
{
|
|
||||||
/* args : self, fd, mode, handler */
|
|
||||||
struct kiwmi_object *obj =
|
|
||||||
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_server");
|
|
||||||
|
|
||||||
struct kiwmi_server *server = obj->object;
|
|
||||||
|
|
||||||
int fd = lua_tonumber(L, 2);
|
|
||||||
int mode = lua_tonumber(L, 3);
|
|
||||||
luaL_checktype(L, 4, LUA_TFUNCTION); // callback
|
|
||||||
|
|
||||||
int event_types;
|
|
||||||
switch(mode) {
|
|
||||||
case O_WRONLY: event_types = WL_EVENT_WRITABLE; break;
|
|
||||||
case O_RDONLY: event_types = WL_EVENT_READABLE; break;
|
|
||||||
default: event_types = WL_EVENT_WRITABLE | WL_EVENT_READABLE; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct kiwmi_lua_callback *lc = malloc(sizeof(*lc));
|
|
||||||
if (!lc) {
|
|
||||||
return luaL_error(L, "failed to allocate kiwmi_lua_callback");
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_log(WLR_INFO, "add fd %d lc=%x\n", fd, lc);
|
|
||||||
|
|
||||||
lc->server = server;
|
|
||||||
/* luaL_ref pops last parameter (callback) from stack */
|
|
||||||
lc->callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
|
||||||
|
|
||||||
lc->event_source =
|
|
||||||
wl_event_loop_add_fd(server->wl_event_loop,
|
|
||||||
fd,
|
|
||||||
event_types,
|
|
||||||
kiwmi_server_event_loop_fd_handler,
|
|
||||||
lc);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kiwmi_server_schedule_handler(void *data)
|
kiwmi_server_schedule_handler(void *data)
|
||||||
{
|
{
|
||||||
@ -463,7 +395,6 @@ static const luaL_Reg kiwmi_server_methods[] = {
|
|||||||
{"verbosity", l_kiwmi_server_verbosity},
|
{"verbosity", l_kiwmi_server_verbosity},
|
||||||
{"view_at", l_kiwmi_server_view_at},
|
{"view_at", l_kiwmi_server_view_at},
|
||||||
{"outputs", l_kiwmi_server_next_output},
|
{"outputs", l_kiwmi_server_next_output},
|
||||||
{"event_loop_add_fd", l_kiwmi_server_event_loop_add_fd},
|
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -247,49 +247,6 @@ l_kiwmi_view_move(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
l_kiwmi_view_matrix(lua_State *L)
|
|
||||||
{
|
|
||||||
struct kiwmi_object *obj =
|
|
||||||
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view");
|
|
||||||
|
|
||||||
if (!obj->valid) {
|
|
||||||
return luaL_error(L, "kiwmi_view no longer valid");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct kiwmi_view *view = obj->object;
|
|
||||||
|
|
||||||
lua_newtable(L);
|
|
||||||
for(int i=0; i< 9; i++) {
|
|
||||||
lua_pushnumber(L, view->matrix[i]);
|
|
||||||
lua_seti(L, -2, 1 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
l_kiwmi_view_set_matrix(lua_State *L)
|
|
||||||
{
|
|
||||||
struct kiwmi_object *obj =
|
|
||||||
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_view");
|
|
||||||
|
|
||||||
if (!obj->valid) {
|
|
||||||
return luaL_error(L, "kiwmi_view no longer valid");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct kiwmi_view *view = obj->object;
|
|
||||||
|
|
||||||
luaL_checktype(L, 2, LUA_TTABLE);
|
|
||||||
|
|
||||||
for(int i=0; i< 9; i++) {
|
|
||||||
lua_geti(L, 2, 1 + i);
|
|
||||||
view->matrix[i] = lua_tonumber(L, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
l_kiwmi_view_pid(lua_State *L)
|
l_kiwmi_view_pid(lua_State *L)
|
||||||
{
|
{
|
||||||
@ -477,8 +434,6 @@ static const luaL_Reg kiwmi_view_methods[] = {
|
|||||||
{"imove", l_kiwmi_view_imove},
|
{"imove", l_kiwmi_view_imove},
|
||||||
{"iresize", l_kiwmi_view_iresize},
|
{"iresize", l_kiwmi_view_iresize},
|
||||||
{"move", l_kiwmi_view_move},
|
{"move", l_kiwmi_view_move},
|
||||||
{"matrix", l_kiwmi_view_matrix},
|
|
||||||
{"set_matrix", l_kiwmi_view_set_matrix},
|
|
||||||
{"on", luaK_callback_register_dispatch},
|
{"on", luaK_callback_register_dispatch},
|
||||||
{"pid", l_kiwmi_view_pid},
|
{"pid", l_kiwmi_view_pid},
|
||||||
{"pos", l_kiwmi_view_pos},
|
{"pos", l_kiwmi_view_pos},
|
||||||
|
@ -33,16 +33,6 @@ Sets the background color (shown behind all views) to `color` (in the format #rr
|
|||||||
|
|
||||||
Returns a reference to the cursor object.
|
Returns a reference to the cursor object.
|
||||||
|
|
||||||
#### kiwmi:event_loop_add_fd(fd, mode, callback)
|
|
||||||
|
|
||||||
By registering with the event loop, arrange for `callback` to be called
|
|
||||||
whenever there is activity on the file descriptor `fd`. The `mode` parameter
|
|
||||||
is one of `O_RDWR`, `O_RDONLY`, `O_WRONLY` as defined in luaposix
|
|
||||||
`posix.fcntl` module.
|
|
||||||
|
|
||||||
If `callback` returns false or nil, the handler will be unregistered
|
|
||||||
from the event loop and not called again.
|
|
||||||
|
|
||||||
#### kiwmi:focused_view()
|
#### kiwmi:focused_view()
|
||||||
|
|
||||||
Returns the currently focused view.
|
Returns the currently focused view.
|
||||||
|
9
rc.fnl
9
rc.fnl
@ -1,16 +1,7 @@
|
|||||||
(local { : GdkPixbuf } (require :lgi))
|
(local { : GdkPixbuf } (require :lgi))
|
||||||
(local { : view } (require :fennel))
|
(local { : view } (require :fennel))
|
||||||
|
|
||||||
(local socket-repl (require :socket-repl))
|
|
||||||
|
|
||||||
(let [repl-socket-name
|
|
||||||
(..
|
|
||||||
(: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "")
|
|
||||||
"/kiwmi-repl."
|
|
||||||
(os.getenv "WAYLAND_DISPLAY")
|
|
||||||
".socket"
|
|
||||||
)]
|
|
||||||
(socket-repl.start repl-socket-name))
|
|
||||||
|
|
||||||
|
|
||||||
(fn texture-from-file [renderer filename]
|
(fn texture-from-file [renderer filename]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
with import <nixpkgs> {} ;
|
with import <nixpkgs> {} ;
|
||||||
let p = callPackage ./. {};
|
let p = callPackage ./. {};
|
||||||
in (p.overrideAttrs (o:{
|
in (p.overrideAttrs (o:{
|
||||||
nativeBuildInputs = with pkgs; [gdb socat];
|
nativeBuildInputs = [pkgs.gdb];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export LUA_PATH=`lua -e 'print(package.path)'`
|
export LUA_PATH=`lua -e 'print(package.path)'`
|
||||||
export LUA_CPATH=`lua -e 'print(package.cpath)'`
|
export LUA_CPATH=`lua -e 'print(package.cpath)'`
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
(local { : fdopen } (require "posix.stdio"))
|
|
||||||
(local fcntl (require "posix.fcntl"))
|
|
||||||
(local unistd (require "posix.unistd"))
|
|
||||||
(local socket (require "posix.sys.socket"))
|
|
||||||
(local { : repl } (require :fennel))
|
|
||||||
|
|
||||||
(fn watch-fd [fd mode handler]
|
|
||||||
(kiwmi:event_loop_add_fd fd mode handler))
|
|
||||||
|
|
||||||
(fn unix-socket-listener [pathname on-connected]
|
|
||||||
(let [sa {:family socket.AF_UNIX
|
|
||||||
:path pathname
|
|
||||||
}
|
|
||||||
fd (socket.socket socket.AF_UNIX socket.SOCK_STREAM 0)]
|
|
||||||
(socket.bind fd sa)
|
|
||||||
(socket.listen fd 5)
|
|
||||||
(watch-fd
|
|
||||||
fd fcntl.O_RDWR
|
|
||||||
#(let [connected-fd (socket.accept $1)]
|
|
||||||
(on-connected connected-fd)))
|
|
||||||
))
|
|
||||||
|
|
||||||
(fn start [pathname]
|
|
||||||
(unistd.unlink pathname)
|
|
||||||
(unix-socket-listener
|
|
||||||
pathname
|
|
||||||
(fn [fd]
|
|
||||||
(let [sock (fdopen fd "w+")
|
|
||||||
repl-coro (coroutine.create repl)]
|
|
||||||
(watch-fd fd fcntl.O_RDONLY
|
|
||||||
(fn [fd]
|
|
||||||
(let [buf (unistd.read fd 1024)
|
|
||||||
input
|
|
||||||
(if (and buf (> (# buf) 0))
|
|
||||||
buf
|
|
||||||
"\n,exit")]
|
|
||||||
(coroutine.resume repl-coro input))
|
|
||||||
(if (= (coroutine.status repl-coro) :dead)
|
|
||||||
(do
|
|
||||||
(sock:write "bye!\n")
|
|
||||||
(sock:close)
|
|
||||||
(unistd.close fd)
|
|
||||||
false)
|
|
||||||
true
|
|
||||||
)))
|
|
||||||
(coroutine.resume repl-coro
|
|
||||||
{:readChunk
|
|
||||||
(fn [{: stack-size}]
|
|
||||||
(sock:write
|
|
||||||
(if (> stack-size 0) ".." ">> "))
|
|
||||||
(sock:flush)
|
|
||||||
(coroutine.yield))
|
|
||||||
:onValues
|
|
||||||
(fn [vals]
|
|
||||||
(sock:write (table.concat vals "\t"))
|
|
||||||
(sock:write "\n"))
|
|
||||||
:onError
|
|
||||||
(fn [errtype err]
|
|
||||||
(sock:write
|
|
||||||
(.. errtype " error: " (tostring err) "\n")))
|
|
||||||
})))))
|
|
||||||
|
|
||||||
|
|
||||||
{ : start }
|
|
Loading…
Reference in New Issue
Block a user