URI: 
       tContinue adding very broken scrollbar support - ltk - Socket-based GUI for X11 (WIP)
  HTML git clone git://lumidify.org/ltk.git (fast, but not encrypted)
  HTML git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 2ed1efbf50d122e1120e32416b71c9838d9c3880
   DIR parent b0338320849b8d570511491a73dee2d75aff5fd9
  HTML Author: lumidify <nobody@lumidify.org>
       Date:   Tue, 19 Jan 2021 22:24:35 +0100
       
       Continue adding very broken scrollbar support
       
       Diffstat:
         M box.c                               |       4 +++-
         M ltk.h                               |       1 +
         M ltkd.c                              |     107 +++++++++++++++++++------------
         M scrollbar.c                         |      13 ++++++++-----
       
       4 files changed, 79 insertions(+), 46 deletions(-)
       ---
   DIR diff --git a/box.c b/box.c
       t@@ -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);
   DIR diff --git a/ltk.h b/ltk.h
       t@@ -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;
   DIR diff --git a/ltkd.c b/ltkd.c
       t@@ -187,7 +187,8 @@ ltk_mainloop(ltk_window *window) {
                maxfd = listenfd;
        
                printf("%d", window->xwindow);
       -        daemonize();
       +        fflush(stdout);
       +        /*daemonize();*/
        
                while (running) {
                        rfds = rallfds;
       t@@ -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);
        
       t@@ -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;
       t@@ -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;
       t@@ -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;
                }
        }
        
       t@@ -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);
        }
        
   DIR diff --git a/scrollbar.c b/scrollbar.c
       t@@ -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;
       t@@ -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;