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 2ed1efbf50d122e1120e32416b71c9838d9c3880
parent b0338320849b8d570511491a73dee2d75aff5fd9
Author: lumidify <nobody@lumidify.org>
Date:   Tue, 19 Jan 2021 22:24:35 +0100

Continue adding very broken scrollbar support

Diffstat:
Mbox.c | 4+++-
Mltk.h | 1+
Mltkd.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mscrollbar.c | 13++++++++-----
4 files changed, 79 insertions(+), 46 deletions(-)

diff --git a/box.c b/box.c @@ -296,7 +296,9 @@ ltk_box_mouse_event(ltk_box *box, XEvent event, void (*handler)(ltk_widget *, XE ltk_widget *widget; int old_sc_pos = box->sc->cur_pos; - if (ltk_collide_rect(box->sc->widget.rect, event.xbutton.x, event.xbutton.y)) { + /* FIXME: THIS IS A HACK! */ + if ((handler == &ltk_widget_motion_notify_event && box->sc->widget.state == LTK_PRESSED) || + (ltk_collide_rect(box->sc->widget.rect, event.xbutton.x, event.xbutton.y))) { handler(box->sc, event); if (old_sc_pos != box->sc->cur_pos) { ltk_recalculate_box(box); diff --git a/ltk.h b/ltk.h @@ -141,6 +141,7 @@ typedef struct ltk_window { Window xwindow; ltk_widget *root_widget; ltk_widget *active_widget; + ltk_widget *pressed_widget; void (*other_event) (ltk_window *, XEvent event); ltk_rect rect; ltk_window_theme theme; diff --git a/ltkd.c b/ltkd.c @@ -187,7 +187,8 @@ ltk_mainloop(ltk_window *window) { maxfd = listenfd; printf("%d", window->xwindow); - daemonize(); + fflush(stdout); + /*daemonize();*/ while (running) { rfds = rallfds; @@ -607,6 +608,8 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int NULL, 0, NULL); XSetWMProtocols(window->dpy, window->xwindow, &window->wm_delete_msg, 1); window->root_widget = NULL; + window->active_widget = NULL; + window->pressed_widget = NULL; ltk_init_text(window->theme.font, window->dpy, window->screen, window->cm); @@ -722,6 +725,14 @@ ltk_collide_rect(ltk_rect rect, int x, int y) { && (rect.y + rect.h) >= y); } +static void +ltk_widget_change_state(ltk_widget *widget) { + if (widget->change_state) + widget->change_state(widget); + if (widget->needs_redraw) + ltk_window_invalidate_rect(widget->window, widget->rect); +} + void ltk_window_remove_active_widget(ltk_window *window) { ltk_widget *widget = window->active_widget; @@ -729,10 +740,7 @@ ltk_window_remove_active_widget(ltk_window *window) { while (widget) { widget->state = LTK_NORMAL; widget->active_widget = NULL; - if (widget->change_state) - widget->change_state(widget); - if (widget->needs_redraw) - ltk_window_invalidate_rect(window, widget->rect); + ltk_widget_change_state(widget); widget = widget->parent; } window->active_widget = NULL; @@ -742,12 +750,14 @@ void ltk_window_set_active_widget(ltk_widget *widget) { widget->window->active_widget = widget; ltk_widget *parent = widget->parent; - widget->state = LTK_ACTIVE; - while (parent) { + while (widget) { widget->state = LTK_ACTIVE; - parent->active_widget = widget; + ltk_widget_change_state(widget); + if (parent) + parent->active_widget = widget; widget = parent; - parent = widget->parent; + if (parent) + parent = widget->parent; } } @@ -801,60 +811,77 @@ ltk_fill_widget_defaults(ltk_widget *widget, const char *id, ltk_window *window, } void -ltk_widget_mouse_press_event(ltk_widget *widget, XEvent event) { - if (!widget || widget->state == LTK_DISABLED) - return; - if (event.xbutton.button == 1) { - /* ltk_widget *parent = widget->parent; FIXME: set pressed widget hierarchy */ +ltk_widget_set_pressed(ltk_window *window, ltk_widget *widget) { + ltk_widget *act = window->active_widget; + ltk_widget *pre = window->pressed_widget; + if (pre) { + if (act) { + act->state = LTK_NORMAL; + if (act->needs_redraw) + ltk_window_invalidate_rect(window, act->rect); + if (act->change_state) + act->change_state(act); + } + pre->state = LTK_ACTIVE; + window->active_widget = pre; + if (pre->needs_redraw) + ltk_window_invalidate_rect(window, pre->rect); + if (pre->change_state) + pre->change_state(pre); + } + window->pressed_widget = widget; + if (widget) { widget->state = LTK_PRESSED; - if (widget->change_state) - widget->change_state(widget); if (widget->needs_redraw) ltk_window_invalidate_rect(widget->window, widget->rect); + if (widget->change_state) + widget->change_state(widget); } - if (widget->mouse_press) { +} + +void +ltk_widget_mouse_press_event(ltk_widget *widget, XEvent event) { + if (!widget || widget->state == LTK_DISABLED) + return; + if (event.xbutton.button == 1) + ltk_widget_set_pressed(widget->window, widget); + if (widget->mouse_press) widget->mouse_press(widget, event); - } } void ltk_widget_mouse_release_event(ltk_widget *widget, XEvent event) { - if (!widget || widget->state == LTK_DISABLED) + if (!widget) return; - /* FIXME: Why does it check for LTK_PRESSED? Is this left over from - old ltkx, where there was a difference between hover and active? */ - if (widget->state == LTK_PRESSED) { - widget->state = LTK_ACTIVE; - if (widget->change_state) - widget->change_state(widget); - if (widget->needs_redraw) - ltk_window_invalidate_rect(widget->window, widget->rect); - } - if (widget->mouse_release) { + /* FIXME: MAKE THIS WORK MORE CONSISTENTLY FOR OTHER MOUSE BUTTONS */ + ltk_widget_set_pressed(widget->window, NULL); + if (widget->state == LTK_DISABLED) + return; + if (widget->mouse_release) widget->mouse_release(widget, event); - } } +/* FIXME: ONLY SET ACTIVE WIDGET AT BOTTOM OF HIERARCHY + -> Don't first set parent as active widget and then child */ void ltk_widget_motion_notify_event(ltk_widget *widget, XEvent event) { if (!widget) return; - /* FIXME: THIS WHOLE STATE HANDLING IS BROKEN */ - int pressed = (event.xmotion.state & Button1Mask) == Button1Mask; - if ((widget->state == LTK_NORMAL) && !pressed) { + /* FIXME: THIS WHOLE STATE HANDLING IS STILL PARTIALLY BROKEN */ + if (((widget->state == LTK_NORMAL) || + (widget->state == LTK_ACTIVE && widget->window->active_widget != widget)) && + !widget->window->pressed_widget) { widget->state = LTK_ACTIVE; if (widget->change_state) widget->change_state(widget); if (widget->mouse_enter) widget->mouse_enter(widget, 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); - } - if (widget->needs_redraw) - ltk_window_invalidate_rect(widget->window, widget->rect); + ltk_window_remove_active_widget(widget->window); + ltk_window_set_active_widget(widget); } - if (widget->motion_notify) + if (widget->window->pressed_widget && widget->window->pressed_widget->motion_notify) + widget->window->pressed_widget->motion_notify(widget->window->pressed_widget, event); + else if (widget->motion_notify) widget->motion_notify(widget, event); } diff --git a/scrollbar.c b/scrollbar.c @@ -160,18 +160,20 @@ ltk_scrollbar_draw(ltk_scrollbar *scrollbar, ltk_rect clip) { static void ltk_scrollbar_mouse_press(ltk_scrollbar *scrollbar, XEvent event) { - scrollbar->last_mouse_x = event.xbutton.x; - scrollbar->last_mouse_y = event.xbutton.y; + if (event.xbutton.button != 1) + return; + scrollbar->last_mouse_x = scrollbar->widget.rect.x; + scrollbar->last_mouse_y = scrollbar->widget.rect.y; + scrollbar->cur_pos = 0; + ltk_scrollbar_motion_notify(scrollbar, event); } static void ltk_scrollbar_motion_notify(ltk_scrollbar *sc, XEvent event) { double scale; int delta, max_pos; - /* FIXME: Make this work properly with LTK_PRESSED */ - if ((event.xmotion.state & Button1Mask) != Button1Mask) + if (sc->widget.state != LTK_PRESSED) return; - ltk_warn("adasd\n"); if (sc->orient == LTK_HORIZONTAL) { delta = event.xbutton.x - sc->last_mouse_x; max_pos = sc->virtual_size > sc->widget.rect.w ? sc->virtual_size - sc->widget.rect.w : 0; @@ -181,6 +183,7 @@ ltk_scrollbar_motion_notify(ltk_scrollbar *sc, XEvent event) { max_pos = sc->virtual_size > sc->widget.rect.h ? sc->virtual_size - sc->widget.rect.h : 0; scale = sc->virtual_size / (double)sc->widget.rect.h; } + /* FIXME: This doesn't work because delta is always only one pixel or so */ sc->cur_pos += (int)(scale * delta); if (sc->cur_pos < 0) sc->cur_pos = 0;