Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
Daniel Barlow | c485e59c3a | |
Daniel Barlow | a19eb2c8de | |
Daniel Barlow | 771d80c70d | |
Daniel Barlow | 32e78a24db | |
Daniel Barlow | 4c4bd9e997 | |
Daniel Barlow | cba4549304 | |
Daniel Barlow | 7dac09a17a | |
Daniel Barlow | 2975908e81 | |
Daniel Barlow | 5a5e1de965 | |
Daniel Barlow | c980f7fe20 | |
Daniel Barlow | 2c51676436 | |
Daniel Barlow | 36496ad126 | |
Daniel Barlow | 41b72f95c1 | |
Daniel Barlow | 9110280373 | |
Daniel Barlow | b34a43897a | |
Daniel Barlow | bd18a20251 | |
Daniel Barlow | 27b28e997b | |
Daniel Barlow | ee2730f757 | |
Daniel Barlow | 8683fce4aa | |
Daniel Barlow | 1875b87592 | |
Daniel Barlow | 69753c2345 | |
Daniel Barlow | 07fd321f94 | |
Daniel Barlow | 67e03c6736 | |
Daniel Barlow | 60d4466857 |
|
@ -0,0 +1,3 @@
|
|||
*~
|
||||
result*
|
||||
*.img
|
57
README.md
57
README.md
|
@ -1,9 +1,11 @@
|
|||
# eufon
|
||||
|
||||
**Broken, not ready for use**
|
||||
|
||||
> *euphony*: _noun_ Harmonious arrangement of sounds in composition; a smooth and agreeable combination of articulate elements in any piece of writing.
|
||||
|
||||
A mostly Fennel-based graphical environment tailored for the Pinephone
|
||||
(other Linux-based mobile devices exist). The principles we aspire to are
|
||||
A mostly Fennel-based graphical environment tailored for Linux-based
|
||||
mobile devices. The principles we aspire to are
|
||||
|
||||
* "habitable software" - build the system in such a way that a
|
||||
technically competent user may change it to serve their needs,
|
||||
|
@ -14,24 +16,51 @@ A mostly Fennel-based graphical environment tailored for the Pinephone
|
|||
hardware buttons, let's play to its strengths instead of compensating for
|
||||
its weaknesses
|
||||
|
||||
As of 2022 these principles are more aspirational than actual.
|
||||
As of 2022 these principles are more aspirational than actual. _This
|
||||
repo is basically in an advanced state of brokenness_
|
||||
|
||||
## Running it
|
||||
## Running the shell/apps locally
|
||||
|
||||
$ nix-shell --run "kiwmi -c init.lua"
|
||||
$ nix-shell
|
||||
nix-shell$ kiwmi -c init.lua
|
||||
|
||||
`shell.nix` sets `LUA_PATH` and `LUA_CPATH` settings appropriately -
|
||||
if you want to write a real derivation (I'll get to it eventually)
|
||||
you'll need to sort that out yourself. Nix generates a wrapper script
|
||||
for the Lua interpreter itself, but it doesn't do the same for kiwmi.
|
||||
This works on desktop or on mobile - Kiwmi is built on wlroots, which
|
||||
will open a window on your existing Wayland or X11 desktop if you're
|
||||
running one.
|
||||
|
||||
If you're connected over ssh and want to run Kiwmi on the console,
|
||||
further contortions are required as you don't have the permissions
|
||||
by default: run this before attempting to start Kiwmi
|
||||
|
||||
nix-shell -p seatd --run "sudo -b seatd -u $USER"
|
||||
|
||||
## 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:
|
||||
By default Eufon opens a Unix socket to which you can connect to
|
||||
interact with a Fennel REPL. The `eufonctl` script is a wrapper around
|
||||
[socat](http://www.dest-unreach.org/socat/)
|
||||
|
||||
$ eufonctl $WAYLAND_DISPLAY
|
||||
|
||||
|
||||
## Building for a device
|
||||
|
||||
Eufon can be installed as a [Mobile NixOS](https://github.com/NixOS/mobile-nixos/) module, by adding
|
||||
`module.nix` to the `imports` in `your configuration.nix`. For example, on my development phone I
|
||||
have
|
||||
|
||||
```nix
|
||||
imports = [
|
||||
(import <mobile-nixos/lib/configuration.nix> {
|
||||
device = "motorola-potter";
|
||||
})
|
||||
/home/dan/src/phoen/eufon/module.nix
|
||||
];
|
||||
```
|
||||
|
||||
Instructions for using Mobile NixOS are currently outside the scope of
|
||||
this README.
|
||||
|
||||
$ socat - unix-connect:${XDG_RUNTIME_DIR}/kiwmi-repl.wayland-1.socket
|
||||
|
||||
|
||||
# TODO
|
||||
|
@ -50,7 +79,7 @@ can connect to and interact with a Fennel REPL. I use
|
|||
- gestures to switch view
|
||||
- gesture to launch terminal?
|
||||
- some way to kill an app
|
||||
- kiwmi may or may not have touch support
|
||||
- finish adding touch support to Kiwmi - https://github.com/buffet/kiwmi/pull/64
|
||||
|
||||
- [ ] some way to add launcher shortcuts for Fennel functions
|
||||
- [ ] hook up system to session bus, to handle incoming calls
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
kiwmi -V -V -c init.lua
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
SOCAT=socat
|
||||
display=$1
|
||||
test -n "$display" || display=$WAYLAND_DISPLAY
|
||||
test -n "$display" || display=wayland-0
|
||||
|
||||
socket_name="${XDG_RUNTIME_DIR}/kiwmi-repl.${display}.socket"
|
||||
|
||||
${SOCAT} - unix-connect:$socket_name
|
|
@ -8,7 +8,7 @@
|
|||
(local Gtk lgi.Gtk)
|
||||
|
||||
(fn relpath [filename]
|
||||
(.. "crier/" filename))
|
||||
(.. (os.getenv "EUFON_PATH") "/crier/" filename))
|
||||
|
||||
(local dbus-service-attrs
|
||||
{
|
27
default.nix
27
default.nix
|
@ -10,6 +10,10 @@
|
|||
, gtk3
|
||||
, gtk-layer-shell
|
||||
, lua5_3
|
||||
, socat
|
||||
, cpio
|
||||
|
||||
, makeWrapper
|
||||
} :
|
||||
let
|
||||
lua = lua5_3;
|
||||
|
@ -62,6 +66,29 @@ stdenv.mkDerivation {
|
|||
gtk3
|
||||
webkitgtk
|
||||
];
|
||||
nativeBuildInputs = [ cpio makeWrapper ];
|
||||
|
||||
installPhase = ''
|
||||
export LUA_PATH="`lua -e 'print(package.path)'`"
|
||||
export LUA_CPATH="`lua -e 'print(package.cpath)'`"
|
||||
mkdir -p $out/bin
|
||||
find . -name kiwmi -prune \
|
||||
-o -type l -prune \
|
||||
-o -name git -prune \
|
||||
-o -print0 | cpio -0 -v --pass-through $out
|
||||
substitute bin/eufonctl.sh $out/bin/eufonctl \
|
||||
--replace SOCAT=socat SOCAT=${socat}/bin/socat
|
||||
makeWrapper ${kiwmi}/bin/kiwmi $out/bin/eufon \
|
||||
--set LUA_PATH "$out/?.lua;$LUA_PATH" \
|
||||
--set LUA_CPATH "$LUA_CPATH" \
|
||||
--prefix PATH : ${kiwmi}/bin:${luaWithPackages}/bin \
|
||||
--set EUFON_PATH "$out" \
|
||||
--set GIO_EXTRA_MODULES "${glib-networking}/lib/gio/modules" \
|
||||
--set GI_TYPELIB_PATH "$GI_TYPELIB_PATH" \
|
||||
--add-flags "-c $out/init.lua"
|
||||
|
||||
chmod +x $out/bin/eufon
|
||||
'';
|
||||
|
||||
src = ./.;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
;; -*- mode: Fennel;
|
||||
|
||||
(local { : view } (require :fennel))
|
||||
|
||||
(local texture (require :texture))
|
||||
(local matrix (require :matrix))
|
||||
(local socket-repl (require :socket-repl))
|
||||
|
||||
(local app-state
|
||||
{
|
||||
:in-overview false
|
||||
:focus-view nil
|
||||
:views []
|
||||
})
|
||||
|
||||
(let [repl-socket-name
|
||||
(..
|
||||
(: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "")
|
||||
"/kiwmi-repl."
|
||||
(os.getenv "WAYLAND_DISPLAY")
|
||||
".socket"
|
||||
)]
|
||||
(socket-repl.start repl-socket-name))
|
||||
|
||||
(fn resize-wayland-backend [output]
|
||||
(when (string.find (output:name) "^WL-")
|
||||
(output:set_mode 360 720 0)))
|
||||
|
||||
(fn kill-window []
|
||||
(print "DIE")
|
||||
true)
|
||||
|
||||
(fn launch []
|
||||
(print "WHOOSH")
|
||||
true)
|
||||
|
||||
(fn eufon-path [f]
|
||||
(.. (os.getenv "EUFON_PATH") "/" f))
|
||||
|
||||
(fn show-overview []
|
||||
(let [facets 64
|
||||
angle (/ (* 2 math.pi) facets)
|
||||
scale 0.6
|
||||
y-offset (+ (* 1 680)
|
||||
(/ (* 360 facets) (* 2 math.pi)))
|
||||
]
|
||||
(each [i view (ipairs app-state.views)]
|
||||
(doto view
|
||||
(: :set_matrix
|
||||
(-> matrix.identity
|
||||
(matrix.scale scale scale)
|
||||
(matrix.translate (* 2 180) (+ y-offset))
|
||||
(matrix.rotate (/ (* (- i 2
|
||||
) angle) 1))
|
||||
(matrix.translate (* -2 180) (- y-offset))
|
||||
(matrix.translate 120 150)
|
||||
))
|
||||
(: :show)))))
|
||||
|
||||
|
||||
(fn hide-overview []
|
||||
(each [k view (pairs app-state.views)]
|
||||
(view:set_matrix matrix.identity)
|
||||
(if (= (view:id) (app-state.focus-view:id))
|
||||
(doto view
|
||||
(: :show)
|
||||
(: :focus))
|
||||
(view:hide))))
|
||||
|
||||
(fn carousel []
|
||||
(let [was app-state.in-overview]
|
||||
(if was
|
||||
(hide-overview)
|
||||
(show-overview))
|
||||
(: (kiwmi:active_output) :redraw)
|
||||
(tset app-state :in-overview (not was))))
|
||||
|
||||
(fn placements [output]
|
||||
(let [(width height) (output:size)
|
||||
bar-height (/ height 15)]
|
||||
{
|
||||
|
||||
:application {
|
||||
:x 0
|
||||
:y 0
|
||||
:w width
|
||||
:h (- height (* bar-height 1.1))
|
||||
}
|
||||
:bar {
|
||||
:x 0
|
||||
:y (- height (* bar-height 1.1))
|
||||
:w width
|
||||
:h (* bar-height 1.1)
|
||||
}
|
||||
:kill {
|
||||
:x (- (* width 0.25) (/ bar-height 2))
|
||||
:y (- height bar-height)
|
||||
:w bar-height
|
||||
:h bar-height
|
||||
:on-press kill-window
|
||||
}
|
||||
:launch {
|
||||
:x (- (* width 0.5) (/ bar-height 2))
|
||||
:y (- height bar-height)
|
||||
:w bar-height
|
||||
:h bar-height
|
||||
:on-press launch
|
||||
}
|
||||
:overview {
|
||||
:x (- (* width 0.75) (/ bar-height 2))
|
||||
:y (- height bar-height)
|
||||
:w bar-height
|
||||
:h bar-height
|
||||
:on-press carousel
|
||||
}
|
||||
}))
|
||||
|
||||
(fn choose-view-at [x y]
|
||||
(let [view (kiwmi:view_at x y)]
|
||||
(tset app-state :focus-view view)
|
||||
(tset app-state :in-overview false)
|
||||
(hide-overview)
|
||||
true))
|
||||
|
||||
(let [cursor (kiwmi:cursor)]
|
||||
(cursor:on "button_up"
|
||||
(fn [button-id]
|
||||
(when app-state.in-overview
|
||||
(let [geom (placements (kiwmi:active_output))
|
||||
(x y) (cursor:pos)]
|
||||
(if (< y geom.application.h)
|
||||
(choose-view-at x y)
|
||||
false))))))
|
||||
|
||||
(kiwmi:on
|
||||
"output"
|
||||
(fn [output]
|
||||
(resize-wayland-backend output)
|
||||
(let [(width height) (output:size)
|
||||
r (output:renderer)
|
||||
kill (texture.from-file r (eufon-path "close-window.png"))
|
||||
launch (texture.from-file r (eufon-path "launcher.png"))
|
||||
overview (texture.from-file r (eufon-path "carousel.png"))]
|
||||
(output:on "render"
|
||||
(fn [{: output : renderer}]
|
||||
(let [buttons (placements output)]
|
||||
(renderer:draw_rect :#77000077
|
||||
buttons.bar.x buttons.bar.y
|
||||
buttons.bar.w buttons.bar.h)
|
||||
(renderer:draw_texture
|
||||
kill
|
||||
matrix.identity
|
||||
buttons.kill.x buttons.kill.y
|
||||
0.7)
|
||||
(renderer:draw_texture
|
||||
launch
|
||||
matrix.identity
|
||||
buttons.launch.x buttons.launch.y
|
||||
0.7)
|
||||
(renderer:draw_texture
|
||||
overview
|
||||
matrix.identity
|
||||
buttons.overview.x buttons.overview.y
|
||||
0.7)))))))
|
||||
|
||||
|
||||
(let [cursor (kiwmi:cursor)]
|
||||
(cursor:on "button_down"
|
||||
(fn [button]
|
||||
(let [(x y) (cursor:pos)]
|
||||
(each [name attribs (pairs (placements (kiwmi:active_output)))]
|
||||
(if (and
|
||||
(<= attribs.x x)
|
||||
(< x (+ attribs.x attribs.w))
|
||||
(<= attribs.y y)
|
||||
(< y (+ attribs.y attribs.h)))
|
||||
(if attribs.on-press (attribs.on-press))))))))
|
||||
|
||||
(kiwmi:on "view"
|
||||
(fn [view]
|
||||
(let [geom (placements (kiwmi:active_output))]
|
||||
(view:resize geom.application.w geom.application.h)
|
||||
(view:move geom.application.x geom.application.y))
|
||||
(view:focus)
|
||||
(view:show)
|
||||
(tset app-state :focus-view view)
|
||||
(table.insert app-state.views view)
|
||||
(view:on "request_move" #(view:imove))
|
||||
(view:on "request_resize" (fn [ev] (view:iresize ev.edges)))))
|
||||
|
||||
(kiwmi:spawn "swaybg -c '#ff00ff'")
|
||||
(kiwmi:spawn "lua -l fennelrun modeline")
|
||||
;(kiwmi:spawn "lua -l fennelrun saturn")
|
||||
(kiwmi:spawn "lua -l fennelrun crier")
|
||||
(kiwmi:spawn "lua -l fennelrun just https://brvt.telent.net")
|
||||
;(kiwmi:spawn "foot")
|
||||
|
||||
;; Local Variables:
|
||||
;; inferior-lisp-program: "eufonctl"
|
||||
;; End:
|
|
@ -1,4 +1,6 @@
|
|||
local fennel = require("fennel")
|
||||
table.insert(package.loaders or package.searchers, fennel.searcher)
|
||||
-- print(fennel.view(arg))
|
||||
fennel.dofile(arg[0], { correlate = true })
|
||||
fennel.path = os.getenv("EUFON_PATH") .. "/?.fnl;" ..
|
||||
os.getenv("EUFON_PATH") .. "/?/init.fnl;"
|
||||
|
||||
require(arg[0])
|
||||
|
|
3
init.lua
3
init.lua
|
@ -3,4 +3,5 @@ print(os.getenv("LUA_CPATH"))
|
|||
|
||||
local fennel = require("fennel")
|
||||
table.insert(package.loaders or package.searchers, fennel.searcher)
|
||||
fennel.dofile("rc.fnl")
|
||||
fennel.path = fennel.path .. ";" .. os.getenv("EUFON_PATH") .. "/?.fnl"
|
||||
require("eufon")
|
||||
|
|
|
@ -39,6 +39,10 @@ struct kiwmi_cursor {
|
|||
struct wl_listener cursor_button;
|
||||
struct wl_listener cursor_axis;
|
||||
struct wl_listener cursor_frame;
|
||||
struct wl_listener cursor_touch_up;
|
||||
struct wl_listener cursor_touch_down;
|
||||
struct wl_listener cursor_touch_motion;
|
||||
struct wl_listener cursor_touch_frame;
|
||||
|
||||
struct {
|
||||
struct wl_signal button_down;
|
||||
|
@ -46,6 +50,7 @@ struct kiwmi_cursor {
|
|||
struct wl_signal destroy;
|
||||
struct wl_signal motion;
|
||||
struct wl_signal scroll;
|
||||
struct wl_signal touch;
|
||||
} events;
|
||||
};
|
||||
|
||||
|
@ -61,6 +66,14 @@ struct kiwmi_cursor_motion_event {
|
|||
double newy;
|
||||
};
|
||||
|
||||
struct kiwmi_cursor_touch_event {
|
||||
char *event;
|
||||
int id;
|
||||
double x;
|
||||
double y;
|
||||
bool handled;
|
||||
};
|
||||
|
||||
struct kiwmi_cursor_scroll_event {
|
||||
const char *device_name;
|
||||
bool is_vertical;
|
||||
|
|
|
@ -15,6 +15,7 @@ struct kiwmi_input {
|
|||
struct wl_listener new_input;
|
||||
struct kiwmi_cursor *cursor;
|
||||
struct kiwmi_seat *seat;
|
||||
int touchpads;
|
||||
|
||||
struct {
|
||||
struct wl_signal keyboard_new;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,8 @@
|
|||
#include "input/seat.h"
|
||||
#include "server.h"
|
||||
|
||||
#include "vvector.h"
|
||||
|
||||
void
|
||||
view_close(struct kiwmi_view *view)
|
||||
{
|
||||
|
@ -182,13 +184,30 @@ view_at(
|
|||
double *sx,
|
||||
double *sy)
|
||||
{
|
||||
float xy[2] = { lx, ly };
|
||||
float xy_[2];
|
||||
float transform[3][3];
|
||||
float inv_transform[3][3];
|
||||
float det;
|
||||
|
||||
struct kiwmi_view *view;
|
||||
|
||||
wl_list_for_each (view, &desktop->views, link) {
|
||||
if (view->hidden || !view->mapped) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (surface_at(view, surface, lx, ly, sx, sy)) {
|
||||
/*
|
||||
The view may have transformation matrix, so we need to map
|
||||
lx, ly into the view co-ordinate space before calling
|
||||
surface_at. Or possibly vice versa. This stuff makes my head
|
||||
hurt.
|
||||
*/
|
||||
memcpy(transform, view->matrix, sizeof transform);
|
||||
INVERT_3X3(inv_transform, det, transform);
|
||||
MAT_DOT_VEC_2X3(xy_, inv_transform, xy);
|
||||
|
||||
if (surface_at(view, surface, xy_[0], xy_[1], sx, sy)) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_pointer.h>
|
||||
#include <wlr/types/wlr_touch.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/types/wlr_xcursor_manager.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
@ -119,6 +120,130 @@ cursor_motion_notify(struct wl_listener *listener, void *data)
|
|||
process_cursor_motion(server, event->time_msec);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_touch_down_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct kiwmi_cursor *cursor =
|
||||
wl_container_of(listener, cursor, cursor_touch_down);
|
||||
struct kiwmi_server *server = cursor->server;
|
||||
struct kiwmi_desktop *desktop = &server->desktop;
|
||||
struct wlr_event_touch_down *event = data;
|
||||
|
||||
struct kiwmi_input *input = &server->input;
|
||||
struct wlr_seat *seat = input->seat->seat;
|
||||
struct wlr_surface *surface = NULL;
|
||||
|
||||
/* FIXME figure out what scaling should be done here.
|
||||
* Does the touch co-ordinate system map onto a single output
|
||||
* (e.g. phone screen) or onto the entire layout (tablet,
|
||||
* maybe?)
|
||||
*/
|
||||
double lx = 720 * event->x;
|
||||
double ly = 1440 * event->y;
|
||||
double sx, sy;
|
||||
|
||||
struct kiwmi_view *view = view_at(
|
||||
desktop,
|
||||
lx, ly,
|
||||
&surface,
|
||||
&sx, &sy);
|
||||
|
||||
wlr_log(WLR_DEBUG, "view %x surface %x %f,%f %f,%f\n",
|
||||
view, surface, lx, ly, sx, sy);
|
||||
|
||||
/* we send the event to lua with 0..1 co-ordinates, because
|
||||
* it may not be over any surface
|
||||
*/
|
||||
struct kiwmi_cursor_touch_event new_event = {
|
||||
.event = "down",
|
||||
.id = event->touch_id,
|
||||
.x = event->x,
|
||||
.y = event->y,
|
||||
};
|
||||
|
||||
wl_signal_emit(&cursor->events.touch, &new_event);
|
||||
|
||||
if(!new_event.handled &&
|
||||
surface &&
|
||||
wlr_surface_accepts_touch(seat, surface)) {
|
||||
wlr_log(WLR_DEBUG, "surface %x %f %f\n",
|
||||
surface, sx, sy);
|
||||
wlr_seat_touch_notify_down(seat, surface, event->time_msec,
|
||||
event->touch_id, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_touch_up_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct kiwmi_cursor *cursor =
|
||||
wl_container_of(listener, cursor, cursor_touch_up);
|
||||
struct kiwmi_server *server = cursor->server;
|
||||
struct wlr_event_touch_up *event = data;
|
||||
struct kiwmi_input *input = &server->input;
|
||||
struct wlr_seat *seat = input->seat->seat;
|
||||
|
||||
struct kiwmi_cursor_touch_event new_event = {
|
||||
.event = "up",
|
||||
.id = event->touch_id,
|
||||
};
|
||||
|
||||
wl_signal_emit(&cursor->events.touch, &new_event);
|
||||
if(!new_event.handled) {
|
||||
wlr_seat_touch_notify_up(seat, event->time_msec, event->touch_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_touch_motion_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct kiwmi_cursor *cursor =
|
||||
wl_container_of(listener, cursor, cursor_touch_motion);
|
||||
struct kiwmi_server *server = cursor->server;
|
||||
struct wlr_event_touch_motion *event = data;
|
||||
struct kiwmi_input *input = &server->input;
|
||||
struct wlr_seat *seat = input->seat->seat;
|
||||
|
||||
struct kiwmi_cursor_touch_event new_event = {
|
||||
.event = "motion",
|
||||
.id = event->touch_id,
|
||||
.x = event->x,
|
||||
.y = event->y,
|
||||
};
|
||||
|
||||
wl_signal_emit(&cursor->events.touch, &new_event);
|
||||
|
||||
|
||||
if(!new_event.handled) {
|
||||
/* UNSURE: should we still send this even if the touch_down
|
||||
* didn't get sent because the surface doesn't accept
|
||||
* touch? */
|
||||
wlr_seat_touch_notify_motion(seat, event->time_msec,
|
||||
event->touch_id, event->x, event->y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_touch_frame_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct kiwmi_cursor *cursor =
|
||||
wl_container_of(listener, cursor, cursor_touch_frame);
|
||||
struct kiwmi_server *server = cursor->server;
|
||||
struct kiwmi_input *input = &server->input;
|
||||
|
||||
struct wlr_seat *seat = input->seat->seat;
|
||||
|
||||
struct kiwmi_cursor_touch_event new_event = {
|
||||
.event = "frame",
|
||||
};
|
||||
|
||||
wl_signal_emit(&cursor->events.touch, &new_event);
|
||||
|
||||
if(!new_event.handled) {
|
||||
wlr_seat_touch_notify_frame(seat);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_motion_absolute_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
@ -252,10 +377,23 @@ cursor_create(
|
|||
cursor->cursor_frame.notify = cursor_frame_notify;
|
||||
wl_signal_add(&cursor->cursor->events.frame, &cursor->cursor_frame);
|
||||
|
||||
cursor->cursor_touch_down.notify = cursor_touch_down_notify;
|
||||
wl_signal_add(&cursor->cursor->events.touch_down, &cursor->cursor_touch_down);
|
||||
|
||||
cursor->cursor_touch_up.notify = cursor_touch_up_notify;
|
||||
wl_signal_add(&cursor->cursor->events.touch_up, &cursor->cursor_touch_up);
|
||||
|
||||
cursor->cursor_touch_motion.notify = cursor_touch_motion_notify;
|
||||
wl_signal_add(&cursor->cursor->events.touch_motion, &cursor->cursor_touch_motion);
|
||||
|
||||
cursor->cursor_touch_frame.notify = cursor_touch_frame_notify;
|
||||
wl_signal_add(&cursor->cursor->events.touch_frame, &cursor->cursor_touch_frame);
|
||||
|
||||
wl_signal_init(&cursor->events.button_down);
|
||||
wl_signal_init(&cursor->events.button_up);
|
||||
wl_signal_init(&cursor->events.destroy);
|
||||
wl_signal_init(&cursor->events.motion);
|
||||
wl_signal_init(&cursor->events.touch);
|
||||
wl_signal_init(&cursor->events.scroll);
|
||||
|
||||
return cursor;
|
||||
|
|
|
@ -28,6 +28,13 @@ new_pointer(struct kiwmi_input *input, struct wlr_input_device *device)
|
|||
wlr_cursor_attach_input_device(input->cursor->cursor, device);
|
||||
}
|
||||
|
||||
static void
|
||||
new_touch(struct kiwmi_input *input, struct wlr_input_device *device)
|
||||
{
|
||||
wlr_cursor_attach_input_device(input->cursor->cursor, device);
|
||||
input->touchpads++;
|
||||
}
|
||||
|
||||
static void
|
||||
new_keyboard(struct kiwmi_input *input, struct wlr_input_device *device)
|
||||
{
|
||||
|
@ -53,6 +60,9 @@ new_input_notify(struct wl_listener *listener, void *data)
|
|||
case WLR_INPUT_DEVICE_POINTER:
|
||||
new_pointer(input, device);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
new_touch(input, device);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
new_keyboard(input, device);
|
||||
break;
|
||||
|
@ -65,6 +75,9 @@ new_input_notify(struct wl_listener *listener, void *data)
|
|||
if (!wl_list_empty(&input->keyboards)) {
|
||||
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
|
||||
}
|
||||
if(input->touchpads) {
|
||||
caps |= WL_SEAT_CAPABILITY_TOUCH;
|
||||
}
|
||||
|
||||
wlr_seat_set_capabilities(input->seat->seat, caps);
|
||||
}
|
||||
|
|
|
@ -162,6 +162,36 @@ kiwmi_cursor_on_motion_notify(struct wl_listener *listener, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kiwmi_cursor_on_touch_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct kiwmi_lua_callback *lc = wl_container_of(listener, lc, listener);
|
||||
struct kiwmi_server *server = lc->server;
|
||||
lua_State *L = server->lua->L;
|
||||
struct kiwmi_cursor_touch_event *event = data;
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushnumber(L, event->x);
|
||||
lua_setfield(L, -2, "x");
|
||||
|
||||
lua_pushnumber(L, event->y);
|
||||
lua_setfield(L, -2, "y");
|
||||
|
||||
lua_pushnumber(L, event->id);
|
||||
lua_setfield(L, -2, "id");
|
||||
|
||||
lua_pushstring(L, event->event);
|
||||
lua_setfield(L, -2, "name");
|
||||
|
||||
if (lua_pcall(L, 1, 0, 0)) {
|
||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kiwmi_cursor_on_scroll_notify(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
@ -267,6 +297,31 @@ l_kiwmi_cursor_on_motion(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
l_kiwmi_cursor_on_touch(lua_State *L)
|
||||
{
|
||||
struct kiwmi_object *obj =
|
||||
*(struct kiwmi_object **)luaL_checkudata(L, 1, "kiwmi_cursor");
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
|
||||
struct kiwmi_cursor *cursor = obj->object;
|
||||
struct kiwmi_server *server = cursor->server;
|
||||
|
||||
lua_pushcfunction(L, luaK_kiwmi_lua_callback_new);
|
||||
lua_pushlightuserdata(L, server);
|
||||
lua_pushvalue(L, 2);
|
||||
lua_pushlightuserdata(L, kiwmi_cursor_on_touch_notify);
|
||||
lua_pushlightuserdata(L, &cursor->events.touch);
|
||||
lua_pushlightuserdata(L, obj);
|
||||
|
||||
if (lua_pcall(L, 5, 0, 0)) {
|
||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
l_kiwmi_cursor_on_scroll(lua_State *L)
|
||||
{
|
||||
|
@ -296,6 +351,7 @@ static const luaL_Reg kiwmi_cursor_events[] = {
|
|||
{"button_down", l_kiwmi_cursor_on_button_down},
|
||||
{"button_up", l_kiwmi_cursor_on_button_up},
|
||||
{"motion", l_kiwmi_cursor_on_motion},
|
||||
{"touch", l_kiwmi_cursor_on_touch},
|
||||
{"scroll", l_kiwmi_cursor_on_scroll},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
|
|
@ -216,20 +216,21 @@ kiwmi_server_event_loop_fd_handler(int fd, uint32_t mask, void *data)
|
|||
lua_State *L = lc->server->lua->L;
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lc->callback_ref);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushinteger(L, fd);
|
||||
lua_pushinteger(L, mask);
|
||||
|
||||
if (lua_pcall(L, 2, 0, 0)) {
|
||||
if (lua_pcall(L, 2, 1, 0)) {
|
||||
wlr_log(WLR_ERROR, "%s", lua_tostring(L, -1));
|
||||
}
|
||||
/*
|
||||
FIXME we need to call
|
||||
|
||||
/* 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);
|
||||
|
||||
when the file is closed, but probably not before then
|
||||
*/
|
||||
}
|
||||
lua_pop(L, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -242,7 +243,6 @@ l_kiwmi_server_event_loop_add_fd(lua_State *L)
|
|||
|
||||
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
|
||||
|
@ -265,12 +265,14 @@ l_kiwmi_server_event_loop_add_fd(lua_State *L)
|
|||
/* luaL_ref pops last parameter (callback) from stack */
|
||||
lc->callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
wl_event_loop_add_fd(server->wl_event_loop,
|
||||
fd,
|
||||
event_types,
|
||||
kiwmi_server_event_loop_fd_handler,
|
||||
lc);
|
||||
return true;
|
||||
lc->event_source =
|
||||
wl_event_loop_add_fd(server->wl_event_loop,
|
||||
fd,
|
||||
event_types,
|
||||
kiwmi_server_event_loop_fd_handler,
|
||||
lc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ 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()
|
||||
|
||||
Returns the currently focused view.
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
;; homogeneous matrix operations for 2d graphics
|
||||
|
||||
(local identity
|
||||
[
|
||||
1 0 0
|
||||
0 1 0
|
||||
0 0 1
|
||||
])
|
||||
|
||||
(fn multiply-matrix [a b]
|
||||
[
|
||||
(+ (* (. a 1) (. b 1)) (* (. a 2) (. b 4)) (* (. a 3) (. b 7)))
|
||||
(+ (* (. a 1) (. b 2)) (* (. a 2) (. b 5)) (* (. a 3) (. b 8)))
|
||||
(+ (* (. a 1) (. b 3)) (* (. a 2) (. b 6)) (* (. a 3) (. b 9)))
|
||||
|
||||
(+ (* (. a 4) (. b 1)) (* (. a 5) (. b 4)) (* (. a 6) (. b 7)))
|
||||
(+ (* (. a 4) (. b 2)) (* (. a 5) (. b 5)) (* (. a 6) (. b 8)))
|
||||
(+ (* (. a 4) (. b 3)) (* (. a 5) (. b 6)) (* (. a 6) (. b 9)))
|
||||
|
||||
(+ (* (. a 7) (. b 1)) (* (. a 8) (. b 4)) (* (. a 9) (. b 7)))
|
||||
(+ (* (. a 7) (. b 2)) (* (. a 8) (. b 5)) (* (. a 9) (. b 8)))
|
||||
(+ (* (. a 7) (. b 3)) (* (. a 8) (. b 6)) (* (. a 9) (. b 9)))
|
||||
])
|
||||
|
||||
(fn scale [matrix x y]
|
||||
(let [scale [
|
||||
x 0 0
|
||||
0 y 0
|
||||
0 0 1]]
|
||||
(multiply-matrix matrix scale)))
|
||||
|
||||
(fn translate [matrix x y]
|
||||
(let [translation [
|
||||
1 0 x
|
||||
0 1 y
|
||||
0 0 1]]
|
||||
(multiply-matrix matrix translation)))
|
||||
|
||||
(fn rotate [matrix rad]
|
||||
(let [sin (math.sin rad)
|
||||
cos (math.cos rad)
|
||||
rotation [
|
||||
cos (- sin) 0
|
||||
sin cos 0
|
||||
0 0 1
|
||||
]]
|
||||
(multiply-matrix matrix rotation)))
|
||||
|
||||
|
||||
{
|
||||
: identity
|
||||
: scale
|
||||
: translate
|
||||
: rotate
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
;(local battery (require :blinkenlicht.metric.battery))
|
||||
(local cpustat (require :blinkenlicht.metric.cpustat))
|
||||
|
||||
(stylesheet "modeline.css")
|
||||
(stylesheet (.. (os.getenv "EUFON_PATH") "/modeline.css"))
|
||||
|
||||
(fn battery-icon-codepoint [status percent]
|
||||
(if (= status "Charging") 0xf0e7
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let eufon = pkgs.callPackage ./default.nix {}; in
|
||||
{
|
||||
systemd.services."eufon" = {
|
||||
wants = [
|
||||
"systemd-machined.service"
|
||||
"accounts-daemon.service"
|
||||
"systemd-udev-settle.service"
|
||||
"dbus.socket"
|
||||
];
|
||||
aliases = [ "display-manager.service" ];
|
||||
after = [
|
||||
"rc-local.service"
|
||||
"systemd-machined.service"
|
||||
"systemd-user-sessions.service"
|
||||
"getty@tty2.service"
|
||||
"plymouth-quit.service"
|
||||
"plymouth-start.service"
|
||||
"systemd-logind.service"
|
||||
"systemd-udev-settle.service"
|
||||
];
|
||||
conflicts = [
|
||||
"getty@tty1.service" # not sure if needed
|
||||
"getty@tty2.service"
|
||||
"plymouth-quit.service"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig =
|
||||
let run-eufon = pkgs.writeScript "run-eufon" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
source ${config.system.build.setEnvironment}
|
||||
${pkgs.dbus}/bin/dbus-run-session ${eufon}/bin/eufon
|
||||
systemd-cat echo "dbus-run-session $?"
|
||||
'';
|
||||
in {
|
||||
WorkingDirectory = "${eufon}";
|
||||
TTYPath = "/dev/tty2";
|
||||
TTYReset = "yes";
|
||||
TTYVHangup = "yes";
|
||||
TTYVTDisallocate = "yes";
|
||||
PAMName = "login";
|
||||
StandardInput = "tty";
|
||||
StandardError = "journal";
|
||||
StandardOutput = "journal";
|
||||
SyslogIdentifier = "eufon";
|
||||
User = "dan";
|
||||
ExecStart = run-eufon;
|
||||
Restart = "always";
|
||||
};
|
||||
environment = {
|
||||
NIX_PATH = "nixpkgs=${<nixpkgs>}";
|
||||
};
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
git eufon
|
||||
];
|
||||
|
||||
boot.postBootCommands = lib.mkOrder (-1) ''
|
||||
brightness=4000
|
||||
echo "Setting brightness to $brightness"
|
||||
echo $brightness > /sys/class/backlight/wled/brightness
|
||||
'';
|
||||
|
||||
services.logind.extraConfig = ''
|
||||
HandlePowerKey=ignore
|
||||
'';
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
# configuration.nix contains settings applicable to _my_ pinephone
|
||||
# pinephone.nix contains settings applicable to eufon on pinephones.
|
||||
# module.nix contains settings applicable to eufon generally
|
||||
|
||||
{
|
||||
config = {
|
||||
powerManagement = {
|
||||
enable = true;
|
||||
cpuFreqGovernor = "ondemand";
|
||||
};
|
||||
mobile.boot.stage-1.firmware = [
|
||||
config.mobile.device.firmware
|
||||
];
|
||||
hardware.sensor.iio.enable = true;
|
||||
hardware.firmware = [ config.mobile.device.firmware ];
|
||||
|
||||
services.fwupd = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
environment.systemPackages =
|
||||
let refresh-bootfs = (import ./refresh-bootfs.nix { inherit config pkgs lib; });
|
||||
in with pkgs; [
|
||||
dtc
|
||||
file
|
||||
refresh-bootfs
|
||||
];
|
||||
|
||||
environment.etc."fwupd/remotes.d/testing.conf" = {
|
||||
mode = "0644";
|
||||
text = ''
|
||||
[fwupd Remote]
|
||||
|
||||
Enabled=true
|
||||
Title=Linux Vendor Firmware Service (testing)
|
||||
MetadataURI=https://cdn.fwupd.org/downloads/firmware-testing.xml.gz
|
||||
ReportURI=https://fwupd.org/lvfs/firmware/report
|
||||
OrderBefore=lvfs,fwupd
|
||||
AutomaticReports=false
|
||||
ApprovalRequired=false
|
||||
'';
|
||||
};
|
||||
|
||||
nixpkgs = {
|
||||
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
||||
"pine64-pinephone-firmware"
|
||||
];
|
||||
|
||||
};
|
||||
# boot.loader.generic-extlinux-compatible.enable = lib.mkForce true;
|
||||
hardware.opengl = {
|
||||
enable = true;
|
||||
driSupport = true;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
101
rc.fnl
101
rc.fnl
|
@ -1,101 +0,0 @@
|
|||
(local { : GdkPixbuf } (require :lgi))
|
||||
(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]
|
||||
(let [pixels
|
||||
(let [(buf err) (GdkPixbuf.Pixbuf.new_from_file filename)]
|
||||
(if (not buf) (print :err err))
|
||||
buf)]
|
||||
(renderer:texture_from_pixels
|
||||
pixels.rowstride
|
||||
pixels.width
|
||||
pixels.height
|
||||
(pixels:get_pixels))))
|
||||
|
||||
(kiwmi:on
|
||||
"output"
|
||||
(fn [output]
|
||||
(output:set_mode 360 720 0)
|
||||
(let [r (output:renderer)
|
||||
kill (texture-from-file r "close-window.png")
|
||||
launch (texture-from-file r "launcher.png")
|
||||
spinner (texture-from-file r "carousel.png")]
|
||||
(output:on "render"
|
||||
(fn [{: output : renderer}]
|
||||
(let [bar-height 40
|
||||
matrix [1 0 0
|
||||
0 1 0
|
||||
0 0 1]]
|
||||
(renderer:draw_rect :#00000077
|
||||
0 (- 720 bar-height)
|
||||
690 360 bar-height)
|
||||
(renderer:draw_texture
|
||||
kill
|
||||
matrix
|
||||
30 (- 720 bar-height)
|
||||
0.7)
|
||||
(renderer:draw_texture
|
||||
launch matrix
|
||||
(- 180 (/ bar-height 2)) (- 720 bar-height)
|
||||
0.7)
|
||||
(renderer:draw_texture
|
||||
spinner
|
||||
matrix
|
||||
(- 360 30 bar-height) (- 720 bar-height)
|
||||
0.7)))))))
|
||||
|
||||
(fn kill-window []
|
||||
(print "DIE")
|
||||
true)
|
||||
|
||||
(fn launch []
|
||||
(print "WHOOSH")
|
||||
true)
|
||||
|
||||
(fn carousel []
|
||||
(print "spin spin sugar")
|
||||
true)
|
||||
|
||||
(let [cursor (kiwmi:cursor)]
|
||||
(cursor:on "button_down"
|
||||
(fn [button]
|
||||
(let [(x y) (cursor:pos)]
|
||||
(if (> y 680)
|
||||
(if (< x 70)
|
||||
(kill-window)
|
||||
(and (< 150 x) (< x 190))
|
||||
(launch)
|
||||
(and (< 285 x) (< x 330))
|
||||
(carousel)
|
||||
false))))))
|
||||
|
||||
|
||||
(kiwmi:on "view"
|
||||
(fn [view]
|
||||
(let [(w h) (: (kiwmi:active_output) :size)]
|
||||
(view:resize w h)
|
||||
(view:move 0 0))
|
||||
(view:focus)
|
||||
(view:show)
|
||||
(view:on "request_move" #(view:imove))
|
||||
(view:on "request_resize" (fn [ev] (view:iresize ev.edges)))))
|
||||
|
||||
|
||||
;(kiwmi:spawn "swaybg -c '#ff00ff'")
|
||||
(kiwmi:spawn "lua -l fennelrun modeline.fnl")
|
||||
(kiwmi:spawn "lua -l fennelrun saturn/main.fnl")
|
||||
(kiwmi:spawn "lua -l fennelrun crier/crier.fnl")
|
||||
(kiwmi:spawn "lua -l fennelrun just/just.fnl")
|
||||
;(kiwmi:spawn "foot")
|
|
@ -0,0 +1,43 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
# nixos/mobile-nixos don't currently (June 2022) update the kernel and
|
||||
# initrd used by the bootloader when nixos-rebuild is run. This is a
|
||||
# workaround until they do. Mount your boot filesystem somewhere
|
||||
# and run "refresh-bootfs /path/to/mounted/bootfs" after switching
|
||||
# configuration
|
||||
|
||||
let
|
||||
inherit (config.mobile.outputs) recovery stage-0;
|
||||
inherit (pkgs) writeScriptBin buildPackages imageBuilder runCommandNoCC;
|
||||
|
||||
kernel = stage-0.mobile.boot.stage-1.kernel.package;
|
||||
kernel_file = "${kernel}/${if kernel ? file then kernel.file else pkgs.stdenv.hostPlatform.linux-kernel.target}";
|
||||
# bootscr = runCommandNoCC "boot.scr" {
|
||||
# nativeBuildInputs = [
|
||||
# buildPackages.ubootTools
|
||||
# ];
|
||||
# } ''
|
||||
# mkimage -C none -A arm64 -T script -d {bootcmd} $out
|
||||
# '';
|
||||
|
||||
in writeScriptBin "refresh-bootfs" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
test -n "$1" || exit 1
|
||||
test -d "$1" || exit 1
|
||||
cd $1
|
||||
test -f ./boot.scr || exit 1
|
||||
mkdir -vp mobile-nixos/{boot,recovery}
|
||||
(
|
||||
cd mobile-nixos/boot
|
||||
cp -v ${stage-0.mobile.outputs.initrd} stage-1
|
||||
cp -v ${kernel_file} kernel
|
||||
cp -vr ${kernel}/dtbs dtbs
|
||||
)
|
||||
(
|
||||
cd mobile-nixos/recovery
|
||||
cp -v ${recovery.mobile.outputs.initrd} stage-1
|
||||
cp -v ${kernel_file} kernel
|
||||
cp -vr ${kernel}/dtbs dtbs
|
||||
)
|
||||
# cp -v {bootscr} ./boot.scr
|
||||
''
|
|
@ -5,5 +5,6 @@ in (p.overrideAttrs (o:{
|
|||
shellHook = ''
|
||||
export LUA_PATH=`lua -e 'print(package.path)'`
|
||||
export LUA_CPATH=`lua -e 'print(package.cpath)'`
|
||||
export EUFON_PATH=`pwd`
|
||||
'';
|
||||
})).override { debug = true; }
|
||||
|
|
|
@ -20,17 +20,29 @@
|
|||
(on-connected connected-fd)))
|
||||
))
|
||||
|
||||
(fn get-input [fd]
|
||||
(let [buf (unistd.read fd 1024)]
|
||||
(if (and buf (> (# buf) 0))
|
||||
buf
|
||||
"\n,exit")))
|
||||
|
||||
(fn start [pathname]
|
||||
(print pathname)
|
||||
(unistd.unlink pathname)
|
||||
(unix-socket-listener
|
||||
pathname
|
||||
(fn [fd]
|
||||
(let [sock (fdopen fd "w+")
|
||||
repl-coro (coroutine.create repl)]
|
||||
(print :fd fd :sock sock)
|
||||
(watch-fd fd fcntl.O_RDONLY
|
||||
#(coroutine.resume repl-coro (unistd.read $1 1024)))
|
||||
(fn [fd]
|
||||
(coroutine.resume repl-coro (get-input fd))
|
||||
(if (= (coroutine.status repl-coro) :dead)
|
||||
(do
|
||||
(sock:write "bye!\n")
|
||||
(sock:close)
|
||||
false)
|
||||
true
|
||||
)))
|
||||
(coroutine.resume repl-coro
|
||||
{:readChunk
|
||||
(fn [{: stack-size}]
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
(local { : GdkPixbuf } (require :lgi))
|
||||
|
||||
(fn from-file [renderer filename]
|
||||
(let [pixels
|
||||
(let [(buf err) (GdkPixbuf.Pixbuf.new_from_file filename)]
|
||||
(if (not buf) (print :err err))
|
||||
buf)]
|
||||
(renderer:texture_from_pixels
|
||||
pixels.rowstride
|
||||
pixels.width
|
||||
pixels.height
|
||||
(pixels:get_pixels))))
|
||||
|
||||
{ : from-file }
|
Loading…
Reference in New Issue