e6e1dcd0ca
Removed software keyboard in Tactility subproject (GuiService, Lvgl.cpp) and re-implemented it in TactilityKernel.
108 lines
3.2 KiB
C++
108 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <Tactility/MessageQueue.h>
|
|
#include <Tactility/PubSub.h>
|
|
#include <Tactility/RecursiveMutex.h>
|
|
#include <Tactility/service/Service.h>
|
|
#include <Tactility/service/loader/Loader.h>
|
|
|
|
#include <Tactility/Semaphore.h>
|
|
|
|
#include <tactility/concurrent/dispatcher.h>
|
|
|
|
#include <lvgl/devices/keyboard.h>
|
|
|
|
namespace tt::service::gui {
|
|
|
|
/**
|
|
* Output a log warning if the current task is the GUI task.
|
|
* This is meant for code that should either create their own task or use a different task to execute on.
|
|
* @param[in] context a descriptive name or label that refers to the caller of this function
|
|
*/
|
|
void warnIfRunningOnGuiTask(const char* context);
|
|
|
|
class GuiService final : public Service {
|
|
|
|
// Thread and lock
|
|
Thread* thread = nullptr;
|
|
DispatcherHandle_t dispatcher = nullptr;
|
|
bool exitRequested = false;
|
|
RecursiveMutex mutex;
|
|
PubSub<loader::LoaderService::Event>::SubscriptionHandle loader_pubsub_subscription = nullptr;
|
|
|
|
// Signaled by hideApp() once App::onHide() has actually finished running on the GUI
|
|
// task. onLoaderEvent() blocks on this (still on the Loader thread, inside the
|
|
// synchronous pubsub publish() call) before returning from the ApplicationHiding
|
|
// branch, so LoaderService::transitionAppToState(Hiding) can't return - and therefore
|
|
// the immediately-following Destroyed transition (which unloads an ELF app's code via
|
|
// esp_elf_deinit) can't run - until onHide() has fully completed. Without this, the
|
|
// ELF's code/data can be unmapped while onHide() (and anything it spawned, like a
|
|
// camera capture task) is still executing it.
|
|
Semaphore hideDoneSem { 1, 0 };
|
|
|
|
// Layers and Canvas
|
|
lv_obj_t* appRootWidget = nullptr;
|
|
lv_obj_t* statusbarWidget = nullptr;
|
|
|
|
// App-specific
|
|
std::shared_ptr<app::AppInstance> appToRender = nullptr;
|
|
|
|
LvglSoftwareKeyboard software_keyboard = {};
|
|
|
|
bool isStarted = false;
|
|
|
|
static int32_t guiMain();
|
|
|
|
static void onGuiDispatch(void* context);
|
|
|
|
void onLoaderEvent(loader::LoaderService::Event event);
|
|
|
|
lv_obj_t* createAppViews(lv_obj_t* parent);
|
|
|
|
void redraw();
|
|
|
|
void lock() const {
|
|
check(mutex.lock(pdMS_TO_TICKS(1000)));
|
|
}
|
|
|
|
void unlock() const {
|
|
mutex.unlock();
|
|
}
|
|
|
|
void showApp(std::shared_ptr<app::AppInstance> app);
|
|
|
|
void hideApp();
|
|
|
|
public:
|
|
|
|
bool onStart(ServiceContext& service) override;
|
|
|
|
void onStop(ServiceContext& service) override;
|
|
|
|
/**
|
|
* Show the on-screen keyboard.
|
|
* @param[in] textarea the textarea to focus the input for
|
|
*/
|
|
void softwareKeyboardShow(lv_obj_t* textarea);
|
|
|
|
/**
|
|
* Hide the on-screen keyboard.
|
|
* Has no effect when the keyboard is not visible.
|
|
*/
|
|
void softwareKeyboardHide();
|
|
|
|
void keyboardAddTextArea(lv_obj_t* textarea);
|
|
|
|
/**
|
|
* 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 on-screen keyboard for text input inside our apps
|
|
*/
|
|
bool softwareKeyboardIsEnabled();
|
|
};
|
|
|
|
std::shared_ptr<GuiService> findService();
|
|
|
|
} // namespace
|