mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-20 07:25:06 +00:00
Simplify keyboard support (#22)
* simplify keyboard support * removed cleanup code as it wasn't necessary * improved docs
This commit is contained in:
parent
7a7b31e426
commit
618f557a16
@ -4,7 +4,6 @@
|
|||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
#include "services/gui/gui.h"
|
#include "services/gui/gui.h"
|
||||||
#include "services/wifi/wifi_credentials.h"
|
#include "services/wifi/wifi_credentials.h"
|
||||||
#include "ui/lvgl_keypad.h"
|
|
||||||
#include "ui/spacer.h"
|
#include "ui/spacer.h"
|
||||||
#include "ui/style.h"
|
#include "ui/style.h"
|
||||||
#include "wifi_connect.h"
|
#include "wifi_connect.h"
|
||||||
@ -13,15 +12,6 @@
|
|||||||
|
|
||||||
#define TAG "wifi_connect"
|
#define TAG "wifi_connect"
|
||||||
|
|
||||||
static void show_keyboard(lv_event_t* event) {
|
|
||||||
gui_keyboard_show(event->current_target);
|
|
||||||
lv_obj_scroll_to_view(event->current_target, LV_ANIM_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hide_keyboard(TT_UNUSED lv_event_t* event) {
|
|
||||||
gui_keyboard_hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_connect(lv_event_t* event) {
|
static void on_connect(lv_event_t* event) {
|
||||||
WifiConnect* wifi = (WifiConnect*)event->user_data;
|
WifiConnect* wifi = (WifiConnect*)event->user_data;
|
||||||
WifiConnectView* view = &wifi->view;
|
WifiConnectView* view = &wifi->view;
|
||||||
@ -104,14 +94,8 @@ void wifi_connect_view_create(App app, void* wifi, lv_obj_t* parent) {
|
|||||||
|
|
||||||
wifi_connect_view_create_bottom_buttons(wifi, parent);
|
wifi_connect_view_create_bottom_buttons(wifi, parent);
|
||||||
|
|
||||||
if (gui_keyboard_is_enabled()) {
|
gui_keyboard_add_textarea(view->ssid_textarea);
|
||||||
lv_obj_add_event_cb(view->ssid_textarea, show_keyboard, LV_EVENT_FOCUSED, NULL);
|
gui_keyboard_add_textarea(view->password_textarea);
|
||||||
lv_obj_add_event_cb(view->ssid_textarea, hide_keyboard, LV_EVENT_DEFOCUSED, NULL);
|
|
||||||
lv_obj_add_event_cb(view->ssid_textarea, hide_keyboard, LV_EVENT_READY, NULL);
|
|
||||||
lv_obj_add_event_cb(view->password_textarea, show_keyboard, LV_EVENT_FOCUSED, NULL);
|
|
||||||
lv_obj_add_event_cb(view->password_textarea, hide_keyboard, LV_EVENT_DEFOCUSED, NULL);
|
|
||||||
lv_obj_add_event_cb(view->password_textarea, hide_keyboard, LV_EVENT_READY, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init from app parameters
|
// Init from app parameters
|
||||||
Bundle* _Nullable bundle = tt_app_get_parameters(app);
|
Bundle* _Nullable bundle = tt_app_get_parameters(app);
|
||||||
@ -126,18 +110,10 @@ void wifi_connect_view_create(App app, void* wifi, lv_obj_t* parent) {
|
|||||||
lv_textarea_set_text(view->password_textarea, password);
|
lv_textarea_set_text(view->password_textarea, password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardware keyboard("keypad") requires a group
|
|
||||||
view->group = lv_group_create();
|
|
||||||
lv_group_add_obj(view->group, view->ssid_textarea);
|
|
||||||
lv_group_add_obj(view->group, view->password_textarea);
|
|
||||||
tt_lvgl_keypad_activate(view->group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifi_connect_view_destroy(TT_UNUSED WifiConnectView* view) {
|
void wifi_connect_view_destroy(TT_UNUSED WifiConnectView* view) {
|
||||||
// Cleanup keypad group
|
// NO-OP
|
||||||
tt_lvgl_keypad_deactivate();
|
|
||||||
lv_group_del(view->group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wifi_connect_view_update(
|
void wifi_connect_view_update(
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#include "check.h"
|
|
||||||
#include "hardware_i.h"
|
#include "hardware_i.h"
|
||||||
|
|
||||||
|
#include "check.h"
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
#define TAG "hardware"
|
#define TAG "hardware"
|
||||||
|
|
||||||
void tt_hardware_init(const HardwareConfig* config) {
|
void tt_hardware_init(const HardwareConfig* config) {
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
void gui_redraw(Gui*);
|
void gui_redraw(Gui*);
|
||||||
static int32_t gui_main(void*);
|
static int32_t gui_main(void*);
|
||||||
|
|
||||||
static Gui* gui = NULL;
|
Gui* gui = NULL;
|
||||||
|
|
||||||
Gui* gui_alloc() {
|
Gui* gui_alloc() {
|
||||||
Gui* instance = malloc(sizeof(Gui));
|
Gui* instance = malloc(sizeof(Gui));
|
||||||
@ -32,6 +32,7 @@ Gui* gui_alloc() {
|
|||||||
instance->keyboard = NULL;
|
instance->keyboard = NULL;
|
||||||
|
|
||||||
tt_check(tt_lvgl_lock(1000 / portTICK_PERIOD_MS));
|
tt_check(tt_lvgl_lock(1000 / portTICK_PERIOD_MS));
|
||||||
|
instance->keyboard_group = lv_group_create();
|
||||||
instance->lvgl_parent = lv_scr_act();
|
instance->lvgl_parent = lv_scr_act();
|
||||||
tt_lvgl_unlock();
|
tt_lvgl_unlock();
|
||||||
|
|
||||||
@ -42,6 +43,11 @@ void gui_free(Gui* instance) {
|
|||||||
tt_assert(instance != NULL);
|
tt_assert(instance != NULL);
|
||||||
tt_thread_free(instance->thread);
|
tt_thread_free(instance->thread);
|
||||||
tt_mutex_free(instance->mutex);
|
tt_mutex_free(instance->mutex);
|
||||||
|
|
||||||
|
tt_check(tt_lvgl_lock(1000 / portTICK_PERIOD_MS));
|
||||||
|
lv_group_del(instance->keyboard_group);
|
||||||
|
tt_lvgl_unlock();
|
||||||
|
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,39 +77,6 @@ void gui_show_app(App app, ViewPortShowCallback on_show, ViewPortHideCallback on
|
|||||||
gui_request_draw();
|
gui_request_draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gui_keyboard_show(lv_obj_t* textarea) {
|
|
||||||
if (gui->keyboard) {
|
|
||||||
gui_lock();
|
|
||||||
|
|
||||||
lv_obj_clear_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
lv_keyboard_set_textarea(gui->keyboard, textarea);
|
|
||||||
|
|
||||||
if (gui->toolbar) {
|
|
||||||
lv_obj_add_flag(gui->toolbar, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
gui_unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_keyboard_hide() {
|
|
||||||
if (gui->keyboard) {
|
|
||||||
gui_lock();
|
|
||||||
|
|
||||||
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
|
|
||||||
if (gui->toolbar) {
|
|
||||||
lv_obj_clear_flag(gui->toolbar, LV_OBJ_FLAG_HIDDEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
gui_unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool gui_keyboard_is_enabled() {
|
|
||||||
return !tt_lvgl_keypad_is_available() || TT_CONFIG_FORCE_ONSCREEN_KEYBOARD;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_hide_app() {
|
void gui_hide_app() {
|
||||||
gui_lock();
|
gui_lock();
|
||||||
ViewPort* view_port = gui->app_view_port;
|
ViewPort* view_port = gui->app_view_port;
|
||||||
|
|||||||
@ -40,14 +40,21 @@ void gui_keyboard_show(lv_obj_t* textarea);
|
|||||||
void gui_keyboard_hide();
|
void gui_keyboard_hide();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is to facilitate hardware keyboards like the one on Lilygo T-Deck.
|
* The on-screen keyboard is only shown when both of these conditions are true:
|
||||||
* The software keyboard is only shown when both of these conditions are true:
|
|
||||||
* - there is no hardware keyboard
|
* - there is no hardware keyboard
|
||||||
* - TT_CONFIG_FORCE_ONSCREEN_KEYBOARD is set to true in tactility_config.h
|
* - TT_CONFIG_FORCE_ONSCREEN_KEYBOARD is set to true in tactility_config.h
|
||||||
* @return if we should show a keyboard for text input inside our apps
|
* @return if we should show a on-screen keyboard for text input inside our apps
|
||||||
*/
|
*/
|
||||||
bool gui_keyboard_is_enabled();
|
bool gui_keyboard_is_enabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Glue code for the on-screen keyboard and the hardware keyboard:
|
||||||
|
* - Attach automatic hide/show parameters for the on-screen keyboard.
|
||||||
|
* - Registers the textarea to the default lv_group_t for hardware keyboards.
|
||||||
|
* @param textarea
|
||||||
|
*/
|
||||||
|
void gui_keyboard_add_textarea(lv_obj_t* textarea);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -49,8 +49,12 @@ static lv_obj_t* create_app_views(Gui* gui, lv_obj_t* parent, App app) {
|
|||||||
lv_obj_set_width(child_container, LV_PCT(100));
|
lv_obj_set_width(child_container, LV_PCT(100));
|
||||||
lv_obj_set_flex_grow(child_container, 1);
|
lv_obj_set_flex_grow(child_container, 1);
|
||||||
|
|
||||||
gui->keyboard = lv_keyboard_create(vertical_container);
|
if (gui_keyboard_is_enabled()) {
|
||||||
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
|
gui->keyboard = lv_keyboard_create(vertical_container);
|
||||||
|
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
gui->keyboard = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return child_container;
|
return child_container;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,16 +27,14 @@ struct Gui {
|
|||||||
|
|
||||||
lv_obj_t* _Nullable toolbar;
|
lv_obj_t* _Nullable toolbar;
|
||||||
lv_obj_t* _Nullable keyboard;
|
lv_obj_t* _Nullable keyboard;
|
||||||
|
lv_group_t* keyboard_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Update GUI, request redraw
|
/** Update GUI, request redraw */
|
||||||
*/
|
|
||||||
void gui_request_draw();
|
void gui_request_draw();
|
||||||
|
|
||||||
/** Lock GUI
|
/** Lock GUI */
|
||||||
*/
|
|
||||||
void gui_lock();
|
void gui_lock();
|
||||||
|
|
||||||
/** Unlock GUI
|
/** Unlock GUI */
|
||||||
*/
|
|
||||||
void gui_unlock();
|
void gui_unlock();
|
||||||
|
|||||||
70
tactility/src/services/gui/gui_keyboard.c
Normal file
70
tactility/src/services/gui/gui_keyboard.c
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include "gui_i.h"
|
||||||
|
|
||||||
|
#include "tactility_config.h"
|
||||||
|
#include "ui/lvgl_keypad.h"
|
||||||
|
#include "ui/lvgl_sync.h"
|
||||||
|
|
||||||
|
extern Gui* gui;
|
||||||
|
|
||||||
|
static void show_keyboard(lv_event_t* event) {
|
||||||
|
gui_keyboard_show(event->current_target);
|
||||||
|
lv_obj_scroll_to_view(event->current_target, LV_ANIM_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hide_keyboard(TT_UNUSED lv_event_t* event) {
|
||||||
|
gui_keyboard_hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gui_keyboard_is_enabled() {
|
||||||
|
return !tt_lvgl_keypad_is_available() || TT_CONFIG_FORCE_ONSCREEN_KEYBOARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_keyboard_show(lv_obj_t* textarea) {
|
||||||
|
gui_lock();
|
||||||
|
|
||||||
|
if (gui->keyboard) {
|
||||||
|
gui_lock();
|
||||||
|
|
||||||
|
lv_obj_clear_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_keyboard_set_textarea(gui->keyboard, textarea);
|
||||||
|
|
||||||
|
if (gui->toolbar) {
|
||||||
|
lv_obj_add_flag(gui->toolbar, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_keyboard_hide() {
|
||||||
|
gui_lock();
|
||||||
|
|
||||||
|
if (gui->keyboard) {
|
||||||
|
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
if (gui->toolbar) {
|
||||||
|
lv_obj_clear_flag(gui->toolbar, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_keyboard_add_textarea(lv_obj_t* textarea) {
|
||||||
|
gui_lock();
|
||||||
|
tt_check(tt_lvgl_lock(0), "lvgl should already be locked before calling this method");
|
||||||
|
|
||||||
|
if (gui_keyboard_is_enabled()) {
|
||||||
|
lv_obj_add_event_cb(textarea, show_keyboard, LV_EVENT_FOCUSED, NULL);
|
||||||
|
lv_obj_add_event_cb(textarea, hide_keyboard, LV_EVENT_DEFOCUSED, NULL);
|
||||||
|
lv_obj_add_event_cb(textarea, hide_keyboard, LV_EVENT_READY, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lv_obj_t auto-remove themselves from the group when they are destroyed (last checked in LVGL 8.3)
|
||||||
|
lv_group_add_obj(gui->keyboard_group, textarea);
|
||||||
|
|
||||||
|
tt_lvgl_keypad_activate(gui->keyboard_group);
|
||||||
|
|
||||||
|
tt_lvgl_unlock();
|
||||||
|
gui_unlock();
|
||||||
|
}
|
||||||
@ -84,7 +84,7 @@ TT_UNUSED void tt_init(const Config* config) {
|
|||||||
tt_hardware_init(config->hardware);
|
tt_hardware_init(config->hardware);
|
||||||
|
|
||||||
// Note: the order of starting apps and services is critical!
|
// Note: the order of starting apps and services is critical!
|
||||||
// System services are registered first so they can be used by the apps
|
// System services are registered first so the apps below can use them
|
||||||
register_and_start_system_services();
|
register_and_start_system_services();
|
||||||
// Then we register system apps. They are not used/started yet.
|
// Then we register system apps. They are not used/started yet.
|
||||||
register_system_apps();
|
register_system_apps();
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* This code relates to the hardware keyboard support also known as "keypads" in LVGL.
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
@ -6,9 +9,28 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if LVGL is configured with a keypad
|
||||||
|
*/
|
||||||
bool tt_lvgl_keypad_is_available();
|
bool tt_lvgl_keypad_is_available();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the keypad.
|
||||||
|
* @param device the keypad device
|
||||||
|
*/
|
||||||
void tt_lvgl_keypad_set_indev(lv_indev_t* device);
|
void tt_lvgl_keypad_set_indev(lv_indev_t* device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate the keypad for a widget group.
|
||||||
|
* @param group
|
||||||
|
*/
|
||||||
void tt_lvgl_keypad_activate(lv_group_t* group);
|
void tt_lvgl_keypad_activate(lv_group_t* group);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deactivate the keypad for the current widget group (if any).
|
||||||
|
* You don't have to call this after calling _activate() because widget
|
||||||
|
* cleanup automatically removes itself from the group it belongs to.
|
||||||
|
*/
|
||||||
void tt_lvgl_keypad_deactivate();
|
void tt_lvgl_keypad_deactivate();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user