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:
| M | box.c |  |  | 4 | +++- | 
| M | ltk.h |  |  | 1 | + | 
| M | ltkd.c |  |  | 107 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ | 
| M | scrollbar.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 == <k_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;