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 2845e91cce752793dfebfac761c4b1ae7c25b023
parent 236104387a38581c2d7e0b50dd208d6f2db4e312
Author: lumidify <nobody@lumidify.org>
Date:   Thu, 31 Dec 2020 20:34:13 +0100

Clean up headers a bit

Diffstat:
Mbutton.c | 10++++++----
Mcolor.c | 1+
Mcolor.h | 1+
Mdraw.c | 18++++++++++--------
Mgrid.c | 23++++++++++++-----------
Mltk.h | 27+++++++++++++--------------
Mltkd.c | 104+++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mtext.h | 3---
Mtext_line.h | 2+-
Mtext_pango.c | 8++++++--
Mtext_stb.c | 11++++++++---
11 files changed, 114 insertions(+), 94 deletions(-)

diff --git a/button.c b/button.c @@ -25,11 +25,13 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <stdarg.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> -#include "util.h" -#include "khash.h" + #include "ltk.h" +#include "util.h" #include "text.h" #include "button.h" @@ -242,12 +244,12 @@ ltk_button_cmd_create( *errstr = "Invalid number of arguments.\n"; return 1; } - if (!ltk_widget_id_free(window, tokens[1])) { + if (!ltk_widget_id_free(tokens[1])) { *errstr = "Widget ID already taken.\n"; return 1; } button = ltk_button_create(window, tokens[1], tokens[3]); - ltk_set_widget(window, button, tokens[1]); + ltk_set_widget(button, tokens[1]); return 0; } diff --git a/color.c b/color.c @@ -1,5 +1,6 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> + #include "defs.h" #include "util.h" #include "color.h" diff --git a/color.h b/color.h @@ -1,4 +1,5 @@ #include "defs.h" + #ifdef USE_XFT #include <X11/Xft/Xft.h> #endif diff --git a/draw.c b/draw.c @@ -23,12 +23,14 @@ #include <stdio.h> #include <stdlib.h> -#include <stdint.h> #include <string.h> +#include <stdarg.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> -#include "util.h" + #include "ltk.h" +#include "util.h" #include "draw.h" static void ltk_draw_draw(ltk_draw *draw); @@ -200,7 +202,7 @@ ltk_draw_cmd_clear( *errstr = "Invalid number of arguments.\n"; return 1; } - draw = ltk_get_widget(window, tokens[1], LTK_DRAW, errstr); + draw = ltk_get_widget(tokens[1], LTK_DRAW, errstr); if (!draw) return 1; ltk_draw_clear(window, draw); @@ -218,7 +220,7 @@ ltk_draw_cmd_set_color( *errstr = "Invalid number of arguments.\n"; return 1; } - draw = ltk_get_widget(window, tokens[1], LTK_DRAW, errstr); + draw = ltk_get_widget(tokens[1], LTK_DRAW, errstr); if (!draw) return 1; ltk_draw_set_color(window, draw, tokens[3]); @@ -238,7 +240,7 @@ ltk_draw_cmd_line( *errstr = "Invalid number of arguments.\n"; return 1; } - draw = ltk_get_widget(window, tokens[1], LTK_DRAW, errstr); + draw = ltk_get_widget(tokens[1], LTK_DRAW, errstr); if (!draw) return 1; x1 = strtonum(tokens[3], 0, 100000, &errstr_num); if (errstr_num) { @@ -278,7 +280,7 @@ ltk_draw_cmd_rect( *errstr = "Invalid number of arguments.\n"; return 1; } - draw = ltk_get_widget(window, tokens[1], LTK_DRAW, errstr); + draw = ltk_get_widget(tokens[1], LTK_DRAW, errstr); if (!draw) return 1; x = strtonum(tokens[3], 0, 100000, &errstr_num); if (errstr_num) { @@ -324,7 +326,7 @@ ltk_draw_cmd_create( *errstr = "Invalid number of arguments.\n"; return 1; } - if (!ltk_widget_id_free(window, tokens[1])) { + if (!ltk_widget_id_free(tokens[1])) { *errstr = "Widget ID already taken.\n"; return 1; } @@ -339,7 +341,7 @@ ltk_draw_cmd_create( return 1; } draw = ltk_draw_create(window, tokens[1], w, h, tokens[5]); - ltk_set_widget(window, draw, tokens[1]); + ltk_set_widget(draw, tokens[1]); return 0; } diff --git a/grid.c b/grid.c @@ -26,12 +26,13 @@ #include <stdio.h> #include <stdlib.h> -#include <stdint.h> +#include <stdarg.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> -#include "util.h" -#include "khash.h" + #include "ltk.h" +#include "util.h" #include "grid.h" static void ltk_grid_set_row_weight(ltk_grid *grid, int row, int weight); @@ -383,8 +384,8 @@ ltk_grid_cmd_add( *errstr = "Invalid number of arguments.\n"; return 1; } - grid = ltk_get_widget(window, tokens[1], LTK_GRID, errstr); - widget = ltk_get_widget(window, tokens[3], LTK_WIDGET, errstr); + grid = ltk_get_widget(tokens[1], LTK_GRID, errstr); + widget = ltk_get_widget(tokens[3], LTK_WIDGET, errstr); if (!grid || !widget) return 1; row = strtonum(tokens[4], 0, grid->rows - 1, &errstr_num); if (errstr_num) { @@ -427,8 +428,8 @@ ltk_grid_cmd_ungrid( *errstr = "Invalid number of arguments.\n"; return 1; } - grid = ltk_get_widget(window, tokens[1], LTK_GRID, errstr); - widget = ltk_get_widget(window, tokens[3], LTK_WIDGET, errstr); + grid = ltk_get_widget(tokens[1], LTK_GRID, errstr); + widget = ltk_get_widget(tokens[3], LTK_WIDGET, errstr); if (!grid || !widget) return 1; return ltk_grid_ungrid(window, widget, grid, errstr); } @@ -447,7 +448,7 @@ ltk_grid_cmd_create( *errstr = "Invalid number of arguments.\n"; return 1; } - if (!ltk_widget_id_free(window, tokens[1])) { + if (!ltk_widget_id_free(tokens[1])) { *errstr = "Widget ID already taken.\n"; return 1; } @@ -462,7 +463,7 @@ ltk_grid_cmd_create( return 1; } grid = ltk_grid_create(window, tokens[1], rows, columns); - ltk_set_widget(window, grid, tokens[1]); + ltk_set_widget(grid, tokens[1]); return 0; } @@ -481,7 +482,7 @@ ltk_grid_cmd_set_row_weight( *errstr = "Invalid number of arguments.\n"; return 1; } - grid = ltk_get_widget(window, tokens[1], LTK_GRID, errstr); + grid = ltk_get_widget(tokens[1], LTK_GRID, errstr); if (!grid) return 1; row = strtonum(tokens[3], 0, grid->rows, &errstr_num); if (errstr_num) { @@ -512,7 +513,7 @@ ltk_grid_cmd_set_column_weight( *errstr = "Invalid number of arguments.\n"; return 1; } - grid = ltk_get_widget(window, tokens[1], LTK_GRID, errstr); + grid = ltk_get_widget(tokens[1], LTK_GRID, errstr); if (!grid) return 1; column = strtonum(tokens[3], 0, grid->columns, &errstr_num); if (errstr_num) { diff --git a/ltk.h b/ltk.h @@ -24,12 +24,7 @@ #ifndef _LTK_H_ #define _LTK_H_ -#include <stdarg.h> - -/* FIXME: standardize the includes... */ -/* Requires the following includes: <X11/Xlib.h>, <X11/Xutil.h> */ - -#include "khash.h" +/* Requires the following includes: <X11/Xlib.h>, <X11/Xutil.h>, <stdarg.h> */ typedef enum { LTK_EVENT_RESIZE = 1 << 0, @@ -105,8 +100,6 @@ typedef struct { XColor bg; } ltk_window_theme; -typedef struct ltk_button_theme ltk_button_theme; - struct ltk_event_queue { ltk_event_type event_type; char *data; @@ -114,7 +107,15 @@ struct ltk_event_queue { struct ltk_event_queue *next; }; -KHASH_MAP_INIT_STR(widget, ltk_widget *) +/* + Historical note concerning ltk_window: This code was originally copied + from my previous attempt at creating a GUI library, which was meant to + be a regular C library and support multiple windows. Since this version + of LTK doesn't support multiple windows (well, the calling script can + just run more instances of ltkd if needed), having an ltk_window struct + passed around is kind of unnecessary. I'm too lazy to change that now, + though, so it's just going to stay that way. +*/ typedef struct ltk_window { Display *dpy; @@ -131,7 +132,6 @@ typedef struct ltk_window { ltk_rect dirty_rect; struct ltk_event_queue *first_event; struct ltk_event_queue *last_event; - khash_t(widget) *widget_hash; } ltk_window; void ltk_window_invalidate_rect(ltk_window *window, ltk_rect rect); @@ -151,9 +151,8 @@ void ltk_fill_widget_defaults(ltk_widget *widget, const char *id, ltk_window * w void ltk_widget_mouse_press_event(ltk_widget *widget, XEvent event); void ltk_widget_mouse_release_event(ltk_widget *widget, XEvent event); void ltk_widget_motion_notify_event(ltk_widget *widget, XEvent event); -int ltk_check_widget_id_free(ltk_window *window, const char *id); -ltk_widget *ltk_get_widget(ltk_window *window, const char *id, - ltk_widget_type type, char **errstr); -void ltk_set_widget(ltk_window *window, ltk_widget *widget, const char *id); +int ltk_check_widget_id_free(const char *id); +ltk_widget *ltk_get_widget(const char *id, ltk_widget_type type, char **errstr); +void ltk_set_widget(ltk_widget *widget, const char *id); #endif diff --git a/ltkd.c b/ltkd.c @@ -21,29 +21,33 @@ * SOFTWARE. */ +#include <time.h> #include <stdio.h> +#include <fcntl.h> +#include <errno.h> #include <stdlib.h> #include <string.h> -#include <stdint.h> -#include <fcntl.h> +#include <stdarg.h> #include <unistd.h> -#include <time.h> -#include <errno.h> #include <signal.h> + +#include <sys/un.h> #include <sys/stat.h> #include <sys/select.h> #include <sys/socket.h> -#include <sys/un.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> -#include "util.h" -#include "khash.h" + #include "ini.h" -#include "text.h" +#include "khash.h" + #include "ltk.h" +#include "util.h" +#include "text.h" #include "grid.h" -#include "button.h" #include "draw.h" +#include "button.h" #define MAX_SOCK_CONNS 20 #define READ_BLK_SIZE 128 @@ -74,15 +78,18 @@ static struct ltk_sock_info { struct token_list tokens; /* current tokens */ } sockets[MAX_SOCK_CONNS]; +KHASH_MAP_INIT_STR(widget, ltk_widget *) +static khash_t(widget) *widget_hash = NULL; + static int ltk_mainloop(ltk_window *window); static char *get_sock_path(char *basedir, Window id); static FILE *open_log(char *dir); static void daemonize(void); static ltk_window *ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h); +static void ltk_destroy_widget_hash(void); static void ltk_destroy_window(ltk_window *window); -static void ltk_cleanup_gui(ltk_window *window); -static void ltk_cleanup_nongui(void); +static void ltk_cleanup(void); static void ltk_redraw_window(ltk_window *window); static void ltk_window_other_event(ltk_window *window, XEvent event); static void ltk_handle_event(ltk_window *window, XEvent event); @@ -130,6 +137,9 @@ int main(int argc, char *argv[]) { ltk_logfile = open_log(ltk_dir); if (!ltk_logfile) ltk_fatal_errno("Unable to open log file.\n"); + widget_hash = kh_init(widget); + if (!widget_hash) ltk_fatal_errno("Unable to initialize widget hash table.\n"); + /* FIXME: set window size properly - I only run it in a tiling WM anyways, so it doesn't matter, but still... */ main_window = ltk_create_window(title, 0, 0, 500, 500); @@ -248,8 +258,7 @@ ltk_mainloop(ltk_window *window) { } - ltk_cleanup_gui(window); - ltk_cleanup_nongui(); + ltk_cleanup(); return 0; } @@ -331,7 +340,7 @@ open_log(char *dir) { } static void -ltk_cleanup_nongui(void) { +ltk_cleanup(void) { if (listenfd >= 0) close(listenfd); if (ltk_dir) @@ -353,11 +362,11 @@ ltk_cleanup_nongui(void) { if (sockets[i].tokens.tokens) free(sockets[i].tokens.tokens); } -} -static void -ltk_cleanup_gui(ltk_window *window) { - ltk_destroy_window(window); + if (widget_hash) + ltk_destroy_widget_hash(); + if (main_window) + ltk_destroy_window(main_window); } void @@ -376,7 +385,7 @@ ltk_set_root_widget_cmd( *errstr = "Invalid number of arguments.\n"; return 1; } - widget = ltk_get_widget(window, tokens[1], LTK_WIDGET, errstr); + widget = ltk_get_widget(tokens[1], LTK_WIDGET, errstr); if (!widget) return 1; window->root_widget = widget; int w = widget->rect.w; @@ -444,9 +453,7 @@ ltk_fatal(const char *format, ...) { va_start(args, format); print_log("Fatal", format, args); va_end(args); - ltk_cleanup_nongui(); - if (main_window) - ltk_cleanup_gui(main_window); + ltk_cleanup(); exit(1); }; @@ -594,8 +601,6 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int window->dirty_rect.x = 0; window->dirty_rect.y = 0; - window->widget_hash = kh_init(widget); - XClearWindow(window->dpy, window->xwindow); XMapRaised(window->dpy, window->xwindow); XSelectInput(window->dpy, window->xwindow, @@ -607,17 +612,21 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int } static void -ltk_destroy_window(ltk_window *window) { +ltk_destroy_widget_hash(void) { khint_t k; ltk_widget *ptr; - XDestroyWindow(window->dpy, window->xwindow); - for (k = kh_begin(window->widget_hash); k != kh_end(window->widget_hash); k++) { - if (kh_exist(window->widget_hash, k)) { - ptr = kh_value(window->widget_hash, k); + for (k = kh_begin(widget_hash); k != kh_end(widget_hash); k++) { + if (kh_exist(widget_hash, k)) { + ptr = kh_value(widget_hash, k); ptr->destroy(ptr, 1); } } - kh_destroy(widget, window->widget_hash); + kh_destroy(widget, widget_hash); +} + +static void +ltk_destroy_window(ltk_window *window) { + XDestroyWindow(window->dpy, window->xwindow); ltk_cleanup_text(); XCloseDisplay(window->dpy); if (window->theme.font) @@ -696,8 +705,8 @@ ltk_window_remove_active_widget(ltk_window *window) { } void -ltk_window_set_active_widget(ltk_window *window, ltk_widget *widget) { - window->active_widget = widget; +ltk_window_set_active_widget(ltk_widget *widget) { + widget->window->active_widget = widget; ltk_widget *parent = widget->parent; widget->state = LTK_ACTIVE; while (parent) { @@ -795,7 +804,7 @@ ltk_widget_motion_notify_event(ltk_widget *widget, XEvent event) { /* FIXME: do this properly */ if (widget->window->active_widget != widget && !widget->motion_notify) { ltk_window_remove_active_widget(widget->window); - ltk_window_set_active_widget(widget->window, widget); + ltk_window_set_active_widget(widget); } if (widget->needs_redraw) ltk_window_invalidate_rect(widget->window, widget->rect); @@ -831,26 +840,25 @@ ltk_handle_event(ltk_window *window, XEvent event) { } int -ltk_widget_id_free(ltk_window *window, const char *id) { +ltk_widget_id_free(const char *id) { khint_t k; - k = kh_get(widget, window->widget_hash, id); - if (k != kh_end(window->widget_hash)) { + k = kh_get(widget, widget_hash, id); + if (k != kh_end(widget_hash)) { return 0; } return 1; } ltk_widget * -ltk_get_widget(ltk_window *window, const char *id, ltk_widget_type type, - char **errstr) { +ltk_get_widget(const char *id, ltk_widget_type type, char **errstr) { khint_t k; ltk_widget *widget; - k = kh_get(widget, window->widget_hash, id); - if (k == kh_end(window->widget_hash)) { + k = kh_get(widget, widget_hash, id); + if (k == kh_end(widget_hash)) { *errstr = "Widget with given ID doesn't exist.\n"; return NULL; } - widget = kh_value(window->widget_hash, k); + widget = kh_value(widget_hash, k); if (type != LTK_WIDGET && widget->type != type) { *errstr = "Widget with given ID has wrong type.\n"; return NULL; @@ -859,7 +867,7 @@ ltk_get_widget(ltk_window *window, const char *id, ltk_widget_type type, } void -ltk_set_widget(ltk_window *window, ltk_widget *widget, const char *id) { +ltk_set_widget(ltk_widget *widget, const char *id) { int ret; khint_t k; /* apparently, khash requires the string to stay accessible */ @@ -867,16 +875,16 @@ ltk_set_widget(ltk_window *window, ltk_widget *widget, const char *id) { char *tmp = strdup(id); if (!tmp) ltk_fatal_errno("Unable to add widget to hash table.\n"); - k = kh_put(widget, window->widget_hash, tmp, &ret); - kh_value(window->widget_hash, k) = widget; + k = kh_put(widget, widget_hash, tmp, &ret); + kh_value(widget_hash, k) = widget; } void -ltk_remove_widget(ltk_window *window, const char *id) { +ltk_remove_widget(const char *id) { khint_t k; - k = kh_get(widget, window->widget_hash, id); - if (k != kh_end(window->widget_hash)) { - kh_del(widget, window->widget_hash, k); + k = kh_get(widget, widget_hash, id); + if (k != kh_end(widget_hash)) { + kh_del(widget, widget_hash, k); } } diff --git a/text.h b/text.h @@ -1,6 +1,3 @@ -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <stdint.h> #include "defs.h" #include "color.h" diff --git a/text_line.h b/text_line.h @@ -26,7 +26,7 @@ /* Requires the following includes: -<X11/Xlib.h>, <X11/Xutil.h>, <stdint.h>, "text_common.h", +<X11/Xlib.h>, <X11/Xutil.h>, <stdint.h> */ typedef struct { diff --git a/text_pango.c b/text_pango.c @@ -2,13 +2,17 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <stdarg.h> + +#include <X11/Xos.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include <X11/Xos.h> + #include <pango/pangoxft.h> + +#include "ltk.h" #include "util.h" #include "text.h" -#include "ltk.h" struct LtkTextLine { char *text; diff --git a/text_stb.c b/text_stb.c @@ -25,14 +25,19 @@ #include <stdlib.h> #include <stdint.h> #include <limits.h> +#include <stdarg.h> + #include <X11/Xlib.h> #include <X11/Xutil.h> -#include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */ -#include "khash.h" + #include <fontconfig/fontconfig.h> + +#include "khash.h" +#include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */ + +#include "ltk.h" #include "util.h" #include "text.h" -#include "ltk.h" typedef struct { stbtt_fontinfo info;