ltkx

GUI toolkit for X11 (WIP)
git clone git://lumidify.org/ltkx.git
Log | Files | Refs | README | LICENSE

commit eaee011ce47b2f57527a241a53dded691735770f
parent 1207520e0aa5ec1696924646f850b1c4a8bc57ed
Author: lumidify <nobody@lumidify.org>
Date:   Fri, 29 May 2020 20:22:21 +0200

Add preparations for adding dropdowns

Diffstat:
Mbutton.c | 23++++++++++++-----------
Mgrid.c | 6+++---
Mltk.c | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mltk.h | 38++++++++++++++++++--------------------
Mtext_buffer.c | 28++++++++++++++--------------
Mtext_common.c | 2--
Mtext_edit.c | 21++++++++++++---------
7 files changed, 229 insertions(+), 109 deletions(-)

diff --git a/button.c b/button.c @@ -36,8 +36,6 @@ #include "text_buffer.h" #include "button.h" -extern Ltk *ltk_global; - void ltk_button_ini_handler(LtkTheme *theme, const char *prop, const char *value) { if (theme->button == NULL) { @@ -78,7 +76,8 @@ ltk_button_ini_handler(LtkTheme *theme, const char *prop, const char *value) { void ltk_button_draw(LtkButton *button) { - LtkButtonTheme *theme = ltk_global->theme->button; + LtkTheme *global_theme = ltk_get_theme(); + LtkButtonTheme *theme = global_theme->button; LtkWindow *window = button->widget.window; LtkRect rect = button->widget.rect; int bw = theme->border_width; @@ -116,15 +115,17 @@ ltk_button_draw(LtkButton *button) { default: ltk_fatal("No style found for button!\n"); } - XSetForeground(ltk_global->display, window->gc, fill.pixel); - XFillRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); + Display *display = ltk_get_display(); + Colormap colormap = ltk_get_colormap(); + XSetForeground(display, window->gc, fill.pixel); + XFillRectangle(display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); /* FIXME: Why did I do this? */ if (bw < 1) return; - XSetForeground(ltk_global->display, window->gc, border.pixel); - XSetLineAttributes(ltk_global->display, window->gc, bw, LineSolid, CapButt, JoinMiter); - XDrawRectangle(ltk_global->display, window->xwindow, window->gc, rect.x + bw / 2, rect.y + bw / 2, rect.w - bw, rect.h - bw); + XSetForeground(display, window->gc, border.pixel); + XSetLineAttributes(display, window->gc, bw, LineSolid, CapButt, JoinMiter); + XDrawRectangle(display, window->xwindow, window->gc, rect.x + bw / 2, rect.y + bw / 2, rect.w - bw, rect.h - bw); if (!img) { - img = ltk_text_line_render(button->tl, ltk_global->display, window->xwindow, window->gc, ltk_global->colormap, theme->text_color, fill); + img = ltk_text_line_render(button->tl, display, window->xwindow, window->gc, colormap, theme->text_color, fill); /* FIXME: any nicer way to do this? */ switch (button->widget.state) { case LTK_NORMAL: @@ -147,7 +148,7 @@ ltk_button_draw(LtkButton *button) { } text_x = rect.x + (rect.w - button->tl->w) / 2; text_y = rect.y + (rect.h - button->tl->h) / 2; - XPutImage(ltk_global->display, window->xwindow, window->gc, img, 0, 0, text_x, text_y, button->tl->w, button->tl->h); + XPutImage(display, window->xwindow, window->gc, img, 0, 0, text_x, text_y, button->tl->w, button->tl->h); } LtkButton * @@ -163,7 +164,7 @@ ltk_button_create(LtkWindow *window, const char *text, void (*callback) (void *, button->callback = callback; button->data = data; - LtkTheme *theme = ltk_global->theme; + LtkTheme *theme = ltk_get_theme(); button->tl = ltk_text_line_create(theme->button->font_size); /* FIXME: support font size */ ltk_text_line_insert_utf8(button->tl, 0, text); diff --git a/grid.c b/grid.c @@ -247,7 +247,7 @@ void ltk_grid_mouse_press(LtkGrid *grid, XEvent event) return; LtkWidget *ptr = grid->widget_grid[row * grid->columns + column]; if (ptr && ltk_collide_rect(ptr->rect, x, y)) { - ltk_mouse_press_event(ptr, event); + ltk_widget_mouse_press_event(ptr, event); } } @@ -262,7 +262,7 @@ void ltk_grid_mouse_release(LtkGrid *grid, XEvent event) LtkWidget *ptr = grid->widget_grid[row * grid->columns + column]; if (ptr) { if (ltk_collide_rect(ptr->rect, x, y)) { - ltk_mouse_release_event(ptr, event); + ltk_widget_mouse_release_event(ptr, event); } else { ltk_remove_hover_widget(grid); ltk_change_active_widget_state(grid, LTK_ACTIVE); @@ -284,7 +284,7 @@ void ltk_grid_motion_notify(LtkGrid *grid, XEvent event) LtkWidget *ptr = grid->widget_grid[row * grid->columns + column]; if (ptr) { if (ltk_collide_rect(ptr->rect, x, y)) - ltk_motion_notify_event(ptr, event); + ltk_widget_motion_notify_event(ptr, event); else if (!pressed) ltk_remove_hover_widget(grid); } diff --git a/ltk.c b/ltk.c @@ -27,22 +27,54 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include "khash.h" -#include "ltk.h" #include "stb_truetype.h" #include <fribidi.h> #include <harfbuzz/hb.h> #include <fontconfig/fontconfig.h> #include "array.h" #include "text_common.h" +#include "ltk.h" #include "text_buffer.h" -Ltk *ltk_global; +/* Window hash */ +KHASH_MAP_INIT_INT(winhash, LtkWindow*) + +static struct { + LtkTheme *theme; + LtkTextManager *tm; + Display *display; + int screen; + Colormap colormap; + khash_t(winhash) *window_hash; + int window_num; + Atom wm_delete_msg; +} ltk_global; struct ltk_redraw_queue { LtkWindow *window; LtkRect rect; }; +LtkTextManager * +ltk_get_text_manager(void) { + return ltk_global.tm; +} + +LtkTheme * +ltk_get_theme(void) { + return ltk_global.theme; +} + +Display * +ltk_get_display(void) { + return ltk_global.display; +} + +Colormap +ltk_get_colormap(void) { + return ltk_global.colormap; +} + static struct ltk_redraw_queue *redraw_queue = NULL; static int num_redraws = 0; static int redraw_queue_bufsize = 0; @@ -93,31 +125,65 @@ error: } void +ltk_widget_set_floating_collision(LtkWidget *widget) { + LtkWindow *window = widget->window; + for (int i = 0; i < window->num_float_widgets; i++) { + if (window->float_widgets[i] == widget) + return; + } + if (window->num_float_widgets + 1 > window->max_float_widgets) { + LtkWidget **new = realloc( + window->float_widgets, + sizeof(LtkWidget *) * (window->max_float_widgets + 1)); + if (!new) goto error; + window->float_widgets = new; + window->max_float_widgets++; + } + window->float_widgets[window->num_float_widgets] = widget; + window->num_float_widgets++; + return; +error: + (void)fprintf(stderr, "Out of memory\n"); + exit(1); +} + +void +ltk_widget_unset_floating_collision(LtkWidget *widget) { + LtkWindow *window = widget->window; + for (int i = 0; i < window->num_float_widgets; i++) { + if (window->float_widgets[i] == widget) { + for (int j = i + 1; j < window->num_float_widgets; j++) { + window->float_widgets[j - 1] = window->float_widgets[j]; + } + window->num_float_widgets--; + break; + } + } +} + +void ltk_init(const char *theme_path) { - ltk_global = malloc(sizeof(Ltk)); - Ltk *ltk = ltk_global; /* For convenience */ - ltk->display = XOpenDisplay(NULL); - ltk->screen = DefaultScreen(ltk->display); - ltk->colormap = DefaultColormap(ltk->display, ltk->screen); - ltk->theme = ltk_load_theme(theme_path); - ltk->window_hash = kh_init(winhash); - ltk->wm_delete_msg = XInternAtom(ltk->display, "WM_DELETE_WINDOW", False); - ltk->tm = ltk_init_text(ltk->theme->window->font); + ltk_global.display = XOpenDisplay(NULL); + ltk_global.screen = DefaultScreen(ltk_global.display); + ltk_global.colormap = DefaultColormap(ltk_global.display, ltk_global.screen); + ltk_global.theme = ltk_load_theme(theme_path); + ltk_global.window_hash = kh_init(winhash); + ltk_global.wm_delete_msg = XInternAtom(ltk_global.display, "WM_DELETE_WINDOW", False); + ltk_global.tm = ltk_init_text(ltk_global.theme->window->font); } void ltk_clean_up(void) { LtkWindow *window; - for (int k = kh_begin(ltk_global->window_hash); k != kh_end(ltk_global->window_hash); k++) { - if (kh_exist(ltk_global->window_hash, k)) { - ltk_destroy_window(kh_value(ltk_global->window_hash, k)); + for (int k = kh_begin(ltk_global.window_hash); k != kh_end(ltk_global.window_hash); k++) { + if (kh_exist(ltk_global.window_hash, k)) { + ltk_destroy_window(kh_value(ltk_global.window_hash, k)); } } - kh_destroy(winhash, ltk_global->window_hash); - XCloseDisplay(ltk_global->display); - ltk_destroy_theme(ltk_global->theme); - ltk_destroy_text_manager(ltk_global->tm); - free(ltk_global); + kh_destroy(winhash, ltk_global.window_hash); + XCloseDisplay(ltk_global.display); + ltk_destroy_theme(ltk_global.theme); + ltk_destroy_text_manager(ltk_global.tm); if (redraw_queue) free(redraw_queue); } @@ -137,9 +203,9 @@ ltk_fatal(const char *msg) { XColor ltk_create_xcolor(const char *hex) { XColor color; - XParseColor(ltk_global->display, ltk_global->colormap, hex, + XParseColor(ltk_global.display, ltk_global.colormap, hex, &color); - XAllocColor(ltk_global->display, ltk_global->colormap, &color); + XAllocColor(ltk_global.display, ltk_global.colormap, &color); return color; } @@ -152,8 +218,8 @@ ltk_mainloop(void) { /* FIXME: compress motion events */ while (1) { - if (XPending(ltk_global->display) || !num_redraws) { - XNextEvent(ltk_global->display, &event); + if (XPending(ltk_global.display) || !num_redraws) { + XNextEvent(ltk_global.display, &event); ltk_handle_event(event); } else if (num_redraws) { for (int i = 0; i < num_redraws; i++) @@ -173,7 +239,7 @@ ltk_redraw_window(LtkWindow *window, LtkRect rect) { rect.w -= rect.x + rect.w - window->rect.w; if (rect.y + rect.h > window->rect.h) rect.h -= rect.y + rect.h - window->rect.h; - XClearArea(ltk_global->display, window->xwindow, rect.x, rect.y, rect.w, rect.h, False); + XClearArea(ltk_global.display, window->xwindow, rect.x, rect.y, rect.w, rect.h, False); if (!window->root_widget) return; ptr = window->root_widget; ptr->draw(ptr); @@ -184,8 +250,8 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int LtkWindow *window = malloc(sizeof(LtkWindow)); if (!window) ltk_fatal("Not enough memory left for window!\n"); - LtkWindowTheme *wtheme = ltk_global->theme->window; /* For convenience */ - Display *display = ltk_global->display; /* For convenience */ + LtkWindowTheme *wtheme = ltk_global.theme->window; /* For convenience */ + Display *display = ltk_global.display; /* For convenience */ window->xwindow = XCreateSimpleWindow(display, DefaultRootWindow(display), x, y, w, h, wtheme->border_width, @@ -196,7 +262,7 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int XSetStandardProperties(display, window->xwindow, title, NULL, None, NULL, 0, NULL); XSetWMProtocols(display, window->xwindow, - &ltk_global->wm_delete_msg, 1); + &ltk_global.wm_delete_msg, 1); window->root_widget = NULL; window->other_event = &ltk_window_other_event; @@ -206,6 +272,10 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int window->rect.x = 0; window->rect.y = 0; + window->num_float_widgets = 0; + window->max_float_widgets = 0; + window->float_widgets = NULL; + XClearWindow(display, window->xwindow); XMapRaised(display, window->xwindow); XSelectInput(display, window->xwindow, @@ -214,9 +284,9 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int StructureNotifyMask | PointerMotionMask); int ret; - int k = kh_put(winhash, ltk_global->window_hash, window->xwindow, &ret); - kh_value(ltk_global->window_hash, k) = window; - ltk_global->window_num++; + int k = kh_put(winhash, ltk_global.window_hash, window->xwindow, &ret); + kh_value(ltk_global.window_hash, k) = window; + ltk_global.window_num++; return window; } @@ -225,20 +295,20 @@ void ltk_remove_window(LtkWindow *window) { /* FIXME: also remove from event queue */ ltk_destroy_window(window); - if (ltk_global->window_num == 0) + if (ltk_global.window_num == 0) ltk_quit(); } void ltk_destroy_window(LtkWindow * window) { - int k = kh_get(winhash, ltk_global->window_hash, window->xwindow); - kh_del(winhash, ltk_global->window_hash, k); + int k = kh_get(winhash, ltk_global.window_hash, window->xwindow); + kh_del(winhash, ltk_global.window_hash, k); LtkWidget *ptr = window->root_widget; if (ptr) ptr->destroy(ptr); - XDestroyWindow(ltk_global->display, window->xwindow); + XDestroyWindow(ltk_global.display, window->xwindow); free(window); - ltk_global->window_num--; + ltk_global.window_num--; } void @@ -267,7 +337,7 @@ ltk_window_other_event(LtkWindow *window, XEvent event) { r.h = event.xexpose.height; ltk_window_invalidate_rect(window, r); } else if (event.type == ClientMessage - && event.xclient.data.l[0] == ltk_global->wm_delete_msg) { + && event.xclient.data.l[0] == ltk_global.wm_delete_msg) { ltk_remove_window(window); } } @@ -405,6 +475,10 @@ ltk_fill_widget_defaults(LtkWidget *widget, LtkWindow *window, widget->rect.y = 0; widget->rect.w = 100; widget->rect.h = 100; + widget->collision_rect.x = 0; + widget->collision_rect.y = 0; + widget->collision_rect.w = 0; + widget->collision_rect.h = 0; widget->row = NULL; widget->column = NULL; @@ -414,7 +488,7 @@ ltk_fill_widget_defaults(LtkWidget *widget, LtkWindow *window, } void -ltk_mouse_press_event(void *widget, XEvent event) { +ltk_widget_mouse_press_event(void *widget, XEvent event) { LtkWidget *ptr = widget; if (!ptr || ptr->state == LTK_DISABLED) return; @@ -434,7 +508,24 @@ ltk_mouse_press_event(void *widget, XEvent event) { } void -ltk_mouse_release_event(void *widget, XEvent event) { +ltk_window_mouse_press_event(LtkWindow *window, XEvent event) { + if (window->float_widgets) { + int x = event.xbutton.x; + int y = event.xbutton.y; + for (int i = 0; i < window->num_float_widgets; i++) { + if (ltk_collide_rect(window->float_widgets[i]->collision_rect, x, y)) { + ltk_widget_mouse_press_event(window->float_widgets[i], event); + return; + } + } + } + if (window->root_widget) { + ltk_widget_mouse_press_event(window->root_widget, event); + } +} + +void +ltk_widget_mouse_release_event(void *widget, XEvent event) { LtkWidget *ptr = widget; if (!ptr || ptr->state == LTK_DISABLED) return; @@ -449,11 +540,27 @@ ltk_mouse_release_event(void *widget, XEvent event) { } void -ltk_motion_notify_event(void *widget, XEvent event) { +ltk_window_mouse_release_event(LtkWindow *window, XEvent event) { + if (window->float_widgets) { + int x = event.xbutton.x; + int y = event.xbutton.y; + for (int i = 0; i < window->num_float_widgets; i++) { + if (ltk_collide_rect(window->float_widgets[i]->collision_rect, x, y)) { + ltk_widget_mouse_release_event(window->float_widgets[i], event); + return; + } + } + } + if (window->root_widget) { + ltk_widget_mouse_release_event(window->root_widget, event); + } +} + +void +ltk_widget_motion_notify_event(void *widget, XEvent event) { LtkWidget *ptr = widget; LtkWidget *parent; - if (!ptr) - return; + if (!ptr) return; short pressed = (event.xmotion.state & Button1Mask) == Button1Mask; if ((ptr->state == LTK_NORMAL || ptr->state == LTK_ACTIVE) && !pressed) { @@ -472,28 +579,41 @@ ltk_motion_notify_event(void *widget, XEvent event) { } void +ltk_window_motion_notify_event(LtkWindow *window, XEvent event) { + if (window->float_widgets) { + int x = event.xbutton.x; + int y = event.xbutton.y; + for (int i = 0; i < window->num_float_widgets; i++) { + if (ltk_collide_rect(window->float_widgets[i]->collision_rect, x, y)) { + ltk_widget_motion_notify_event(window->float_widgets[i], event); + return; + } + } + } + if (window->root_widget) { + ltk_widget_motion_notify_event(window->root_widget, event); + } +} + +void ltk_handle_event(XEvent event) { LtkWidget *root_widget; - int k = kh_get(winhash, ltk_global->window_hash, event.xany.window); - LtkWindow *window = kh_value(ltk_global->window_hash, k); + int k = kh_get(winhash, ltk_global.window_hash, event.xany.window); + LtkWindow *window = kh_value(ltk_global.window_hash, k); if (!window) return; - root_widget = window->root_widget; switch (event.type) { case KeyPress: break; case KeyRelease: break; case ButtonPress: - if (root_widget) - ltk_mouse_press_event(root_widget, event); + ltk_window_mouse_press_event(window, event); break; case ButtonRelease: - if (root_widget) - ltk_mouse_release_event(root_widget, event); + ltk_window_mouse_release_event(window, event); break; case MotionNotify: - if (root_widget) - ltk_motion_notify_event(root_widget, event); + ltk_window_motion_notify_event(window, event); break; default: /* FIXME: users should be able to register other events like closing the window */ diff --git a/ltk.h b/ltk.h @@ -24,7 +24,7 @@ #ifndef _LTK_H_ #define _LTK_H_ -/* Requires the following includes: <X11/Xlib.h>, <X11/Xutil.h>, "khash.h" */ +/* Requires the following includes: <X11/Xlib.h>, <X11/Xutil.h> */ typedef struct { int x; @@ -64,12 +64,15 @@ typedef struct LtkWidget { 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 (*resize) (void *, int, int); void (*draw) (void *); void (*destroy) (void *); - LtkRect rect; + LtkRect collision_rect; /* rect for collision with mouse */ + LtkRect rect; /* rect in grid - this is only different when the widget is floating */ unsigned int row; unsigned int column; unsigned int row_span; @@ -82,9 +85,12 @@ typedef struct LtkWidget { typedef struct LtkWindow { Window xwindow; GC gc; - void *root_widget; + LtkWidget *root_widget; int (*other_event) (LtkWindow *, XEvent event); LtkRect rect; + LtkWidget **float_widgets; + int num_float_widgets; + int max_float_widgets; } LtkWindow; typedef struct LtkWindowTheme { @@ -101,23 +107,15 @@ typedef struct { LtkButtonTheme *button; } LtkTheme; -LtkTheme *ltk_load_theme(const char *path); - typedef struct LtkTextManager LtkTextManager; +LtkTextManager *ltk_get_text_manager(void); +LtkTheme *ltk_get_theme(void); +Display *ltk_get_display(void); +Colormap ltk_get_colormap(void); -/* Window hash */ -KHASH_MAP_INIT_INT(winhash, LtkWindow*) +LtkTheme *ltk_load_theme(const char *path); -typedef struct { - LtkTheme *theme; - LtkTextManager *tm; - Display *display; - int screen; - Colormap colormap; - khash_t(winhash) *window_hash; - int window_num; - Atom wm_delete_msg; -} Ltk; +typedef struct LtkTextManager LtkTextManager; void ltk_window_invalidate_rect(LtkWindow *window, LtkRect rect); @@ -155,11 +153,11 @@ void ltk_remove_hover_widget(void *widget); void ltk_fill_widget_defaults(LtkWidget *widget, LtkWindow * window, void (*draw) (void *), void (*destroy) (void *), unsigned int needs_redraw); -void ltk_mouse_press_event(void *widget, XEvent event); +void ltk_widget_mouse_press_event(void *widget, XEvent event); -void ltk_mouse_release_event(void *widget, XEvent event); +void ltk_widget_mouse_release_event(void *widget, XEvent event); -void ltk_motion_notify_event(void *widget, XEvent event); +void ltk_widget_motion_notify_event(void *widget, XEvent event); void ltk_handle_event(XEvent event); diff --git a/text_buffer.c b/text_buffer.c @@ -38,8 +38,6 @@ #include "text_buffer.h" #include "ltk.h" -extern Ltk *ltk_global; - LTK_ARRAY_INIT_IMPL(uint32, uint32_t) LTK_ARRAY_INIT_IMPL(script, hb_script_t) LTK_ARRAY_INIT_IMPL(level, FriBidiLevel) @@ -623,8 +621,9 @@ ltk_text_line_itemize(struct ltk_text_line *tl) { } static void -ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr, +ltk_text_run_shape(struct ltk_text_run *tr, struct ltk_text_line *tl, uint16_t font_size, uint16_t font_id, int *ret_y_max) { + LtkTextManager *tm = ltk_get_text_manager(); khash_t(glyphinfo) *glyph_cache; khint_t k; @@ -707,7 +706,8 @@ ltk_text_run_shape(LtkTextManager *tm, struct ltk_text_run *tr, } static void -ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) { +ltk_text_line_shape(struct ltk_text_line *tl) { + LtkTextManager *tm = ltk_get_text_manager(); struct ltk_text_run *run = tl->first_run; tl->w = tl->h = 0; int y_max; @@ -735,7 +735,7 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) { run->font = kh_value(tm->font_cache, k); FcPatternDestroy(match); FcPatternDestroy(pat); - ltk_text_run_shape(tm, run, tl, tl->font_size, font_id, &y_max); + ltk_text_run_shape(run, tl, tl->font_size, font_id, &y_max); if (y_max_overall < y_max) y_max_overall = y_max; /* tr->start_y is -y_min */ @@ -771,8 +771,9 @@ ltk_text_run_destroy(struct ltk_text_run *tr) { LtkFont *font; LtkGlyph *glyph; khint_t k; - k = kh_get(glyphinfo, ltk_global->tm->glyph_cache, tr->font_id << 16 + tr->font_size); - gcache = kh_value(ltk_global->tm->glyph_cache, k); + LtkTextManager *tm = ltk_get_text_manager(); + k = kh_get(glyphinfo, tm->glyph_cache, tr->font_id << 16 + tr->font_size); + gcache = kh_value(tm->glyph_cache, k); for (int i = 0; i < tr->num_glyphs; i++) { glyph = &tr->glyphs[i]; if (--glyph->info->refs < 1) { @@ -781,10 +782,10 @@ ltk_text_run_destroy(struct ltk_text_run *tr) { ltk_destroy_glyph_info(glyph->info); } } - k = kh_get(fontstruct, ltk_global->tm->font_cache, tr->font_id); - font = kh_value(ltk_global->tm->font_cache, k); + k = kh_get(fontstruct, tm->font_cache, tr->font_id); + font = kh_value(tm->font_cache, k); if (--font->refs < 1) { - kh_del(fontstruct, ltk_global->tm->font_cache, k); + kh_del(fontstruct, tm->font_cache, k); ltk_destroy_font(font); } free(tr->glyphs); @@ -803,7 +804,7 @@ ltk_text_line_destroy_runs(struct ltk_text_run *runs) { } static void -ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) { +ltk_text_line_recalculate(struct ltk_text_line *tl) { FriBidiCharType par_dir = FRIBIDI_TYPE_ON; fribidi_log2vis( tl->log_buf->buf, tl->log_buf->len, @@ -816,7 +817,7 @@ ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) { struct ltk_text_run *old_runs = tl->first_run; ltk_text_line_itemize(tl); struct ltk_text_run *cur = tl->first_run; - ltk_text_line_shape(tm, tl); + ltk_text_line_shape(tl); /* this needs to be done after shaping so the fonts, etc. aren't removed if their reference counts drop and then loaded again right afterwards */ @@ -837,8 +838,7 @@ ltk_text_line_insert_utf32(struct ltk_text_line *tl, size_t index, uint32_t *tex ltk_array_resize_int(tl->vis2log, tl->len + len); ltk_array_resize_level(tl->bidi_levels, tl->len + len); tl->len += len; - /* FIXME: Why am I passing tm? It's global anyways */ - ltk_text_line_recalculate(ltk_global->tm, tl); + ltk_text_line_recalculate(tl); } /* must be NULL-terminated */ diff --git a/text_common.c b/text_common.c @@ -36,8 +36,6 @@ #include "text_common.h" #include "ltk.h" -extern Ltk *ltk_global; - /* These unicode routines are taken from * https://github.com/JeffBezanson/cutef8 */ diff --git a/text_edit.c b/text_edit.c @@ -26,21 +26,21 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include "khash.h" -#include "ltk.h" #include "stb_truetype.h" #include <fribidi.h> #include <harfbuzz/hb.h> #include <fontconfig/fontconfig.h> #include "text_common.h" +#include "ltk.h" #include "array.h" #include "text_buffer.h" #include "text_edit.h" #include "grid.h" -extern Ltk *ltk_global; - void ltk_text_edit_draw(LtkTextEdit *te) { + Display *display = ltk_get_display(); + LtkTheme *theme = ltk_get_theme(); if (!te->img) ltk_text_edit_resize(te, 0, 0); LtkRect rect = te->widget.rect; @@ -48,10 +48,10 @@ ltk_text_edit_draw(LtkTextEdit *te) { int x = rect.x; if (te->tl->dir == HB_DIRECTION_RTL) x += rect.w - te->img->width; - XSetForeground(ltk_global->display, window->gc, ltk_global->theme->window->bg.pixel); - XFillRectangle(ltk_global->display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); + XSetForeground(display, window->gc, theme->window->bg.pixel); + XFillRectangle(display, window->xwindow, window->gc, rect.x, rect.y, rect.w, rect.h); XPutImage( - ltk_global->display, + display, window->xwindow, window->gc, te->img, @@ -67,12 +67,15 @@ ltk_text_edit_resize(LtkTextEdit *te, int orig_w, int orig_h) { if (te->tl->soft_lines->len == 1 && te->widget.rect.w >= te->img->width && orig_w >= te->img->width) return; - XColor fg = ltk_global->theme->window->fg; - XColor bg = ltk_global->theme->window->bg; + LtkTheme *theme = ltk_get_theme(); + Display *display = ltk_get_display(); + Colormap colormap = ltk_get_colormap(); + XColor fg = theme->window->fg; + XColor bg = theme->window->bg; LtkWindow *window = te->widget.window; ltk_text_line_wrap(te->tl, te->widget.rect.w); if (te->img) XDestroyImage(te->img); - te->img = ltk_text_line_render(te->tl, ltk_global->display, window->xwindow, window->gc, ltk_global->colormap, fg, bg); + te->img = ltk_text_line_render(te->tl, display, window->xwindow, window->gc, colormap, fg, bg); } #if 0