jscene: fix geometric dispatch of touch events + count padding

This commit is contained in:
Lephenixnoir 2025-04-15 05:02:35 +02:00
parent 0d0919ecd7
commit 5d3a6639ee
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
4 changed files with 88 additions and 22 deletions

View file

@ -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

View file

@ -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

View file

@ -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);
}
//---

View file

@ -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)