2021-09-19 20:50:43 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright 2021 Johannes Marbach
|
|
|
|
|
*
|
|
|
|
|
* This file is part of unl0kr, hereafter referred to as the program.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
2021-09-02 20:08:45 +02:00
|
|
|
|
|
|
|
|
|
2021-09-23 21:05:36 +02:00
|
|
|
#include "command_line.h"
|
2021-09-25 21:02:00 +02:00
|
|
|
#include "config.h"
|
2021-09-24 09:07:37 +02:00
|
|
|
#include "indev.h"
|
2021-09-23 21:05:36 +02:00
|
|
|
#include "log.h"
|
|
|
|
|
#include "unl0kr.h"
|
2021-10-05 20:53:37 +02:00
|
|
|
#include "theme.h"
|
|
|
|
|
#include "themes.h"
|
2021-09-19 13:35:53 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
#include "lv_drivers/display/fbdev.h"
|
|
|
|
|
|
|
|
|
|
#include "lvgl/lvgl.h"
|
|
|
|
|
|
2021-09-19 13:35:53 +02:00
|
|
|
#include "squeek2lvgl/sq2lv.h"
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include <sys/reboot.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Static variables
|
|
|
|
|
*/
|
2021-09-06 10:26:59 +02:00
|
|
|
|
2021-09-25 21:02:00 +02:00
|
|
|
ul_cli_opts cli_opts;
|
|
|
|
|
ul_config_opts conf_opts;
|
|
|
|
|
|
2021-10-05 20:53:37 +02:00
|
|
|
bool is_alternate_theme = false;
|
2021-09-25 21:02:00 +02:00
|
|
|
bool is_password_obscured = true;
|
2021-09-19 20:50:43 +02:00
|
|
|
bool is_keyboard_hidden = false;
|
2021-09-06 13:02:24 +02:00
|
|
|
|
2021-09-06 10:26:59 +02:00
|
|
|
lv_obj_t *keyboard = NULL;
|
|
|
|
|
|
2021-09-06 11:42:00 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/**
|
|
|
|
|
* Static prototypes
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_CLICKED events from the theme toggle button.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void toggle_theme_btn_clicked_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Toggle between the light and dark theme.
|
|
|
|
|
*/
|
|
|
|
|
static void toggle_theme(void);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the UI theme.
|
|
|
|
|
*
|
|
|
|
|
* @param is_dark true if the dark theme should be applied, false if the light theme should be applied
|
|
|
|
|
*/
|
|
|
|
|
static void set_theme(bool is_dark);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_CLICKED events from the show/hide password toggle button.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void toggle_pw_btn_clicked_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Toggle between showing and hiding the password.
|
|
|
|
|
*/
|
2021-09-25 21:02:00 +02:00
|
|
|
static void toggle_password_obscured(void);
|
2021-09-19 20:50:43 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show / hide the password.
|
|
|
|
|
*
|
|
|
|
|
* @param is_hidden true if the password should be hidden, false if it should be shown
|
|
|
|
|
*/
|
2021-09-25 21:02:00 +02:00
|
|
|
static void set_password_obscured(bool is_obscured);
|
2021-09-19 20:50:43 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_CLICKED events from the show/hide keyboard toggle button.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void toggle_kb_btn_clicked_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Toggle between showing and hiding the keyboard.
|
|
|
|
|
*/
|
|
|
|
|
static void toggle_keyboard_hidden(void);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show / hide the keyboard
|
|
|
|
|
*
|
|
|
|
|
* @param is_hidden true if the keyboard should be hidden, false if it should be shown
|
|
|
|
|
*/
|
|
|
|
|
static void set_keyboard_hidden(bool is_hidden);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Callback for the keyboard's vertical slide in / out animation.
|
|
|
|
|
*
|
|
|
|
|
* @param obj keyboard widget
|
|
|
|
|
* @param value y position
|
|
|
|
|
*/
|
|
|
|
|
static void keyboard_anim_y_cb(void *obj, int32_t value);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_VALUE_CHANGED events from the keyboard layout dropdown.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void layout_dropdown_value_changed_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_CLICKED events from the shutdown button.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void shutdown_btn_clicked_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_VALUE_CHANGED events from the shutdown message box.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void shutdown_mbox_value_changed_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_VALUE_CHANGED events from the keyboard widget.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void keyboard_value_changed_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle LV_EVENT_READY events from the keyboard widget.
|
|
|
|
|
*
|
|
|
|
|
* @param event the event object
|
|
|
|
|
*/
|
|
|
|
|
static void keyboard_ready_cb(lv_event_t *event);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Static functions
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void toggle_theme_btn_clicked_cb(lv_event_t *event) {
|
|
|
|
|
toggle_theme();
|
2021-09-06 11:42:00 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void toggle_theme(void) {
|
2021-10-05 20:53:37 +02:00
|
|
|
is_alternate_theme = !is_alternate_theme;
|
|
|
|
|
set_theme(is_alternate_theme);
|
2021-09-06 13:02:24 +02:00
|
|
|
}
|
|
|
|
|
|
2021-10-05 20:53:37 +02:00
|
|
|
static void set_theme(bool is_alternate) {
|
|
|
|
|
ul_theme_apply(is_alternate ? &ul_themes_breezy_light : &ul_themes_breezy_dark);
|
2021-09-09 13:06:19 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void toggle_pw_btn_clicked_cb(lv_event_t *event) {
|
2021-09-25 21:02:00 +02:00
|
|
|
toggle_password_obscured();
|
2021-09-02 20:08:45 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-25 21:02:00 +02:00
|
|
|
static void toggle_password_obscured(void) {
|
|
|
|
|
is_password_obscured = !is_password_obscured;
|
|
|
|
|
set_password_obscured(is_password_obscured);
|
2021-09-02 20:08:45 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-25 21:02:00 +02:00
|
|
|
static void set_password_obscured(bool is_obscured) {
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_obj_t *textarea = lv_keyboard_get_textarea(keyboard);
|
2021-09-25 21:02:00 +02:00
|
|
|
lv_textarea_set_password_mode(textarea, is_obscured);
|
2021-09-19 20:50:43 +02:00
|
|
|
}
|
2021-09-08 22:19:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void toggle_kb_btn_clicked_cb(lv_event_t *event) {
|
|
|
|
|
toggle_keyboard_hidden();
|
|
|
|
|
}
|
2021-09-08 22:19:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void toggle_keyboard_hidden(void) {
|
|
|
|
|
is_keyboard_hidden = !is_keyboard_hidden;
|
|
|
|
|
set_keyboard_hidden(is_keyboard_hidden);
|
|
|
|
|
}
|
2021-09-08 22:19:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void set_keyboard_hidden(bool is_hidden) {
|
2021-09-25 21:02:00 +02:00
|
|
|
if (!conf_opts.general.animations) {
|
|
|
|
|
lv_obj_set_y(keyboard, is_hidden ? lv_obj_get_height(keyboard) : 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_anim_t keyboard_anim;
|
|
|
|
|
lv_anim_init(&keyboard_anim);
|
|
|
|
|
lv_anim_set_var(&keyboard_anim, keyboard);
|
|
|
|
|
|
|
|
|
|
if (is_hidden) {
|
|
|
|
|
lv_anim_set_values(&keyboard_anim, 0, lv_obj_get_y(keyboard));
|
|
|
|
|
lv_anim_set_path_cb(&keyboard_anim, lv_anim_path_ease_in_out);
|
|
|
|
|
} else {
|
|
|
|
|
lv_anim_set_values(&keyboard_anim, lv_obj_get_height(keyboard), 0);
|
|
|
|
|
lv_anim_set_path_cb(&keyboard_anim, lv_anim_path_overshoot);
|
2021-09-08 22:19:45 +02:00
|
|
|
}
|
2021-09-19 13:35:53 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_anim_set_time(&keyboard_anim, 500);
|
|
|
|
|
lv_anim_set_exec_cb(&keyboard_anim, keyboard_anim_y_cb);
|
|
|
|
|
lv_anim_start(&keyboard_anim);
|
2021-09-08 22:19:45 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void keyboard_anim_y_cb(void *obj, int32_t value) {
|
|
|
|
|
lv_obj_set_y(obj, value);
|
2021-09-06 13:02:24 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void layout_dropdown_value_changed_cb(lv_event_t *event) {
|
|
|
|
|
lv_obj_t *dropdown = lv_event_get_target(event);
|
|
|
|
|
uint16_t idx = lv_dropdown_get_selected(dropdown);
|
|
|
|
|
sq2lv_switch_layout(keyboard, idx);
|
2021-09-06 11:42:00 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void shutdown_btn_clicked_cb(lv_event_t *event) {
|
|
|
|
|
static const char *btns[] = { "Yes", "No", "" };
|
|
|
|
|
lv_obj_t *mbox = lv_msgbox_create(NULL, NULL, "Shutdown device?", btns, false);
|
|
|
|
|
lv_obj_add_event_cb(mbox, shutdown_mbox_value_changed_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
|
|
|
|
lv_obj_center(mbox);
|
|
|
|
|
}
|
2021-09-09 13:06:19 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void shutdown_mbox_value_changed_cb(lv_event_t *event) {
|
|
|
|
|
lv_obj_t *mbox = lv_event_get_current_target(event);
|
|
|
|
|
if (lv_msgbox_get_active_btn(mbox) == 0) {
|
|
|
|
|
sync();
|
|
|
|
|
reboot(RB_POWER_OFF);
|
2021-09-09 13:06:19 +02:00
|
|
|
}
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_msgbox_close(mbox);
|
2021-09-09 13:06:19 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void keyboard_value_changed_cb(lv_event_t *event) {
|
|
|
|
|
lv_obj_t *kb = lv_event_get_target(event);
|
2021-09-06 11:42:00 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
uint16_t btn_id = lv_btnmatrix_get_selected_btn(kb);
|
|
|
|
|
if (btn_id == LV_BTNMATRIX_BTN_NONE) {
|
|
|
|
|
return;
|
2021-09-06 10:26:59 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
if (sq2lv_is_layer_switcher(kb, btn_id)) {
|
|
|
|
|
sq2lv_switch_layer(kb, btn_id);
|
|
|
|
|
return;
|
2021-09-08 10:27:51 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_keyboard_def_event_cb(event);
|
|
|
|
|
}
|
2021-09-08 10:27:51 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
static void keyboard_ready_cb(lv_event_t *event) {
|
|
|
|
|
lv_obj_t *kb = lv_event_get_target(event);
|
|
|
|
|
lv_obj_t *ta = lv_keyboard_get_textarea(kb);
|
|
|
|
|
printf("%s\n", lv_textarea_get_text(ta));
|
|
|
|
|
exit(0);
|
2021-09-08 10:27:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/**
|
|
|
|
|
* Main
|
|
|
|
|
*/
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-23 21:05:36 +02:00
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
/* Parse command line options */
|
2021-09-25 21:02:00 +02:00
|
|
|
ul_cli_parse_opts(argc, argv, &cli_opts);
|
2021-09-25 14:20:54 +02:00
|
|
|
|
2021-09-23 21:05:36 +02:00
|
|
|
/* Set up log level */
|
2021-09-25 21:02:00 +02:00
|
|
|
if (cli_opts.verbose) {
|
2021-09-25 14:20:54 +02:00
|
|
|
ul_log_set_level(UL_LOG_LEVEL_VERBOSE);
|
2021-09-23 21:05:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Announce ourselves */
|
|
|
|
|
ul_log(UL_LOG_LEVEL_VERBOSE, "unl0kr %s", UL_VERSION);
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-25 21:02:00 +02:00
|
|
|
/* Parse config files */
|
|
|
|
|
ul_config_parse(cli_opts.config_files, cli_opts.num_config_files, &conf_opts);
|
|
|
|
|
|
2021-09-23 21:05:36 +02:00
|
|
|
/* Initialise LVGL and set up logging callback */
|
|
|
|
|
lv_init();
|
2021-09-25 14:20:54 +02:00
|
|
|
lv_log_register_print_cb(ul_log_print_cb);
|
2021-09-23 21:05:36 +02:00
|
|
|
|
|
|
|
|
/* Initialise framebuffer driver and query display size */
|
|
|
|
|
fbdev_init();
|
2021-09-02 20:08:45 +02:00
|
|
|
uint32_t hor_res;
|
|
|
|
|
uint32_t ver_res;
|
2021-09-23 21:05:36 +02:00
|
|
|
fbdev_get_sizes(&hor_res, &ver_res);
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-23 21:05:36 +02:00
|
|
|
/* Override display size with command line options if necessary */
|
2021-09-25 21:02:00 +02:00
|
|
|
if (cli_opts.hor_res > 0) {
|
|
|
|
|
hor_res = LV_MIN(hor_res, cli_opts.hor_res);
|
2021-09-23 21:05:36 +02:00
|
|
|
}
|
2021-09-25 21:02:00 +02:00
|
|
|
if (cli_opts.ver_res > 0) {
|
|
|
|
|
ver_res = LV_MIN(ver_res, cli_opts.ver_res);
|
2021-09-23 21:05:36 +02:00
|
|
|
}
|
2021-09-09 09:24:38 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Prepare display buffer */
|
|
|
|
|
const size_t buf_size = hor_res * ver_res / 10; /* At least 1/10 of the display size is recommended */
|
2021-09-02 20:08:45 +02:00
|
|
|
lv_disp_draw_buf_t disp_buf;
|
|
|
|
|
lv_color_t *buf = (lv_color_t *)malloc(buf_size * sizeof(lv_color_t));
|
|
|
|
|
lv_disp_draw_buf_init(&disp_buf, buf, NULL, buf_size);
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Initialise display driver */
|
2021-09-02 20:08:45 +02:00
|
|
|
static lv_disp_drv_t disp_drv;
|
|
|
|
|
lv_disp_drv_init(&disp_drv);
|
|
|
|
|
disp_drv.draw_buf = &disp_buf;
|
|
|
|
|
disp_drv.flush_cb = fbdev_flush;
|
|
|
|
|
disp_drv.hor_res = hor_res;
|
|
|
|
|
disp_drv.ver_res = ver_res;
|
|
|
|
|
lv_disp_drv_register(&disp_drv);
|
|
|
|
|
|
2021-09-24 09:07:37 +02:00
|
|
|
/* Connect input devices */
|
|
|
|
|
ul_indev_auto_connect();
|
|
|
|
|
ul_indev_set_up_mouse_cursor();
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-22 13:11:28 +02:00
|
|
|
/* Hide the on-screen keyboard by default if a physical keyboard is connected */
|
2021-09-24 09:07:37 +02:00
|
|
|
if (ul_indev_is_keyboard_connected()) {
|
2021-09-22 13:11:28 +02:00
|
|
|
is_keyboard_hidden = true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 20:53:37 +02:00
|
|
|
/* Initialise theme */
|
|
|
|
|
set_theme(is_alternate_theme);
|
2021-09-06 22:14:15 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Figure out a few numbers for sizing and positioning */
|
2021-09-09 09:24:38 +02:00
|
|
|
const int keyboard_height = ver_res / 3;
|
|
|
|
|
const int row_height = keyboard_height / 4;
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Button row */
|
|
|
|
|
lv_obj_t *btn_row = lv_obj_create(lv_scr_act());
|
|
|
|
|
static lv_coord_t btn_row_col_dsc[] = { 64, 64, LV_GRID_FR(1), 64, LV_GRID_TEMPLATE_LAST };
|
|
|
|
|
static lv_coord_t btn_row_row_dsc[] = { 64, LV_GRID_TEMPLATE_LAST };
|
|
|
|
|
lv_obj_set_grid_dsc_array(btn_row, btn_row_col_dsc, btn_row_row_dsc);
|
|
|
|
|
lv_obj_set_size(btn_row, LV_PCT(100), LV_SIZE_CONTENT);
|
|
|
|
|
lv_obj_align(btn_row, LV_ALIGN_TOP_MID, 0, 0);
|
|
|
|
|
|
|
|
|
|
/* Theme switcher button */
|
|
|
|
|
lv_obj_t *toggle_theme_btn = lv_btn_create(btn_row);
|
|
|
|
|
lv_obj_add_event_cb(toggle_theme_btn, toggle_theme_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
|
lv_obj_set_grid_cell(toggle_theme_btn, LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
|
|
|
|
lv_obj_set_size(toggle_theme_btn, 64, 64);
|
|
|
|
|
lv_obj_t *toggle_theme_btn_label = lv_label_create(toggle_theme_btn);
|
2021-10-05 20:53:37 +02:00
|
|
|
lv_label_set_text(toggle_theme_btn_label, UL_SYMBOL_ADJUST);
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_obj_center(toggle_theme_btn_label);
|
|
|
|
|
|
|
|
|
|
/* Show / hide keyboard button */
|
|
|
|
|
lv_obj_t *toggle_kb_btn = lv_btn_create(btn_row);
|
|
|
|
|
lv_obj_add_event_cb(toggle_kb_btn, toggle_kb_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
|
lv_obj_set_grid_cell(toggle_kb_btn, LV_GRID_ALIGN_CENTER, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
|
|
|
|
lv_obj_set_size(toggle_kb_btn, 64, 64);
|
|
|
|
|
lv_obj_t *toggle_kb_btn_label = lv_label_create(toggle_kb_btn);
|
|
|
|
|
lv_label_set_text(toggle_kb_btn_label, LV_SYMBOL_KEYBOARD);
|
|
|
|
|
lv_obj_center(toggle_kb_btn_label);
|
|
|
|
|
|
|
|
|
|
/* Keyboard layout dropdown */
|
|
|
|
|
lv_obj_t *layout_dropdown = lv_dropdown_create(btn_row);
|
|
|
|
|
lv_dropdown_set_options(layout_dropdown, sq2lv_layout_short_names);
|
|
|
|
|
lv_obj_add_event_cb(layout_dropdown, layout_dropdown_value_changed_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
|
|
|
|
lv_obj_set_grid_cell(layout_dropdown, LV_GRID_ALIGN_START, 2, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
2021-10-05 20:53:37 +02:00
|
|
|
// lv_obj_set_height(layout_dropdown, 64);
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_obj_set_width(layout_dropdown, 160);
|
|
|
|
|
|
|
|
|
|
/* Shutdown button */
|
|
|
|
|
lv_obj_t *shutdown_btn = lv_btn_create(btn_row);
|
|
|
|
|
lv_obj_add_event_cb(shutdown_btn, shutdown_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
|
lv_obj_set_grid_cell(shutdown_btn, LV_GRID_ALIGN_CENTER, 3, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
|
|
|
|
lv_obj_set_size(shutdown_btn, 64, 64);
|
|
|
|
|
lv_obj_t *shutdown_btn_label = lv_label_create(shutdown_btn);
|
|
|
|
|
lv_label_set_text(shutdown_btn_label, LV_SYMBOL_POWER);
|
|
|
|
|
lv_obj_center(shutdown_btn_label);
|
|
|
|
|
|
|
|
|
|
/* Textarea */
|
|
|
|
|
lv_obj_t *textarea = lv_textarea_create(lv_scr_act());
|
2021-09-08 08:23:00 +02:00
|
|
|
lv_textarea_set_one_line(textarea, true);
|
|
|
|
|
lv_textarea_set_password_mode(textarea, true);
|
|
|
|
|
lv_textarea_set_placeholder_text(textarea, "Enter password...");
|
2021-10-05 20:53:37 +02:00
|
|
|
// lv_obj_set_size(textarea, hor_res - 60 > 512 ? 512 : hor_res - 60, 64);
|
|
|
|
|
lv_obj_set_width(textarea, hor_res - 60 > 512 ? 512 : hor_res - 60);
|
2021-09-09 09:24:38 +02:00
|
|
|
lv_obj_align(textarea, LV_ALIGN_CENTER, 0, ver_res / 2 - keyboard_height - 3 * row_height / 2);
|
2021-09-08 08:23:00 +02:00
|
|
|
lv_obj_add_state(textarea, LV_STATE_FOCUSED);
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Route physical keyboard input into textarea */
|
2021-09-24 09:07:37 +02:00
|
|
|
ul_indev_set_up_textarea_for_keyboard_input(textarea);
|
2021-09-19 20:50:43 +02:00
|
|
|
|
2021-09-25 21:02:00 +02:00
|
|
|
/* Reveal / obscure password button */
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_obj_t *toggle_pw_btn = lv_btn_create(lv_scr_act());
|
|
|
|
|
lv_obj_align(toggle_pw_btn, LV_ALIGN_CENTER, (hor_res - 60 > 512 ? 512 : hor_res - 60) / 2 + 32, ver_res / 2 - keyboard_height - 3 * row_height / 2);
|
2021-10-05 20:53:37 +02:00
|
|
|
// lv_obj_set_size(toggle_pw_btn, 64, 64);
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_obj_t *toggle_pw_btn_label = lv_label_create(toggle_pw_btn);
|
|
|
|
|
lv_obj_center(toggle_pw_btn_label);
|
|
|
|
|
lv_label_set_text(toggle_pw_btn_label, LV_SYMBOL_EYE_OPEN);
|
|
|
|
|
lv_obj_add_event_cb(toggle_pw_btn, toggle_pw_btn_clicked_cb, LV_EVENT_CLICKED, NULL);
|
|
|
|
|
|
|
|
|
|
/* Label */
|
2021-09-02 20:08:45 +02:00
|
|
|
lv_obj_t *spangroup = lv_spangroup_create(lv_scr_act());
|
|
|
|
|
lv_spangroup_set_align(spangroup, LV_TEXT_ALIGN_CENTER);
|
|
|
|
|
lv_spangroup_set_mode(spangroup, LV_SPAN_MODE_BREAK);
|
2021-09-09 09:24:38 +02:00
|
|
|
lv_obj_set_size(spangroup, hor_res - 40, 2 * row_height);
|
2021-09-02 20:08:45 +02:00
|
|
|
lv_obj_align(spangroup, LV_ALIGN_CENTER, 0, ver_res / 2 - keyboard_height);
|
|
|
|
|
lv_span_t *span1 = lv_spangroup_new_span(spangroup);
|
|
|
|
|
lv_span_t *span2 = lv_spangroup_new_span(spangroup);
|
2021-10-08 21:20:39 +02:00
|
|
|
lv_span_t *span3 = lv_spangroup_new_span(spangroup);
|
|
|
|
|
|
|
|
|
|
/* Label text */
|
|
|
|
|
const char *crypttab_tried = getenv("CRYPTTAB_TRIED");
|
|
|
|
|
if (crypttab_tried && atoi(crypttab_tried) > 0) {
|
|
|
|
|
lv_span_set_text(span1, "Password incorrect. Please enter password to unlock ");
|
|
|
|
|
lv_span_set_text(span3, ".");
|
|
|
|
|
} else {
|
|
|
|
|
lv_span_set_text(span1, "Please enter password to unlock ");
|
|
|
|
|
}
|
|
|
|
|
lv_span_set_text(span2, getenv("CRYPTTAB_SOURCE"));
|
2021-09-02 20:08:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Keyboard (after textarea / label so that key popovers are not drawn over) */
|
2021-09-08 08:23:00 +02:00
|
|
|
keyboard = lv_keyboard_create(lv_scr_act());
|
|
|
|
|
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
|
2021-09-19 20:50:43 +02:00
|
|
|
lv_keyboard_set_textarea(keyboard, textarea);
|
|
|
|
|
lv_obj_remove_event_cb(keyboard, lv_keyboard_def_event_cb);
|
|
|
|
|
lv_obj_add_event_cb(keyboard, keyboard_value_changed_cb, LV_EVENT_VALUE_CHANGED, NULL);
|
|
|
|
|
lv_obj_add_event_cb(keyboard, keyboard_ready_cb, LV_EVENT_READY, NULL);
|
2021-09-22 13:11:28 +02:00
|
|
|
lv_obj_set_pos(keyboard, 0, is_keyboard_hidden ? keyboard_height : 0);
|
2021-09-08 08:23:00 +02:00
|
|
|
lv_obj_set_size(keyboard, hor_res, keyboard_height);
|
2021-10-05 20:53:37 +02:00
|
|
|
ul_theme_prepare_keyboard(keyboard);
|
2021-09-06 13:02:24 +02:00
|
|
|
|
2021-09-25 21:02:00 +02:00
|
|
|
/* Apply textarea options */
|
|
|
|
|
set_password_obscured(conf_opts.textarea.obscured);
|
|
|
|
|
|
|
|
|
|
/* Apply keyboard options */
|
|
|
|
|
sq2lv_switch_layout(keyboard, conf_opts.keyboard.layout_id);
|
|
|
|
|
lv_dropdown_set_selected(layout_dropdown, conf_opts.keyboard.layout_id);
|
|
|
|
|
if (conf_opts.keyboard.popovers) {
|
2021-10-01 21:08:10 +02:00
|
|
|
lv_keyboard_set_popovers(keyboard, true);
|
2021-09-25 21:02:00 +02:00
|
|
|
}
|
2021-09-08 22:19:45 +02:00
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/* Run lvgl in "tickless" mode */
|
2021-09-02 20:08:45 +02:00
|
|
|
while(1) {
|
|
|
|
|
lv_task_handler();
|
|
|
|
|
usleep(5000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-09-19 20:50:43 +02:00
|
|
|
/**
|
|
|
|
|
* Tick generation
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generate tick for LVGL.
|
|
|
|
|
*
|
|
|
|
|
* @return tick in ms
|
|
|
|
|
*/
|
|
|
|
|
uint32_t ul_get_tick(void) {
|
2021-09-02 20:08:45 +02:00
|
|
|
static uint64_t start_ms = 0;
|
|
|
|
|
if (start_ms == 0) {
|
|
|
|
|
struct timeval tv_start;
|
|
|
|
|
gettimeofday(&tv_start, NULL);
|
|
|
|
|
start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct timeval tv_now;
|
|
|
|
|
gettimeofday(&tv_now, NULL);
|
|
|
|
|
uint64_t now_ms;
|
|
|
|
|
now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
|
|
|
|
|
|
|
|
|
|
uint32_t time_ms = now_ms - start_ms;
|
|
|
|
|
return time_ms;
|
|
|
|
|
}
|