jscene, jlist: start handling touch events

This commit is contained in:
Lephenixnoir 2025-04-13 17:34:02 +02:00
parent cd73b2ea6f
commit 50df5fe37c
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
6 changed files with 72 additions and 1 deletions

View file

@ -16,6 +16,6 @@
#endif
/* Set to 1 to enable a touch-following widget inspector. */
#define J_CONFIG_TOUCH_INSPECTOR (J_CONFIG_TOUCH && 1)
#define J_CONFIG_TOUCH_INSPECTOR (J_CONFIG_TOUCH && 0)
#endif /* _JUSTUI_CONFIG */

View file

@ -77,6 +77,8 @@ typedef struct jlist {
/* Currently selected item, -1 if none */
int cursor;
/* Index of the currently touch-clicked item, -1 none */
int touch_cursor;
/* User data pointer */
void *user;

View file

@ -434,6 +434,9 @@ void jwidget_render(void *w, int x, int y);
while the widget has focus, the focus will be lost. */
void jwidget_set_focus_policy(void *w, jwidget_focus_policy_t fp);
/* Check whether a widget accepts focus. */
bool jwidget_accepts_focus(void *w);
/* Check whether a widget is currently focused within its surrounding scope. */
GINLINE static bool jwidget_has_focus(void *w)
{

View file

@ -1,6 +1,7 @@
#include <justui/jwidget.h>
#include <justui/jwidget-api.h>
#include <justui/jlist.h>
#include <justui/config.h>
#include "util.h"
#include <gint/display.h>
@ -38,6 +39,7 @@ jlist *jlist_create(jlist_item_info_function info_function,
l->info_function = info_function;
l->paint_function = paint_function;
l->cursor = -1;
l->touch_cursor = -1;
l->user = NULL;
return l;
}
@ -165,6 +167,25 @@ jrect jlist_selected_region(jlist *l)
// Polymorphic widget operations
//---
static int item_index_at(void *l0, int ly)
{
jlist *l = l0;
int y = 0;
for(int i = 0; i < l->item_count; i++) {
jlist_item_info *info = &l->items[i];
int h = info->delegate
? jwidget_full_height(info->delegate)
: info->natural_height;
if(ly >= y && ly < y + h)
return i;
y += h;
}
return -1;
}
static void jlist_poly_csize(void *l0)
{
jlist *l = l0;
@ -224,10 +245,38 @@ static bool jlist_poly_event(void *l0, jevent e)
{
jlist *l = l0;
if(e.type == JWIDGET_FOCUS_CHANGED && !jwidget_has_active_focus(l))
l->touch_cursor = -1;
if(e.type != JWIDGET_KEY || l->cursor < 0)
return false;
key_event_t ev = e.key;
#if J_CONFIG_TOUCH
if(ev.type == KEYEV_TOUCH_DOWN || ev.type == KEYEV_TOUCH_DRAG ||
ev.type == KEYEV_TOUCH_UP) {
int lx = ev.x - jwidget_absolute_content_x(l);
int ly = ev.y - jwidget_absolute_content_y(l);
uint w = jwidget_content_width(l);
uint h = jwidget_content_height(l);
int index = ((uint)lx < w && (uint)ly < h) ? item_index_at(l, ly) : -1;
if(ev.type == KEYEV_TOUCH_DOWN && index >= 0) {
jlist_select(l, index);
l->touch_cursor = jlist_selected_item(l);
}
if(ev.type == KEYEV_TOUCH_DRAG && index >= 0)
jlist_select(l, index);
if(ev.type == KEYEV_TOUCH_UP && index >= 0 && index == l->touch_cursor) {
jevent e = { .type = JLIST_ITEM_TRIGGERED,
.data = l->touch_cursor };
jwidget_emit(l, e);
}
return true;
}
#endif
if(ev.type != KEYEV_DOWN && ev.type != KEYEV_HOLD)
return false;

View file

@ -283,6 +283,16 @@ void jscene_show_and_focus(jscene *scene, void *w0)
bool jscene_process_key_event(jscene *scene, key_event_t event)
{
/* If the event is a touch down, start by moving the focus. */
#if J_CONFIG_TOUCH
if(event.type == KEYEV_TOUCH_DOWN) {
jwidget *w = jscene_widget_at(scene, event.x - scene->x,
event.y - scene->y, true);
if(w && jwidget_accepts_focus(w))
jscene_set_focused_widget(scene, w);
}
#endif
jwidget *candidate = jscene_focused_widget(scene);
jevent e = { .type = JWIDGET_KEY, .key = event };

View file

@ -753,6 +753,13 @@ void jwidget_set_focus_policy(void *w0, jwidget_focus_policy_t fp)
w->focus_policy = fp;
}
bool jwidget_accepts_focus(void *w0)
{
J_CAST(w)
return w->focus_policy == J_FOCUS_POLICY_SCOPE ||
w->focus_policy == J_FOCUS_POLICY_ACCEPT;
}
static void notify_focus_changed(jwidget *w)
{
jevent e;