yutani: basic Kuroko bindings, demo 'app'
This commit is contained in:
parent
946c45312c
commit
5fe8d3b0d1
8
Makefile
8
Makefile
@ -46,6 +46,8 @@ APPS_X=$(foreach app,$(APPS),base/bin/$(app))
|
||||
APPS_Y=$(foreach app,$(APPS),.make/$(app).mak)
|
||||
APPS_SH=$(patsubst apps/%.sh,%.sh,$(wildcard apps/*.sh))
|
||||
APPS_SH_X=$(foreach app,$(APPS_SH),base/bin/$(app))
|
||||
APPS_KRK=$(patsubst apps/%.krk,%.krk,$(wildcard apps/*.krk))
|
||||
APPS_KRK_X=$(foreach app,$(APPS_KRK),base/bin/$(app))
|
||||
|
||||
##
|
||||
# LIBS = C sources from lib/
|
||||
@ -63,7 +65,7 @@ tags: $(SOURCE_FILES)
|
||||
|
||||
##
|
||||
# Files that must be present in the ramdisk (apps, libraries)
|
||||
RAMDISK_FILES= ${APPS_X} ${APPS_SH_X} ${LIBS_X} base/lib/ld.so base/lib/libm.so ${KUROKO_FILES}
|
||||
RAMDISK_FILES= ${APPS_X} ${APPS_SH_X} ${APPS_KRK_X} ${LIBS_X} base/lib/ld.so base/lib/libm.so ${KUROKO_FILES}
|
||||
|
||||
# Kernel / module flags
|
||||
|
||||
@ -251,6 +253,10 @@ base/bin/%.sh: apps/%.sh
|
||||
cp $< $@
|
||||
chmod +x $@
|
||||
|
||||
base/bin/%.krk: apps/%.krk
|
||||
cp $< $@
|
||||
chmod +x $@
|
||||
|
||||
# Ramdisk
|
||||
fatbase/ramdisk.img: ${RAMDISK_FILES} $(shell find base) Makefile util/createramdisk.py | dirs
|
||||
python3 util/createramdisk.py
|
||||
|
35
apps/krk_yutani_test.krk
Normal file
35
apps/krk_yutani_test.krk
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/kuroko
|
||||
import _yutani
|
||||
|
||||
# Connect
|
||||
let y = _yutani.Yutani()
|
||||
|
||||
# Create window
|
||||
let w = _yutani.Window(300,200,title="Kuroko Demo")
|
||||
w.move(100,100)
|
||||
|
||||
def drawWindow():
|
||||
w.fill()
|
||||
_yutani.Decorator.render(w)
|
||||
w.flip()
|
||||
|
||||
drawWindow()
|
||||
|
||||
while True:
|
||||
let msg = y.poll()
|
||||
if msg.type == _yutani.Message.MSG_SESSION_END:
|
||||
print("Asked to exit.")
|
||||
break
|
||||
else if msg.type == _yutani.Message.MSG_KEY_EVENT:
|
||||
print("key event")
|
||||
else if msg.type == _yutani.Message.MSG_WINDOW_FOCUS_CHANGE:
|
||||
print("focus change")
|
||||
if msg.wid == w.wid:
|
||||
w.set_focused(msg.focused)
|
||||
drawWindow()
|
||||
else if msg.type == _yutani.Message.MSG_WINDOW_MOUSE_EVENT:
|
||||
if _yutani.Decorator.handle_event(msg) == 2:
|
||||
print("Clicked close button")
|
||||
break
|
||||
print(f"W({msg.wid}) mouse {msg.new_x},{msg.new_y}")
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Kuroko bindings for Yutani */
|
||||
#include <assert.h>
|
||||
#include <toaru/yutani.h>
|
||||
#include <toaru/decorations.h>
|
||||
#include "kuroko/src/kuroko.h"
|
||||
#include "kuroko/src/vm.h"
|
||||
#include "kuroko/src/value.h"
|
||||
@ -8,6 +9,8 @@
|
||||
|
||||
static KrkClass * Message;
|
||||
static KrkClass * Yutani;
|
||||
static KrkClass * YutaniWindow;
|
||||
static KrkClass * Decorator;
|
||||
|
||||
static KrkInstance * module;
|
||||
static KrkInstance * yctxInstance = NULL;
|
||||
@ -163,6 +166,9 @@ static KrkValue _yutani_init(int argc, KrkValue argv[], int hasKw) {
|
||||
krk_runtimeError(vm.exceptions.ioError, "Failed to connect to compositor.");
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
init_decorations();
|
||||
|
||||
fprintf(stderr, "Attaching field...\n");
|
||||
((struct YutaniClass*)self)->yctx = yctx;
|
||||
yctxInstance = self;
|
||||
@ -214,6 +220,173 @@ static KrkValue _yutani_wait_for(int argc, KrkValue argv[]) {
|
||||
return krk_pop();
|
||||
}
|
||||
|
||||
struct WindowClass {
|
||||
KrkInstance inst;
|
||||
yutani_window_t * window;
|
||||
gfx_context_t * ctx;
|
||||
int doubleBuffered;
|
||||
};
|
||||
|
||||
#define GET_ARG(p,name,type) do { \
|
||||
if (hasKw && krk_tableGet(AS_DICT(argv[argc]), OBJECT_VAL(S(#name)), &name)) { \
|
||||
if (!krk_isInstanceOf(name,type)) \
|
||||
return krk_runtimeError(vm.exceptions.typeError, #name " argument should be " #type ", not '%s'", krk_typeName(name)); \
|
||||
} else if (argc > p) { \
|
||||
name = argv[p]; \
|
||||
if (!krk_isInstanceOf(name,type)) \
|
||||
return krk_runtimeError(vm.exceptions.typeError, #name " argument should be " #type ", not '%s'", krk_typeName(name)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static KrkValue _window_init(int argc, KrkValue argv[], int hasKw) {
|
||||
if (!yctxInstance) return krk_runtimeError(vm.exceptions.valueError, "Compositor is not initialized");
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "Failed to initialize window");
|
||||
|
||||
if (argc < 3 || !IS_INTEGER(argv[1]) || !IS_INTEGER(argv[2]))
|
||||
return krk_runtimeError(vm.exceptions.argumentError, "Expected at least two (integer) arguments (width, height)");
|
||||
|
||||
if (hasKw) argc--;
|
||||
|
||||
KrkInstance * _self = AS_INSTANCE(argv[0]);
|
||||
struct WindowClass * self = (struct WindowClass*)_self;
|
||||
krk_integer_type width = AS_INTEGER(argv[1]);
|
||||
krk_integer_type height = AS_INTEGER(argv[2]);
|
||||
|
||||
KrkValue flags = INTEGER_VAL(0), title = NONE_VAL(), icon = NONE_VAL(), doublebuffer = BOOLEAN_VAL(0);
|
||||
GET_ARG(3, flags, vm.baseClasses.intClass);
|
||||
GET_ARG(4, title, vm.baseClasses.strClass);
|
||||
GET_ARG(5, icon, vm.baseClasses.strClass);
|
||||
GET_ARG(6, doublebuffer, vm.baseClasses.boolClass);
|
||||
|
||||
self->window = yutani_window_create_flags(((struct YutaniClass*)yctxInstance)->yctx,
|
||||
width, height, AS_INTEGER(flags));
|
||||
|
||||
self->doubleBuffered = AS_BOOLEAN(doublebuffer);
|
||||
|
||||
if (self->doubleBuffered) {
|
||||
self->ctx = init_graphics_yutani_double_buffer(self->window);
|
||||
} else {
|
||||
self->ctx = init_graphics_yutani(self->window);
|
||||
}
|
||||
|
||||
if (!IS_NONE(title)) {
|
||||
if (!IS_NONE(icon)) {
|
||||
yutani_window_advertise_icon(((struct YutaniClass*)yctxInstance)->yctx, self->window, AS_CSTRING(title), AS_CSTRING(icon));
|
||||
} else {
|
||||
yutani_window_advertise(((struct YutaniClass*)yctxInstance)->yctx, self->window, AS_CSTRING(title));
|
||||
}
|
||||
}
|
||||
|
||||
krk_attachNamedValue(&_self->fields, "title", title);
|
||||
krk_attachNamedValue(&_self->fields, "icon", icon);
|
||||
krk_attachNamedValue(&_self->fields, "closed", BOOLEAN_VAL(0));
|
||||
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static KrkValue _window_fill(int argc, KrkValue argv[]) {
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected window");
|
||||
KrkInstance * _self = AS_INSTANCE(argv[0]);
|
||||
struct WindowClass * self = (struct WindowClass*)_self;
|
||||
draw_fill(self->ctx, rgba(127,127,127,255));
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
static KrkValue _window_flip(int argc, KrkValue argv[]) {
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected window");
|
||||
KrkInstance * _self = AS_INSTANCE(argv[0]);
|
||||
struct WindowClass * self = (struct WindowClass*)_self;
|
||||
if (self->doubleBuffered) {
|
||||
flip(self->ctx);
|
||||
}
|
||||
yutani_flip(((struct YutaniClass*)yctxInstance)->yctx, self->window);
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
static KrkValue _window_move(int argc, KrkValue argv[]) {
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected window");
|
||||
if (argc < 3 || !IS_INTEGER(argv[1]) || !IS_INTEGER(argv[2]))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected two integer arguments");
|
||||
KrkInstance * _self = AS_INSTANCE(argv[0]);
|
||||
struct WindowClass * self = (struct WindowClass*)_self;
|
||||
yutani_window_move(((struct YutaniClass*)yctxInstance)->yctx, self->window, AS_INTEGER(argv[1]), AS_INTEGER(argv[2]));
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
static KrkValue _window_set_focused(int argc, KrkValue argv[]) {
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected window");
|
||||
if (argc < 2 || !IS_INTEGER(argv[1]))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected integer argument");
|
||||
KrkInstance * _self = AS_INSTANCE(argv[0]);
|
||||
struct WindowClass * self = (struct WindowClass*)_self;
|
||||
self->window->focused = AS_INTEGER(argv[1]);
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
#define WINDOW_PROPERTY(name) \
|
||||
static KrkValue _window_ ## name (int argc, KrkValue argv[]) { \
|
||||
KrkInstance * _self = AS_INSTANCE(argv[0]); \
|
||||
struct WindowClass * self = (struct WindowClass*)_self; \
|
||||
return INTEGER_VAL(self->window-> name); \
|
||||
}
|
||||
|
||||
WINDOW_PROPERTY(width);
|
||||
WINDOW_PROPERTY(height);
|
||||
WINDOW_PROPERTY(wid);
|
||||
WINDOW_PROPERTY(focused);
|
||||
|
||||
static KrkValue _decor_get_bounds(int argc, KrkValue argv[]) {
|
||||
if (argc > 0 && !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected window");
|
||||
struct decor_bounds bounds;
|
||||
|
||||
decor_get_bounds((argc > 0) ? ((struct WindowClass*)AS_INSTANCE(argv[0]))->window : NULL,
|
||||
&bounds);
|
||||
|
||||
KRK_PAUSE_GC();
|
||||
|
||||
KrkValue result = krk_dict_of(6 * 2, (KrkValue[]) {
|
||||
OBJECT_VAL(S("top_height")), INTEGER_VAL(bounds.top_height),
|
||||
OBJECT_VAL(S("bottom_height")), INTEGER_VAL(bounds.bottom_height),
|
||||
OBJECT_VAL(S("left_width")), INTEGER_VAL(bounds.left_width),
|
||||
OBJECT_VAL(S("right_width")), INTEGER_VAL(bounds.right_width),
|
||||
OBJECT_VAL(S("width")), INTEGER_VAL(bounds.width),
|
||||
OBJECT_VAL(S("height")), INTEGER_VAL(bounds.height)
|
||||
});
|
||||
|
||||
KRK_RESUME_GC();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static KrkValue _decor_handle_event(int argc, KrkValue argv[]) {
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], Message))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected message");
|
||||
return INTEGER_VAL(decor_handle_event(((struct YutaniClass*)yctxInstance)->yctx, ((struct MessageClass*)AS_INSTANCE(argv[0]))->msg));
|
||||
}
|
||||
|
||||
static KrkValue _decor_render(int argc, KrkValue argv[]) {
|
||||
if (argc < 1 || !krk_isInstanceOf(argv[0], YutaniWindow))
|
||||
return krk_runtimeError(vm.exceptions.typeError, "expected window");
|
||||
char * title = (argc > 1 && IS_STRING(argv[1])) ? AS_CSTRING(argv[1]) : NULL;
|
||||
if (title == NULL) {
|
||||
KrkValue winTitle;
|
||||
if (!krk_tableGet(&AS_INSTANCE(argv[0])->fields, OBJECT_VAL(S("title")), &winTitle) || !IS_STRING(winTitle)) {
|
||||
title = "";
|
||||
} else {
|
||||
title = AS_CSTRING(winTitle);
|
||||
}
|
||||
}
|
||||
render_decorations(((struct WindowClass*)AS_INSTANCE(argv[0]))->window,
|
||||
((struct WindowClass*)AS_INSTANCE(argv[0]))->ctx, title);
|
||||
return NONE_VAL();
|
||||
}
|
||||
|
||||
KrkValue krk_module_onload__yutani(void) {
|
||||
fprintf(stderr, "Loading...\n");
|
||||
module = krk_newInstance(vm.moduleClass);
|
||||
@ -272,6 +445,26 @@ KrkValue krk_module_onload__yutani(void) {
|
||||
#endif
|
||||
krk_finalizeClass(Yutani);
|
||||
|
||||
YutaniWindow = krk_createClass(module, "Window", NULL);
|
||||
YutaniWindow->allocSize = sizeof(struct WindowClass);
|
||||
krk_defineNative(&YutaniWindow->methods, ".__init__", _window_init);
|
||||
krk_defineNative(&YutaniWindow->methods, ".fill", _window_fill);
|
||||
krk_defineNative(&YutaniWindow->methods, ".flip", _window_flip);
|
||||
krk_defineNative(&YutaniWindow->methods, ".move", _window_move);
|
||||
krk_defineNative(&YutaniWindow->methods, ".set_focused", _window_set_focused);
|
||||
/* Properties */
|
||||
krk_defineNative(&YutaniWindow->methods, ":width", _window_width);
|
||||
krk_defineNative(&YutaniWindow->methods, ":height", _window_height);
|
||||
krk_defineNative(&YutaniWindow->methods, ":wid", _window_wid);
|
||||
krk_defineNative(&YutaniWindow->methods, ":focused", _window_focused);
|
||||
krk_finalizeClass(YutaniWindow);
|
||||
|
||||
Decorator = krk_createClass(module, "Decorator", NULL);
|
||||
krk_defineNative(&Decorator->fields, "get_bounds", _decor_get_bounds);
|
||||
krk_defineNative(&Decorator->fields, "render", _decor_render);
|
||||
krk_defineNative(&Decorator->fields, "handle_event", _decor_handle_event);
|
||||
krk_finalizeClass(Decorator);
|
||||
|
||||
|
||||
/**
|
||||
* class MsgKeyEvent(Message):
|
||||
|
Loading…
Reference in New Issue
Block a user