From e2363b0e2cd683ca8409943c0eed3588fea8283a Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 24 Apr 2022 19:32:10 +0100 Subject: [PATCH] plugins: Add touch API to plugin API and revamp touchscreen test Change-Id: Iefb658693b03e0cda43e2a9fc93086485e790b4e --- apps/plugin.c | 14 ++ apps/plugin.h | 19 ++ apps/plugins/test_touchscreen.c | 367 +++++++++++++++++++++++--------- 3 files changed, 304 insertions(+), 96 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index 519fcd53bd..0f7074f32d 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -852,6 +852,20 @@ static const struct plugin_api rockbox_api = { #ifdef USB_ENABLE_AUDIO usb_audio_get_playing, #endif +#ifdef HAVE_TOUCHSCREEN + action_get_touch_event, + action_gesture_reset, + action_gesture_get_event_in_vp, + action_gesture_get_event, + action_gesture_is_valid, + action_gesture_is_pressed, + gesture_reset, + gesture_process, + gesture_get_event_in_vp, + gesture_vel_reset, + gesture_vel_process, + gesture_vel_get, +#endif }; static int plugin_buffer_handle; diff --git a/apps/plugin.h b/apps/plugin.h index fcf7bf58ea..c4e246ebff 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -74,6 +74,7 @@ int plugin_open(const char *plugin, const char *parameter); #include "thread.h" #include "button.h" #include "action.h" +#include "gesture.h" #include "load_code.h" #include "usb.h" #include "font.h" @@ -997,6 +998,24 @@ struct plugin_api { #ifdef USB_ENABLE_AUDIO bool (*usb_audio_get_playing)(void); #endif +#ifdef HAVE_TOUCHSCREEN + int (*action_get_touch_event)(struct touchevent *ev); + void (*action_gesture_reset)(void); + bool (*action_gesture_get_event_in_vp)(struct gesture_event *gevt, + const struct viewport *vp); + bool (*action_gesture_get_event)(struct gesture_event *gevt); + bool (*action_gesture_is_valid)(void); + bool (*action_gesture_is_pressed)(void); + void (*gesture_reset)(struct gesture *g); + void (*gesture_process)(struct gesture *g, const struct touchevent *ev); + bool (*gesture_get_event_in_vp)(struct gesture *g, + struct gesture_event *gevt, + const struct viewport *vp); + void (*gesture_vel_reset)(struct gesture_vel *gv); + void (*gesture_vel_process)(struct gesture_vel *gv, + const struct touchevent *ev); + bool (*gesture_vel_get)(struct gesture_vel *gv, int *xvel, int *yvel); +#endif }; /* plugin header */ diff --git a/apps/plugins/test_touchscreen.c b/apps/plugins/test_touchscreen.c index 0d8e91f6a9..79eb48f75e 100644 --- a/apps/plugins/test_touchscreen.c +++ b/apps/plugins/test_touchscreen.c @@ -50,109 +50,284 @@ # error "No keymap defined!" #endif +static bool usb_exit = false; + +static const struct button_mapping tstest_context[] = { + {ACTION_STD_OK, TOUCHSCREEN_TOGGLE, BUTTON_NONE}, + {ACTION_STD_CANCEL, TOUCHSCREEN_QUIT, BUTTON_NONE}, + LAST_ITEM_IN_LIST, +}; + +static const struct button_mapping *get_context_map(int context) +{ + (void)context; + return tstest_context; +} + +static void draw_tsbutton_rect(int x, int y) +{ + int x0 = x*LCD_WIDTH/3; + int y0 = y*LCD_HEIGHT/3; + int x1 = (x+1)*LCD_WIDTH/3; + int y1 = (y+1)*LCD_HEIGHT/3; + + rb->lcd_set_foreground(LCD_RGBPACK(0xc0, 0, 0)); + rb->lcd_fillrect(x0, y0, x1 - x0, y1 - y0); +} + +static void draw_crosshair(int x, int y, unsigned fg) +{ + rb->lcd_set_foreground(fg); + rb->lcd_hline(x-7, x+7, y); + rb->lcd_vline(x, y-7, y+7); +} + +static void tstest_button_mode(void) +{ + rb->splashf(HZ, "Button mode test"); + rb->touchscreen_set_mode(TOUCHSCREEN_BUTTON); + + int button = BUTTON_NONE; + while (true) + { + rb->lcd_clear_display(); + + if ((button & BUTTON_TOPLEFT) && !(button & BUTTON_REL)) + draw_tsbutton_rect(0, 0); + if ((button & BUTTON_TOPMIDDLE) && !(button & BUTTON_REL)) + draw_tsbutton_rect(1, 0); + if ((button & BUTTON_TOPRIGHT) && !(button & BUTTON_REL)) + draw_tsbutton_rect(2, 0); + if ((button & BUTTON_MIDLEFT) && !(button & BUTTON_REL)) + draw_tsbutton_rect(0, 1); + if ((button & BUTTON_CENTER) && !(button & BUTTON_REL)) + draw_tsbutton_rect(1, 1); + if ((button & BUTTON_MIDRIGHT) && !(button & BUTTON_REL)) + draw_tsbutton_rect(2, 1); + if ((button & BUTTON_BOTTOMLEFT) && !(button & BUTTON_REL)) + draw_tsbutton_rect(0, 2); + if ((button & BUTTON_BOTTOMMIDDLE) && !(button & BUTTON_REL)) + draw_tsbutton_rect(1, 2); + if ((button & BUTTON_BOTTOMRIGHT) && !(button & BUTTON_REL)) + draw_tsbutton_rect(2, 2); + + rb->lcd_update(); + + if (button & TOUCHSCREEN_QUIT) + break; + if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + { + usb_exit = true; + break; + } + + button = rb->button_get(true); + } +} + +static void tstest_pointing_mode(void) +{ + struct touchevent tevent; + + rb->splashf(HZ, "Pointing mode test"); + rb->touchscreen_set_mode(TOUCHSCREEN_POINT); + + rb->lcd_clear_display(); + rb->lcd_update(); + + while (true) + { + int action = rb->get_custom_action(CONTEXT_PLUGIN, TIMEOUT_BLOCK, + get_context_map); + if (action == ACTION_TOUCHSCREEN) + { + rb->lcd_clear_display(); + rb->action_get_touch_event(&tevent); + draw_crosshair(tevent.x, tevent.y, LCD_RGBPACK(0, 0xc0, 0)); + rb->lcd_update(); + } + else if (action == ACTION_STD_CANCEL) + { + break; + } + else if (rb->default_event_handler(action) == SYS_USB_CONNECTED) + { + usb_exit = true; + break; + } + } +} + +static void tstest_gesture(void) +{ + static const char *const gesture_names[] = { + [GESTURE_NONE] = "none", + [GESTURE_TAP] = "tap", + [GESTURE_LONG_PRESS] = "long press", + [GESTURE_HOLD] = "hold", + [GESTURE_DRAGSTART] = "dragstart", + [GESTURE_DRAG] = "drag", + [GESTURE_RELEASE] = "release", + }; + + struct gesture_event gevt; + int gevent_array[10]; + int gevent_count = 0; + + rb->splashf(HZ, "Gesture test"); + rb->touchscreen_set_mode(TOUCHSCREEN_POINT); + + rb->lcd_clear_display(); + rb->lcd_update(); + + while (true) + { + int action = rb->get_custom_action(CONTEXT_PLUGIN, TIMEOUT_BLOCK, + get_context_map); + if (action == ACTION_TOUCHSCREEN) + { + rb->lcd_clear_display(); + + if (rb->action_gesture_get_event_in_vp(&gevt, NULL)) + { + if (gevt.id == GESTURE_NONE) + { + gevent_array[gevent_count] = GESTURE_NONE; + gevent_count = 1; + } + + if (gevt.id != gevent_array[gevent_count-1]) + { + if (gevent_count < (int)ARRAYLEN(gevent_array)) + { + gevent_array[gevent_count] = gevt.id; + gevent_count++; + } + } + + rb->lcd_set_foreground(LCD_RGBPACK(0xff, 0xff, 0xff)); + for (int i = 0; i < gevent_count; ++i) + rb->lcd_puts(0, i, gesture_names[gevent_array[i]]); + + draw_crosshair(gevt.x, gevt.y, LCD_RGBPACK(0, 0xc0, 0)); + draw_crosshair(gevt.ox, gevt.oy, LCD_RGBPACK(0xc0, 0, 0)); + } + + rb->lcd_update(); + } + else if (action == ACTION_STD_OK) + { + rb->splashf(HZ, "Gesture reset"); + rb->action_gesture_reset(); + rb->lcd_clear_display(); + rb->lcd_update(); + } + else if (action == ACTION_STD_CANCEL) + { + break; + } + else if (rb->default_event_handler(action) == SYS_USB_CONNECTED) + { + usb_exit = true; + break; + } + } +} + +static void tstest_velocity(void) +{ + struct touchevent tevent; + struct gesture_vel gv; + + rb->splashf(HZ, "Velocity test"); + rb->touchscreen_set_mode(TOUCHSCREEN_POINT); + + rb->lcd_clear_display(); + rb->lcd_update(); + + rb->gesture_vel_reset(&gv); + + while (true) + { + int action = rb->get_custom_action(CONTEXT_PLUGIN, TIMEOUT_BLOCK, + get_context_map); + if (action == ACTION_TOUCHSCREEN) + { + rb->lcd_clear_display(); + rb->action_get_touch_event(&tevent); + rb->gesture_vel_process(&gv, &tevent); + + int xvel, yvel; + rb->gesture_vel_get(&gv, &xvel, &yvel); + + rb->lcd_set_foreground(LCD_RGBPACK(0xff, 0xff, 0xff)); + rb->lcd_putsf(0, 0, "xvel=%4d yvel=%4d", xvel, yvel); + + draw_crosshair(tevent.x, tevent.y, LCD_RGBPACK(0, 0xc0, 0)); + rb->lcd_update(); + + if (tevent.type == TOUCHEVENT_RELEASE) + rb->gesture_vel_reset(&gv); + } + else if (action == ACTION_STD_OK) + { + rb->splashf(HZ, "Velocity reset"); + rb->gesture_vel_reset(&gv); + rb->lcd_clear_display(); + rb->lcd_update(); + } + else if (action == ACTION_STD_CANCEL) + { + break; + } + else if (rb->default_event_handler(action) == SYS_USB_CONNECTED) + { + usb_exit = true; + break; + } + } +} + /* plugin entry point */ enum plugin_status plugin_start(const void* parameter) { - int button = 0; - enum touchscreen_mode mode = TOUCHSCREEN_BUTTON; - - /* standard stuff */ (void)parameter; - - rb->touchscreen_set_mode(mode); - /* wait until user closes plugin */ - do + int sel; + MENUITEM_STRINGLIST(menu, "Touchscreen test", + NULL, + "Button mode test", + "Pointing mode test", + "Gesture test", + "Velocity test", + "Quit"); + + while (true) { - short x = 0; - short y = 0; - bool draw_rect = false; - - button = rb->button_get(true); + rb->touchscreen_set_mode(rb->global_settings->touch_mode); + switch (rb->do_menu(&menu, &sel, NULL, false)) + { + case 0: + tstest_button_mode(); + break; - if (button & BUTTON_TOPLEFT) - { - draw_rect = true; - x = 0; y = 0; - } - else if (button & BUTTON_TOPMIDDLE) - { - draw_rect = true; - x = LCD_WIDTH/3; y = 0; - } - else if (button & BUTTON_TOPRIGHT) - { - draw_rect = true; - x = 2*(LCD_WIDTH/3); y = 0; - } - else if (button & BUTTON_MIDLEFT) - { - draw_rect = true; - x = 0; y = LCD_HEIGHT/3; - } - else if (button & BUTTON_CENTER) - { - draw_rect = true; - x = LCD_WIDTH/3; y = LCD_HEIGHT/3; - } - else if (button & BUTTON_MIDRIGHT) - { - draw_rect = true; - x = 2*(LCD_WIDTH/3); y = LCD_HEIGHT/3; - } - else if (button & BUTTON_BOTTOMLEFT) - { - draw_rect = true; - x = 0; y = 2*(LCD_HEIGHT/3); - } - else if (button & BUTTON_BOTTOMMIDDLE) - { - draw_rect = true; - x = LCD_WIDTH/3; y = 2*(LCD_HEIGHT/3); - } - else if (button & BUTTON_BOTTOMRIGHT) - { - draw_rect = true; - x = 2*(LCD_WIDTH/3); y = 2*(LCD_HEIGHT/3); + case 1: + tstest_pointing_mode(); + break; + + case 2: + tstest_gesture(); + break; + + case 3: + tstest_velocity(); + break; + + default: + return PLUGIN_OK; } - if (button & TOUCHSCREEN_TOGGLE && (button & BUTTON_REL)) - { - mode = (mode == TOUCHSCREEN_POINT) ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT; - rb->touchscreen_set_mode(mode); - } - - if (button & BUTTON_REL) draw_rect = false; - - rb->lcd_clear_display(); - - if (draw_rect) - { - rb->lcd_set_foreground(LCD_RGBPACK(0xc0, 0, 0)); - rb->lcd_fillrect(x, y, LCD_WIDTH/3, LCD_HEIGHT/3); - } - - if (draw_rect || button & BUTTON_TOUCHSCREEN) - { - intptr_t button_data = rb->button_get_data(); - x = button_data >> 16; - y = button_data & 0xffff; - - rb->lcd_set_foreground(LCD_RGBPACK(0, 0, 0xc0)); - rb->lcd_fillrect(x-7, y-7, 14, 14); - - /* in stylus mode, show REL position in black */ - if (mode == TOUCHSCREEN_POINT && (button & BUTTON_REL)) - rb->lcd_set_foreground(LCD_BLACK); - else - rb->lcd_set_foreground(LCD_WHITE); - - rb->lcd_hline(x-5, x+5, y); - rb->lcd_vline(x, y-5, y+5); - } - rb->lcd_update(); - - } while (button != TOUCHSCREEN_QUIT); - - return PLUGIN_OK; + if (usb_exit) + return PLUGIN_USB_CONNECTED; + } }