commit 8e162e7755e980a1f9bb03541201482b15fd89eb
parent dd010d6ac6864d58107799eb3625cdd4660684a1
Author: lumidify <nobody@lumidify.org>
Date:   Sun, 24 Jan 2021 17:24:30 +0100
Make button clipping work somewhat
Diffstat:
8 files changed, 57 insertions(+), 23 deletions(-)
diff --git a/button.c b/button.c
@@ -132,6 +132,15 @@ ltk_button_draw(ltk_button *button, ltk_rect clip) {
 	/* no idea why it would be less than 0, but whatever */
 	if (clip_final.w <= 0 || clip_final.h <= 0)
 		return;
+	XCopyArea(window->dpy, button->pixmap, window->xwindow, window->gc,
+	    clip_final.x - rect.x, clip_final.y - rect.y,
+	    clip_final.w, clip_final.h, clip_final.x, clip_final.y);
+}
+
+static void
+ltk_button_redraw_pixmap(ltk_button *button) {
+	ltk_window *window = button->widget.window;
+	ltk_rect rect = button->widget.rect;
 	int bw = theme.border_width;
 	LtkColor *border;
 	LtkColor *fill;
@@ -156,25 +165,42 @@ ltk_button_draw(ltk_button *button, ltk_rect clip) {
 		ltk_fatal("No style found for button!\n");
 	}
 	XSetForeground(window->dpy, window->gc, fill->xcolor.pixel);
-	XFillRectangle(window->dpy, window->xwindow, window->gc, clip_final.x,
-	    clip_final.y, clip_final.w, clip_final.h);
+	XFillRectangle(window->dpy, button->pixmap, window->gc, 0, 0, rect.w, rect.h);
 	/* FIXME: Why did I do this? */
 	if (bw < 1) return;
-	/* FIXME: Maybe draw to tmp pixmap first, so this can be done properly? */
-	/*
 	XSetForeground(window->dpy, window->gc, border->xcolor.pixel);
 	XSetLineAttributes(window->dpy, window->gc, bw, LineSolid,
 	    CapButt, JoinMiter);
-	XDrawRectangle(window->dpy, window->xwindow, window->gc,
-	    rect.x + bw / 2, rect.y + bw / 2, rect.w - bw, rect.h - bw);
-	*/
+	XDrawRectangle(window->dpy, button->pixmap, window->gc,
+	    bw / 2, bw / 2, rect.w - bw, rect.h - bw);
 
 	int text_w, text_h;
 	ltk_text_line_get_size(button->tl, &text_w, &text_h);
-	int text_x = rect.x + (rect.w - text_w) / 2;
-	int text_y = rect.y + (rect.h - text_h) / 2;
-	/* FIXME: Actually use button->text_pixmap */
-	ltk_text_line_draw(button->tl, window->gc, text_x, text_y, clip_final);
+	int text_x = (rect.w - text_w) / 2;
+	int text_y = (rect.h - text_h) / 2;
+	/* FIXME: Remove clipping rect from text line - this is just used here as a dummy
+	   because it is completely ignored */
+	ltk_text_line_draw(button->tl, button->pixmap, window->gc, text_x, text_y, rect);
+}
+
+/* FIXME: Make this amortised constant; make it generic for all widgets */
+static void
+ltk_button_resize(ltk_button *button) {
+	Window win;
+	int x, y, w, h, bw, d;
+	int new_w, new_h;
+	ltk_window *window = button->widget.window;
+	ltk_rect rect = button->widget.rect;
+	XGetGeometry(window->dpy, button->pixmap, &win, &x, &y, &w, &h, &bw, &d);
+
+	new_w = w < rect.w ? rect.w : w;
+	new_h = h < rect.h ? rect.h : h;
+	if (new_w < w && new_h < h)
+		return;
+	XFreePixmap(window->dpy, button->pixmap);
+	button->pixmap = XCreatePixmap(window->dpy, window->xwindow,
+	    new_w, new_h, window->depth);
+	ltk_button_redraw_pixmap(button);
 }
 
 static void
@@ -198,6 +224,7 @@ ltk_button_change_state(ltk_button *button) {
 		ltk_fatal("No style found for button!\n");
 	}
 	ltk_text_line_render(button->tl, fill, &theme.text_color);
+	ltk_button_redraw_pixmap(button);
 }
 
 static int
@@ -215,6 +242,7 @@ ltk_button_create(ltk_window *window, const char *id, const char *text) {
 	ltk_fill_widget_defaults(&button->widget, id, window,
 	    <k_button_draw, <k_button_change_state, <k_button_destroy, 1, LTK_BUTTON);
 	button->widget.mouse_release = <k_button_mouse_release;
+	button->widget.resize = <k_button_resize;
 	uint16_t font_size = window->theme.font_size;
 	text_copy = strdup(text);
 	if (!text_copy)
@@ -224,6 +252,8 @@ ltk_button_create(ltk_window *window, const char *id, const char *text) {
 	ltk_text_line_get_size(button->tl, &text_w, &text_h);
 	button->widget.ideal_w = text_w + theme.border_width * 2 + theme.pad * 2;
 	button->widget.ideal_h = text_h + theme.border_width * 2 + theme.pad * 2;
+	button->pixmap = XCreatePixmap(window->dpy, window->xwindow,
+	    button->widget.ideal_w, button->widget.ideal_h, window->depth);
 	/* render text */
 	ltk_button_change_state(button);
 
diff --git a/button.h b/button.h
@@ -29,7 +29,7 @@
 typedef struct {
 	ltk_widget widget;
 	LtkTextLine *tl;
-	Pixmap text_pixmap;
+	Pixmap pixmap;
 } ltk_button;
 
 void ltk_button_setup_theme_defaults(ltk_window *window);
diff --git a/draw.c b/draw.c
@@ -37,7 +37,7 @@
 static void ltk_draw_draw(ltk_draw *draw);
 static ltk_draw *ltk_draw_create(ltk_window *window,
     const char *id, int w, int h, const char *color);
-static void ltk_draw_resize(ltk_draw *draw, int orig_w, int orig_h);
+static void ltk_draw_resize(ltk_draw *draw);
 static void ltk_draw_destroy(ltk_draw *draw, int shallow);
 static void ltk_draw_clear(ltk_window *window, ltk_draw *draw);
 static void ltk_draw_set_color(ltk_window *window, ltk_draw *draw, const char *color);
@@ -79,7 +79,6 @@ ltk_draw_draw(ltk_draw *draw) {
 
 static ltk_draw *
 ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *color) {
-	XWindowAttributes attrs;
 	ltk_draw *draw = malloc(sizeof(ltk_draw));
 	if (!draw) ltk_fatal_errno("Unable to allocate memory for ltk_draw.\n");
 
@@ -88,9 +87,7 @@ ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *co
 	draw->widget.resize = <k_draw_resize;
 	draw->widget.rect.w = w;
 	draw->widget.rect.h = h;
-	XGetWindowAttributes(window->dpy, window->xwindow, &attrs);
-	draw->depth = attrs.depth;
-	draw->pix = XCreatePixmap(window->dpy, window->xwindow, w, h, draw->depth);
+	draw->pix = XCreatePixmap(window->dpy, window->xwindow, w, h, window->depth);
 	if (!ltk_create_xcolor(window, color, &draw->bg)) {
 		free(draw);
 		ltk_fatal_errno("Unable to allocate XColor.\n");
@@ -103,7 +100,7 @@ ltk_draw_create(ltk_window *window, const char *id, int w, int h, const char *co
 }
 
 static void
-ltk_draw_resize(ltk_draw *draw, int orig_w, int orig_h) {
+ltk_draw_resize(ltk_draw *draw) {
 	Window win;
 	int x, y, w, h, bw, d;
 	int new_w, new_h;
@@ -116,7 +113,7 @@ ltk_draw_resize(ltk_draw *draw, int orig_w, int orig_h) {
 	if (new_w < w && new_h < h)
 		return;
 	Pixmap tmp = XCreatePixmap(window->dpy, window->xwindow,
-	    new_w, new_h, draw->depth);
+	    new_w, new_h, window->depth);
 	XSetForeground(window->dpy, window->gc, draw->bg.pixel);
 	XFillRectangle(window->dpy, tmp, window->gc, 0, 0, new_w, new_h);
 	XCopyArea(window->dpy, draw->pix, tmp, window->gc,
diff --git a/ltk.h b/ltk.h
@@ -139,6 +139,7 @@ typedef struct ltk_window {
 	int screen;
 	Atom wm_delete_msg;
 	Window xwindow;
+	int depth;
 	ltk_widget *root_widget;
 	ltk_widget *active_widget;
 	ltk_widget *pressed_widget;
diff --git a/ltkd.c b/ltkd.c
@@ -581,6 +581,7 @@ ltk_window_other_event(ltk_window *window, XEvent event) {
 static ltk_window *
 ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h) {
 	char *theme_path;
+	XWindowAttributes attrs;
 
 	ltk_window *window = malloc(sizeof(ltk_window));
 	if (!window)
@@ -601,6 +602,8 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int 
 	    XCreateSimpleWindow(window->dpy, DefaultRootWindow(window->dpy), x, y,
 				w, h, window->theme.border_width,
 				window->theme.fg.xcolor.pixel, window->theme.bg.xcolor.pixel);
+	XGetWindowAttributes(window->dpy, window->xwindow, &attrs);
+	window->depth = attrs.depth;
 	window->gc = XCreateGC(window->dpy, window->xwindow, 0, 0);
 	XSetForeground(window->dpy, window->gc, window->theme.fg.xcolor.pixel);
 	XSetBackground(window->dpy, window->gc, window->theme.bg.xcolor.pixel);
diff --git a/text.h b/text.h
@@ -10,7 +10,7 @@ void ltk_init_text(const char *default_font, Display *dpy, int screen, Colormap 
 void ltk_cleanup_text(void);
 LtkTextLine *ltk_text_line_create(Window window, uint16_t font_size, char *text, int width);
 void ltk_text_line_render(LtkTextLine *tl, LtkColor *bg, LtkColor *fg);
-void ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y, ltk_rect clip);
+void ltk_text_line_draw(LtkTextLine *tl, Drawable d, GC gc, int x, int y, ltk_rect clip);
 void ltk_text_line_set_width(LtkTextLine *tl, int width);
 void ltk_text_line_get_size(LtkTextLine *tl, int *w, int *h);
 void ltk_text_line_destroy(LtkTextLine *tl);
diff --git a/text_pango.c b/text_pango.c
@@ -98,8 +98,8 @@ ltk_text_line_render(LtkTextLine *tl, LtkColor *bg, LtkColor *fg) {
 }
 
 void
-ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y, ltk_rect clip) {
-	XCopyArea(tm.dpy, tl->pixmap, tl->window, gc, 0, 0, tl->w, tl->h, x, y);
+ltk_text_line_draw(LtkTextLine *tl, Drawable d, GC gc, int x, int y, ltk_rect clip) {
+	XCopyArea(tm.dpy, tl->pixmap, d, gc, 0, 0, tl->w, tl->h, x, y);
 }
 
 void
diff --git a/text_stb.c b/text_stb.c
@@ -534,7 +534,8 @@ ltk_text_line_render(
 
 /* FIXME: error checking if img is rendered yet, tm initialized, etc. */
 void
-ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y, ltk_rect clip) {
+ltk_text_line_draw(LtkTextLine *tl, Drawable d, GC gc, int x, int y, ltk_rect clip) {
+	/*
 	int xoff = clip.x - x;
 	int yoff = clip.y - y;
 	xoff = xoff >= 0 ? xoff : 0;
@@ -542,6 +543,8 @@ ltk_text_line_draw(LtkTextLine *tl, GC gc, int x, int y, ltk_rect clip) {
 	int w = clip.w > tl->w - xoff ? tl->w - xoff : clip.w;
 	int h = clip.h > tl->h - yoff ? tl->h - yoff : clip.h;
 	XPutImage(tm.dpy, tl->window, gc, tl->img, xoff, yoff, x + xoff, y + yoff, w, h);
+	*/
+	XPutImage(tm.dpy, d, gc, tl->img, 0, 0, x, y, tl->w, tl->h);
 }
 
 void