Simplify keyboard support (#22)

* simplify keyboard support

* removed cleanup code as it wasn't necessary

* improved docs
This commit is contained in:
Ken Van Hoeylandt 2024-01-28 00:04:47 +01:00 committed by GitHub
parent 7a7b31e426
commit 618f557a16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 126 additions and 74 deletions

View File

@ -4,7 +4,6 @@
#include "lvgl.h"
#include "services/gui/gui.h"
#include "services/wifi/wifi_credentials.h"
#include "ui/lvgl_keypad.h"
#include "ui/spacer.h"
#include "ui/style.h"
#include "wifi_connect.h"
@ -13,15 +12,6 @@
#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) {
WifiConnect* wifi = (WifiConnect*)event->user_data;
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);
if (gui_keyboard_is_enabled()) {
lv_obj_add_event_cb(view->ssid_textarea, show_keyboard, LV_EVENT_FOCUSED, NULL);
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);
}
gui_keyboard_add_textarea(view->ssid_textarea);
gui_keyboard_add_textarea(view->password_textarea);
// Init from app parameters
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);
}
}
// 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) {
// Cleanup keypad group
tt_lvgl_keypad_deactivate();
lv_group_del(view->group);
// NO-OP
}
void wifi_connect_view_update(

View File

@ -1,6 +1,8 @@
#include "check.h"
#include "hardware_i.h"
#include "check.h"
#include "lvgl.h"
#define TAG "hardware"
void tt_hardware_init(const HardwareConfig* config) {

View File

@ -16,7 +16,7 @@
void gui_redraw(Gui*);
static int32_t gui_main(void*);
static Gui* gui = NULL;
Gui* gui = NULL;
Gui* gui_alloc() {
Gui* instance = malloc(sizeof(Gui));
@ -32,6 +32,7 @@ Gui* gui_alloc() {
instance->keyboard = NULL;
tt_check(tt_lvgl_lock(1000 / portTICK_PERIOD_MS));
instance->keyboard_group = lv_group_create();
instance->lvgl_parent = lv_scr_act();
tt_lvgl_unlock();
@ -42,6 +43,11 @@ void gui_free(Gui* instance) {
tt_assert(instance != NULL);
tt_thread_free(instance->thread);
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);
}
@ -71,39 +77,6 @@ void gui_show_app(App app, ViewPortShowCallback on_show, ViewPortHideCallback on
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() {
gui_lock();
ViewPort* view_port = gui->app_view_port;

View File

@ -40,14 +40,21 @@ void gui_keyboard_show(lv_obj_t* textarea);
void gui_keyboard_hide();
/**
* This function is to facilitate hardware keyboards like the one on Lilygo T-Deck.
* The software keyboard is only shown when both of these conditions are true:
* The on-screen keyboard is only shown when both of these conditions are true:
* - there is no hardware keyboard
* - 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();
/**
* 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
}
#endif

View File

@ -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_flex_grow(child_container, 1);
gui->keyboard = lv_keyboard_create(vertical_container);
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
if (gui_keyboard_is_enabled()) {
gui->keyboard = lv_keyboard_create(vertical_container);
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
} else {
gui->keyboard = NULL;
}
return child_container;
}

View File

@ -27,16 +27,14 @@ struct Gui {
lv_obj_t* _Nullable toolbar;
lv_obj_t* _Nullable keyboard;
lv_group_t* keyboard_group;
};
/** Update GUI, request redraw
*/
/** Update GUI, request redraw */
void gui_request_draw();
/** Lock GUI
*/
/** Lock GUI */
void gui_lock();
/** Unlock GUI
*/
/** Unlock GUI */
void gui_unlock();

View 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();
}

View File

@ -84,7 +84,7 @@ TT_UNUSED void tt_init(const Config* config) {
tt_hardware_init(config->hardware);
// 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();
// Then we register system apps. They are not used/started yet.
register_system_apps();

View File

@ -1,3 +1,6 @@
/**
* This code relates to the hardware keyboard support also known as "keypads" in LVGL.
*/
#pragma once
#include "lvgl.h"
@ -6,9 +9,28 @@
extern "C" {
#endif
/**
* @return true if LVGL is configured with a keypad
*/
bool tt_lvgl_keypad_is_available();
/**
* Set the keypad.
* @param device the keypad 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);
/**
* 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();
#ifdef __cplusplus