aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2018-04-01 23:23:34 +0200
committerAlex Auvolat <alex@adnab.me>2018-04-01 23:23:34 +0200
commita36c6528b10cb5b5d48fbf30a941443f738c9dd1 (patch)
tree19249d98dbe3a55d5f18050797959d7ca64a97bd
parent67db86ec53336da886153797deb643483e9596d0 (diff)
downloadkogata-a36c6528b10cb5b5d48fbf30a941443f738c9dd1.tar.gz
kogata-a36c6528b10cb5b5d48fbf30a941443f738c9dd1.zip
Terminal inside Lua window manager
-rw-r--r--src/kernel/user/syscall.c1
-rw-r--r--src/lib/include/kogata/mainloop.h2
-rw-r--r--src/lib/libkogata/mainloop.c20
-rw-r--r--src/sysapp/login/main.lua25
-rw-r--r--src/sysbin/terminal/main.c44
-rw-r--r--src/syslua/lx/gip.lua177
-rw-r--r--src/syslua/lx/gui.lua19
-rw-r--r--src/syslua/lx/protodef.lua29
-rw-r--r--src/syslua/lx/sysdef.lua2
-rw-r--r--src/syslua/lx/tk.lua56
10 files changed, 361 insertions, 14 deletions
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
index db32fa9..34b8802 100644
--- a/src/kernel/user/syscall.c
+++ b/src/kernel/user/syscall.c
@@ -724,6 +724,7 @@ void setup_syscall_table() {
sc_handlers[SC_SELECT] = select_sc;
sc_handlers[SC_MK_CHANNEL] = make_channel_sc;
+ sc_handlers[SC_MK_SHM] = make_shm_sc;
sc_handlers[SC_GEN_TOKEN] = gen_token_sc;
sc_handlers[SC_USE_TOKEN] = use_token_sc;
diff --git a/src/lib/include/kogata/mainloop.h b/src/lib/include/kogata/mainloop.h
index 2b447ef..6352916 100644
--- a/src/lib/include/kogata/mainloop.h
+++ b/src/lib/include/kogata/mainloop.h
@@ -12,6 +12,7 @@ typedef struct mainloop_fd mainloop_fd_t;
typedef void (*buf_full_callback_t)(mainloop_fd_t *fd);
typedef void (*fd_error_callback_t)(mainloop_fd_t *fd);
+typedef void (*idle_callback_t)(void* data);
typedef struct {
size_t size, written;
@@ -41,6 +42,7 @@ void mainloop_rm_fd(mainloop_fd_t* fd);
void mainloop_expect(mainloop_fd_t *fd, void* buf, size_t size, buf_full_callback_t cb);
bool mainloop_nonblocking_write(mainloop_fd_t *fd, void* buf, size_t size, bool must_free_buf);
+void mainloop_when_idle(idle_callback_t cb, void* data);
void mainloop_run();
void mainloop_exit();
diff --git a/src/lib/libkogata/mainloop.c b/src/lib/libkogata/mainloop.c
index c1758a4..75fb252 100644
--- a/src/lib/libkogata/mainloop.c
+++ b/src/lib/libkogata/mainloop.c
@@ -7,6 +7,9 @@ mainloop_fd_t *mainloop_fds = 0;
bool mainloop_fds_change = false;
bool mainloop_must_exit = false;
+idle_callback_t mainloop_idle_cb = 0;
+void* mainloop_idle_cb_data = 0;
+
void mainloop_add_fd(mainloop_fd_t* fd) {
mainloop_fds_change = true;
@@ -53,12 +56,19 @@ bool mainloop_nonblocking_write(mainloop_fd_t *fd, void* buf, size_t size, bool
return false;
}
+void mainloop_when_idle(idle_callback_t cb, void* data) {
+ mainloop_idle_cb = cb;
+ mainloop_idle_cb_data = data;
+}
+
void mainloop_run() {
sel_fd_t *sel_arg = 0;
int nfds = 0;
mainloop_fds_change = true;
mainloop_must_exit = false;
+
+ bool after_idle_step = false;
while(!mainloop_must_exit) {
if (mainloop_fds_change) {
nfds = 0;
@@ -91,11 +101,12 @@ void mainloop_run() {
// ---- Do the select
/*dbg_printf("(mainloop) begin select\n");*/
- bool ok = sc_select(sel_arg, nfds, -1);
+ bool ok = sc_select(sel_arg, nfds, (after_idle_step || mainloop_idle_cb == 0 ? -1 : 0));
if (!ok) {
- dbg_printf("(mainloop) Failed to select.\n");
- free(sel_arg);
- return;
+ // nothing happenned
+ if (mainloop_idle_cb != 0) mainloop_idle_cb(mainloop_idle_cb_data);
+ after_idle_step = true;
+ continue;
}
/*dbg_printf("(mainloop) end select\n");*/
@@ -131,6 +142,7 @@ void mainloop_run() {
}
i++;
}
+ after_idle_step = false;
}
}
}
diff --git a/src/sysapp/login/main.lua b/src/sysapp/login/main.lua
index 67ce3fe..3aa0695 100644
--- a/src/sysapp/login/main.lua
+++ b/src/sysapp/login/main.lua
@@ -145,6 +145,31 @@ local grid = tk.grid({border_size = 1}, {
wm:add({title = "Filesystems", x = 300, y = 20},
tk.box({vresize = true, hresize = true, vscroll = true, hscroll = true}, grid))
+function open_terminal(title, binfile)
+ local term_widget = tk.gipwidget({width = 480, height = 360})
+ wm:add({title = title, x = 300, y = 200}, term_widget)
+ local tty_a, tty_b = sys.make_channel(false)
+
+ local term_bin_pid = sys.new_proc()
+ sys.bind_fs(term_bin_pid, "sys", "sys")
+ sys.bind_fs(term_bin_pid, "config", "config")
+ sys.bind_fd(term_bin_pid, sysdef.STD_FD_GIP, term_widget.ch_cli)
+ sys.bind_fd(term_bin_pid, sysdef.STD_FD_TTYSRV, tty_a)
+ sys.dbg_print("Start terminal.bin, pid: " .. tonumber(term_bin_pid))
+ sys.proc_exec(term_bin_pid, "sys:/bin/terminal.bin")
+
+ local shell_bin_pid = sys.new_proc()
+ sys.bind_fs(shell_bin_pid, "root", "root")
+ sys.bind_fs(shell_bin_pid, "sys", "sys")
+ sys.bind_fs(shell_bin_pid, "config", "config")
+ sys.bind_fd(shell_bin_pid, sysdef.STD_FD_TTY_STDIO, tty_b)
+ sys.dbg_print("Start " .. binfile .. ", pid: " .. tonumber(shell_bin_pid))
+ sys.proc_exec(shell_bin_pid, binfile)
+end
+
+open_terminal("Shell", "sys:/bin/shell.bin")
+open_terminal("Lua prompt", "sys:/bin/lx.bin")
+
mainloop.run()
os.exit()
diff --git a/src/sysbin/terminal/main.c b/src/sysbin/terminal/main.c
index 77bf141..604228a 100644
--- a/src/sysbin/terminal/main.c
+++ b/src/sysbin/terminal/main.c
@@ -39,6 +39,7 @@ typedef struct {
fb_t *fb;
uint32_t sv_features, cl_features;
+ fb_region_t damage;
font_t *font;
int cw, ch; // size of a character
@@ -56,6 +57,7 @@ typedef struct {
int csrl, csrc;
bool csr_visible;
+ gip_handler_t *handler;
mainloop_fd_t app;
char rd_c_buf;
char wr_c_buf;
@@ -72,6 +74,8 @@ void gip_async_initiate(gip_handler_t *s, gip_msg_header *p, void* msgdata, void
void term_on_rd_c(mainloop_fd_t *fd);
void term_app_on_error(mainloop_fd_t *fd);
+void idle_cb(void* data);
+
gip_handler_callbacks_t term_gip_cb = {
.reset = 0,
@@ -106,8 +110,11 @@ int main(int argc, char **argv) {
term.cw = g_text_width(term.font, "#", 8);
term.ch = g_text_height(term.font, "#", 8);
+ term.damage.x = term.damage.y = term.damage.h = term.damage.w = -1;
+
gip_handler_t *h = new_gip_handler(&term_gip_cb, &term);
ASSERT(h != 0);
+ term.handler = h;
h->mainloop_item.fd = STD_FD_GIP;
mainloop_add_fd(&h->mainloop_item);
@@ -121,6 +128,8 @@ int main(int argc, char **argv) {
gip_msg_header reset_msg = { .code = GIPC_RESET, .arg = 0 };
gip_cmd(h, &reset_msg, 0, gip_async_initiate, 0);
+ mainloop_when_idle(idle_cb, &term);
+
mainloop_run();
return 0;
@@ -128,6 +137,24 @@ int main(int argc, char **argv) {
// Terminal features
+void term_damage_at(term_t *t, int x, int y, int w, int h) {
+ if (t->damage.x == -1) {
+ t->damage.x = x;
+ t->damage.y = y;
+ t->damage.w = w;
+ t->damage.h = h;
+ } else {
+ int px1 = t->damage.x + t->damage.w;
+ int py1 = t->damage.y + t->damage.h;
+ int nx1 = (px1 > x+w ? px1 : x+w);
+ int ny1 = (py1 > y+h ? py1 : y+h);
+ t->damage.x = (t->damage.x < x ? t->damage.x : x);
+ t->damage.y = (t->damage.y < y ? t->damage.y : y);
+ t->damage.w = nx1 - t->damage.x;
+ t->damage.h = ny1 - t->damage.y;
+ }
+}
+
void term_draw_c(term_t *t, int l, int c) {
color_t bg = t->bg;
if (l == t->csrl && c == t->csrc) bg = t->csr_bg;
@@ -139,6 +166,7 @@ void term_draw_c(term_t *t, int l, int c) {
if (t->fb) {
g_fillrect(t->fb, c * t->cw, l * t->ch, t->cw, t->ch, bg);
g_write(t->fb, c * t->cw, l * t->ch, ss, t->font, 16, t->fg);
+ term_damage_at(t, c * t->cw, l * t->ch, t->cw, t->ch);
}
}
@@ -162,8 +190,10 @@ void term_clear_screen(term_t *t) {
for (int i = 0; i < t->w * t->h; i++) t->scr_chars[i] = ' ';
- if (t->fb)
+ if (t->fb) {
g_fillrect(t->fb, 0, 0, t->mode.width, t->mode.height, t->bg);
+ term_damage_at(t, 0, 0, t->mode.width, t->mode.height);
+ }
term_move_cursor(t, 0, 0);
}
@@ -179,6 +209,7 @@ void term_scroll1(term_t *t) {
if (t->fb) {
g_scroll_up(t->fb, t->ch);
g_fillrect(t->fb, 0, t->ch * (t->h - 1), t->cw * t->w, t->ch, t->bg);
+ term_damage_at(t, 0, 0, t->mode.width, t->mode.height);
}
}
@@ -386,6 +417,17 @@ void term_on_rd_c(mainloop_fd_t *fd) {
term_putc(t, t->rd_c_buf);
}
+void idle_cb(void* data) {
+ term_t *t = (term_t*)data;
+
+ // we are done processing events ; flush damaged region
+ if (t->damage.x != -1) {
+ gip_msg_header damage_msg = { .code = GIPN_BUFFER_DAMAGE, .arg = 0 };
+ gip_cmd(t->handler, &damage_msg, &t->damage, 0, 0);
+ t->damage.x = t->damage.y = t->damage.w = t->damage.h = -1;
+ }
+}
+
void term_app_on_error(mainloop_fd_t *fd) {
// TODO
}
diff --git a/src/syslua/lx/gip.lua b/src/syslua/lx/gip.lua
new file mode 100644
index 0000000..8ae06bf
--- /dev/null
+++ b/src/syslua/lx/gip.lua
@@ -0,0 +1,177 @@
+local sys = require 'lx.sys'
+local protodef = require 'lx.protodef'
+local mainloop = require 'lx.mainloop'
+
+local gip = {}
+
+gip.proto = {
+ -- Definitions from proto/gip.h
+ GIPF_DOUBLE_BUFFER = 0x1,
+ GIPF_DAMAGE_NOTIF = 0x2,
+ GIPF_MODESET = 0x4,
+ GIPF_MOUSE_XY = 0x10,
+ GIPF_MOUSE_CURSOR = 0x20,
+
+ GIPC_RESET = 0,
+ GIPR_INITIATE = 1,
+ GIPR_OK = 2,
+ GIPR_FAILURE = 3,
+ GIPC_ENABLE_FEATURES = 4,
+ GIPC_DISABLE_FEATURES = 5,
+
+ GIPN_BUFFER_INFO = 10,
+ GIPC_QUERY_MODE = 11,
+ GIPR_MODE_INFO = 12,
+ GIPC_SET_MODE = 13,
+
+ GIPN_BUFFER_DAMAGE = 14,
+ GIPC_SWITCH_BUFFER = 15,
+
+ GIPN_KEY_DOWN = 20,
+ GIPN_KEY_UP = 21,
+
+ GIPN_MOUSE_DATA = 30,
+ GIPN_MOUSE_XY = 31,
+ GIPN_MOUSE_PRESSED = 32,
+ GIPN_MOUSE_RELEASED = 33,
+
+ gip_msg_header = {
+ fmt = 'LLL', -- code, req_id, arg
+ len = 12
+ },
+ -- buffer_info_msg = protodef.token .. protodef.fb_info
+ buffer_info_msg = {
+ len = protodef.token.len + protodef.fb_info.len
+ },
+ -- mode_info_msg = protodef.fb_info
+ mode_info_msg = {
+ len = protodef.fb_info.len
+ },
+ -- buffer_damage_msg = protodef.fb_region
+ buffer_damage_msg = {
+ len = protodef.fb_region.len
+ },
+}
+
+gip.new_handler = function(fd)
+ local h = {}
+ h.fd = fd
+
+ -- Replacable callbacks
+ function h:cb_reset(req_id, arg) end
+ function h:cb_initiate(req_id, arg) end
+ function h:cb_ok(req_id, arg) end
+ function h:cb_failure(req_id, arg) end
+ function h:cb_enable_features(req_id, arg) end
+ function h:cb_disable_features(req_id, arg) end
+ function h:cb_query_mode(req_id, arg) end
+ function h:cb_set_mode(req_id, arg) end
+ function h:cb_switch_buffer(req_id, arg) end
+ function h:cb_key_down(req_id, arg) end
+ function h:cb_key_up(req_id, arg) end
+ function h:cb_buffer_info(req_id, arg, token, fb_info) end
+ function h:cb_mode_info(req_id, arg, fb_info) end
+ function h:cb_buffer_damage(req_id, arg, region) end
+ function h:cb_unknown_message(code, req_id, arg) error("Unknown GIP message") end
+ function h:fd_error() error("GIP FD error") end
+
+ h.requests_in_progress = {}
+ h.msg_id = 0
+
+ h.mainloop_fd = mainloop.add_fd(h.fd, function() h:fd_error() end)
+
+ function h:send_msg(code, req_id, arg, data)
+ if req_id == nil then
+ req_id = h.msg_id
+ h.msg_id = h.msg_id + 1
+ end
+
+ local msgdata = string.pack(gip.proto.gip_msg_header.fmt, code, req_id, arg)
+ if code == gip.proto.GIPN_BUFFER_INFO then
+ msgdata = msgdata .. string.pack(protodef.token.fmt, data.tok)
+ .. string.pack(protodef.fb_info.fmt, data.geom.width, data.geom.height,
+ data.geom.pitch, data.geom.bpp, data.geom.memory_model)
+ elseif code == gip.proto.GIPN_MODE_INFO then
+ error("Not implemented") --TODO
+ elseif code == gip.proto.GIPN_BUFFER_DAMAGE then
+ error("Not implemented") --TODO
+ end
+
+ h.mainloop_fd:write(msgdata)
+ return req_id
+ end
+
+ function h:cmd(code, arg, data, cb)
+ local req_id = h:send_msg(code, nil, arg, data)
+ h.requests_in_progress[req_id] = cb
+ end
+
+ function h:got_reply(code, req_id, arg, data)
+ if h.requests_in_progress[req_id] ~= nil then
+ h.requests_in_progress[req_id](code, arg, data)
+ h.requests_in_progress[req_id] = nil
+ end
+ end
+
+ local function gip_handler(ev)
+ local code, req_id, arg = string.unpack(gip.proto.gip_msg_header.fmt, ev)
+
+ if code == gip.proto.GIPC_RESET then
+ h:cb_reset(req_id, arg)
+ elseif code == gip.proto.GIPR_INITIATE then
+ h:cb_initiate(req_id, arg)
+ h:got_reply(code, req_id, arg)
+ elseif code == gip.proto.GIPR_OK then
+ h:cb_ok(req_id, arg)
+ h:got_reply(code, req_id, arg)
+ elseif code == gip.proto.GIPR_FAILURE then
+ h:cb_failure(req_id, arg)
+ h:got_reply(code, req_id, arg)
+ elseif code == gip.proto.GIPC_ENABLE_FEATURE then
+ h:cb_enable_feature(req_id, arg)
+ elseif code == gip.proto.GIPC_DISABLE_FEATURE then
+ h:cb_disable_feature(req_id, arg)
+ elseif code == gip.proto.GIPC_QUERY_MODE then
+ h:cb_query_mode(req_id, arg)
+ elseif code == gip.proto.GIPC_SET_MODE then
+ h:cb_set_mode(req_id, arg)
+ elseif code == gip.proto.GIPC_SWITCH_BUFFER then
+ h:cb_switch_buffer(req_id, arg)
+ elseif code == gip.proto.GIPN_KEY_DOWN then
+ h:cb_key_down(req_id, arg)
+ elseif code == gip.proto.GIPN_KEY_UP then
+ h:cb_key_up(req_id, arg)
+ elseif code == gip.proto.GIPN_BUFFER_INFO then
+ h.mainloop_fd:expect(gip.proto.buffer_info_msg.len, function(msg)
+ local tok, p1 = string.unpack(protodef.token.fmt, msg)
+ local w, h, pitch, bpp, mm = string.unpack(protodef.fb_info.fmt, msg, p1)
+ h:cb_buffer_info(req_id, arg, token, {
+ width = w, height = h,
+ pitch = pitch, bpp = bpp, memory_model = mm })
+ end)
+ elseif code == gip.proto.GIPR_MODE_INFO then
+ h.mainloop_fd:expect(gip.proto.mode_info_msg.len, function(msg)
+ local w, h, pitch, bpp, mm = string.unpack(protodef.fb_info.fmt, msg)
+ local info = {
+ width = w, height = h,
+ pitch = pitch, bpp = bpp, memory_model = mm }
+ h:cb_mode_info(req_id, arg, info)
+ h:got_reply(code, req_id, arg, info)
+ end)
+ elseif code == gip.proto.GIPN_BUFFER_DAMAGE then
+ h.mainloop_fd:expect(gip.proto.buffer_damage_msg.len, function(msg)
+ local rx, ry, rw, rh = string.unpack(protodef.fb_region.fmt, msg)
+ h:cb_buffer_damage(req_id, arg, { x = rx, y = ry, w = rw, h = rh })
+ end)
+ else
+ h:cb_unknown_message(code, req_id, arg)
+ end
+
+ h.mainloop_fd:expect(gip.proto.gip_msg_header.len, gip_handler)
+ end
+ h.mainloop_fd:expect(gip.proto.gip_msg_header.len, gip_handler)
+
+ return h
+end
+
+return gip
diff --git a/src/syslua/lx/gui.lua b/src/syslua/lx/gui.lua
index 6cfb545..9342025 100644
--- a/src/syslua/lx/gui.lua
+++ b/src/syslua/lx/gui.lua
@@ -1,5 +1,6 @@
local sys = require 'lx.sys'
-local sysdef= require 'lx.sysdef'
+local sysdef = require 'lx.sysdef'
+local protodef = require 'lx.protodef'
local ioctl = require 'lx.ioctl'
local draw = require 'lx.draw'
@@ -44,12 +45,12 @@ function gui.open_io()
gui.pckbd_mainloop_fd = mainloop.add_fd(gui.pckbd_fd, function() error('pckbd fd error') end)
local function pckbd_handler(ev)
- local scancode, ty = string.unpack("HH", ev)
+ local scancode, ty = string.unpack(protodef.kbd_event.fmt, ev)
gui.on_keyboard(scancode, ty)
- gui.pckbd_mainloop_fd:expect(4, pckbd_handler)
+ gui.pckbd_mainloop_fd:expect(protodef.kbd_event.len, pckbd_handler)
end
- gui.pckbd_mainloop_fd:expect(4, pckbd_handler)
+ gui.pckbd_mainloop_fd:expect(protodef.kbd_event.len, pckbd_handler)
gui.kbdlib = kbd.init()
@@ -59,13 +60,13 @@ function gui.open_io()
gui.pcmouse_mainloop_fd = mainloop.add_fd(gui.pcmouse_fd, function() error("pcmouse fd error") end)
local function pcmouse_handler(ev)
- local dx, dy, dw, lb, rb, mb = string.unpack("hhbBBB", ev)
+ local dx, dy, dw, lb, rb, mb = string.unpack(protodef.mouse_event.fmt, ev)
local change_but = false
while not change_but do
- local bytes, n = sys.read(gui.pcmouse_fd, 1, 8)
+ local bytes, n = sys.read(gui.pcmouse_fd, 1, protodef.mouse_event.len)
if n == 8 then
- local dx2, dy2, dw2, lb2, rb2, mb2 = string.unpack("hhbBBB", ev)
+ local dx2, dy2, dw2, lb2, rb2, mb2 = string.unpack(protodef.mouse_event.fmt, ev)
change_but = change_but or (lb2 ~= lb) or (rb2 ~= rb) or (mb2 ~= mb)
dx = dx + dx2
dy = dy + dy2
@@ -78,9 +79,9 @@ function gui.open_io()
end
gui.on_mouse(dx, dy, dw, lb, rb, mb)
- gui.pcmouse_mainloop_fd:expect(8, pcmouse_handler)
+ gui.pcmouse_mainloop_fd:expect(protodef.mouse_event.len, pcmouse_handler)
end
- gui.pcmouse_mainloop_fd:expect(8, pcmouse_handler)
+ gui.pcmouse_mainloop_fd:expect(protodef.mouse_event.len, pcmouse_handler)
end
function gui.open_gip()
diff --git a/src/syslua/lx/protodef.lua b/src/syslua/lx/protodef.lua
new file mode 100644
index 0000000..f7f3fc0
--- /dev/null
+++ b/src/syslua/lx/protodef.lua
@@ -0,0 +1,29 @@
+local protodef = {
+ mouse_event = {
+ -- common/include/proto/mouse.h
+ fmt = 'hhbBBB',
+ len = 8
+ },
+ kbd_event = {
+ -- common/include/proto/keyboard.h
+ fmt = 'HH',
+ len = 4
+ },
+ token = {
+ -- common/include/proto/token.h
+ fmt = 'c16',
+ len = 16
+ }
+}
+
+-- common/include/proto/fb.h
+protodef.fb_info = {
+ fmt = 'lllll',
+ len = 20
+}
+protodef.fb_region = {
+ fmt = 'llll',
+ len = 16
+}
+
+return protodef
diff --git a/src/syslua/lx/sysdef.lua b/src/syslua/lx/sysdef.lua
index 43015e2..e2144bc 100644
--- a/src/syslua/lx/sysdef.lua
+++ b/src/syslua/lx/sysdef.lua
@@ -62,4 +62,6 @@ return {
PS_FINISHED = 3,
PS_FAILURE = 4,
PS_KILLED = 5,
+
}
+
diff --git a/src/syslua/lx/tk.lua b/src/syslua/lx/tk.lua
index e8686ba..f38efe2 100644
--- a/src/syslua/lx/tk.lua
+++ b/src/syslua/lx/tk.lua
@@ -1,5 +1,8 @@
local draw = require 'lx.draw'
local sys = require 'lx.sys'
+local gui = require 'lx.gui'
+local gip = require 'lx.gip'
+local kbdcode = require 'lx.kbdcode'
local tk = {}
@@ -225,6 +228,10 @@ function tk.widget(width, height, opts)
self.left_click_valid = false
end
+ function w:on_keyboard(scancode, ty)
+ -- Handler for raw keyboard event
+ end
+
function w:on_text_input(char)
-- Handler for text input
end
@@ -266,6 +273,12 @@ function tk.init(gui, root_widget)
root_widget:do_resize(gui.surface:width(), gui.surface:height())
+ local prev_gui_on_keyboard = gui.on_keyboard
+ gui.on_keyboard = function(scancode, ty)
+ root_widget:on_keyboard(scancode, ty)
+ prev_gui_on_keyboard(scancode, ty)
+ end
+
gui.on_key_down = function(key) root_widget:on_key_down(key) end
gui.on_key_up = function(key) root_widget:on_key_up(key) end
gui.on_text_input = function(key) root_widget:on_text_input(char) end
@@ -919,8 +932,51 @@ function tk.window_manager()
end
end
+ function wm:on_keyboard(scancode, ty)
+ wm.windows[#wm.windows].content:on_keyboard(scancode, ty)
+ end
+
return wm
end
+function tk.gipwidget(opts)
+ local w = tk.widget(nil, nil, opts)
+
+ w.geom = {
+ bpp = gui.surface_geom.bpp,
+ memory_model = gui.surface_geom.memory_model,
+ width = opts.width,
+ height = opts.height,
+ pitch = opts.width * gui.surface_geom.bpp // 8
+ }
+ w.shm_fd = sys.make_shm(w.geom.height * w.geom.pitch)
+ w.framebuffer = draw.surface_from_fd(w.shm_fd, w.geom)
+
+ w.ch_srv, w.ch_cli = sys.make_channel(false)
+ w.gip_handler = gip.new_handler(w.ch_srv)
+
+ function w.gip_handler:cb_reset(req_id, arg)
+ w.gip_handler:send_msg(gip.proto.GIPR_INITIATE, req_id, gip.proto.GIPF_DAMAGE_NOTIF)
+ w.gip_handler:send_msg(gip.proto.GIPN_BUFFER_INFO, 0, 0, { tok = sys.gen_token(w.shm_fd), geom = w.geom })
+ end
+
+ function w.gip_handler:cb_buffer_damage(req_id, arg, region)
+ w:redraw(region.x, region.y, region.w, region.h)
+ end
+
+ function w:draw(x0, y0, buf)
+ if x0 < self.framebuffer:width() and y0 < self.framebuffer:height() then
+ buf:blit(0, 0, self.framebuffer:sub(x0, y0, self.framebuffer:width(), self.framebuffer:height()))
+ end
+ end
+
+ function w:on_keyboard(scancode, ty)
+ sys.dbg_print("gipwidget:on_keyboard " .. tostring(scancode) .. "\n")
+ w.gip_handler:send_msg(ty == kbdcode.event.KEYPRESS and gip.proto.GIPN_KEY_DOWN or gip.proto.GIPN_KEY_UP, nil, scancode)
+ end
+
+ return w
+end
+
return tk