From 5d3a6639eebc114a3b1e9f9a3ab812634d36cecd Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Tue, 15 Apr 2025 05:02:35 +0200 Subject: [PATCH] jscene: fix geometric dispatch of touch events + count padding --- include/justui/jscene.h | 8 +++---- include/justui/jwidget.h | 15 +++++++++++++ src/jscene.c | 39 ++++++++++++++++++-------------- src/jwidget.c | 48 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 88 insertions(+), 22 deletions(-) diff --git a/include/justui/jscene.h b/include/justui/jscene.h index 1024f17..5d8ddbb 100644 --- a/include/justui/jscene.h +++ b/include/justui/jscene.h @@ -79,10 +79,10 @@ void jscene_render(jscene *scene); next, and increasing within child index order within each group. * For widgets with a stacked layout, only the active child is considered. - If content_only is set, this function only intersects with the content box. - Otherwise, an intersection with the full box (padding, border and margin - included) is performed. */ -jwidget *jscene_widget_at(jscene *scene, int x, int y, bool content_only); + If exclude_mp is set, this function only intersects with the content and + padding box, excluding margins and borders. Otherwise, an intersection with + the full box (padding, border and margin included) is performed. */ +jwidget *jscene_widget_at(jscene *scene, int x, int y, bool exclude_mp); //--- // Events sent from the scene to the user diff --git a/include/justui/jwidget.h b/include/justui/jwidget.h index ffbf66a..48b4bb9 100644 --- a/include/justui/jwidget.h +++ b/include/justui/jwidget.h @@ -341,6 +341,8 @@ void jwidget_layout(void *scene_root); /* jwidget_absolute_x(): Absolute x-position of a widget jwidget_absolute_y(): Absolute y-position of a widget + jwidget_absolute_padding_x(): Absolute x-position of a widget's padding box + jwidget_absolute_padding_y(): Absolute y-position of a widget's padding box jwidget_absolute_content_x(): Absolute x-position of a widget's content box jwidget_absolute_content_y(): Absolute y-position of a widget's content box @@ -348,6 +350,8 @@ void jwidget_layout(void *scene_root); with a full-screen scene. */ int jwidget_absolute_x(void *w); int jwidget_absolute_y(void *w); +int jwidget_absolute_padding_x(void *w); +int jwidget_absolute_padding_y(void *w); int jwidget_absolute_content_x(void *w); int jwidget_absolute_content_y(void *w); @@ -361,6 +365,17 @@ int jwidget_absolute_content_y(void *w); int jwidget_content_width(void *w); int jwidget_content_height(void *w); +/* jwidget_width(): With of a widget's padding box + jwidget_height(): Height of a widget's padding box + + These functions return the size of the padding box of a widget, which + includes the content and padding. These are the dimensions that appear as + the widget's size when there is a background. These dimensions are known + only after layout; calling these functions when the layout is not up-to-date + will return funny results. */ +int jwidget_padding_width(void *w); +int jwidget_padding_height(void *w); + /* jwidget_full_width(): Width of a widget's margin box jwidget_full_height(): Height of a widget's margin box diff --git a/src/jscene.c b/src/jscene.c index 4881395..eed997c 100644 --- a/src/jscene.c +++ b/src/jscene.c @@ -97,10 +97,10 @@ void jscene_render(jscene *s) jwidget *w = jscene_widget_at(s, s->touch_last_x, s->touch_last_y, true); if(w) { - int x1 = jwidget_absolute_content_x(w); - int y1 = jwidget_absolute_content_y(w); - int x2 = x1 + jwidget_content_width(w) - 1; - int y2 = y1 + jwidget_content_height(w) - 1; + int x1 = jwidget_absolute_padding_x(w); + int y1 = jwidget_absolute_padding_y(w); + int x2 = x1 + jwidget_padding_width(w) - 1; + int y2 = y1 + jwidget_padding_height(w) - 1; drect_border(x1, y1, x2, y2, C_NONE, 1, C_RED); dprint_opt(DWIDTH-1, 0, C_WHITE, C_RED, DTEXT_RIGHT, DTEXT_TOP, @@ -112,24 +112,31 @@ void jscene_render(jscene *s) /* Find sub-widget based on w-local coordinates. */ static jwidget *jscene_widget_at_rec( - jwidget *w, int x, int y, bool content_only, bool visible_only) + jwidget *w, int x, int y, bool exclude_mp, bool visible_only) { if(!w) return NULL; jwidget *found; jwidget_geometry const *g = jwidget_geometry_r(w); + /* Content box (this is what children's xy are measured against) */ int xC = g->margin.left + g->border.left + g->padding.left; - int yC = w->y + g->margin.top + g->border.top + g->padding.top; + int yC = g->margin.top + g->border.top + g->padding.top; uint wC = jwidget_content_width(w); uint hC = jwidget_content_height(w); + /* Padding box */ + int xP = xC - g->padding.left; + int yP = yC - g->padding.top; + uint wP = wC + g->padding.left + g->padding.right; + uint hP = hC + g->padding.top + g->padding.bottom; + /* Full box (implicitly starts at 0,0) */ uint wF = jwidget_full_width(w); uint hF = jwidget_full_height(w); /* Check if we intersect w at all */ bool intersects; - if(content_only) - intersects = ((uint)(x - xC) < wC) && ((uint)(y - yC) < hC); + if(exclude_mp) + intersects = ((uint)(x - xP) < wP) && ((uint)(y - yP) < hP); else intersects = (uint)x < wF && (uint)y < hF; if(!intersects) @@ -141,8 +148,8 @@ static jwidget *jscene_widget_at_rec( if(stack->active < 0) return w; jwidget *child = w->children[stack->active]; - found = jscene_widget_at_rec(child, x - xC, y - yC, content_only, - visible_only); + found = jscene_widget_at_rec(child, x - xC - child->x, + y - yC - child->y, exclude_mp, visible_only); return found ? found : w; } @@ -150,8 +157,8 @@ static jwidget *jscene_widget_at_rec( for(int k = 0; k < w->child_count; k++) { jwidget *child = w->children[k]; if(child->visible >= visible_only && child->floating) { - found = jscene_widget_at_rec(child, x - xC, y - yC, content_only, - visible_only); + found = jscene_widget_at_rec(child, x - xC - child->x, + y - yC - child->y, exclude_mp, visible_only); if(found) return found; } @@ -161,8 +168,8 @@ static jwidget *jscene_widget_at_rec( for(int k = 0; k < w->child_count; k++) { jwidget *child = w->children[k]; if(child->visible >= visible_only && !child->floating) { - found = jscene_widget_at_rec(child, x - xC, y - yC, content_only, - visible_only); + found = jscene_widget_at_rec(child, x - xC - child->x, + y - yC - child->y, exclude_mp, visible_only); if(found) return found; } @@ -172,9 +179,9 @@ static jwidget *jscene_widget_at_rec( return w; } -jwidget *jscene_widget_at(jscene *scene, int x, int y, bool content_only) +jwidget *jscene_widget_at(jscene *scene, int x, int y, bool exclude_mp) { - return jscene_widget_at_rec(&scene->widget, x, y, content_only, true); + return jscene_widget_at_rec(&scene->widget, x, y, exclude_mp, true); } //--- diff --git a/src/jwidget.c b/src/jwidget.c index e2e0f9d..168258b 100644 --- a/src/jwidget.c +++ b/src/jwidget.c @@ -570,13 +570,39 @@ void jwidget_layout(void *root0) int jwidget_absolute_x(void *w0) { J_CAST(w) - return w ? w->x + jwidget_absolute_x(w->parent) : 0; + if(!w) + return 0; + jwidget_geometry const *g = jwidget_geometry_r(w); + return jwidget_absolute_content_x(w) - + g->padding.left - g->border.left - g->margin.left; } int jwidget_absolute_y(void *w0) { J_CAST(w) - return w ? w->y + jwidget_absolute_y(w->parent) : 0; + if(!w) + return 0; + jwidget_geometry const *g = jwidget_geometry_r(w); + return jwidget_absolute_content_y(w) - + g->padding.top - g->border.top - g->margin.top; +} + +int jwidget_absolute_padding_x(void *w0) +{ + J_CAST(w) + if(!w) + return 0; + jwidget_geometry const *g = jwidget_geometry_r(w); + return jwidget_absolute_content_x(w) - g->padding.left; +} + +int jwidget_absolute_padding_y(void *w0) +{ + J_CAST(w) + if(!w) + return 0; + jwidget_geometry const *g = jwidget_geometry_r(w); + return jwidget_absolute_content_y(w) - g->padding.top; } int jwidget_absolute_content_x(void *w0) @@ -617,6 +643,24 @@ int jwidget_content_height(void *w0) - g->margin.bottom - g->border.bottom - g->padding.bottom; } +int jwidget_padding_width(void *w0) +{ + J_CAST(w) + jwidget_geometry const *g = jwidget_geometry_r(w); + + return w->w - g->margin.left - g->border.left + - g->margin.right - g->border.right; +} + +int jwidget_padding_height(void *w0) +{ + J_CAST(w) + jwidget_geometry const *g = jwidget_geometry_r(w); + + return w->h - g->margin.top - g->border.top + - g->margin.bottom - g->border.bottom; +} + int jwidget_full_width(void *w0) { J_CAST(w)