ltk

Socket-based GUI for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

commit 87d191828a7c0dd4eec3f61dc07fd40768a45f8c
parent 700df2e2739b914fa2738404f949f791814cf7d4
Author: lumidify <nobody@lumidify.org>
Date:   Thu,  7 Jan 2021 20:41:23 +0100

Add 'destroy' command; make grid sticky format more readable

Diffstat:
Mgrid.c | 29+++++++++++++++++++++++------
Mltk.h | 16+++++++++-------
Mltkd.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Mtest.gui | 4++--
Mtest.sh | 8++++++--
5 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/grid.c b/grid.c @@ -111,6 +111,7 @@ ltk_grid_create(ltk_window *window, const char *id, int rows, int columns) { grid->widget.mouse_release = &ltk_grid_mouse_release; grid->widget.motion_notify = &ltk_grid_motion_notify; grid->widget.resize = &ltk_recalculate_grid; + grid->widget.remove_child = &ltk_grid_ungrid; grid->rows = rows; grid->columns = columns; @@ -258,6 +259,7 @@ ltk_recalculate_grid(ltk_grid *grid) { } } +/* FIXME: Check if widget already exists at position */ static int ltk_grid_add(ltk_window *window, ltk_widget *widget, ltk_grid *grid, int row, int column, int row_span, int column_span, unsigned short sticky, char **errstr) { @@ -376,18 +378,22 @@ ltk_grid_cmd_add( char **tokens, size_t num_tokens, char **errstr) { + const char *c; ltk_grid *grid; ltk_widget *widget; const char *errstr_num; - int row, column, row_span, column_span, sticky; + int row, column, row_span, column_span, sticky = 0; if (num_tokens != 9) { *errstr = "Invalid number of arguments.\n"; return 1; } grid = ltk_get_widget(tokens[1], LTK_GRID, errstr); widget = ltk_get_widget(tokens[3], LTK_WIDGET, errstr); - if (!grid || !widget) return 1; + if (!grid || !widget) { + *errstr = "Invalid widget ID.\n"; + return 1; + } row = strtonum(tokens[4], 0, grid->rows - 1, &errstr_num); if (errstr_num) { *errstr = "Invalid row number.\n"; @@ -408,11 +414,22 @@ ltk_grid_cmd_add( *errstr = "Invalid column span.\n"; return 1; } - sticky = strtonum(tokens[8], 0, 15, &errstr_num); - if (errstr_num) { - *errstr = "Invalid sticky setting.\n"; - return 1; + + for (c = tokens[8]; *c != '\0'; c++) { + if (*c == 'n') { + sticky |= LTK_STICKY_TOP; + } else if (*c == 's') { + sticky |= LTK_STICKY_BOTTOM; + } else if (*c == 'e') { + sticky |= LTK_STICKY_RIGHT; + } else if (*c == 'w') { + sticky |= LTK_STICKY_LEFT; + } else if (*c != 'u') { + *errstr = "Invalid sticky specification.\n"; + return 1; + } } + return ltk_grid_add(window, widget, grid, row, column, row_span, column_span, sticky, errstr); } diff --git a/ltk.h b/ltk.h @@ -70,19 +70,21 @@ typedef struct ltk_widget { struct ltk_widget *parent; char *id; - void (*key_press) (void *, XEvent event); - void (*key_release) (void *, XEvent event); - void (*mouse_press) (void *, XEvent event); - void (*mouse_release) (void *, XEvent event); - void (*motion_notify) (void *, XEvent event); - void (*mouse_leave) (void *, XEvent event); - void (*mouse_enter) (void *, XEvent event); + void (*key_press) (void *, XEvent); + void (*key_release) (void *, XEvent); + void (*mouse_press) (void *, XEvent); + void (*mouse_release) (void *, XEvent); + void (*motion_notify) (void *, XEvent); + void (*mouse_leave) (void *, XEvent); + void (*mouse_enter) (void *, XEvent); void (*resize) (void *, int, int); void (*draw) (void *); void (*change_state) (void *); void (*destroy) (void *, int); + int (*remove_child) (ltk_window *, void *, void *, char **); + ltk_widget_type type; ltk_widget_state state; unsigned int sticky; diff --git a/ltkd.c b/ltkd.c @@ -1,5 +1,6 @@ /* FIXME: error checking in tokenizer (is this necessary?) */ /* FIXME: parsing doesn't work properly with bs? */ +/* FIXME: strip whitespace at end of lines in socket format */ /* * This file is part of the Lumidify ToolKit (LTK) * Copyright (c) 2016, 2017, 2018, 2020, 2021 lumidify <nobody@lumidify.org> @@ -111,6 +112,7 @@ static ltk_rect ltk_rect_union(ltk_rect r1, ltk_rect r2); static int add_client(int fd); static int listen_sock(const char *sock_path); static int accept_sock(int listenfd); +static int ltk_widget_destroy(ltk_window *window, char **tokens, size_t num_tokens, char **errstr); static short maxsocket = -1; static short running = 1; @@ -753,6 +755,7 @@ ltk_fill_widget_defaults(ltk_widget *widget, const char *id, ltk_window *window, widget->draw = draw; widget->change_state = change_state; widget->destroy = destroy; + widget->remove_child = NULL; widget->needs_redraw = needs_redraw; widget->state = LTK_NORMAL; @@ -1151,6 +1154,8 @@ process_commands(ltk_window *window, struct ltk_sock_info *sock) { err = ltk_draw_cmd(window, tokens, num_tokens, &errstr); } else if (strcmp(tokens[0], "quit") == 0) { ltk_quit(window); + } else if (strcmp(tokens[0], "destroy") == 0) { + err = ltk_widget_destroy(window, tokens, num_tokens, &errstr); } else { errstr = "Invalid command.\n"; err = 1; @@ -1175,3 +1180,43 @@ process_commands(ltk_window *window, struct ltk_sock_info *sock) { sock->read_cur = 0; } } + +static int +ltk_widget_destroy( + ltk_window *window, + char **tokens, + size_t num_tokens, + char **errstr) { + int err = 0, shallow = 1; + khint_t k; + if (num_tokens != 2 && num_tokens != 3) { + *errstr = "Invalid number of arguments.\n"; + return 1; + } + if (num_tokens == 3) { + if (strcmp(tokens[2], "deep") == 0) { + shallow = 0; + } else if (strcmp(tokens[2], "shallow") == 0) { + shallow = 1; + } else { + *errstr = "Invalid argument: must be 'shallow' or 'deep'.\n"; + return 1; + } + } + ltk_widget *widget = ltk_get_widget(tokens[1], LTK_WIDGET, errstr); + if (!widget) { + *errstr = "Invalid widget ID.\n"; + return 1; + } + ltk_remove_widget(tokens[1]); + /* widget->parent->remove_child should never be NULl because of the fact that + the widget is set as parent, but let's just check anyways... */ + if (widget->parent && widget->parent->remove_child) { + err = widget->parent->remove_child( + window, widget, widget->parent, errstr + ); + } + widget->destroy(widget, shallow); + + return err; +} diff --git a/test.gui b/test.gui @@ -5,6 +5,6 @@ grid grd1 set-column-weight 0 1 grid grd1 set-column-weight 1 1 set-root-widget grd1 button btn1 create "I'm a button!" -grid grd1 add btn1 0 0 1 1 0 +grid grd1 add btn1 0 0 1 1 u button btn2 create "I'm also a button!" -grid grd1 add btn2 1 0 1 2 3 +grid grd1 add btn2 1 0 1 2 ew diff --git a/test.sh b/test.sh @@ -16,7 +16,11 @@ fi cat test.gui | ./ltkc $ltk_id | while read cmd do case "$cmd" in - "btn1 button_click") echo "quit" - ;; + "btn1 button_click") + echo "quit" + ;; + *) + printf "%s\n" "$cmd" >&2 + ;; esac done | ./ltkc $ltk_id